How to avoid backslashes in GSON JsonObject? - java

I have a Java POJO
public class TagBean {
private String type;
private String id;
public TagBean(String type, String id) {
this.type = type;
this.id = id;
}
// getters
// setters
}
I'm building pojo's and adding them to a List, as
....
List<TagBean> channelsList = new ArrayList<>();
List<TagBean> showsList = new ArrayList<>();
for each <business logic> {
if value=channels {
channelsList.add(new TagBean(...));
}
if value=shows {
showsList.add(new TagBean(...));
}
}
Gson gson = new GsonBuilder().create();
JsonObject tjsonObject = new JsonObject();
tjsonObject.addProperty("channels", gson.toJson(channelsList));
tjsonObject.addProperty("shows", gson.toJson(showsList));
JsonObject mainjsonObject = mainjsonObject.add("tags", tjsonObject);
return mainjsonObject;
My output is:
{
"tags": {
"channels": "[{\"type\":\"channel\",\"id\":\"channel\",\"name\":\"Channel\",\"parent\":\"SXM\"}]",
"shows": "[{\"type\":\"shows\",\"id\":\"shows\",\"name\":\"Shows\",\"parent\":\"SXM\"},{\"type\":\"shows\",\"id\":\"howard\",\"name\":\"Howard Stern\",\"parent\":\"shows\"},{\"type\":\"shows\",\"id\":\"howardstern\",\"name\":\"Howard Stern\",\"parent\":\"howard\"}]",
"sports": "[]"
}
}
How can i remove the backslashes? So the output is like:
{
"tags": {
"channels": " [{"type":"channel","id":"channel","name":"Channel","parent":"SXM"}]",
"shows": "[{"type":"shows","id":"shows","name":"Shows","parent":"SXM"},{"type":"shows","id":"howard","name":"Howard Stern","parent":"shows"}....
There were few other posts, but none explained this.

The problem is caused by this:
tjsonObject.addProperty("channels", gson.toJson(channelsList));
What that is doing is converting channelsList to a string containing a representation of the list in JSON, then setting the property to that string. Since the string contains JSON meta-characters, they must be escaped when the strings are serialized ... a second time.
I think that you need to do this instead:
tjsonObject.add("channels", gson.toJsonTree(channelsList));
That should produce this:
{
"tags": {
"channels":
[{"type":"channel","id":"channel","name":"Channel","parent":"SXM"}],
"shows":
[{"type":"shows","id":"shows","name":"Shows","parent":"SXM"},
{"type":"shows","id":"howard","name":"Howard Stern","parent":"shows"}
....
That is slightly different to what your question asked for, but it has the advantage of being syntactically valid JSON!

String mainJsonStr = mainjsonObject.toString();
mainJsonStr = mainJsonStr.replace("\\\\", ""); //replace the \
System.out.println(mainJsonStr);

The problem is that gson.toJson returns a String, and
tjsonObject.addProperty("channels", gson.toJson(channelsList));
this will add channels as a string and not as a JSON object.
One possible solution is to convert the string returned from gson.toJson to JSON object first then add it to the parent JSON object like
Gson gson = new GsonBuilder().create();
JsonObject tjsonObject = new JsonObject();
tjsonObject.put("channels", new JsonObject(gson.toJson(channelsList)));
tjsonObject.put("shows", new JsonObject(gson.toJson(showsList)));
this will treat channels and shows as JSON object

All strings in java have to escape quotes in them. So jsonInString should have slashes in it. When you output jsonInString though it shouldn't have the quotes. Are you looking at it in a debugger or something?
Just parse json directly and check - will get the output

above solution is not working anymore since GSON 2.8.*
use gson.toJsonTree(jsonText).getAsString(); instead

Related

Simplest way to convert this array in to the specified one using Java

I have this String Json Payload
[
"key1":{
"atr1":"key1",
"atr2":"value1",
"atr3":"value2",
"atr4":"value3,
"atr5":"value4"
},
"key2":{
"atr1":"key2",
"atr2":"value5",
"atr3":"value6",
"atr4":value7,
"atr5":"value8"
}
]
and I want it to be converted in to the following format using Java
[
{
"atr2":"value1",
"atr3":"value2",
"atr4":"value3,
"atr5":"value4"
},
{
"atr2":"value5",
"atr3":"value6",
"atr4": "value7",
"atr5":"value8"
}
]
What would be the simplest way of transforming this ?
You cannot, because the example below is not valid json.
Check it out using this JSON validator.
If you paste this in (I've fixed some basic errors with lack of quotes)
{
{
"atr2":"value1",
"atr3":"value2",
"atr4":"value3",
"atr5":"value4"
},
{
"atr2":"value5",
"atr3":"value6",
"atr4":"value7",
"atr5":"value8"
}
}
You will get these errors ...
It can work if you change the target schema to something like this by using a json-array to contain your data.
[
{
"atr2":"value1",
"atr3":"value2",
"atr4":"value3",
"atr5":"value4"
},
{
"atr2":"value5",
"atr3":"value6",
"atr4":"value7",
"atr5":"value8"
}
]
If this works for you, then this problem can easily be solved by using the ObjectMapper class.
You use it to deserealize the original JSON into a class, which has two fields "key1" and "key2"
Extract the values of these fields and then just store them in an array ...
Serialize the array using the ObjectMapper.
Here a link, which explains how to use the ObjectMapper class to achieve the goals above.
EDIT:
So you'll need the following classes to solve the problem ...
Stores the object data
class MyClass {
String atr2;
String art3;
}
Then you have a container class, which is used to store the initial json.
class MyClassContainer {
MyClass key1;
MyClass key2;
}
Here's how you do the parse from the original json to MyClassContainer
var mapper = new ObjectMapper()
var json = //Get the json String somehow
var myClassContainer = mapper.readValue(json,MyClassContainer.class)
var mc1 = myClassContainer.getKey1();
var mc2 = myClassContainer.getKey2();
var myArray = {key1, key2}
var resultJson = mapper.writeValueAsString(myArray)
Assuming that you will correct the JSON into a valid one (which involves replacing the surrounding square braces with curly ones, and correct enclosure of attribute values within quotes), here's a simpler way which involves only a few lines of core logic.
try{
ObjectMapper mapper = new ObjectMapper();
mapper.configure( DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false );
HashMap<String, Data> map = mapper.readValue( jsonString, new TypeReference<HashMap<String, Data>>(){} );
String json = mapper.writeValueAsString( map.values() );
System.out.println( json );
}
catch( JsonProcessingException e ){
e.printStackTrace();
}
jsonString above is your original JSON corrected and valid JSON input.
Also notice the setting of FAIL_ON_UNKNOWN_PROPERTIES to false to allow atr1 to be ignored while deserializing into Data.
Since we are completely throwing away attr1 and its value, the Data class will represent all fields apart from that.
private static class Data{
private String atr2;
private String atr3;
private String atr4;
private String atr5;
}

Json strings to Json array

Good day!
I have an array of json objects like this :
[{
"senderDeviceId":0,
"recipientDeviceId":0,
"gmtTimestamp":0,
"type":0
},
{
"senderDeviceId":0,
"recipientDeviceId":0,
"gmtTimestamp":0,
"type":4
}]
For some reasons I need to split then to each element and save to storage. In the end I have many objects like
{ "senderDeviceId":0,
"recipientDeviceId":0,
"gmtTimestamp":0,
"type":0
}
{
"senderDeviceId":0,
"recipientDeviceId":0,
"gmtTimestamp":0,
"type":4
}
After some time I need to combine some of them back into json array.
As I can see - I can get objects from storage, convert them with Gson to objects, out objects to a list, like this:
String first = "..."; //{"senderDeviceId":0,"recipientDeviceId":0,"gmtTimestamp":0,"type":0}
String second = "...";//{"senderDeviceId":0,"recipientDeviceId":0,"gmtTimestamp":0,"type":4}
BaseMessage msg1 = new Gson().fromJson(first, BaseMessage.class);
BaseMessage msg2 = new Gson().fromJson(second, BaseMessage.class);
List<BaseMessage> bmlist = new ArrayList<>();
bmlist.add(msg1);
bmlist.add(msg2);
//and then Serialize to json
But I guess this is not the best way. Is there any way to combine many json-strings to json array? I rtyed to do this:
JsonElement elementTm = new JsonPrimitive(first);
JsonElement elementAck = new JsonPrimitive(second);
JsonArray arr = new JsonArray();
arr.add(elementAck);
arr.add(elementTm);
But JsonArray gives me escaped string with json - like this -
["{
\"senderDeviceId\":0,
\"recipientDeviceId\":0,
\"gmtTimestamp\":0,
\"type\":4
}","
{
\"senderDeviceId\":0,
\"recipientDeviceId\":0,
\"gmtTimestamp\":0,
\"type\":0
}"]
How can I do this?
Thank you.
At the risk of making things too simple:
String first = "...";
String second = "...";
String result = "[" + String.join(",", first, second) + "]";
Saves you a deserialization/serialization cycle.

How to convert this json String to normal java arraylist using gson

I tried to convert following JSON string into Array and got following error:
Exception in thread "AWT-EventQueue-0" java.lang.NoClassDefFoundError:
org/apache/commons/logging/LogFactory at
net.sf.json.AbstractJSON.(AbstractJSON.java:54) at
net.sf.json.util.CycleDetectionStrategy.(CycleDetect‌​ionStrategy.java:36)
at net.sf.json.JsonConfig.(JsonConfig.java:65) at
net.sf.json.JSONSerializer.toJSON(JSONSerializer.java:84)
JSON:
[
{
"file_name":"1.xml",
"file_ext":"application/octet-stream",
"sr_no":"0.1",
"status":"Checked ",
"rev":"1",
"locking":"0"
},
{
"file_name":"2.xml",
"file_ext":"json/octet-stream",
"sr_no":"0.2",
"status":"Not Checked ",
"rev":"2",
"locking":"1"
},
{
"file_name":"3.xml",
"file_ext":"application/json-stream",
"sr_no":"0.3",
"status":"Checked ",
"rev":"1",
"locking":"3"
},
{
"file_name":"4.xml",
"file_ext":"application/octet-stream",
"sr_no":"0.4",
"status":"Checked ",
"rev":"0.4",
"locking":"4"
}
]
Code:
JSONArray nameArray = (JSONArray) JSONSerializer.toJSON(output);
System.out.println(nameArray.size());
for(Object js : nameArray)
{
JSONObject json = (JSONObject) js;
System.out.println("File_Name :" +json.get("file_name"));
}
I know the question is about converting JSON String to Java Array, but I would like to also answer about how to convert the JSON String to an ArrayList using the Gson Library.
Since I spend a good amount of time in solving this, I hope my solution may help others.
My JSON string looks similar to this one -
I had an object named StockHistory, and I wanted to convert this JSON into an ArrayList of StockHistory.
This is how my StockHistory class looked -
class StockHistory {
Date date;
Double open;
Double high;
Double low;
Double close;
Double adjClose;
Double volume;
}
The code that I used to convert the JSON Array to the ArrayList of StockHistory is as follows -
Gson gson = new Gson();
Type listType = new TypeToken< ArrayList<StockHistory> >(){}.getType();
List<StockHistory> history = gson.fromJson(reader, listType);
Now if you are reading your JSON from a file, the reader's initialization would be -
Reader reader = new FileReader(fileName);
and if you are just converting a string to JSON object then, the reader's initialization would simply be -
String reader = "{ // json String }";
Hope that helps. Cheers!!!
You can create a java class with entities are: file_name, file_ext, sr_no, status, rev, locking in string type.
public class TestJson {
private String file_name, file_ext, sr_no, status, rev, locking;
//get & set
}
}
Then you call:
public static void main(String[] args) {
String json = your json string;
TestJson[] respone = new Gson().fromJson(json, TestJson[].class);
for (TestJson s : respone) {
System.out.println("File name: " + s.getFile_name());
}
}
So, you have a list of object you want.
Firstly I have to say your question is quite "ugly" and next time please improve your question's quality.
Answer:
Try to use com.fasterxml.jackson.databind.ObjectMapper
If you have a java class to describe your items in the list:
final ObjectMapper mapper = new ObjectMapper();
YourClass[] yourClasses = mapper.readValue(YourString, YourClass[].class);
Then convert the array to a List.
If you don't have a java class, just you LinkedHashMap instead.

GSON parsing unspecified type variable

I parse server JSON response with GSON library. Backend guys sometimes tell me: "We can't specify variable type in JSON for some reason" (old php, they don't know how to do it and so on and so forth).
GSON likes strong typing in its object model. So I can't parse Object as String.
GSON wait for:
{
"service":{
"description":null,
"name":"Base",
"id":"4c7a90410529"
}
}
But it gets (empty data):
"service": ""
And I get
java.lang.IllegalStateException: Expected BEGIN_OBJECT but was STRING at line 1 column 1396
What is the best practice to parse such response?
Another question:
How can I build object, it can recognize Integer variable which returned from time to time as Integer or as String? The same server side issue.
"data": "1"
or
"data": 1
I know - we should use specific types in Java. But sometime it is worth to make concessions,
Thanks
EDIT:
My solution based on Java Developer's answer.
ServiceDeserializer class deserialize every object depending on its internal value.
public class ServiceDeserializer implements JsonDeserializer<ServiceState>{
#Override
public ServiceState deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
String name = "";
String uuid = "";
String description = "";
if (json.isJsonObject()) {
JsonObject obj = json.getAsJsonObject();
if (!obj.get("name").isJsonNull()) {
name = obj.get("name").getAsString();
}
if (!obj.get("uuid").isJsonNull()) {
uuid = obj.get("uuid").getAsString();
}
if (!obj.get("description").isJsonNull()) {
description = obj.get("description").getAsString();
}
}
return new ServiceState(name, uuid, description);
}
}
And my GSON constructor with type adapter for ServiceState.
Gson gson = new GsonBuilder()
.registerTypeAdapter(ServiceState.class, new ServiceDeserializer())
.create();
You need to scrape the JSON response before trying to deserialize it into your Response Java object. You can make use of Java org.json parser to verify that service object actually exists and fix it otherwise.
String json = "{\"service\":{\r\n" +
" \"description\":null,\r\n" +
" \"name\":\"Base\",\r\n" +
" \"id\":\"4c7a90410529\"\r\n" +
"}}";
String json2 = "{\"service\":\"\"}";
JSONObject root = new JSONObject(json);
// JSONObject root = new JSONObject(json2);
if (root.optJSONObject("service") == null) {
root.put("service", new JSONObject());
}
Gson gson = new Gson();
Response response = gson.fromJson(root.toString(), Response.class);
System.out.println(response.getService());
Output :
// for JSONObject root = new JSONObject(json);
Service [id=4c7a90410529, name=Base, description=null]
// for JSONObject root = new JSONObject(json2);
Service [id=null, name=null, description=null]
Secondly, Gson is smart enough to do simple conversions like String to Integer etc. So, deserializing such JSON properties shouldn't give you any troubles.
System.out.println(gson.fromJson("10", Integer.class)); // 10
System.out.println(gson.fromJson("\"20\"", Integer.class)); // 20
If you want to stick with strictly gson you can provide a custom deserializer. Since we know that service is either a property of the base json string or embedded within some other property, we can use the deserializer to step-wise parse out the offending components and handle them accordingly.
public class MyJsonDeserializer implements JsonDeserializer<YourParsedData> {
#Override
public YourParsedData deserialize(final JsonElement je, final Type type, final JsonDeserialization Context jdc) throws JsonParseException
{
final JsonObject obj = je.getAsJsonObject(); //our original full json string
final JsonElement serviceElement = obj.get("service");
//here we provide the functionality to handle the naughty element. It seems emtpy string is returned as a JsonPrimitive... so one option
if(serviceElement instanceOf JsonPrimitive)
{
//it was empty do something
}
return YourParsedData.create(); //provide the functionality to take in the parsed data
}
}
The custom deserializer would be called as follows:
final Gson gson = new GsonBuilder().registerTypeAdapter(YourParsedData.class, new MyJsonDeserializer()).create();
gson.fromJson("{service: ''}", YourParsedData.class);
I typed all this up so if I missed some syntax my apologies.
Your json is invalid and any Json parser wouldn't be able to parse a syntactically incorrect json:
"service": {
"description": null,
"name": "Base",
"id": "4c7a90410529"
}
should be encapsulated in curly braces as mentioned here:
{
"service": {
"description": null,
"name": "Base",
"id": "4c7a90410529"
}
}
A json structure is enclosed within {}. Your response seems to be missing that. You can manually append { and } at the beginning and end of the string to make it into a valid json structure.
Once this is done, you can use Gson to parse your json response normally.
What is the best practice to parse such response?
Use a good enough Json parser. That's more than enough. And try to have a class representing the exact same Structure as the response to avoid parsing the json responses level by level, manually.

How to properly format JSON string in java?

I have a jersey client that is getting JSON from a source that I need to get into properly formatted JSON:
My JSON String looks like the folllowing when grabbing it via http request:
{
"properties": [
{
someproperty: "aproperty",
set of data: {
keyA: "SomeValueA",
keyB: "SomeValueB",
keyC: "SomeValueC"
}
}
]
}
I am having problems because the json has to be properly formatted and keyA, keB, and keyC are not surrounded in quotes. Is there some library that helps add quotes or some best way to go about turning this string to properly formatted json? Or if there is some easy way to convert this to a json object without writing a bunch of classes with variables and lists that match the incoming structure?
you can use json-lib. it's very convenient! you can construct your json string like this:
JSONObject dataSet = new JSONObject();
dataSet.put("keyA", "SomeValueA") ;
dataSet.put("keyB", "SomeValueB") ;
dataSet.put("keyC", "SomeValueC") ;
JSONObject someProperty = new JSONObject();
dataSet.put("someproperty", "aproperty") ;
JSONArray properties = new JSONArray();
properties.add(dataSet);
properties.add(someProperty);
and of course you can get your JSON String simply by calling properties.toString()
I like Flexjson, and using lots of initilizers:
public static void main(String[] args) {
Map<String, Object> object = new HashMap<String, Object>() {
{
put("properties", new Object[] { new HashMap<String, Object>() {
{
put("someproperty", "aproperty");
put("set of dada", new HashMap<String, Object>() {
{
put("keyA", "SomeValueA");
put("keyB", "SomeValueB");
put("keyC", "SomeValueC");
}
});
}
} });
}
};
JSONSerializer json = new JSONSerializer();
json.prettyPrint(true);
System.out.println(json.deepSerialize(object));
}
results in:
{
"properties": [
{
"someproperty": "aproperty",
"set of dada": {
"keyA": "SomeValueA",
"keyB": "SomeValueB",
"keyC": "SomeValueC"
}
}
]
}
Your string isn't JSON. It's something that bears a resemblance to JSON. There is no form of JSON that makes those quotes optional. AFAIK, there is no library that will reads your string and cope with the missing quotes and then spit it back out correctly. You need to find the code that produced this and repair it to produce actual JSON.
You can use argo, a simple JSON parser and generator in Java

Categories