Map JSON to Java object - java

I have these type of JSON object which I'm getting from gridx filter expression:
{
"op": "or",
"data": [
{
"op": "contain",
"data": [
{
"op": "string",
"data": "id",
"isCol": true
},
{
"op": "string",
"data": "sdfv"
}
]
},
{
"op": "contain",
"data": [
{
"op": "string",
"data": "post",
"isCol": true
},
{
"op": "string",
"data": "sdfv"
}
]
},
{
"op": "contain",
"data": [
{
"op": "string",
"data": "birthday",
"isCol": true
},
{
"op": "string",
"data": "sdfv"
}
]
}
]
}
How I can map this to a Java object and then deserialize using Gson?
I've made these two classes:
package dto.Filter;
public class FilterData extends FilterExpression {
private String op;
private boolean isCol;
private String data;
public String getOp() {
return op;
}
public void setOp(String op) {
this.op = op;
}
public boolean isCol() {
return isCol;
}
public void setCol(boolean col) {
isCol = col;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
package dto.Filter;
import java.util.List;
public class FilterExpression {
private List<FilterData> filters;
private String op;
public List<FilterData> getFilters() {
return filters;
}
public void setFilters(List<FilterData> filters) {
this.filters = filters;
}
public String getOp() {
return op;
}
public void setOp(String op) {
this.op = op;
}
}
The problem is that I have both data as Object and String type. Do I need to use my custom TypeAdapter?

Make your data structure as
class DataStructure {
private String op;
private String data;
private String isCol;
public DataStructure(){
op="";
data="";
isCol="";
}
public String getOp() {
return op;
}
public void setOp(String op) {
this.op = op;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
public String isCol() {
return isCol;
}
public void setCol(String isCol) {
this.isCol = isCol;
}
#Override
public String toString() {
return "DataStructure [op=" + op + ", data=" + data + ", isCol=" + isCol + "]";
}
}
I have parse the JSON file using google GSON library. Here is maven repository.
Note: to read using GSON library add '[' at starting and ']' at ending.
I have read the JSON file and store the data in ArrayList. Hope after getting array list you can do serialization.
public class FilterData {
private static Gson gson = new Gson();
private static JsonParser parser = new JsonParser();
public static List<DataStructure> getData(List<DataStructure> datas){
List<DataStructure> result = new ArrayList<>();
for (DataStructure data : datas) {
for (JsonElement object : parser.parse(data.getData()).getAsJsonArray()) {
DataStructure dataStructure = new DataStructure();
JsonObject jObject = gson.fromJson(object, JsonObject.class);
dataStructure.setOp(jObject.get("op").toString());
dataStructure.setData(jObject.get("data").toString());
if (jObject.has("isCol"))
dataStructure.setData(jObject.get("isCol").toString());
System.out.println(dataStructure);
result.add(dataStructure);
}
}
return result;
}
public static void main(String[] args) throws FileNotFoundException {
JsonReader reader = new JsonReader(new InputStreamReader(new FileInputStream("input.json")));
List<DataStructure> datas = new ArrayList<>();
JsonArray jArray = parser.parse(reader).getAsJsonArray();
for (JsonElement object : jArray) {
DataStructure dataStructure = new DataStructure();
JsonObject jObject = gson.fromJson(object, JsonObject.class);
dataStructure.setOp(jObject.get("op").toString());
dataStructure.setData(jObject.get("data").toString());
if (jObject.has("isCol"))
dataStructure.setData(jObject.get("isCol").toString());
System.out.println(dataStructure);
datas.add(dataStructure);
}
List<DataStructure> insideData = getData(datas);
List<DataStructure> inside2Data = getData(insideData);
}
}

Related

Java reading JSON with multiple objects

The json looks like:
{
"id": "SMAAZGD20R",
"data": [
{
"blukiiId": "CC78AB5E73C8",
"macAddress": "CC78AB5E73C8",
"type": "SENSOR_BEACON",
"battery": 97,
"advInterval": 1000,
"firmware": "003.007",
"rssi": [
{
"rssi": -96,
"timestamp": 1594642177138
}
],
"beaconSensorData": {
"environment": [
{
"airPressure": 994.4,
"light": 5,
"humidity": 26,
"temperature": 28.4,
"timestamp": 1594642177138
}
]
}
}
]
}
The code looks like:
public class getJSON
{
public static void main(String[] args) throws Exception{
JSONParser parser = new JSONParser();
try{
Object obj = parser.parse(new FileReader("C:\\test.json"));
JSONObject jsonObj = (JSONObject)obj;
JSONArray jsonArr = (JSONArray)jsonObj.get("data");
Iterator itr = jsonArr.iterator();
while(itr.hasNext()){
System.out.println(itr.next());
}
}catch(Exception e){
e.printStackTrace();
}
}
}
Output:
{"macAddress":"CC78AB5E73C8","rssi":[{"rssi":-96,"timestamp":1594642177138}],"advInterval":1000,"blukiiId":"CC78AB5E73C8","type":"SENSOR_BEACON","battery":97,"firmware":"003.007","beaconSensorData":{"environment":[{"light":5,"airPressure":994.4,"temperature":28.4,"humidity":26,"timestamp":1594642177138}]}}
I get an Array with the object "data", but the array includes only one value with all objects from "data".
How can i address the array "environment" and get the values tempreature, light,...
Have you should try to use a framework like jackson
Who will let unmarshall your json to real java object of your choice
for example :
public class Data
{
private String blukiiId;
private String macAddress;
private String type;
...
private List<RSSI> rssi;
private BeaconSensorData beaconSensorData;
}
With Rssi,BeaconSensorData another class like that etc...
Now your code will get Converted as below
public class getJSON
{
public static void main(String[] args) throws Exception{
ObjectMapper mapper = new ObjectMapper();
// Set any extra configs like ignore fields etc here
try{
Data data = mapper.convertValue(Files.readAllBytes(Paths.get("test.json"), Data.class);
//Now you can access the value as below
data.getBeaconSensorData().getEnvironment().getTemperature();
}catch(Exception e){
e.printStackTrace();
}
}
}
If you can only use org.json.simple.parser.JSONParser, please refer to the following java code by recursion.
import java.io.FileReader;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import org.json.simple.JSONArray;
import org.json.simple.JSONObject;
import org.json.simple.parser.JSONParser;
public class getJSON
{
private static void visitElement(Object obj, Map<Object, Object> map) throws Exception {
if(obj instanceof JSONArray) {
JSONArray jsonArr = (JSONArray)obj;
Iterator<?> itr = jsonArr.iterator();
while(itr.hasNext())
visitElement(itr.next(), map);
}
else if(obj instanceof JSONObject) {
JSONObject jsonObj = (JSONObject)obj;
Iterator<?> itr = jsonObj.keySet().iterator();
while(itr.hasNext()) {
Object key = itr.next();
Object value = jsonObj.get(key);
map.put(key, value);
visitElement(value, map);
}
}
}
public static void main(String[] args) throws Exception{
JSONParser parser = new JSONParser();
try{
Object obj = parser.parse(new FileReader("C:/test.json"));
Map<Object, Object> map = new HashMap<>();
visitElement(obj, map);
for(Object key : map.keySet())
System.out.println(key + ": " + map.get(key));
}catch(Exception e){
e.printStackTrace();
}
}
}
Look at my code below.
[
{
"title": "Dywizjon 303",
"year": 2019,
"type": "Dokumentalny",
"director": "Zbigniew Zbigniew",
"actors": ["Maria Joao","Jose Raposo"]
},
{
"title": "Szeregowiec Ryan",
"year": 2006,
"type": "Historyczny",
"director": "Stanislaw Stanislaw",
"actors": ["Rosa Canto","Amalia Reis","Maria Garcia"]
},
{
"title": "Duzy",
"year": 1988,
"type": "Dramat",
"director": "Penny Marshall",
"actors": ["Rosa Canto"]
},
{
"title": "Syberiada Polska",
"year": 2013,
"type": "Wojenny",
"director": "Janusz Zaorski",
"actors": ["Harvey Glazer"]
}
]
This is my Entity named Movie
package objectMapper.app;
import java.util.Arrays;
import java.util.List;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement;
#JacksonXmlRootElement(localName="Class")
public class Movie {
#JacksonXmlProperty(localName="title")
private String title;
#JacksonXmlProperty(localName="year")
private int year;
#JacksonXmlProperty(localName="type")
private String type;
#JacksonXmlProperty(localName="director")
private String director;
#JacksonXmlProperty(localName="actors")
private String[] actors;
public Movie()
{
}
public Movie(String title, int year, String type, String director, String[] actors) {
this.title = title;
this.year = year;
this.type = type;
this.director = director;
this.actors = actors;
}
public String getTitle() {
return title;
}
public void setTitle(String title) {
this.title = title;
}
public int getYear() {
return year;
}
public void setYear(int year) {
this.year = year;
}
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getDirector() {
return director;
}
public void setDirector(String director) {
this.director = director;
}
public String[] getActors() {
return actors;
}
public void setActors(String[] actors) {
this.actors = actors;
}
#Override
public String toString() {
return "Movie [title=" + title + ", year=" + year + ", type=" + type + ", director=" + director + ", actors="
+ Arrays.toString(actors) + "]";
}
}
Function to read movies.json
public Movie[] readJSONFile() throws JsonParseException, JsonMappingException, IOException
{
ObjectMapper mapper= new ObjectMapper();
Movie[] jsonObj=mapper.readValue(new File("movies.json"),Movie[].class);
return jsonObj;
}
Lets do something with our POJO class
List<String> titles=new ArrayList();
for(Movie itr: tempMovies)
{
titles.add(itr.getTitle().toLowerCase());
}
if(titles.contains(tempTitle.toLowerCase()))
{
for(Movie itr2 : tempMovies)
{
if(tempTitle.toLowerCase().equals(itr2.getTitle().toLowerCase()))
{
System.out.println("Title: "+itr2.getTitle());
System.out.println("Year: "+itr2.getYear());
System.out.println("Type: "+itr2.getType());
System.out.println("Director: "+itr2.getDirector());
String[] tempActorsStrings=itr2.getActors();
int size=tempActorsStrings.length;
for(int i=0;i<size;i++)
{
System.out.println("Actor: "+tempActorsStrings[i]);
}
status=false;
}
}
}
else
{
System.out.println("Movie title does not exist!");
}

How to fix "Expected BEGIN_OBJECT but was BEGIN_ARRAY"?

I'm sending an HTTP request using Retrofit 2, I've done everything regularly, however, the situation is "not standard". I have a problem that one of the objects to receive in the response class is once sent as an object and in the other as a list. So I don't know whether to initialize it in the response class as an object or as an array.
Here is my full JSON response:
{
"data": [
{
"name": "John",
"surname": "Smith",
"nicname": "Joe",
"age": "32",
"description": "Example",
"state": "Nevada",
"city": "Las Vegas",
"job": "Security",
"adress": "Some adress 1",
"postcode": "412421",
"details": {
"intro": {
"title": "Mr.",
"married": "No",
"children": "2"
},
"rest": {
"pitctures":"24",
"chats": "7",
"lastChat": "12-01-2016",
"lastVisited": "07-04-2017",
}
}
},
{
"name": "John",
"surname": "Smith",
"nicname": "Joe",
"age": "32",
"description": "Example",
"state": "Nevada",
"city": "Las Vegas",
"job": "Security",
"adress": "Some adress 1",
"postcode": "412421",
"details": {
"intro": {
"title": "Mr.",
"married": "No",
"children": "No"
},
"rest": []
}
}
],
"errors": false,
"update_notifications": {
"message": [],
"friend_request": [],
"code": "IzS0hivN1cyHBdygpeWv"
}
}
Details.java class:
public class Details {
#SerializedName("intro")
#Expose
private Intro intro;
#SerializedName("rest")
#Expose
private Rest restObject;
private ArrayList<Rest> restList;
public Details(Intro intro, Rest restObject) {
this.intro = intro;
this.restObject = restObject;
}
public Details(Intro intro, ArrayList<Rest> restList) {
this.intro = intro;
this.restList = restList;
}
public Intro getIntro() {
return intro;
}
public void setIntro(Intro intro) {
this.intro = intro;
}
public Rest getRestObject() {
return restObject;
}
public void setRestObject(Rest restObject) {
this.restObject = restObject;
}
public ArrayList<Rest> getRestList() {
return restList;
}
public void setRestList(ArrayList<Rest> restList) {
this.restList = restList;
}
}
And here is my CustomDeserializer.java (rest array neeed to be empty, maybe that's a problem) based on #Farid's answer:
public class CustomDeserializer implements JsonDeserializer<Details> {
#Override
public Details deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject detailsObject = json.getAsJsonObject().get("details").getAsJsonObject();
Details details;
JsonObject introObject = detailsObject.get("intro").getAsJsonObject();
String title = introObject.get("title").getAsString();
String married = introObject.get("married").getAsString();
String children = introObject.get("children").getAsString();
try {
JsonObject restObject = detailsObject.get("rest").getAsJsonObject();
String pitctures = restObject.get("pitctures ").getAsString();
String chats = restObject.get("chats ").getAsString();
String lastChat = restObject.get("lastChat ").getAsString();
String lastVisited = restObject.get("lastVisited ").getAsString();
details = new Details(new Intro(title, married, children),
new Rest(pitctures, chats, lastChat, lastVisited));
}catch (IllegalStateException e){
JsonArray restArray = detailsObject.get("rest").getAsJsonArray();
ArrayList<Rest> restList = new ArrayList<>();
details = new Details(new Intro(title, married, children), restList);
}
return details;
}
}
In MainActivity based on #Farid's answer:
Gson gsonConverter = new GsonBuilder().registerTypeAdapter(Details.class, new CustomDeserializer()).create();
Retrofit retrofit = new Retrofit.Builder()
.baseUrl(myUrl)
.addConverterFactory(GsonConverterFactory.create(gsonConverter))
.build();
service1 = retrofit.create(MyAPI.class);
final ProgressDialog progressDialog = new ProgressDialog(this);
progressDialog.setCancelable(false);
progressDialog.setMessage("Please wait!");
progressDialog.show();
final MyRequest myRequest = new MyRequest();
myRequest.setPin(pin);
final Call<MyResponse> myResponseCall = service1.get (code, myRequest);
myResponseCall.enqueue(new Callback<MyResponse>() {
#Override
public void onResponse(Call<MyResponse> call, Response<MyResponse> response) {
}
});
It's possible. You'll have to create a custom Deserializer. As you can see there is JsonDeserializer<Details> whose type parameter is Details that means any time GSON tries to deserialize Details object, it will call CustomDeserializer to deserialize it. Anything inside Details object should be deserialized manually as seen in the CustomDeserializer class whereas all other types outside Details class (e.g. Class, String, int) will be handled by GSON seamlessly
CustomDeserializer.java
public class CustomDeserializer implements JsonDeserializer<Details> {
#Override
public Details deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject detailsObject = json.getAsJsonObject();
Details details;
Intro intro = new Intro(detailsObject.get("intro").getAsJsonObject().get("example").getAsString());
try {
JsonObject restObject = detailsObject.get("rest").getAsJsonObject();
String example = restObject.get("example").getAsString();
details = new Details(intro, new Rest(example));
}catch (IllegalStateException e){ // In case rest is ArrayList
JsonArray restArray = detailsObject.get("rest").getAsJsonArray();
ArrayList<Rest> resList = new ArrayList<>();
for (JsonElement element: restArray){
JsonObject restObject = element.getAsJsonObject();
String example = restObject.get("example").getAsString();
resList.add(new Rest(example));
}
details = new Details(intro, resList);
}
return details;
}
}
Then you have to register CustomDeserializer as TypeAdapter as below:
Gson gsonConverter = GsonBuilder().registerTypeAdapter(Details::class.java,
CustomDeserializer()).create();
Retrofit retrofit = new Retrofit.Builder()
.addConverterFactory(GsonConverterFactory.create(gsonConverter))
///Rest of Retrofit builder code
If you want to know more about custom deserialization, search for "gson deserialization" and find a tutorial that appeals to you most.
Below code snippets are OP specific classes
Response.java
public class Response {
private List<DataItem> data = null;
private Boolean errors;
private String example;
public List<DataItem> getData() {
return data;
}
public void setData(List<DataItem> data) {
this.data = data;
}
public Boolean getErrors() {
return errors;
}
public void setErrors(Boolean errors) {
this.errors = errors;
}
public String getExample() {
return example;
}
public void setExample(String example) {
this.example = example;
}
}
Data.java
public class DataItem {
private String example;
private Details details;
public String getExample() {
return example;
}
public void setExample(String example) {
this.example = example;
}
public Details getDetails() {
return details;
}
public void setDetails(Details details) {
this.details = details;
}
}
Details.java
public class Details {
private Intro intro;
private Rest restObject;
private ArrayList<Rest> restList;
public Details(Intro intro, ArrayList<Rest> restList) {
this.intro = intro;
this.restList = restList;
}
public Details(Intro intro, Rest restObject) {
this.intro = intro;
this.restObject = restObject;
}
public Rest getRestObject() {
return restObject;
}
public ArrayList<Rest> getRestList() {
return restList;
}
public Intro getIntro() {
return intro;
}
public void setIntro(Intro intro) {
this.intro = intro;
}
}
Intro.java
public class Intro {
public Intro(String example) {
this.example = example;
}
private String example;
public String getExample() {
return example;
}
public void setExample(String example) {
this.example = example;
}
}
Rest.java
public class Rest {
private String example;
public Rest(String example) {
this.example = example;
}
public String getExample() {
return example;
}
}

Expected BEGIN_ARRAY but was BEGIN_OBJECT at line 1 column 5921 path $.data[5].courier.data

I have this model object Courier :
public class Courier {
#SerializedName("data")
private List<User> data = null;
public Courier() {
}
public Courier(List<User> data) {
this.data = data;
}
public List<User> getData() {
return data;
}
public void setData(List<User> data) {
this.data = data;
}
}
I get this response from server:
{
"data": [
{
"id": 446,
"courier": {
"data": []
},
"title": "гром",
"description": "Логойский тракт 24 в России в начале следующей",
"departure": "ChIJPQKUckNv2UYRLr1NasgXZ08",
"arrival": "EkHQodC10YDQtdCx0YDRj9C90YvQuSDQv9C10YDQtdGD0LvQvtC6LCDQnNC-0YHQutCy0LAsINCg0L7RgdGB0LjRjw"
},
{
"id": 438,
"courier": {
"data": []
},
"title": "тест",
"description": "гппг лмш ш ш ш ш г У меня на сковородке стоит ли брать сва в кино мы все равно обсуждаем",
"departure": "ChIJH10nmDnP20YR-n7Kq6Whd5w",
"arrival": "Ej_QnNC-0YHQutCy0L7RgNC10YbQutCw0Y8g0YPQu9C40YbQsCwg0JzQvtGB0LrQstCwLCDQoNC-0YHRgdC40Y8"
},
{
"id": 439,
"courier": {
"data": []
},
"title": "лаьаьаат",
"description": "лала слат алс ал ала ал кща да аьад",
"departure": "ChIJH7D4cTnP20YRKlzSCnP6Mak",
"arrival": "Ej_QnNC-0YHQutCy0L7RgNC10YbQutCw0Y8g0YPQu9C40YbQsCwg0JzQvtGB0LrQstCwLCDQoNC-0YHRgdC40Y8"
},
{
"id": 442,
"courier": {
"data": {
"id": 122,
"email": null,
"phone": "73339999999",
"photo": null,
"rating": 0
}
},
"title": "картошечка",
"description": "Крупная сортированная",
"departure": "ChIJnZRv1jnP20YRWiezW55d1tA",
"arrival": "ChIJpfH6UJtp1EYRlhM20g-jzF4"
}
]
}
If object courier not have data, i get array "data": [], if object courier has data, i get object :
"courier": {
"data": {
"id": 122,
"email": null,
"phone": "73339999999",
"photo": null,
"rating": 0
}
}
And then I get error... Please give me advice how handle this case in android application...
is one of the most common mistakes when you start to use JSON with a client, for android please refer to this tutorial to understand
the best source to understand this kind of mistake is to read this post
a canonical SO post.
Is better to read it and understand it, that asking for a simple solution because you will go really often into this error.
while deserializing, Gson was expecting a JSON object, but found a
JSON array
A JSON Object is wrapped by a {
A JSON Array is wrapped by a [
What you need is to adapt your class Courier, to deserialize in the right way the JSON response.
take in mind that; a JSON array become deserialized in java as a Collection type or an array type;
PLEASE notice that is confusing to use two times data
on top of everything, the first data is
public class MyPojo
{
private Data[] data;
public Data[] getData ()
{
return data;
}
public void setData (Data[] data)
{
this.data = data;
}
#Override
public String toString()
{
return "ClassPojo [data = "+data+"]";
}
}
Data.class
public class Data
{
private String id;
private String title;
private String description;
private Courier courier;
private String arrival;
private String departure;
public String getId ()
{
return id;
}
public void setId (String id)
{
this.id = id;
}
public String getTitle ()
{
return title;
}
public void setTitle (String title)
{
this.title = title;
}
public String getDescription ()
{
return description;
}
public void setDescription (String description)
{
this.description = description;
}
public Courier getCourier ()
{
return courier;
}
public void setCourier (Courier courier)
{
this.courier = courier;
}
public String getArrival ()
{
return arrival;
}
public void setArrival (String arrival)
{
this.arrival = arrival;
}
public String getDeparture ()
{
return departure;
}
public void setDeparture (String departure)
{
this.departure = departure;
}
#Override
public String toString()
{
return "ClassPojo [id = "+id+", title = "+title+", description = "+description+", courier = "+courier+", arrival = "+arrival+", departure = "+departure+"]";
}
}
Courier.class
public class Courier
{
private String[] data;
public String[] getData ()
{
return data;
}
public void setData (String[] data)
{
this.data = data;
}
#Override
public String toString()
{
return "ClassPojo [data = "+data+"]";
}
}
I suggest you just to create a class Data with fields id, email, etc. And make field Data data in the class Courier instead of a List<> data
EDIT: then you can use a JsonDeserializer. Just remove #SerializedName("data") over the Data field, so that the Json will not parse this field. Then create a class:
public class CourierDeserializer implements JsonDeserializer<Courier> {
#Override
public Courier deserialize(final JsonElement json, final Type type,
final JsonDeserializationContext context) {
Courier result = new Gson().fromJson(json, Courier.class);
try {
if (json != null) {
result.setData((Data) context.deserialize(json, Data.class));
}
} catch (JsonParseException e) {
result.setData(null);
}
return result;
}
}
and finally register it where you create your GsonBuilder:
GsonBuilder gson = new GsonBuilder();
gson.registerTypeAdapter(Courier.class, new CourierDeserializer());
mGson = gson.create();
builder.setConverter(new GsonConverter(mGson));
if you use Retrofit.

how can i parsing this Json String in Java

my JSON String :
{
"categorySetName": "TSN",
"rows": [
{
"date": 201750,
"rank1": {
"label": "\uBC30\uACBD",
"search_keyword": "\uBC30\uACBD",
"frequency": 3975,
"score": 69.27185
},
"rank2": {
"label": "\uBC30\uACBD\uD654\uBA74",
"search_keyword": "\uBC30\uACBD\uD654\uBA74",
"frequency": 3736,
"score": 109.83768
},
"rank3": {
"label": "\uC544\uC774\uD3F0x",
"search_keyword": "\uC544\uC774\uD3F0x",
"frequency": 3382,
"score": 62.057728
},
.
.
.
.
"rank500": {
"label": "\uC544\uC774\uD3F0x",
"search_keyword": "\uC544\uC774\uD3F0x",
"frequency": 1572,
"score": 68.057728
}
}
}
my Deserializer.Java
#SuppressWarnings("serial")
public class AssociationTopRowDeserializer extends StdDeserializer<AssociationTopRow> {
public static final String DATE = "date";
public static final List<String> knownFieldNames = Arrays.asList(DATE);
public AssociationTopRowDeserializer() {
this(null);
}
public AssociationTopRowDeserializer(Class<AssociationTopRow> c) {
super(c);
}
#Override
#SuppressWarnings("unchecked")
public AssociationTopRow deserialize(JsonParser jsonParser, DeserializationContext desContext) throws IOException {
AssociationTopRow row = new AssociationTopRow();
JsonNode jsonNode = jsonParser.getCodec().readTree(jsonParser);
ObjectMapper objectMapper = new ObjectMapper();
row.setDate(jsonNode.get(DATE).asText());
String unknownField = getUnknownField(jsonNode.fieldNames());
if (unknownField != null) {
Map<String, AssociationTopRowDetail> map = new HashMap<String, AssociationTopRowDetail>();
map.put(unknownField, (AssociationTopRowDetail) objectMapper.convertValue(jsonNode.get(unknownField),
AssociationTopRowDetail.class));
row.setTransMap(map);
}
return row;
}
public String getUnknownField(Iterator<String> fieldNames) {
while (fieldNames.hasNext()) {
String next = fieldNames.next();
if (!knownFieldNames.contains(next))
return next;
}
return null;
}
}
This shows me only information about only 'rank1'
You can use #JsonAnySetter annotation instead of a custom deserializer:
public class AssociationTopRow {
private String date;
private final Map<String, AssociationTopRowDetail> details = new LinkedHashMap<>();
// getter & setter for date
#JsonAnySetter
public void addDetail(String key, AssociationTopRowDetail detail) {
details.put(key, detail);
}
#JsonAnyGetter
public Map<String, AssociationTopRowDetail> getDetails() {
return details;
}
}

GSON parsing for changing json data

I am parsing a JSON data using GSON library and the issue what I am facing is, a part of my json data keeps changing below is how my JSON data looks.
{
"body": [{
"result": [
{
"EndTime": "1411495899000",
"StartTime": "1411495360000"
},
{
"EndTime": "1411495359000",
"StartTime": "1411494784000"
}],
"rule": {
"ruleid": "73B5EEB4"
}
},
{
"result": [
{
"noOfErrors": "5",
"severity": "high"
},
{
"noOfErrors": "4",
"severity": "low"
}],
"rule": {
"ruleid": "35B5EEB4"
}
}
],
"header": {
"contentver": "5.5"
}
}
So in the above JSON data the result array content keeps changing based on the ruleid and I want to choose the java bean for result content at runtime based on the ruleid. Any idea?
-Regards
Well, this is going to be a long answer ...
You could use a custom JsonDeserializer to deserialize the variable part of the json string based on the ruleid.
public class MessageAdapter implements JsonDeserializer<Message> {
private Map<String, Class<? extends Result>> ruleToResultClassMap;
public MessageAdapter() {
this.ruleToResultClassMap = new HashMap<String, Class<? extends Result>>();
ruleToResultClassMap.put("73B5EEB4", DurationResults.class);
ruleToResultClassMap.put("35B5EEB4", ErrorResults.class);
}
#java.lang.Override
public Message deserialize(JsonElement json, java.lang.reflect.Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject messageObject = json.getAsJsonObject();
JsonArray bodyArray = messageObject.getAsJsonArray("body");
List<Result> results = new ArrayList<Result>();
for (JsonElement bodyElement : bodyArray) {
JsonObject resultObject = bodyElement.getAsJsonObject();
JsonObject ruleObject = resultObject.getAsJsonObject("rule");
String ruleId = ruleObject.getAsJsonPrimitive("ruleid").getAsString();
Class<? extends Result> resultClass = ruleToResultClassMap.get(ruleId);
if (resultClass != null) {
Result result = context.deserialize(resultObject, resultClass);
results.add(result);
} else {
throw new IllegalArgumentException("Illegal ruleId: " + ruleId);
}
}
return new Message(results, context.<Header>deserialize(messageObject.getAsJsonObject("header"), Header.class));
}
}
You need to register the custom deserializer with GsonBuilder:
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(Message.class, new MessageAdapter());
Gson gson = gsonBuilder.create();
String jsonString = null; // your json string
Message message = gson.fromJson(jsonString, Message.class);
Here Message is the root POJO of the json string, you probably have your own. For full reference, I include all classes here:
public class Message {
private List<? extends Result> body;
private Header header;
public Message(List<? extends Result> body, Header header) {
this.body = body;
this.header = header;
}
public List<? extends Result> getBody() {
return body;
}
public Header getHeader() {
return header;
}
}
public class Header {
private String contentver;
public Header(String contentVer) {
this.contentver = contentVer;
}
public String getContentVer() {
return contentver;
}
}
public interface Result {
public Rule getRule();
}
public final class Rule {
private String ruleid;
public String getRuleid() {
return ruleid;
}
}
public class DurationResults implements Result {
private Duration[] result;
private Rule rule;
public Duration[] getResult() {
return result;
}
#Override
public Rule getRule() {
return rule;
}
public static final class Duration {
private long EndTime;
private long StartTime;
public long getStartTime() {
return StartTime;
}
public long getEndTime() {
return EndTime;
}
}
}
public class ErrorResults implements Result {
private Error[] result;
private Rule rule;
public Error[] getResult() {
return result;
}
#Override
public Rule getRule() {
return rule;
}
public static final class Error {
private int noOfErrors;
private String severity;
public int getNoOfErrors() {
return noOfErrors;
}
public String getSeverity() {
return severity;
}
}
}
I think you have to parse your json if your result change.
Replace first "result" to "FirstResult" , and replace second "result" to "SecondResult".
Your json have to look like this:
{
"body": [{
"FirstResult": [
{
"EndTime": "1411495899000",
"StartTime": "1411495360000"
},
{
"EndTime": "1411495359000",
"StartTime": "1411494784000"
}],
"rule": {
"ruleid": "73B5EEB4"
}
},
{
"SecondResult": [
{
"noOfErrors": "5",
"severity": "high"
},
{
"noOfErrors": "4",
"severity": "low"
}],
"rule": {
"ruleid": "35B5EEB4"
}
}
],
"header": {
"contentver": "5.5"
}
}
And you can parse json to Java Objects. If you have first result parse to FirstResultObject.java , if you have second result parse to SecondResult.java
SecondResult.java
public class SecondResult
{
private String noOfErrors;
private String severity;
public String getNoOfErrors ()
{
return noOfErrors;
}
public void setNoOfErrors (String noOfErrors)
{
this.noOfErrors = noOfErrors;
}
public String getSeverity ()
{
return severity;
}
public void setSeverity (String severity)
{
this.severity = severity;
}
}
FirstResult.java
public class FirstResult
{
private String EndTime;
private String StartTime;
public String getEndTime ()
{
return EndTime;
}
public void setEndTime (String EndTime)
{
this.EndTime = EndTime;
}
public String getStartTime ()
{
return StartTime;
}
public void setStartTime (String StartTime)
{
this.StartTime = StartTime;
}
}

Categories

Resources