how to parse this nested json using gson - java

I have this json as a string (this is from google custom search). I have made equivalent java classes that are neccessary to parse this. I use gson and am getting a NullPointerException.
"items": [
{
"kind": "customsearch#result",
"title": "A Florida Road Trip - Articles | Travel + Leisure",
"htmlTitle": "A \u003cb\u003eFlorida\u003c/b\u003e Road Trip - \u003cb\u003eArticles\u003c/b\u003e | Travel + Leisure",
"link": "http://www.travelandleisure.com/articles/paradise-usa",
"displayLink": "www.travelandleisure.com",
"snippet": "On a road trip across Florida, Karrie Jacobs goes in search of the authentic amid New Urbanist experiments in postmodern nostalgia.",
"htmlSnippet": "On a road trip across \u003cb\u003eFlorida\u003c/b\u003e, Karrie Jacobs goes in search of the authentic amid \u003cbr\u003e New Urbanist experiments in postmodern nostalgia.",
"cacheId": "QrfYt6p-U3gJ",
"formattedUrl": "www.travelandleisure.com/articles/paradise-usa",
"htmlFormattedUrl": "www.travelandleisure.com/\u003cb\u003earticles\u003c/b\u003e/paradise-usa",
"pagemap": {
"cse_image": [
{
"src": "http://static0.travelandleisure.com/images/amexpub/0000/6261/200702_urban.jpg"
}
],
"cse_thumbnail": [
{
"width": "160",
"height": "200",
"src": "https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcR_Jhmej45Lu7L3bQoKz1poITJ5ZeuVvKhH62myfBOj-1VEX9oqwIhvH74"
}
],
"metatags": [
{
"fb:app_id": "145695458805001",
"og:url": "http://www.travelandleisure.com/articles/paradise-usa",
"og:site_name": "Travel + Leisure",
"og:image": "http://static0.travelandleisure.com/images/amexpub/0000/6261/200702_urban.jpg",
"og:type": "article",
"og:title": "Driving: Florida’s New Urbanist Experiments",
"og:description": "On a road trip across Florida, Karrie Jacobs goes in search of the authentic amid New Urbanist exper..."
}
]
}
}
And my equivalent java classes are as follows:
public Class Mapper
{
public Items[] items;
}
public Class Items
{
public String title;
public String htmlSnippet;
public String link;
public Pagemap pagemap;
}
public Class Pagemap
{
public Cse_image[] image;
}
public Class Cse_image
{
public String src;
}
public Class Parser
{
public static void main(String[] args)
{
//assume json is the string representation of the above json
Gson gson = new GsonBuilder().create();
Mapper mapper= gson.fromJson(json,Mapper.class);
System.out.println("src here"+mapper.items[0].pagemap.image[0].src);
}
}
The above code throws me a NullPointerException , but if I print till the pagemap ,I get an object with a valid hashcode. Any pointers?

Whenever dealing with JSON, it is a good practice to use a LINT software to verify the contents of JSON. I recommend using jsonlint.com. The JSON list shows multiple errors in the JSON string. Running some REPL cycles here is the corrected JSON.
{
"items": [
{
"kind": "customsearch#result",
"title": "AFloridaRoadTrip-Articles|Travel+Leisure",
"htmlTitle": "A<b>Florida</b>RoadTrip-<b>Articles</b>|Travel+Leisure",
"link": "http: //www.travelandleisure.com/articles/paradise-usa",
"displayLink": "www.travelandleisure.com",
"snippet": "OnaroadtripacrossFlorida,KarrieJacobsgoesinsearchoftheauthenticamidNewUrbanistexperimentsinpostmodernnostalgia.",
"htmlSnippet": "Onaroadtripacross<b>Florida</b>,KarrieJacobsgoesinsearchoftheauthenticamid<br>NewUrbanistexperimentsinpostmodernnostalgia.",
"cacheId": "QrfYt6p-U3gJ",
"formattedUrl": "www.travelandleisure.com/articles/paradise-usa",
"htmlFormattedUrl": "www.travelandleisure.com/<b>articles</b>/paradise-usa",
"pagemap": {
"cse_image": [
{
"src": "http: //static0.travelandleisure.com/images/amexpub/0000/6261/200702_urban.jpg"
}
],
"cse_thumbnail": [
{
"width": "160",
"height": "200",
"src": "https: //encrypted-tbn1.gstatic.com/images?q=tbn: ANd9GcR_Jhmej45Lu7L3bQoKz1poITJ5ZeuVvKhH62myfBOj-1VEX9oqwIhvH74"
}
],
"metatags": [
{
"fb: app_id": "145695458805001",
"og: url": "http: //www.travelandleisure.com/articles/paradise-usa",
"og: site_name": "Travel+Leisure",
"og: image": "http: //static0.travelandleisure.com/images/amexpub/0000/6261/200702_urban.jpg",
"og: type": "article",
"og: title": "Driving: Florida’sNewUrbanistExperiments",
"og: description": "OnaroadtripacrossFlorida,KarrieJacobsgoesinsearchoftheauthenticamidNewUrbanistexper..."
}
]
}
}
]
}

First rename your class Cse_Image to a more conventional java name (CseImage maybe?), same for the thumbnail class.
Then you can try genson library http://code.google.com/p/genson/.
Put #JsonProperty("cse_image") annotation on your image field (or on your setter/getter if you have) and it works :
Genson genson = new Genson();
Mapper mapper= genson.deserialize(json,Mapper.class);
System.out.println("src here"+mapper.items[0].pagemap.image[0].src);

Related

How to make com.fasterxml.jackson print array vertically? [duplicate]

I have data that looks like this:
{
"status": "success",
"data": {
"irrelevant": {
"serialNumber": "XYZ",
"version": "4.6"
},
"data": {
"lib": {
"files": [
"data1",
"data2",
"data3",
"data4"
],
"another file": [
"file.jar",
"lib.jar"
],
"dirs": []
},
"jvm": {
"maxHeap": 10,
"maxPermSize": "12"
},
"serverId": "134",
"version": "2.3"
}
}
}
Here is the function I'm using to prettify the JSON data:
public static String stringify(Object o, int space) {
ObjectMapper mapper = new ObjectMapper();
try {
return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(o);
} catch (Exception e) {
return null;
}
}
I am using the Jackson JSON Processor to format JSON data into a String.
For some reason the JSON format is not in the format that I need. When passing the data to that function, the format I'm getting is this:
{
"status": "success",
"data": {
"irrelevant": {
"serialNumber": "XYZ",
"version": "4.6"
},
"another data": {
"lib": {
"files": [ "data1", "data2", "data3", "data4" ],
"another file": [ "file.jar", "lib.jar" ],
"dirs": []
},
"jvm": {
"maxHeap": 10,
"maxPermSize": "12"
},
"serverId": "134",
"version": "2.3"
}
}
}
As you can see under the "another data" object, the arrays are displayed as one whole line instead of a new line for each item in the array. I'm not sure how to modify my stringify function for it to format the JSON data correctly.
You should check how DefaultPrettyPrinter looks like. Really interesting in this class is the _arrayIndenter property. The default value for this property is FixedSpaceIndenter class. You should change it with Lf2SpacesIndenter class.
Your method should looks like this:
public static String stringify(Object o) {
try {
ObjectMapper mapper = new ObjectMapper();
DefaultPrettyPrinter printer = new DefaultPrettyPrinter();
printer.indentArraysWith(new Lf2SpacesIndenter());
return mapper.writer(printer).writeValueAsString(o);
} catch (Exception e) {
return null;
}
}
I don't have enough reputation to add the comment, but referring to the above answer Lf2SpacesIndenter is removed from the newer Jackson's API (2.7 and up), so instead use:
printer.indentArraysWith(DefaultIndenter.SYSTEM_LINEFEED_INSTANCE);
Source of the solution

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")

GSON from JSON nested object null pointer exception

I have the following JSON file:
{
“weight": {
"type": "weight",
"range": [
"2016-02-15",
"2016-02-16",
"2016-02-17",
"2016-02-18",
"2016-02-19",
"2016-02-20",
"2016-02-21"
],
"days": [
{
"weight": [
{
"bmi": 29.5,
"date": "2016-02-14",
"logId": 1455494399000,
"source": "API",
"time": "23:59:59",
"weight": 90.3
},
]
}
I then have the following classes that I want this JSON to be added to.
public class fitbitTypeWeight {
public fitbitDays weight;
}
public class fitbitDays {
public fitbitDayWeight days;
}
public class fitbitDayWeight {
public fitbitWeight weight;
}
public class fitbitDayWeight {
public fitbitWeight weight;
}
Then, I have the following code to try and parse it.
public static void readJSON() {
Gson gson = new Gson();
type = gson.fromJson(file, fitbitTypeWeight.class);
GsonBuilder builder = new GsonBuilder();
gson = builder.create();
createFitBitInfo();
}
private static void createFitBitInfo() throws ITrustException{
RemoteMonitoringDAO db = new RemoteMonitoringDAO(prodDAO);
RemoteMonitoringDataBean temp=new RemoteMonitoringDataBean();
fitbitDayWeight info = type.weight.days;
temp.setFitbitWeight(info.weight.weight);
temp.setFitbitDate(info.weight.date);
temp.setLoggedInMID(userID);
db.storeFitbitData(temp);
}
However, I am getting a NPE exception on fitbitDayWeight info = type.weight.days;
Any suggestions on what could be going wrong?
Your JSON is malformed. Looking just at the days element, we have:
"days": [
{
"weight": [
{
"bmi": 29.5,
"date": "2016-02-14",
"logId": 1455494399000,
"source": "API",
"time": "23:59:59",
"weight": 90.3
},
]
Looking at that, you've got:
dangling , on list weight
no closing ] on list weight
no closing } on 0 in list days
(To be complete, the if the final , were not there, ] would close weight then } would close object 0 in list days, leaving days and base unclosed.)
Also, you have a “ as your first quote instead of ". I don't know for sure if GSON is ok with angle quotes, but I know the JSON standard asks for " on all quotes.
I'm honestly slightly surprised GSON doesn't spit errors on load because of this. But the reason you're getting a NullPointerException is because type.weight.days is set to the default value because GSON couldn't read a value for it.

Having trouble deserializing JSON response with gson

I am using an API where I supply an input string, and it returns some keyword autocompletions and product nodes.
My goal is to deserialize the response and get a list of the autocompletion Strings I can use. I'm trying implement this in an android application with the Retrofit library, which uses gson.
First off, I'm not sure the response I have is a typical JSON response. The 'nodes' item has key / value pairs, but the input string and the autocompletions list don't seem to have keys I can use.
["pol",
["polaroid camera",
"polo",
"polo ralph lauren",
"polo ralph lauren men",
"polar heart rate monitor",
"polaroid",
"polo shirt",
"polar watch",
"police scanner",
"polar"],
[{
"nodes": [{
"alias": "electronics",
"name": "Electronics"
},
{
"alias": "electronics-tradein",
"name": "Electronics Trade-In"
}]
},
{
},
{
},
{
},
{
},
{
},
{
},
{
},
{
},
{
}],
[]]
This is my attempt at the java classes for gson to deserialize to. However, it doesn't work as from what I understand, gson needs the class variables to match the JSON keys (true for Node class but not the rest).
class Response {
String input;
List<String> keywords;
List<Node> nodes;
}
class Node {
String alias;
String name;
}
the json only has a couple of keys in it, this is largely a Json Array.
if you can change the JSON, make it more like this
{
"input" : "pol",
"keywords" : ["polaroid camera","polo",...],
"nodes": [{
"alias": "electronics",
"name": "Electronics"
},
{
"alias": "electronics-tradein",
"name": "Electronics Trade-In"
}]
}

Gson help with parse array - works without array but won't with array

Can somebody help me with Gson parser. When I remove change from JSON and Result it works fine but with change it throws JsonParseException-Parse failed.
Result[] response = gson.fromJson(fileData.toString(), Result[].class);
I have classes like this
public class Result {
public String start_time;
public String end_time;
public change[] change;
}
and
public class change {
public String id;
public String name;
}
and Json string like
[
{
"start_time": "8:00",
"end_time": "10:00",
"change": [
{
"id": "1",
"name": "Sam"
},
{
"id": "2",
"name": "John"
}
]
},
{
"start_time": "9:00",
"end_time": "15:00",
"change": [
{
"id": "1",
"name": "Sam"
},
{
"id": "2",
"name": "John"
}
]
}
]
Can somebody tell me what I did wrong ? Any idea why it won't work with array ?
As has been suggested, you need to use a list instead. Gson has pretty good documentation for using parametized types with the parser, you can read more about it here. Your code will end up looking like this:
Type listType = new TypeToken<List<Result>>() {}.getType();
List<Result> results = gson.fromJson(reader, listType);
for (Result r : results) {
System.out.println(r);
}

Categories