Format of POJO for nested JSON? - java

So lets say the JSON response is:
[{ "data" : { "item1": value1, "item2:" value2 }}]
How do you get the values 'value1' and 'value2' when you must first access data?
If the fields were at the root then I could just have the method return a POJO with those field names.
I basically want the below to work.
#GET("/path/to/data/")
Pojo getData();
class Pojo
{
public String item1;
public String item2;
}

You can try below code to convert your json string to Pojo object with required fields using Gson library.
Gson gson = new Gson();
JsonArray jsonArray = gson.fromJson (jsonString, JsonElement.class).getAsJsonArray(); // Convert the Json string to JsonArray
JsonObject jsonObj = jsonArray.get(0).getAsJsonObject(); //Get the first element of array and convert it to Json object
Pojo pojo = gson.fromJson(jsonObj.get("data").toString(), Pojo.class); //Get the data property from json object and convert it to Pojo object
or you can define your nested Pojo class to parse it.
class Pojo
{
private String item1;
private String item2;
//Setters and Getters
}
class Data
{
private Pojo data;
//Setters and Getters
}
ArrayList<Data> yourArray = new Gson().fromJson(jsonString, new TypeToken<List<Data>>(){}.getType());
EDIT : Try below code to get value1 and value2 using Retrofit.
class Pojo
{
private String item1;
private String item2;
//Setters and Getters
}
class Data
{
private Pojo data;
//Setters and Getters
}
class MyData
{
private ArrayList<Data> dataList;
//Setters and Getters
}
IService service = restAdapter.create(IService.class);
MyData data = service.getData();
ArrayList<Data> list = data.getDataList(); // Retrive arraylist from MyData
Data obj = list.get(0); // Get first element from arraylist
Pojo pojo = obj.getData(); // Get pojo from Data
Log.e("pojo", pojo.item1 + ", " + pojo.item2);

Related

Gson - Nested Object inside a CustomObject - java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to java.util.List

