Parsing Json Feeds with google Gson - java

I would like to know how to parse a JSON feed by items (eg. url / title / description for each item). I have had a look to the doc / api but, it didn't help me.
This is what I got so far
import com.google.gson.Gson;
import com.google.gson.JsonObject;
public class ImportSources extends Job {
public void doJob() throws IOException {
String json = stringOfUrl("http://feed.test/all.json");
JsonObject jobj = new Gson().fromJson(json, JsonObject.class);
Logger.info(jobj.get("responseData").toString());
}
public static String stringOfUrl(String addr) throws IOException {
ByteArrayOutputStream output = new ByteArrayOutputStream();
URL url = new URL(addr);
IOUtils.copy(url.openStream(), output);
return output.toString();
}
}

Depends on the actual JSON format. You can in fact just create a custom Javabean class which matches the JSON format. Any fields in JSON can be mapped as String, Integer, Boolean, etc Javabean properties. Any arrays can be mapped as List properties. Any objects can be mapped as another nested Javabean property. It greatly eases further processing in Java.
Without a JSON string example from your side, it's only guessing how it would look like, so I can't give a basic example here. But I've posted similar answers before here, you may find it useful:
Converting JSON to Java
Generate Java class from JSON?
Gson has also an User Guide, you may find it useful as well.

Gson 1.4 has a new API JsonStreamParser that lets you parse multiple JSON objects one by one from a stream.

You can create corresponding java classes for the json objects. The integer, string values can be mapped as is. Json can be parsed like this-
Gson gson = new GsonBuilder().create();
Response r = gson.fromJson(jsonString, Response.class);
Here is an example- http://rowsandcolumns.blogspot.com/2013/02/url-encode-http-get-solr-request-and.html

I don't know if GSON can do streaming/incremental binding (I thought it did not).
But is there specific reason to only consider that particular library? Other Java JSON processing libraries do allow such processing (you can check links the other answer has for some ideas), since it is quite important feature when processing large feeds.

Related

getting exact part of json

I have a json string, here is example
{
"Param1":"Value1",
"Param2":{...}
"ParamThatINeed":{...}
}
I want to get only "ParamThatINeed" object using gson lib in java, what is the best way to get what I need - write root class, then write class for "ParamThatINeed" and then decode json and use only "ParamThatINeed" object?
Or maybe it's better to beforehand convert my jsonString to another string, which will be only "ParamThatINeed" jsonString object using for example regexp? Or maybe there is a better way?
Your suggested solution is painless and extensible (i.e. if you decide to read an additional field in the future, you just add another field to your object). In general that's exactly how you want to use Gson - construct the necessary Java classes to represent the data you care about and Gson will silently discard the fields you don't care about. For your example that could look like:
private static final Gson GSON = ...;
public static class MyJsonData {
private final ParamThatINeed paramThatINeed;
public ParamThatINeed getParamThatINeed() { ... }
}
public static class ParamThatINeed {
...
}
public static ParamThatINeed extractParamThatINeed(String json) {
return GSON.fromJson(json, MyJsonData.class).getParamThatINeed();
}
You could parse the field yourself as #GuiSim suggests, but this won't scale as easily if your requirements change, and generally speaking the idea behind Gson is to avoid working directly with JsonElement and related classes.
I would definitely discourage a pre-processing step converting the JSON string into a different format. Structured data and string manipulations don't mix, as they lead to brittle code. JSON parsing libraries like Gson exist exactly to avoid such string manipulations.
JsonObject jobj = new Gson().fromJson(YOUR_JSON_HERE, JsonObject.class);
JsonElement value = jobj.get("ParamThatINeed");
value will contain the element associated with the ParamThatINeed key.

Convert Json to a java object

What is the way to generate a Java object with get and set methods?
You should write a java bean with properties maching the JSON key's, from that point since you already have a reader its a simple as
YourObject obj = gson.fromJson(br, YourObject.class);
UPDATE
With respect to your comment, when you don't want or can't create a bean it usually boils down to parsing JSON to map. GSON (afaik) doesn't have a built-in for this, but its not hard to build a method that will traverse GSON's objects. You have an example in this blog
http://itsmyviewofthings.blogspot.it/2013/04/jsonconverter-code-that-converts-json.html
As you seem to be open to alternatives, take a look at Jackson as well (the two libs are the de-facto standard in JAVA).
With jackson you don't have to create a bean to support deserialization, e.g.
String json = "{\"id\":\"masterslave\"}";
Map<String,String> map = new HashMap<String,String>();
ObjectMapper mapper = new ObjectMapper();
//convert JSON string to Map
map = mapper.readValue(json,
new TypeReference<HashMap<String,String>>(){});
http://www.jsonschema2pojo.org/
That link helps generate the Java object format based on the GSON you feed in. Just make sure you set the settings exactly as you need it. As always, it's not a good idea to just copy-paste generated code, but it might be of help.

Using Gson how to add variable name as top level parameter for json of a REST call

