How parse variable name JSON objects using GSON? - java

How can I parse JSON using GSON with variable object names? The "routes" objects has the same structure, but different name. It has many different names because it reflects to travel lines. I'm trying to read it directly to Java class (Android, Retrofit), but I wouldn't create single class for all travel lines in Budapest. Is it possible to read it somehow?
{
"version": 2,
"status": "OK",
"code": 200,
"text": "OK",
"currentTime": 1448881433747,
"data": {
"limitExceeded": false,
"references": {
"routes": {
"BKK_9630": {
"id": "BKK_9630",
"shortName": "963",
"longName": null,
"description": "Hűvösvölgy | Nagykovácsi, Tisza István tér",
"type": "BUS",
"url": null,
"color": "1E1E1E",
"textColor": "FFFFFF",
"agencyId": "BKK",
"bikesAllowed": false
},
"BKK_0630": {
"id": "BKK_0630",
"shortName": "63",
"longName": null,
"description": "Hűvösvölgy | Nagykovácsi, Tisza István tér",
"type": "BUS",
"url": null,
"color": "009FE3",
"textColor": "FFFFFF",
"agencyId": "BKK",
"bikesAllowed": false
}
},
"trips": {},
"alerts": {}
}
}
}
The full JSON response:
http://futar.bkk.hu/bkk-utvonaltervezo-api/ws/otp/api/where/search.json?query=Erd%C3%A9szh%C3%A1z
Thanks in advance!

Here's your class structure:
MyObject (main object):
public class MyObject{
private Integer version;
private String status;
private Integer code;
private Data data;
}
Data:
public class Data{
private boolean limitExceeded;
private References references;
}
References:
public class References{
private Map<String, Route> routes;
}
Route:
public class Route{
private String shortName;
}
And then:
String json = "{'version':2,'status':'OK','code':200,'text':'OK','currentTime':1448881433747,'data':{'limitExceeded':false,'references':{'routes':{'BKK_9630':{'id':'BKK_9630','shortName':'963','longName':null,'description':'Hűvösvölgy | Nagykovácsi, Tisza István tér','type':'BUS','url':null,'color':'1E1E1E','textColor':'FFFFFF','agencyId':'BKK','bikesAllowed':false},'BKK_0630':{'id':'BKK_0630','shortName':'63','longName':null,'description':'Hűvösvölgy | Nagykovácsi, Tisza István tér','type':'BUS','url':null,'color':'009FE3','textColor':'FFFFFF','agencyId':'BKK','bikesAllowed':false}},'trips':{},'alerts':{}}}}";
Gson gson = new Gson();
MyObject fromJson = gson.fromJson( json, MyObject.class );
System.out.println( fromJson );
Result:
MyObject [version=2, status=OK, code=200, data=Data [limitExceeded=false, references=References [routes={BKK_9630=Route [shortName=963], BKK_0630=Route [shortName=63]}]]]
Note that, I didn't write all fields you have to write them. Also don't forget to create getter and setters and toString overrides.

Related

Null values being returned in json while using gson in java

I have the following Json file which I am trying to read:
{
"billingInformation": {
"taxes": {
"gst": 2.5,
"hst": 7.8
},
"billTo": {
"name" : "Mike",
"address" : "123, Lake Shore Drive, California",
"phoneNumber" : "601 855 1249"
},
"salesAgent": {
"name" : "Charlotte Thompson",
"agentCode" : 44551
},
"items": {
"item": [
{
"hsnCode": "5112",
"description": "TV Set",
"originCountry": "US",
"quantity": 1,
"unitPrice": 150.00
}
],
"currency": "USD"
}
}
}
I used direct Object Mapping provided by Gson:
result = new String(Files.readAllBytes(Paths.get(path)));
BillingInformation billingInformation = gson.fromJson(result, BillingInformation.class);
But it always resulted in:
class BillingInformation {
taxes: null
billTo: null
salesAgent: null
items: null
}
How can I get the data inside the other objects?
Edit:
Here is the BillingInformation Class:
public class BillingInformation {
#SerializedName("taxes")
private Taxes taxes;
#SerializedName("billTo")
private BillTo billTo;
#SerializedName("salesAgent")
private SalesAgent salesAgent;
#SerializedName("items")
private Items items;
}
and I have the usual getters and setters for the above fields.
You should create a class that looks like this:
class Data {
private BillingInformation billingInformation;
}
And then do the deserialization:
Data fromFile = gson.fromJson(result, Data.class);