I googled and saw many question and answers but none of it are helping me. Here is the issue. I have a Class
public class ResponseData {
public static transient final int SUCCESS = 1;
public static transient final int FAILED = 0;
public String id;
public int status;
public Object data;
// Constructor, Getters and Setters
}
I'm using ResponseData as the common return object for my server and the server has many APIs. In one of the API, it is setting the data parameter to ArrayList. Then converting as json using Gson (2.8.0).
And then sending back to caller. (It's not HTTP)
public class MyServerClass {
private final Gson gson;
public MyServerClass() {
GsonBuilder builder = new GsonBuilder();
gson = builder.serializeNulls().create();
}
public String someAPI() {
ResponseData responseData = new Response("myid", ResponseData.SUCCESS, Arrays.asList("Some string value", ArrayList<MyCustomObject>, "Some other Value"));
String json = gson.toJson(response)
}
}
And the MyCustomClass is a plain POJO class with some set of attributes.
public class MyCustomClass {
private String name;
private String id;
private String createdTime;
//Constructor, Getters & Setters
}
At the receiving side I have below code.
private Gson gson = null;
GsonBuilder builder = new GsonBuilder();
gson = builder.create();
///
ResponseData response = gson.fromJson(eventData, ResponseData.class);
ArrayList list = (ArrayList) respone.getData();
String val = (String) list.get(0);
List rwData = (List) list.get(1);
for(List<List<String>> entry: rwData) { // Exception is thrown Here. How to get it as List?
//Coverting Data
}
Exception is thrown when trying to get the data as List<List<String>>. How to convert the json string properly here? I cannot use the MyCustomClass at my client layer. That's why trying list
Exception occured:com.google.gson.internal.LinkedTreeMap cannot be cast to java.util.List
java.lang.ClassCastException: com.google.gson.internal.LinkedTreeMap cannot be cast to java.util.List

json serialization with a variable field as a string

I have a pojo that I am unmarshalling a REST response to. One of the fields ("variable value") is just a Json variable element (can be any form).
Is there a way to tell it to treat the field as a plain string for all cases instead of trying to deserialize to an object?
Here's a json obiect ("variable value" can be any form):
{"id":1, "variable value": {"name":"one", "age": 22, "data":{"key":"value"}}}
I would like to save this json as a class object using gson
public class SomeCommand {
private Long id;
private String data;
}
It sounds that you would like to parse the given JSON string to transform variable value into String object. You can achieve this by creating 2 classes - SomeCommandOriginal and SomeCommand as follows:
First, convert the JSON string to SomeCommandOriginal to map the value of variable value to JsonNode.
class SomeCommandOriginal {
private Long id;
#JsonProperty("variable value")
private JsonNode variableValue;
//general getters and setters
}
class SomeCommand {
private Long id;
private String data;
public SomeCommand(SomeCommandOriginal someCommandOriginal) {
super();
this.id = someCommandOriginal.id;
this.data = someCommandOriginal.variableValue.toString();
}
//general getters and setters
}
Second, initialize an instance of SomeCommand and pass someCommandOriginal as the argument of customized constructor:
ObjectMapper mapper = new ObjectMapper();
SomeCommandOriginal someCommandOriginal = mapper.readValue(jsonStr, SomeCommandOriginal.class);
SomeCommand someCommand = new SomeCommand(someCommandOriginal);
System.out.println(someCommand.getData());
Console output:
{"name":"one", "age": 22, "data":{"key":"value"}}
UPDATED
If you are using Gson, just modify the datatype of variableValue to be JsonObject and switch to #SerializedName annotation as follows:
class SomeCommandOriginal {
private Long id;
#SerializedName("variable value")
private JsonObject variableValue;
//general getters and setters
}
And then you can get the same result as well:
Gson gson = new Gson();
SomeCommandOriginal someCommandOriginal = gson.fromJson(jsonStr, SomeCommandOriginal.class);
SomeCommand someCommand = new SomeCommand(someCommandOriginal);
System.out.println(someCommand.getData());

Parse json using ObjectMapper where json key contains json as a value

I have a class with such structure:
class SomeClass {
private String stringValue;
private Collection<String> collectionValue = new ArrayList<>();
private String jsonStringValue;
private boolean booleanValue;
}
And then I use
objectMapper.readValue(jsonString, SomeClass.class);
to parse this object from JSON.
The main problem is that jsonStringValue is a json inside of json:
{"stringValue" : "someString",
"collectionValue" : ["123456", "234567", "hello"],
"jsonStringValue" : "{
"someKey" : 1,
"anotherKey" : {
"againKey" : "value"
}
},
"booleanValue" : true
}
And trying to parse jsonStringValue it throws
com.fasterxml.jackson.core.JsonParseException: Unexpected character ('a' (code 97)): was expecting comma to separate Object entries
Exactly "a" character from my example (json modified on security purposes)
I believe there should be some escaping rule for parsing json as a String.
How do I parse json value as a string?
First, your JSON string is not valid because there is a redundant double quote before the left bracket in jsonStringValue. The valid one looks like this:
{
"stringValue" : "someString",
"collectionValue" : ["123456", "234567", "hello"],
"jsonStringValue" : {
"someKey" : 1,
"anotherKey" : {
"againKey" : "value"
}
},
"booleanValue" : true
}
Second, jsonStringValue is not a simple String object, it is a nested JSON objects. Therefore, you are supposed to create corresponding classes for it as follows:
Class SomeClass {
private String stringValue;
private List<String> collectionValue = new ArrayList<>();
private JsonStringValue jsonStringValue;
private boolean booleanValue;
//general getters and setters
}
Class JsonStringValue {
private int someKey;
private AnotherKey anotherKey;
//general getters and setters
}
Class AnotherKey {
private String againKey;
//general getters and setters
}
At last, the given JSON string can be transformed into SomeClass POJO with ObjectMapper.
ObjectMapper mapper = new ObjectMapper();
SomeClass someClass = mapper.readValue(jsonStr, SomeClass.class);
System.out.println(someClass.getjsonStringValue().getAnotherKey().getAgainKey());
Console output:
value
UPDATED
If you still want to transform the jsonStringValue object into String, an alternative way is shown as follows:
Create 2 classes - SomeClassOriginal and SomeClass, the only difference between them is the data type of jsonStringValue. The former one is JsonNode and later one is String.
Class SomeClassOriginal {
private String stringValue;
private List<String> collectionValue = new ArrayList<>();
private JsonNode jsonStringValue;
private boolean booleanValue;
//general getters and setters
}
Class SomeClass {
private String stringValue;
private List<String> collectionValue = new ArrayList<>();
private String jsonStringValue;
private boolean booleanValue;
public SomeClass(SomeClassOriginal someClassOriginal) {
super();
this.stringValue = someClassOriginal.stringValue;
this.collectionValue = someClassOriginal.collectionValue ;
this.jsonStringValue= someClassOriginal.jsonStringValue.toString();
this.booleanValue= someClassOriginal.booleanValue;
}
//general getters and setters
}
Then you can get the jsonStringValue as String like this:
ObjectMapper mapper = new ObjectMapper();
SomeClassOriginal someClassOriginal = mapper.readValue(jsonStr, SomeClassOriginal.class);
SomeClass someClass = new SomeClass(SomeClassOriginal);
System.out.println(someClass.getjsonStringValue());
Console output:
{"someKey":1,"anotherKey":{"againKey":"value"}}