I am trying call a REST service and using gson I am getting the following json for the following java pojo.
pojo
public class AlphaParameters {
private int one;
private int two;
private int three;
//getter setters
//constructors
}
Json
{"one":4,
"two":5,
"three":10
}
I am using the following code
Gson gson = new Gson()
AlphaParameters alphaParameters = new AlphaParameters(one,two,three);
gson.toJson(alphaParameters );
Earlier this code used to work, but now seems the server side which is on .net changed their implementation and now they are expecting the json in the following format. Everything is same but seems now they want the toplevel variable name in the json.
{"alphaParameters":
{"one":4,
"two":5,
"three":10
}
}
Question : Is there a specific api of Gson which I can use to generate the above json without refactoring my code ?
Or writing a wrapper class to include alphaParameters will be a better approach .
( I will have to write a lot of boilerplate code for latter ).
Thanks for your help.
I don't think Gson itself allows this kind of serialization but there is a number of ways you could tackle this problem without creating wrapper classes.
In my comment, I suggested putting the object in a map but that's a bit strange and you can do it so it looks more obvious in the code and probably performs better.
public Gson wrapJson(Object objectToSerialize) {
Gson gson = new Gson();
JsonObject result = new JsonObject();
//Obtain a serialized version of your object
JsonElement jsonElement = gson.toJsonTree(objectToSerialize);
result.add(objectToSerialize.getClass().getSimpleName(), jsonElement);
return result;
}
Then you can use it like this:
AlphaParameters alphaParameters = new AlphaParameters(one,two,three);
wrapJson(alphaParameters);
This allows you to use one pretty universal method in every case like this without writing boilerplate classes.
I used the class name to generate the key but feel free to modify this as it suits you. You could pass the key name as a parameter to make this wrapper utility more flexible.

From org.json JSONObject to org.codehaus.jackson

I want to move from org.json to org.codehaus.jackson. How do I convert the following Java code?
private JSONObject myJsonMessage(String message){
JSONObject obj = new JSONObject();
obj.put("message",message);
return obj;
}
I left out the try-catch block for simplicity.
Instead of JSONObject use Jackson's ObjectMapper and ObjectNode:
ObjectMapper mapper = new ObjectMapper();
ObjectNode node = mapper.createObjectNode();
node.put("message", "text");
This would be Jackson's equivalent of your current org.json code.
However, where Jackson really excels is in its capacity to do complex mappings between your Java classes (POJOs) and their JSON representation, as well as its streaming API which allows you to do really fast serialization, at least when compared with org.json's counterparts.
There is no JSONObject in Jackson api. Rather than returning a JSONObject, you can either return a Map or a Java Bean with message property that has getters and setters for it.
public class MyMessage {
private String message;
public void setMessage(final String message) {
this.message = message;
}
public String getMessage() {
return this.message;
}
}
So, your method will be reduced to:
private MyMessage(String message) {
MyMessage myMessage = new MyMessage();
myMessage.setMessage(message);
return myMessage;
}
Another aspect of this change would be changing the serialization code, to convert MyMessage back to json string. Jackson does Java Beans, maps by default, you don't need to create a JSONObject e.g.,
private String serializeMessage(MyMessage message){
//Note: you probably want to put it in a global converter and share the object mapper
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(message);
}
The above will return {message: "some message"}
I have skipped the exceptions for brevity.
If you want to upgrade from org.json library to Jackson piece by piece, and initially retaining same API, you might want to read "Upgrade from org.json to Jackson".
This would at least make your code about 3x faster for basic JSON reading and writing; plus you could -- if you so choose -- start converting processing, as Jackson makes it easy to convert between Trees and POJOs (ObjectMapper.treeToValue(...), valueToTree, convertValue between POJOs etc. etc).
Just keep in mind that tools that you are familiar with may bias your thinking to certain patterns, and keeping an open mind can help you find even better ones.
In case of Jackson (or GSON or other mature Java JSON tools), you really should consider where proper data-binding could help, instead of using JSON-centered tree model (that org.json offers). Tree Models keep your thinking grounded to JSON structure, which is sometimes useful; but might also prevent you from seeing more natural patterns that come from defining POJO structure to reflect expected JSON, and operating on Java Objects directly.

Serialize an object to json in Java?

I am trying to serialize an instance of Campaign in Adwords API with gson at first with the code below:
Campaign c = new Campaign();
c.setName("beijing");
c.setId(23423L);
Gson gson = new Gson();
String json = gson.toJson(c);
and I get the exception that class Money declares multiple JSON fields named __equalsCalc. When I try to serialize the instance with json plugin of struts2 with the code below
String str = org.apache.struts2.json.JSONUtil.serialize(c);
System.out.println(str);
It works and output the correct result
{"adServingOptimizationStatus":null,"biddingStrategy":null,"budget":null,"campaignStats":null,"conversionOptimizerEligibility":null,"endDate":null,"frequencyCap":null,"id":23423,"name":"beijing","networkSetting":null,"servingStatus":null,"settings":null,"startDate":null,"status":null}
Then my question is that why can the json plugin of struts2 can serialize the instance correctly while gson cannot? Can I use the json plugin of struts2 to serialize objects to json since it is design to produce json result in struts2 not for this situation.
You can use the json plugin in struts2 to serialize your object manually to json string. You can do that by calling the serialize static method.
String jsonString = JSONUtil.serialize(your_object);
Don't forget to include xwork-core jar in your classpath because it depends on it.
Sounds like either a bug in Gson or it is more particular/less robust. Without looking at the code for either it would be hard to know more.
Personally I use Jackson for JSON to POJO transformations.
Ultimately as long as the Structs2 plugin is available on your classpath I don't see why you couldn't leverage it's classes to handle JSON transformations. Ultimately JSON is a format therefore all JSON libraries need to produce commonly understandable data.
I had a similar problem and solved it by moving my use of SimpleDateFormat from the class level to inside a method. GSON doesn't have to serialize SimpleDateFormat this way.
Hope this helps someone - 45 minutes of head banging for me! :-)

Categories