Getting Error while converting from JSON String Java Model Class

I am have a problem in converting JSON String to Java object. As per my scenario Database (PostgreSQL) is returning JSON String in PGOBJECT through function.
Which I am trying to convert into model Class. Returned value JSON sample is:
{
"A_REASON": [
{
"cd": "CLOSE",
"name": "CLOSE",
"value": "A_REASON",
"type": "A_REASON"
}
],
"P_MODE": [
{
"cd": "CLOSE",
"name": "CLOSE",
"value": "A_REASON",
"type": "A_REASON"
}
],
"F_TYPE": [
{
"cd": "CLOSE",
"name": "CLOSE",
"value": "A_REASON",
"type": "A_REASON"
} ] }
I have created My Model Classes like below.
public class MODEL {
private List<MISCDTO> A_REASON;
private List<MISCDTO> P_MODE;
private List<MISCDTO> F_TYPE;
//settter and Getter
}
public class MISCDTO{
private String cd;
private String name;
private String value;
private String type;
}
When I am trying to convert into Model Class from JSON String it gives error, I have tried multiple ways
ObjectMapper mapper = new ObjectMapper();
MODEL object = mapper.readValue(pGobject.getValue(), MODEL.class);
List<MODEL> list = mapper.readValue(pGobject.getValue(), new TypeReference<List<MODEL >>(){});
MODEL object= mapper.readValue(pGobject.getValue(), new TypeReference<MODEL>() {});
I am looking to convert into either Map> or MODEL object having List, List etc. Please help. Please do help in Formatting as i am trying to Write in Stack Standard. Still novice on this.

How to parse a Json with a field containg several kind of objects

