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.
Related
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")
UPDATE! Fixed, there was a missed public statement on prices attribute that was the reason this error occurred.
I am trying out Jackson for converting between .json files and objects. However, I keep receiving this error "UnrecognizedPropertyException: Unrecognized field "Prices" (class imp.JsonDTO), not marked as ignorable (one known property: "Ticker"]" .
I am trying to convert a json file that looks like this:
{
"Ticker": "AAPL",
"Prices": [
{
"Date": "1986-01-02T00:00:00",
"Value": 22.25,
"Action": "Sell"
},
{
"Date": "1986-01-03T00:00:00",
"Value": 22.38,
"Action": "Buy"
},
{
"Date": "1986-01-06T00:00:00",
"Value": 22.38,
"Action": "Sell"
}
]
}
I am converting like this:
ObjectMapper mapper = new ObjectMapper();
File file = new File("INTC.json");
JsonDTO dto = mapper.readValue(file, JsonDTO.class);
DTO's that I am using:
public class JsonDTO {
public String Ticker;
List<PriceDTO> Prices = new ArrayList<PriceDTO>();
}
and..
public class PriceDTO {
public String Date;
public double Value;
public String Action;
}
Tried a few different ways for "Prices" but seem unable to get it right.Thanks for help :)
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
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.
I am working with an API that responds like the following for a single user resource:
{
"data": {
"id": 11,
"first_name": "First",
"last_name": "Last",
"books": {
"data": [
{
"id": 13,
"name": "Halo"
}
]
},
"games": {
"data": [
{
"id": 1,
"name": "Halo"
}
]
}
}
}
or like the following for multiple user resources:
{
"data": [
{
"id": 11,
"first_name": "First",
"last_name": "Last",
"books": {
"data": [
{
"id": 13,
"name": "Halo"
}
]
},
"games": {
"data": [
{
"id": 1,
"name": "Halo"
}
]
}
},
],
"meta": {
"pagination": {
"total": 11,
"count": 10,
"per_page": 10,
"current_page": 1,
"total_pages": 2,
"links": {
"next": "http://api.###.com/users?page=2"
}
}
}
}
Key things to notice are:
all resources are nested under a data key, single as an object or multiple as an array of objects. This includes nested resources such as books and games in the example above.
I need to be able retrieve the values of the meta key for my pagination routines
User model
public class User extends BaseModel {
public Integer id;
public String firstName;
public String lastName;
public List<Book> books; // These will not receive the deserialized
public List<Game> games; // JSON due to the parent data key
}
Custom JSON deserializer
public class ItemTypeAdapterFactory implements TypeAdapterFactory {
public <T> TypeAdapter<T> create(Gson gson, final TypeToken<T> type) {
final TypeAdapter<T> delegate = gson.getDelegateAdapter(this, type);
final TypeAdapter<JsonElement> elementAdapter = gson.getAdapter(JsonElement.class);
return new TypeAdapter<T>() {
public void write(JsonWriter out, T value) throws IOException {
delegate.write(out, value);
}
public T read(JsonReader in) throws IOException {
JsonElement jsonElement = elementAdapter.read(in);
if (jsonElement.isJsonObject()) {
JsonObject jsonObject = jsonElement.getAsJsonObject();
// If the data key exists and is an object or array, unwrap it and return its contents
if (jsonObject.has("data") && (jsonObject.get("data").isJsonObject() || jsonObject.get("data").isJsonArray())) {
jsonElement = jsonObject.get("data");
}
}
return delegate.fromJsonTree(jsonElement);
}
}.nullSafe();
}
}
This is all working fine but I can't figure out how to access the meta key for pagination.
Ideally I would get Gson to deserialize the response to the following POJO:
public class ApiResponse {
public Object data;
public Meta meta
}
and I could just cast the response field to the correct type in the response callback like the following:
Map<String, String> params = new HashMap<String, String>();
params.put("include", "books,games");
ApiClient.getClient().authenticatedUser(params, new ApiClientCallback<ApiResponse>() {
#Override
public void failure(RestError restError) {
Log.d("TAG", restError.message);
}
#Override
public void success(ApiResponse response, Response rawResponse) {
User user = (User) response.data; // Cast data field to User type
Log.d("TAG", user.firstName);
Log.d("TAG", "Total pages" + response.meta.pagination.total.toString()); // Still have access to meta key data
}
});
However the data field of the ApiResponse object is null.
My Java is very rusty and I have no idea if this is even possible nor do I understand how to go about it correctly, any help would be much appreciated.
I needed the same thing and have managed to get it working by adding an if statement to your custom serializer:
…
// If the meta key exists, consider the element to be root and don't unwrap it
if (!jsonObject.has("meta")) {
// If the data key exists and is an object or array, unwrap it and return its contents
if (jsonObject.has("data") && (jsonObject.get("data").isJsonObject() || jsonObject.get("data").isJsonArray())) {
jsonElement = jsonObject.get("data");
}
}
…
The reason why the data field of your ApiResponse was null is because your original deserializer was processing the whole response and making you "loose" the root object's data and meta elements.
I've also parametized the ApiResponse class:
public class ApiResponse<T> {
public Meta meta;
public T data;
}
That way deserializing still works without creating many different Response classes, while casting isn't needed anymore and you can specify the type of ApiResponse's data field as needed (eg. ApiResponse<User> for single user resource, ApiResponse<List<User>> for multiple user resources, etc.).