GSON parsing multiple keys of the same type

I'm working on a personal project in Android and I want to use GSON to parse a JSON file containing the data I need.
I have a local JSON file with the following structure:
{
"Object1": {
"foo": "value1",
"bar": "value2",
"baz": "value3",
...
},
"Object2": {
"foo": "value4",
"bar": "value5",
"baz": "value6",
...
},
...
}
I have already made an Object class of the following structure:
Class Object {
String data;
...
}
How would I parse this JSON file with this structure?
EDIT: The JSON file I use is very large, it contains about 400+ of these objects of type Object. I would have to iterate over each object to create a new JSONObject, but I do not know how to do this.
In the solution below, we convert the JSON you've provided in your link as a JSONOject. Then we get the list of names contained in the JSON ("Abaddon", "Archeri", ...). Once we have the list we iterate through it. For each name we get the JSON object associated with it.
Then we use GSON to convert each object into a Demon object. The Demon class has been generated using http://www.jsonschema2pojo.org/ as suggested above.
As all the objects in the JSON have the same structure we need only one class to deserialize every single one of them.
Deserializer
public List<Demon> deserialize(String json) {
try {
JSONObject jsonObject = new JSONObject(json);
final JSONArray names = jsonObject.names();
final List<Demon> demons = new ArrayList<>();
final Gson gson = new Gson();
Demon demon;
for (int i = 0; i < names.length(); i++) {
demon = gson.fromJson(jsonObject.get(names.getString(i)).toString(), Demon.class);
demons.add(demon);
}
return demons;
} catch (JSONException e) {
e.printStackTrace();
return null;
}
}
Demon class
public class Demon {
#SerializedName("ailments")
#Expose
public String ailments;
#SerializedName("align")
#Expose
public String align;
#SerializedName("code")
#Expose
public Integer code;
#SerializedName("inherits")
#Expose
public String inherits;
#SerializedName("lvl")
#Expose
public Integer lvl;
#SerializedName("pcoeff")
#Expose
public Integer pcoeff;
#SerializedName("race")
#Expose
public String race;
#SerializedName("resists")
#Expose
public String resists;
#SerializedName("skills")
#Expose
public List<String> skills = null;
#SerializedName("source")
#Expose
public List<String> source = null;
#SerializedName("stats")
#Expose
public List<Integer> stats = null;
public Demon(){
// Default constructor
}
}

How to extract property from JSON embedded within JSON?

This is the JSON String I am getting back from a URL and I would like to extract highDepth value from the below JSON String.
{
"description": "",
"bean": "com.hello.world",
"stats": {
"highDepth": 0,
"lowDepth": 0
}
}
I am using GSON here as I am new to GSON. How do I extract highDepth from the above JSON Strirng using GSON?
String jsonResponse = restTemplate.getForObject(url, String.class);
// parse jsonResponse to extract highDepth
You create a pair of POJOs
public class ResponsePojo {
private String description;
private String bean;
private Stats stats;
//getters and setters
}
public class Stats {
private int highDepth;
private int lowDepth;
//getters and setters
}
You then use that in the RestTemplate#getForObject(..) call
ResponsePojo pojo = restTemplate.getForObject(url, ResponsePojo.class);
int highDepth = pojo.getStats().getHighDepth();
No need for Gson.
Without POJOs, since RestTemplate by default uses Jackson, you can retrieve the JSON tree as an ObjectNode.
ObjectNode objectNode = restTemplate.getForObject(url, ObjectNode.class);
JsonNode highDepth = objectNode.get("stats").get("highDepth");
System.out.println(highDepth.asInt()); // if you're certain of the JSON you're getting.
Refering to JSON parsing using Gson for Java, I would write something like
JsonElement element = new JsonParser().parse(jsonResponse);
JsonObject rootObject = element.getAsJsonObject();
JsonObject statsObject = rootObject.getAsJsonObject("stats");
Integer highDepth = Integer.valueOf(statsObject.get("highDepth").toString());

Categories