How to parse a Json with a field "data" which can contain several types of objets, or an object and a simple message (outside the object structure).
An Android app request information to its backend. In most cases, the response has the same structure and if the "data" field only contains one kind of object i can complete the process.
But if the "data" field contains several kinds of objects or one object with a external message, i can´t parse it.
Normal Response structure (I can parse these cases):
{
"success": true,
"code": "OK",
"error": null,
"data": {
"_type": "auth",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImlzcyI6Im9mZnRpbWUiLCJzdWIiOiJkZXZlbG9wZXIifQ==.eyJyb2xlIjpbImFwcCJdLCgfgdfgJhcgdfgdfAiOiJPRkZUSU1FIEFuZHJvaWQiLCJvd25lcdsgsghhjghkukI6Ik9zY2FyIn0=.7PiMEmX8M3ABs7P8KymuXvBpTL1gdgdfLRajFbwxP5IBARM=",
"refresh": null,
"logout": null
}
}
Response with an object "user" and a message (i have problems parsing it):
{
"success": true,
"code": "USER_ALREADY_EXISTS",
"error": null,
"data": {
"user": {
"_type": "user",
"id": 32,
"name": "Pascual22",
"email": "pascual22#juanedc.com",
"picture": null
},
"message": "This email is already registered, you will receive an email with the reset password instructions"
}
}
Response with several kinds of objects (i have problems parsing it):
{
"success": true,
"code": "OK",
"error": null,
"data": {
"auth": {
"_type": "auth",
"token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImlzcyI6Im9mZnRpbWUiLCJzdWIiOiJ1c2VyIiwiZXhwIjoxNTYwNTk2MzUwfQ==.eyJyb2xlIjpbImFwcCIsInVzZXIiXSwib3duZXIiOjI2LCJkZXZpY2UiOiI5In0=.JxbidqCnZNCt8eyRUbLE8HEJKeWgwFejz/9rMJPoKS0=",
"refresh": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImlzcyI6Im9mZnRpbWUiLCJzdWIiOiJ1c2VyIiwiZXhwIjoxNTYwNzY5MTUwfQ==.eyJyb2xlIjpbImFwcCIsInVzZXIiLCJyZWZyZXNoIl0sIm93bmVyIjoyNiwiZGV2aWNlIjoiOSIsInJlZnJlc2giOiJleUowZVhBaU9pSktWMVFpTENKaGJHY2lPaUpJVXpJMU5pSXNJbWx6Y3lJNkltOW1ablJwYldVaUxDSnpkV0lpT2lKMWMyVnlJaXdpWlhod0lqb3hOVFl3TlRrMk16VXdmUT09LmV5SnliMnhsSWpwYkltRndjQ0lzSW5WelpYSWlYU3dpYjNkdVpYSWlPakkyTENKa1pYWnBZMlVpT2lJNUluMD0uSnhiaWRxQ25aTkN0OGV5UlViTEU4SEVKS2VXZ3dGZWp6XC85ck1KUG9LUzA9In0=.JBTIyHAtVS8PgH7LzUzL3TTg8yoe7vVMBH6eauPgc7o=",
"logout": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiIsImlzcyI6Im9mZnRpbWUiLCJzdWIiOiJ1c2VyIiwiZXhwIjoxNTYwNTk2MzUwfQ==.eyJyb2xlIjpbImFwcCIsInVzZXIiLCJsb2dvdXQiXSwib3duZXIiOjI2LCJkZXZpY2UiOiI5IiwibG9nb3V0IjoiZXlKMGVYQWlPaUpLVjFRaUxDSmhiR2NpT2lKSVV6STFOaUlzSW1semN5STZJbTltWm5ScGJXVWlMQ0p6ZFdJaU9pSjFjMlZ5SWl3aVpYaHdJam94TlRZd05UazJNelV3ZlE9PS5leUp5YjJ4bElqcGJJbUZ3Y0NJc0luVnpaWElpWFN3aWIzZHVaWElpT2pJMkxDSmtaWFpwWTJVaU9pSTVJbjA9Lkp4YmlkcUNuWk5DdDhleVJVYkxFOEhFSktlV2d3RmVqelwvOXJNSlBvS1MwPSJ9.syuKoi8XiHp/me/AJAydyXfRbXa63KVWqPSKS7ySGQc="
},
"user": {
"_type": "user",
"id": 26,
"name": "Sin Foto 2",
"email": "sf2#yopmail.com",
"picture": null
},
"device": {
"_type": "device",
"id": "9",
"category": "mobile",
"manufacturer": "Xiaomi",
"model": "Mi A1",
"os": "android",
"os_version": "9",
"sim_support": true,
"name": null,
"added": "2019-06-10 10:59:10"
}
}
}
My class response:
#JsonIgnoreProperties(ignoreUnknown = true)
public class Response {
#JsonProperty("success")
private String success;
#JsonProperty("code")
private String code;
#JsonProperty("error")
private String error;
#JsonProperty("data")
private Object data;
public String getSuccess() {return success;}
public void setSuccess(String success) {this.success = success;}
public String getCode() {return code;}
public void setCode(String code) {this.code = code;}
public String getError() {return error;}
public void setError(String error) {this.error = error;}
public Object getData() {return data;}
public void setData(Object data) {this.data = data;}
}
Initial parsing process (from Json to Response Object, using spring for android framework, ):
responseApi = restTemplate.exchange(uri, HttpMethod.POST, requestEntity, Response.class);
Parsing Process of data field to Objects (Example with a user object in "data"):
try {
User user = mapper.convertValue(responseApi.getBody().getData(), User.class);
}
catch (Exception e){
e.printStackTrace();
}
I tried to make a Data class with a generic object and a message atributes, but, it din´t work. I need to parse the response in all cases, how can i achieve it? Some suggestions about the class structure in order to make a correct automatic parsing process?

Spring RestTemplate parse JSON object with variable keyname

