I have a JSON response that looks like this. I want to extract the values of "text" and put them into a Set of Strings (i.e. I don't necessarily need the entire JSON to be derialised).
I am using the GSON library
So far my method looks like this (It's obviously wrong):
public static Response deserialise(String json){
Gson gson = new Gson();
Response r = gson.fromJson(json, Response.class);
return r;
}
I am calling deserialise with this:
Response r = deserialise(json);
System.out.println("[status]: "+r.getStatus()); // works fine
Collection<Keyword> coll = r.getKeywords();
Iterator<Keyword> itr = coll.iterator();
while(itr.hasNext()){
System.out.println(itr.next().getWord()); //prints null every time
}
Response is a class with the following member variables (with getters and setters):
private String status;
private String usage;
private String language;
private Collection<Keyword> keywords;
Keyword is a class with the following member variables (with getters and setters):
private String word;
private String relevance;
The JSON looks like this:
{
"status": "OK",
"usage": "By accessing AlchemyAPI or using information generated by AlchemyAPI, you are agreeing to be bound by the AlchemyAPI Terms of Use: http://www.alchemyapi.com/company/terms.html",
"url": "http://www.theage.com.au/world/aussie-trying-to-make-a-difference-gunned-down-20110510-1egnv.html",
"language": "english",
"keywords": [
{
"text": "Mr McNichols",
"relevance": "0.99441"
},
{
"text": "Ms Benton",
"relevance": "0.392337"
},
{
"text": "Detroit",
"relevance": "0.363931"
},
{
"text": "Crocodile Hunter",
"relevance": "0.350197"
}
]
}
The problem is that the Collection of Keywords returns null values - although it seems to have the correct size, which is positive.
This just works:
public class Keyword {
public String text;
public String relevance;
}
public class MyJSON {
public String status;
public String usage;
public String language;
public Collection<Keyword> keywords;
}
In the main method
String str = "{\"status\": \"OK\","+
"\"usage\": \"By accessing AlchemyAPI or using information generated by AlchemyAPI, you are agreeing to be bound by the AlchemyAPI Terms of Use: http://www.alchemyapi.com/company/terms.html\","+
"\"url\": \"http://www.theage.com.au/world/aussie-trying-to-make-a-difference-gunned-down-20110510-1egnv.html\","+
"\"language\": \"english\","+
"\"keywords\": ["+
"{"+
"\"text\": \"Mr McNichols\","+
"\"relevance\": \"0.99441\""+
"},"+
"{"+
"\"text\": \"Ms Benton\","+
"\"relevance\": \"0.392337\""+
"},"+
"{"+
"\"text\": \"Detroit\","+
"\"relevance\": \"0.363931\""+
"},"+
"{"+
"\"text\": \"Crocodile Hunter\","+
"\"relevance\": \"0.350197\""+
"}"+
"]"+
"}";
Gson gson = new Gson();
MyJSON mj = gson.fromJson(str, MyJSON.class);
System.out.println(mj.language);
for(Keyword k: mj.keywords)
System.out.println(k.text+":"+k.relevance);
This prints
english
Mr McNichols:0.99441
Ms Benton:0.392337
Detroit:0.363931
Crocodile Hunter:0.350197
Look carefully at my Keyword class!(and my JSON string starts with {).
This was all down to my own stupidity.
In the keyword class I called the variable word when it should have been text in order to map properly to the JSON.
Related
I am trying to parse a JSON response documents using Gson but after parse it's giving me a null value
My JSON response is a Array of Documents
Java Code
//Code to convert the response into JSON
String res = gson.toJson(results);
//Parse the JSON
java.lang.reflect.Type collectionType = new TypeToken<List<Objects.JsonResponse>>() {}.getType();
List<Objects.JsonResponse> resp = gson.fromJson(res, collectionType);
System.out.println(resp.get(2).getName());
JAVA Object
package Objects;
import java.util.List;
import com.google.gson.annotations.SerializedName;
public class JsonResponse {
#SerializedName("product_id")
public static String product_id; //17
#SerializedName("create_date")
public static String create_date; //45
#SerializedName("image_small")
public static String image_small; //85
#SerializedName("image_large")
public static String image_large; //133
#SerializedName("name")
private static String name; //174
#SerializedName("description")
public static String description; //266
#SerializedName("tagline")
public static List<String> tagline;
#SerializedName("category")
public static List<String> category;
#SerializedName("catlevel0")
public static List<String> catlevel0;
#SerializedName("catlevel1")
public static List<String> catlevel1;
#SerializedName("catlevel2")
public static List<String> catlevel2;
#SerializedName("color")
public static List<String> color;
#SerializedName("size")
public static List<String> size;
#SerializedName("_version_")
public static String _version_;
#SerializedName("product_id")
public static String getName() {
return name;
}
public static void setName(String name) {
JsonResponse.name = name;
}
}
JSON document to be parsed is:
[
{
"product_id": "prod3400008",
"create_date": "2011-02-17T00:00:00Z",
"image_small": "/hul_images/small/17_Rexona.jpg",
"image_large": "/hul_images/large/17_Rexona.jpg",
"name": "Small Shell Cluster Loop Earrings",
"description": "Small Shell Cluster Loop Earrings",
"tagline": [
"B1G1 75% Off Jewelry "
],
"category": [
"Earrings"
],
"catlevel0": [
"Accessories"
],
"catlevel1": [
"Jewelry"
],
"catlevel2": [
"Earrings"
],
"color": [
"Clearly Coral",
"Mocha Brown",
"Blue Lagoon",
"Hunter Green",
"Medium Purple"
],
"_version_": 1527034576315089000
}
]
This is not a solutions, more like a tip. I found out the problem in your question. The problem is with the json array. If you remove all the arrays and just an object, this problem wont come. I dont know if you are aware of that already.
Please try the following json
{
"product_id": "prod3400008",
"create_date": "2011-02-17T00:00:00Z",
"image_small": "/hul_images/small/17_Rexona.jpg",
"image_large": "/hul_images/large/17_Rexona.jpg",
"name": "Small Shell Cluster Loop Earrings",
"description": "Small Shell Cluster Loop Earrings",
"_version_": 1527034576315089000
}
I removed all the arrays.
I have also removed the static declaration of your class JsonResponse, and static declaration of all your member variables.
And this is try this code:
Gson gson = new Gson();
String res = gson.toJson(results);
JsonResponse response = gson.fromJson(results, JsonResponse.class);
System.out.println(response.product_id);
System.out.println(response.create_date);
Hope this will help to figure out the problem. If you still cant find out, let me know... I will try harder... :-)
Object attributes are static and you should tell the GsonBuilder to serialize it.
follow this stack for more information.
Better practice would be not to make pojo class filed as static :)
Maybe it's giving you null because you messed up your annotations...
Also, remove static from all the methods and fields, you are trying to make instance variables, not class variables.
#SerializedName("product_id") // <---- not right
public String getName() { // <--- removed "static"
return name;
}
I trying to deserialize this json to array of objects:
[{
"name": "item 1",
"tags": ["tag1"]
},
{
"name": "item 2",
"tags": ["tag1","tag2"]
},
{
"name": "item 3",
"tags": []
},
{
"name": "item 4",
"tags": ""
}]
My java class looks like this:
public class MyObject
{
#Expose
private String name;
#Expose
private List<String> tags = new ArrayList<String>();
}
The problem is json's tags property which can be just empty string or array. Right now gson gives me error: com.google.gson.JsonSyntaxException: java.lang.IllegalStateException: Expected BEGIN_ARRAY but was STRING
How should I deserialize this json?
I do not have any control to this json, it comes from 3rd pary api.
I do not have any control to this json, it comes from 3rd pary api.
If you don't have the control over the data, your best solution is to create a custom deserializer in my opinion:
class MyObjectDeserializer implements JsonDeserializer<MyObject> {
#Override
public MyObject deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
JsonObject jObj = json.getAsJsonObject();
JsonElement jElement = jObj.get("tags");
List<String> tags = Collections.emptyList();
if(jElement.isJsonArray()) {
tags = context.deserialize(jElement.getAsJsonArray(), new TypeToken<List<String>>(){}.getType());
}
//assuming there is an appropriate constructor
return new MyObject(jObj.getAsJsonPrimitive("name").getAsString(), tags);
}
}
What it does it that it checks whether "tags" is a JsonArray or not. If it's the case, it deserializes it as usual, otherwise you don't touch it and just create your object with an empty list.
Once you've written that, you need to register it within the JSON parser:
Gson gson = new GsonBuilder().registerTypeAdapter(MyObject.class, new MyObjectDeserializer()).create();
//here json is a String that contains your input
List<MyObject> myObjects = gson.fromJson(json, new TypeToken<List<MyObject>>(){}.getType());
Running it, I get as output:
MyObject{name='item 1', tags=[tag1]}
MyObject{name='item 2', tags=[tag1, tag2]}
MyObject{name='item 3', tags=[]}
MyObject{name='item 4', tags=[]}
Before converting the json into object replace the string "tags": "" with "tags": []
Use GSON's fromJson() method to de serialize your JSON.
You can better understand this by the example given below:
import java.util.ArrayList;
import com.google.gson.Gson;
import com.google.gson.JsonArray;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
public class JsonToJava {
/**
* #param args
*/
public static void main(String[] args) {
String json = "[{\"firstName\":\"John\", \"lastName\":\"Doe\", \"id\":[\"10\",\"20\",\"30\"]},"
+ "{\"firstName\":\"Anna\", \"lastName\":\"Smith\", \"id\":[\"40\",\"50\",\"60\"]},"
+ "{\"firstName\":\"Peter\", \"lastName\":\"Jones\", \"id\":[\"70\",\"80\",\"90\"]},"
+ "{\"firstName\":\"Ankur\", \"lastName\":\"Mahajan\", \"id\":[\"100\",\"200\",\"300\"]},"
+ "{\"firstName\":\"Abhishek\", \"lastName\":\"Mahajan\", \"id\":[\"400\",\"500\",\"600\"]}]";
jsonToJava(json);
}
private static void jsonToJava(String json) {
Gson gson = new Gson();
JsonParser parser = new JsonParser();
JsonArray jArray = parser.parse(json).getAsJsonArray();
ArrayList<POJO> lcs = new ArrayList<POJO>();
for (JsonElement obj : jArray) {
POJO cse = gson.fromJson(obj, POJO.class);
lcs.add(cse);
}
for (POJO pojo : lcs) {
System.out.println(pojo.getFirstName() + ", " + pojo.getLastName()
+ ", " + pojo.getId());
}
}
}
POJO class:
public class POJO {
private String firstName;
private String lastName;
private String[] id;
//Getters and Setters.
I hope this will solve your issue.
You are mixing datatypes. You cant have both an Array and a string. Change
"tags": ""
to
"tags": null
and you are good to go.
Use Jacskon Object Mapper
See below simple example
[http://www.mkyong.com/java/how-to-convert-java-object-to-from-json-jackson/][1]
Jackson type safety is way better than Gson. At times you will stackoverflow in Gson.
I need to serialize a list of simple Java objects to JSON using Google Gson library.
The object:
public class SimpleNode {
private String imageIndex;
private String text;
public String getImageIndex() {
return imageIndex;
}
public void setImageIndex(String imageIndex) {
this.imageIndex = imageIndex;
}
public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}
I have written the following code for serialization:
List<SimpleNode> testNodes = repository.getElements(0);
Gson gson = new Gson();
String jsonNodesAsString = gson.toJson(testNodes);
It works, but the field name of the JSON objects is lowerCamelCase. Like this:
[
{
"imageIndex": "1",
"text": "Text 1"
},
{
"imageIndex": "2",
"text": "Text 2"
}
]
How do I get a JSON with UpperCamelCase field name, like this:
[
{
"ImageIndex": "1",
"Text": "Text 1"
},
{
"ImageIndex": "2",
"Text": "Text 2"
}
]
I think that I can rename member variables in to UpperCamelCase, but may be there is another way?
Taken from the docs:
Gson supports some pre-defined field naming policies to convert the standard Java field names (i.e. camel cased names starting with lower case --- "sampleFieldNameInJava") to a Json field name (i.e. sample_field_name_in_java or SampleFieldNameInJava). See the FieldNamingPolicy class for information on the pre-defined naming policies.
It also has an annotation based strategy to allows clients to define custom names on a per field basis. Note, that the annotation based strategy has field name validation which will raise "Runtime" exceptions if an invalid field name is provided as the annotation value.
The following is an example of how to use both Gson naming policy features:
private class SomeObject {
#SerializedName("custom_naming")
private final String someField;
private final String someOtherField;
public SomeObject(String a, String b) {
this.someField = a;
this.someOtherField = b;
}
}
SomeObject someObject = new SomeObject("first", "second");
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
String jsonRepresentation = gson.toJson(someObject);
System.out.println(jsonRepresentation);
======== OUTPUT ========
{"custom_naming":"first","SomeOtherField":"second"}
However, for what you want, you could just use this:
Gson gson = new GsonBuilder().setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE).create();
By using the UPPER_CAMEL_CASE option, you'll achieve your goal.
I am trying to parse the response from the server something like this
public class TestClass {
public class TaskResponse {
private String id;
private List<String> links;
public String getId(){
return id;
}
}
public static void main(String args[]){
String response = "{
"task": {
"id": 10,
"links": [
{
"href": "http://localhost:9000/v1/115e4ad38aef463e8f99991baad1f809/os-hosts/svs144/onboard/10"
}
]
}
}";
JsonParser parser = new JsonParser();
JsonObject obj = parser.parse(response).getAsJsonObject();
Gson gson = new Gson();
TaskResponse tskResponse = gson.fromJson(response, TaskResponse.class);
String taskId = tskResponse.getId();
System.out.println("The task Id is "+taskId);
}
}
In what I am originally doing I get the task id as null but in this code also which I have written above to try and understand the problem, Eclipse is giving error in the string response, it does not recognize it is a proper string.
Please see to it that I can't change the response string as it is coming from server. Any help of any kind or any links to sort out the error will be highly appreciated.
Thanx in Advance.
Gson will try to match the JSON-string to your class' structure.
Since your JSON starts with task : { ... } it will try to find a property task on the class TaskResponse. Since there's no such field, it won't set anything on your instance.
So either convert it more generally (e.g. using Map.class as the target) or add the task property to a wrapper class:
class TaskResponse {
private Task task;
}
class Task {
private Long id;
private List<Link> links;
}
class Link {
String href;
}
There's also a third option detailed in this answer.
inside the string " can not directly be use
u need to escape it by replacing it to \"
" ===> \"
String response = "{
\"task\": {
\"id\": 10,
\"links\": [
{
\"href\": \"http://`localhost`:9000/v1/115e4ad38aef463e8f99991baad1f809/os-hosts/svs144/onboard/10\"
}
]
}
}";
I have the followed snipets of Json String:
{
"networks": {
"tech11": {
"id": "1",
"name": "IDEN"
},
"tech12": {
"id": "2",
"name": "EVDO_B"
}
}
}
I use some methods to convert this String to Object:
private static Gson mGson = new Gson();
...
public static WebObjectResponse convertJsonToObject(String jsonString) {
WebObjectResponse webObjectResponse = null;
if(jsonString != null && jsonString.length() > 1){
webObjectResponse = mGson.fromJson(jsonString, WebObjectResponse.class);
}
return webObjectResponse;
}
Where WebObjectResponse is class that should represent above mentioned String.
Its not complicated if I get static fields.
But in my case the values have different names: tech11, tech12 ....
I can use #SerializedName but its works in specific cases like convert "class" to "class_".
As you see networks Object defined as list of tech Objects but with different post-fix.
public class WebObjectResponse{
private DataInfoList networks = null;
}
This is static implementation, i defined 2 values tech11 and tech12 but next response might be techXX
public class DataInfoList {
private DataInfo tech11 = null;
private DataInfo tech12 = null;
}
public class DataInfo {
private String id = null;
private String name = null;
}
What is the good way to convert current Json String to Object where list of elements are Objects too and have different names?
Thank you.
Use a Map!
I would do the following
public class WebObjectResponse {
private Map<String, DataInfo> networks;
}
public class DataInfo {
private String id = null;
private String name = null;
}
// later
Gson gson = new Gson();
String json = "{\"networks\": {\"tech11\": { \"id\": \"1\",\"name\": \"IDEN\" }, \"tech12\": { \"id\": \"2\", \"name\": \"EVDO_B\" } }}";
WebObjectResponse response = gson.fromJson(json, WebObjectResponse .class);
For each object in json networks, a new entry will be added to the Map field of your class WebObjectResponse. You then reference them by techXX or iterate through the keyset.
Assuming a structure like this
{
"networks": {
"tech11": {
"id": "1",
"name": "IDEN"
},
"tech12": {
"id": "2",
"name": "EVDO_B"
},
"tech13": {
"id": "3",
"name": "WOHOO"
}, ...
}
}
We would need your class structure for more details.
As far as I am aware, I think you will need to have some mappings defined somewhere (I used xml's) and then try to match json with one of the mappings to create objects.
Google gson is good. I did it in Jackson
Also, converting objects should be trivial. But since you might have variable fields like tech11 and tech12 , you might want to store the "network" value as a string and then extract fields out of it when required.
Hope I could help.
Edit : Sotirious nails it.
Please use this link for converting SON Response to Java POJO class
http://www.jsonschema2pojo.org/