I have a REST API call that returns the following JSON object. I need to parse this with Spring's RestTemplate. The problem is that the first key ISBN:0132856204 is variable (the numbers change depending on the book). How would I go about doing this?
{
"ISBN:0132856204": {
"publishers": [
{
"name": "Pearson"
}
],
"pagination": "xxiv, 862p",
"identifiers": {
"isbn_13": [
"978-0-13-285620-1"
],
"openlibrary": [
"OL25617855M"
]
},
"weight": "1340 grams",
"title": "Computer networking",
"url": "https://openlibrary.org/books/OL25617855M/Computer_networking",
"number_of_pages": 862,
"cover": {
"small": "https://covers.openlibrary.org/b/id/7290810-S.jpg",
"large": "https://covers.openlibrary.org/b/id/7290810-L.jpg",
"medium": "https://covers.openlibrary.org/b/id/7290810-M.jpg"
},
"publish_date": "2013",
"key": "/books/OL25617855M",
"authors": [
{
"url": "https://openlibrary.org/authors/OL31244A/James_F._Kurose",
"name": "James F. Kurose"
},
{
"url": "https://openlibrary.org/authors/OL658909A/Keith_W._Ross",
"name": "Keith W. Ross"
}
],
"subtitle": "A Top-Down Approach"
}
}
In here "ISBN:0132856204" is a value and also a key for your business.
To get ISBN first, what about wrapping json content with 1 more closure?
{
"yourAwesomePlaceHolderKey" :
{
"ISBN:0132856204": {
......
}
}
}
First get the ISBN key as a value, then your ISBN value can be used as a key to get related content.
First goal will be extracting -String1,Object1- pair where String1 is "yourAwesomePlaceholderKey" and second goal will be again extracting -String2,Object2- from Object1 where String2 is your ISBN key.
This is the way I solved it, using JsonPath for getting the book out of the JSON object and Jackson for mapping it to a Book object:
RestTemplate restTemplate = new RestTemplate();
String isbn = "0132856204";
String endpoint = "https://openlibrary.org/api/books?jscmd=data&format=json&bibkeys=ISBN:{isbn}";
//Get JSON as String
String jsonString = restTemplate.getForObject(endpoint, String.class, isbn);
//Configure JsonPath to use Jackson for mapping
Configuration.setDefaults(new Configuration.Defaults() {
private final JsonProvider jsonProvider = new JacksonJsonProvider();
private final MappingProvider mappingProvider = new JacksonMappingProvider();
#Override
public JsonProvider jsonProvider() {
return jsonProvider;
}
#Override
public MappingProvider mappingProvider() {
return mappingProvider;
}
#Override
public Set<Option> options() {
return EnumSet.noneOf(Option.class);
}
});
//Parse the JSON as a book
Book book = JsonPath.parse(jsonString).read("$.ISBN:" + isbn, Book.class);
You can use JsonProperty to solve
#JsonProperty("ISBN:0132856204")

Parsing JSON in java: Malformed JSON: Unexpected 'C'

Good day,
I am parsing some JSON in java (a notification from a cisco CMX system). I've parsed a lot of JSON in my time but this one refuses to get parsed. I've tried several methods: a reader with lenient mode, plain gson, etc.
The JSON I parse is valid according to jsonlint, which leads me to believe it is a problem with the parser, or maybe some hidden characters that I am unable to sanitize out. This is the JSON I receive:
{
"startTime": "08:00",
"previousEndDate": null,
"startDate": "2016-02-17",
"title": "Visitors",
"executionTime": 29,
"value": {
"primary": {
"title": "TotalVisitors",
"value": 16,
"peakValue": 0,
"breakdown": [{
"title": "RepeatVisitors",
"value": 11
}, {
"title": "NewVisitors",
"value": 5
}]
},
"average": {
"title": "TotalVisitors",
"value": 19,
"peakValue": 0,
"breakdown": [{
"title": "RepeatVisitors",
"value": 15
}, {
"title": "NewVisitors",
"value": 4
}]
},
"previousTimeRange": {
"title": "TotalVisitors",
"value": 23,
"peakValue": 0,
"breakdown": [{
"title": "RepeatVisitors",
"value": 19
}, {
"title": "NewVisitors",
"value": 4
}]
}
},
"areas": [{
"id": 20,
"name": "CineCitta"
}],
"previousStartDate": "2016-02-16",
"endDate": null,
"endTime": "09:29"
}
It seems valid to me, and the object I try to parse it into has the correct fields.
I've tried filtering out \r \t \n \0 and some combinations between them.
The code I currently have in java is:
String result = "{\"startTime\":\"08:00\",\"previousEndDate\":null,\"startDate\":\"2016-02-17\",\"title\":\"Visitors\",\"executionTime\":29,\"value\":{\"primary\":{\"title\":\"TotalVisitors\",\"value\":16,\"peakValue\":0,\"breakdown\":[{\"title\":\"RepeatVisitors\",\"value\":11},{\"title\":\"NewVisitors\",\"value\":5}]},\"average\":{\"title\":\"TotalVisitors\",\"value\":19,\"peakValue\":0,\"breakdown\":[{\"title\":\"RepeatVisitors\",\"value\":15},{\"title\":\"NewVisitors\",\"value\":4}]},\"previousTimeRange\":{\"title\":\"TotalVisitors\",\"value\":23,\"peakValue\":0,\"breakdown\":[{\"title\":\"RepeatVisitors\",\"value\":19},{\"title\":\"NewVisitors\",\"value\":4}]}},\"areas\":[{\"id\":20,\"name\":\"CineCitta\"}],\"previousStartDate\":\"2016-02-16\",\"endDate\":null,\"endTime\":\"09:29\"}";
JsonReader reader = new JsonReader(new StringReader(result));
reader.setLenient(true);
Gson gson = new Gson();
ClientInfo info = gson.fromJson(reader, ClientInfo.class);
The question is: Does anyone know how to debug a problem like this? are there sanitization techniques I can use? Other parsers?
EDIT: The code to clientinfo as requested (using project lombok, all fields are public):
#ToString
#FieldDefaults(level = AccessLevel.PUBLIC)
public class ClientInfo {
String startTime;
String previousEndDate;
String startDate;
String title;
Integer executionTime;
Value value;
Area [] areas;
String previousStartDate;
String endDate;
String endTime;
}
public class Value {
public Visitors primary;
public Visitors average;
public Visitors previousTimeRange;
}
#FieldDefaults(level = AccessLevel.PUBLIC)
public class Area {
Integer id;
String name;
}
#FieldDefaults(level = AccessLevel.PUBLIC)
public class Visitors {
String title;
Integer value;
Integer peakValue;
Record [] breakdown;
}
public class Record {
public String title;
public Integer value;
}
Thanks and good day
String result = "{\"startTime\":\"08:00\",\"previousEndDate\":null,\"startDate\":\"2016-02-17\",\"title\":\"Visitors\",\"executionTime\":29,\"value\":{\"primary\":{\"title\":\"TotalVisitors\",\"value\":16,\"peakValue\":0,\"breakdown\":[{\"title\":\"RepeatVisitors\",\"value\":11},{\"title\":\"NewVisitors\",\"value\":5}]},\"average\":{\"title\":\"TotalVisitors\",\"value\":19,\"peakValue\":0,\"breakdown\":[{\"title\":\"RepeatVisitors\",\"value\":15},{\"title\":\"NewVisitors\",\"value\":4}]},\"previousTimeRange\":{\"title\":\"TotalVisitors\",\"value\":23,\"peakValue\":0,\"breakdown\":[{\"title\":\"RepeatVisitors\",\"value\":19},{\"title\":\"NewVisitors\",\"value\":4}]}},\"areas\":[{\"id\":20,\"name\":\"CineCitta\"}],\"previousStartDate\":\"2016-02-16\",\"endDate\":null,\"endTime\":\"09:29\"}";
Gson gson = new Gson();
JsonParser parser = new JsonParser();
JsonObject jsonObj = parser.parse(result).getAsJsonObject();
ClientInfo info = gson.fromJson( jsonObj , ClientInfo.class);
You can give a try with above code.
I am a dumdum.
I assumed the parsing was what went wrong, but it was actually that my service was supposed to produce a JSON, where I did not return it as json, but the object itself resulting in a bad parsing.
Because I was so focused on the parsing I was doing I did not realize the error itself occurred on the implicit json parsing of the restful service.
That'll teach me not to test in a simple environment before moving my code to the a restful client.
Thanks and dumb greetings,
Dries

Categories