Parsing JSON with google-gson - java

From the server comes the answer
{
"error":false,
"lessons":[
{
"id":1,
"discipline":"??????????",
"type":"LECTURE",
"comment":"no comments"
},
{
"id":2,
"discipline":"???. ??",
"type":"LECTURE",
"comment":"no comments"
}
]
}
How correctly read object "lessons", and add to List ?

Use a wrapper object and you could directly read it as Wrapper obj = new Gson().fromJson(data, Wrapper.class);
import java.util.List;
import com.google.gson.Gson;
class Wrapper {
boolean error;
List<Lesson> lessons;
//Getters & Setters
}
class Lesson {
String id;
String discipline;
String type;
String comment;
//Getters & Setters
}
public class GsonSample {
public static void main(String[] args) {
String data = "{\"error\":false,\"lessons\":[{\"id\":1,\"discipline\":\"??????????\",\"type\":\"LECTURE\",\"comment\":\"no comments\"},{\"id\":2,\"discipline\":\"???. ??\",\"type\":\"LECTURE\",\"comment\":\"no comments\"}]}";
Wrapper obj = new Gson().fromJson(data, Wrapper.class);
System.out.println(obj.getLessons());
}
}

JSONArray lessions = response.getJSONArray("lessons");
JSONObject obj1 = lessions.getJSONObject(1); // 1 is index of elemet of array
String id = Obj1.getString("id");
And Same for others

Related

How to convert Json Array to Java Array of Objects

I have a json object which has following contents :
{
"similarUserScores":[
{
"user":"u26",
"score":0.6199970840986468
},
{
"user":"u37",
"score":0.5405403752816058
},
{
"user":"u12",
"score":0.523836143999991
},
{
"user":"u24",
"score":0.4990480549411648
}
]
}
I need to convert it into java objects. So I created a java class to map this :
public class SimilarUserScores {
private String user;
private double score;
public String getUser() {
return user;
}
public void setUser(String user) {
this.user = user;
}
public double getScore() {
return score;
}
public void setScore(double score) {
this.score = score;
}
}
So how can I convert the above JSON to a list of java objects?
//Get Recommendations for this user
JsonObject recommendedUserJson = PredictionIoClientHelper
.getInstance().getRecommendedUser("u"+userId, limit);
if(recommendedUserJson != null) {
Gson gson = new Gson();
String jsonString = recommendedUserJson.toString();
SimilarUserScores[] recommendedUsers= gson.fromJson(jsonString, SimilarUserScores[].class);
}
I tried to use the above snippet however it did not worked.
You have to initialize a JSONObject and an ArrayList<SimilarUserScores>.
Then you have to get the JSONArray and iterate over it.
For each iteration you set the data into the object and then append it to the output list. Here's an example of working code:
import java.util.ArrayList;
import org.json.JSONArray;
import org.json.JSONObject;
String s = "{\"similarUserScores\":[{\"user\":\"u26\",\"score\":0.6199970840986468}, ...
ArrayList<SimilarUserScores> objects = new ArrayList();
JSONObject obj = new JSONObject(s);
JSONArray scores = obj.getJSONArray("similarUserScores");
for (int i = 0; i < scores.length(); i++) {
JSONObject element = scores.getJSONObject(i);
SimilarUserScores object = new SimilarUserScores();
object.setUser(element.getString("user"));
object.setScore(element.getDouble("score"));
objects.add(object);
}
The previous code assumes that the JSON is in a String variable and that you have already defined SimilarUserScores class.
This code uses "JSON" library. If you are using maven, you can import it adding the following snippet in your pom.xml under the tag <dependencies>
<dependency>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20180130</version>
</dependency>
You need an wrapper around your SimilarUserScores.
Honestly, your inner class should be better named UserScore
public class SimilarUserScores {
private List<UserScore> similarUserScores;
// Getter setter
}
public class UserScore {
private String user;
private double score;
}
Now parse your json against SimilarUserScores class

Gson- Parsing a JSON array of JSON objects to ArrayList<org.json.JSONObject>

I have a JSON string like this:
{
"r": [
{
"pic": "1.jpg",
"name": "Name1"
},
{
"pic": "2.jpg",
"name": "Name2"
},
{
"pic": "3.jpg",
"name": "Name3"
}
]
}
I want to parse to this POJO model:
public class Catalog {
#SerializedName("r")
#Expose
private List<JSONObject> r = new ArrayList<JSONObject>();
public List<JSONObject> getR() {
return r;
}
public void setR(List<JSONObject> r) {
this.r = r;
}
}
I am parsing this way:
Catalog cat = new Gson().fromJson(jsonString,Catalog.class);
But finally am getting this json
{
"r": [
{
"nameValuePairs": {}
},
{
"nameValuePairs": {}
},
{
"nameValuePairs": {}
}
]
}
Please note that I don't want to use com.google.gson.JsonObject.
I want to use org.json.JSONObject. How to achieve this because almost all of my code uses it?
As it was already mentioned in other answer and comments, you probably might not really want to use org.json.JSONObject for several reasons. But if it's a must for you, you just have to create your org.json.JSONObject-aware Gson instance.
final class JSONObjectJsonDeserializer
implements JsonDeserializer<JSONObject> {
// The implementation is fully thread-safe and can be instantiated once
private static final JsonDeserializer<JSONObject> jsonObjectJsonDeserializer = new JSONObjectJsonDeserializer();
// Type tokens are immutable values and therefore can be considered constants (and final) and thread-safe as well
private static final TypeToken<Map<String, Object>> mapStringToObjectTypeToken = new TypeToken<Map<String, Object>>() {
};
private JSONObjectJsonDeserializer() {
}
static JsonDeserializer<JSONObject> getJsonObjectJsonDeserializer() {
return jsonObjectJsonDeserializer;
}
#Override
public JSONObject deserialize(final JsonElement jsonElement, final Type type, final JsonDeserializationContext context) {
// Convert the input jsonElement as if it were a Map<String, Object> (a generic representation for JSON objectS)
final Map<String, Object> map = context.deserialize(jsonElement, mapStringToObjectTypeToken.getType());
// And forward the map to the JSONObject constructor - it seems to accept it nice
return new JSONObject(map);
}
}
Gson is designed thread-safe and does not need to be instantiated every time serialization or deserialization is necessary:
private static final Gson gson = new GsonBuilder()
.registerTypeAdapter(JSONObject.class, getJsonObjectJsonDeserializer())
.create();
And finally:
final Catalog catalog = gson.fromJson(jsonString, Catalog.class);
out.println(catalog.getR());
with the following result:
[{"name":"Name1","pic":"1.jpg"}, {"name":"Name2","pic":"2.jpg"}, {"name":"Name3","pic":"3.jpg"}]
Anyway, I would suggest you to redesign your mappings model.
I think you don't need JSONObject.
Try this
// is wrapped class for serialized json.
public class JsonExample
{
List<Catalog> r;
}
public class Catalog {
private String pic;
private String name;
public String getPic() {
return pic;
}
public String getName() {
return name;
}
}
JsonExample example = new Gson().fromJson(json, JsonExample.class);
Additional - using JSONObject
JSONObject obj = new JSONObject(json);
JSONArray arr = obj.getJSONArray("r");
List<Catalog> cataList = new ArrayList<>();
for(int i = 0 ; i < arr.length() ; ++i)
{
cataList.add(new Catalog(arr.getJSONObject(i)));
}
public class Catalog {
private String pic;
private String name;
public Catalog(JSONObject obj) throws JSONException
{
pic = obj.getString("pic");
name = obj.getString("name");
}
public String getPic() {
return pic;
}
public String getName() {
return name;
}
}
I think in your case, usage of gson library is not required at all.
Only org.json can solve the entire problem.
E.g.:
JSONObject json = new JSONObject(jsonString);
JSONArray jsonArray = json.getJSONArray("r");
List<JSONObject> jsonList = new ArrayList<>();
for (int i = 0; i < jsonArray.length(); i++) {
jsonList.add(jsonArray.getJSONObject(i));
}
Catalog catalog = new Catalog();
catalog.setR(jsonList);

How to extract array values within nested JSON data

I have JSON data in the following format:
{
"data": {
"id": 14810798216415,
"name": "crescentbahuman.com",
"is_organization": true,
"email_domains": [
"crescentbahuman.com"
]
}
}
I want to get the string in the "email_domains" field. I wrote the following code as my attempt:
JSONObject dataObject2= (JSONObject)jsonObject2.get("data");
long id = (long) dataObject2.get("id");
System.out.println("worksapce id is: " + id);
String name = (String) dataObject2.get("name");
System.out.println("The worksapce name is: " + name);
boolean is_organization = (boolean) dataObject2.get("is_organization");
System.out.println("The workspace is organization: " + is_organization);
JSONArray email_domains = (JSONArray) jsonObject2.get("email_domains");
Iterator<String> iterator = email_domains.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
In this code to get "email_domains" only, a JSON Array object is created that get data from the JSON object and then its iterator is used to get values from within the array. However, it throws a NullPointerException on this line:
Iterator<String> iterator = email_domains.iterator();
I am stuck due to this problem. Can anyone kindly suggest a solution?
If you are using the JSON library from http://www.json.org/java/, then you should not be using JSONObject.get() so frequently. The library has other methods to get specific types, such as getLong(), getJSONArray(), and so forth. For your case with the "email_domains" field, you should try:
JSONArray array = dataObject2.getJSONArray("email_domains");
String value = array.getString(0);
org.json.JSONArray email_domains = (org.json.JSONArray) json.get("email_domains");
int length = email_domains.length();
for(int i = length-1; i > 0; i--) {
org.json.JSONObject jsonData = (org.json.JSONObject) email_domains.get(i);
System.out.println(jsonData);
}
My solution? I hate to be someone to offer a solution in another library... but look into google collections and the Gson helper. It can turn your Json into a map for you, and then back to json again when you are done.
Map map = gson.fromJson(jsonText, Map.class);
JsonArray's can then be cast into List's
try this to fetch "email_domains"
JSONArray email_domains = ((JSONArray) jsonObject).get("email_domains");
or
JSONObject obj = new JSONObject(jsonObject.Tostring());
JSONArray email_domains = obj.optJSONArray("email_domains");
"email_address" is JSONArray so we need to fetch this like
JSONArray email_domains = (JSONArray) dataObject2.getJSONArray("email_domains");
email_domains.get(0); // this will return crescentbahuman.com
Use this implementation
import java.lang.reflect.Field;
import java.util.List;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
public class JsonConvertor {
private static GsonBuilder gsonBuilder;
private static Gson gson;
private JsonConvertor() {
}
public static Object fromJson(String json, Class clz)
{
gson=new Gson();
return gson.fromJson(json,clz);
}
public static String toJson(Object obj) {
gsonBuilder = new GsonBuilder();
gsonBuilder = gsonBuilder
.addSerializationExclusionStrategy(new CustomIclusionStrategy(
obj.getClass()));
gson = gsonBuilder.create();
String json = gson.toJson(obj);
return json;
}
}
class CustomIclusionStrategy implements ExclusionStrategy {
private Class classToIclude;
private Field[] declaredFields;
private List<FieldAttributes> fields;
public CustomIclusionStrategy(List<FieldAttributes> fields) {
this.fields = fields;
}
public CustomIclusionStrategy(Class classToIclude) {
this.classToIclude = classToIclude;
this.declaredFields=classToIclude.getDeclaredFields();
}
// called only if shouldSkipClass returns false
#Override
public boolean shouldSkipField(FieldAttributes f) {
try {
classToIclude.getSuperclass().getDeclaredField(f.getName());
System.out.println(f.getName());
return true;
} catch (Exception e) {
}
return false;
}
#Override
public boolean shouldSkipClass(Class<?> clazz) {
// if returns false shouldSkipField will be called, otherwise
//shouldSkipField will not be called
return false;
}
}
public class Org {
private Data data;
public Org(Data data) {
super();
this.data = data;
}
public Data getData() {
return data;
}
public void setData(Data data) {
this.data = data;
}
public String toJson()
{
return JsonConvertor.toJson(this);
}
public static void main(String[] args) {
String json="{\"data\": {\"id\":\"1\",\"name\":\"org1\",\"is_organization\":true,\"email_domains\": [\"email1\",\"email2\",\"email3\",\"email4\"]}}";
Org o=(Org) JsonConvertor.fromJson(json, Org.class);
System.out.println(o.getData().getEmail_domains());
}
}

Deserialize a JSON response with Gson containing a field of variable type

The responses of a REST API always return a JSON with the following structure:
{
"status": "<status_code>",
"data": <data_object>
}
My problem is that the value of data doesn't have an unique type, but it can be a String, a JSON Object or a JSON Array, depending on the called endpoint. I can't figure out how to deserialize it in the right way to create the different Java objects...
For example, I've already prepared some POJOs: the root element
public class ApiResult {
#SerializedName("status")
public String status;
#SerializedName("data")
public JsonElement data; // should I define it as a JsonElement??
}
and two objects that reflects two of the endpoints:
// "data" can be a list of NavItems
public class NavItem {
#SerializedName("id")
public String id;
#SerializedName("name")
public String name;
#SerializedName("icon")
public String icon;
#SuppressWarnings("serial")
public static class List extends ArrayList<NavItem> {}
}
and
// "data" can be a single object representing a Profile
public class Profile {
#SerializedName("id")
public String id;
#SerializedName("fullname")
public String fullname;
#SerializedName("avatar")
public String avatar;
}
Reading some StackOverflow questions, I've seen I should use the JsonDeserializer<T> interface. But how if the type of data in ApiResult is variable?
You should use a a custom JsonDeserializer and write all your logic there, like this
ApiResult.java
public class ApiResult {
#SerializedName("status")
public String status;
#SerializedName("data")
public Object data;
}
ApiResultDeserializer.java
import java.lang.reflect.Type;
import java.util.List;
import com.google.gson.JsonDeserializationContext;
import com.google.gson.JsonDeserializer;
import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParseException;
import com.google.gson.reflect.TypeToken;
public class ApiResultDeserializer implements JsonDeserializer<ApiResult> {
private Type listType = new TypeToken<List<NavItem>>(){}.getType();
#Override
public ApiResult deserialize(JsonElement value, Type type,
JsonDeserializationContext context) throws JsonParseException {
final JsonObject apiResultJson = value.getAsJsonObject();
final ApiResult result = new ApiResult();
result.status = apiResultJson.get("status").getAsString();
JsonElement dataJson = apiResultJson.get("data");
if(dataJson.isJsonObject()) {
result.data = context.deserialize(dataJson, NavItem.class);
} else if(dataJson.isJsonPrimitive()) {
result.data = context.deserialize(dataJson, String.class);
} else if(dataJson.isJsonArray()) {
result.data = context.deserialize(dataJson, listType);
}
return result;
}
}
and try to create different kinds of data (List, Object, or String) as you mentioned
Main.java
Gson gson = new GsonBuilder()
.registerTypeAdapter(ApiResult.class, new ApiResultDeserializer())
.create();
List<NavItem> navItems = new ArrayList<NavItem>();
for(int i = 1 ; i < 6 ; ++i) {
navItems.add(new NavItem(i+"", "Name-" + i, "Icon-" + i ));
}
ApiResult result = new ApiResult();
result.status = "OK";
result.data = navItems;
// Serialization
System.out.println(gson.toJson(result)); // {\"status\":\"OK\",\"data\":[{\"id\":\"1\",\"name\":\"Name-1\",\"icon\":\"Icon-1\"},{\"id\":\"2\",\"name\":\"Name-2\",\"icon\":\"Icon-2\"},{\"id\":\"3\",\"name\":\"Name-3\",\"icon\":\"Icon-3\"},{\"id\":\"4\",\"name\":\"Name-4\",\"icon\":\"Icon-4\"},{\"id\":\"5\",\"name\":\"Name-5\",\"icon\":\"Icon-5\"}]}
result.data = navItems.get(0);
System.out.println(gson.toJson(result)); // {\"status\":\"OK\",\"data\":{\"id\":\"1\",\"name\":\"Name-1\",\"icon\":\"Icon-1\"}}
result.data = "Test";
System.out.println(gson.toJson(result)); // {\"status\":\"OK\",\"data\":\"Test\"}
// Deserialization
String input = "{\"status\":\"OK\",\"data\":[{\"id\":\"1\",\"name\":\"Name-1\",\"icon\":\"Icon-1\"},{\"id\":\"2\",\"name\":\"Name-2\",\"icon\":\"Icon-2\"},{\"id\":\"3\",\"name\":\"Name-3\",\"icon\":\"Icon-3\"},{\"id\":\"4\",\"name\":\"Name-4\",\"icon\":\"Icon-4\"},{\"id\":\"5\",\"name\":\"Name-5\",\"icon\":\"Icon-5\"}]}";
ApiResult newResult = gson.fromJson(input, ApiResult.class);
System.out.println(newResult.data); // Array
input = "{\"status\":\"OK\",\"data\":{\"id\":\"1\",\"name\":\"Name-1\",\"icon\":\"Icon-1\"}}";
newResult = gson.fromJson(input, ApiResult.class);
System.out.println(newResult.data); // Object
input = "{\"status\":\"OK\",\"data\":\"Test\"}";
newResult = gson.fromJson(input, ApiResult.class);
System.out.println(newResult.data); // String
I managed to make it work as I wanted, and without using any custom deserializer!
For each endpoint, I wait for the response (btw I'm using Volley), then I first generate the "root" ApiResult object, check if the status is OK, then I proceed instantiating the data field as the requested type.
The POJOs are the same of the question. In ApiResult, "data" is a JsonElement.
// ... called the endpoint that returns a NavItem list
public void onResponse(String response) {
ApiResult rootResult = gson.fromJson(response.toString(), ApiResult.class);
if (rootResult.status.equals(STATUS_OK)) {
Log.d(LOG_TAG, response.toString());
NavItem.List resData = gson.fromJson(rootResult.data, NavItem.List.class); // <-- !!!!!
callback.onSuccess(resData);
}
else {
Log.e(LOG_TAG, response.toString());
callback.onError(-1, null);
}
}
Obviously the only thing to change for the "Profile" endpoint is the line with !!!!!

Converting Java objects to JSON with Jackson

I want my JSON to look like this:
{
"information": [{
"timestamp": "xxxx",
"feature": "xxxx",
"ean": 1234,
"data": "xxxx"
}, {
"timestamp": "yyy",
"feature": "yyy",
"ean": 12345,
"data": "yyy"
}]
}
Code so far:
import java.util.List;
public class ValueData {
private List<ValueItems> information;
public ValueData(){
}
public List<ValueItems> getInformation() {
return information;
}
public void setInformation(List<ValueItems> information) {
this.information = information;
}
#Override
public String toString() {
return String.format("{information:%s}", information);
}
}
and
public class ValueItems {
private String timestamp;
private String feature;
private int ean;
private String data;
public ValueItems(){
}
public ValueItems(String timestamp, String feature, int ean, String data){
this.timestamp = timestamp;
this.feature = feature;
this.ean = ean;
this.data = data;
}
public String getTimestamp() {
return timestamp;
}
public void setTimestamp(String timestamp) {
this.timestamp = timestamp;
}
public String getFeature() {
return feature;
}
public void setFeature(String feature) {
this.feature = feature;
}
public int getEan() {
return ean;
}
public void setEan(int ean) {
this.ean = ean;
}
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
#Override
public String toString() {
return String.format("{timestamp:%s,feature:%s,ean:%s,data:%s}", timestamp, feature, ean, data);
}
}
I just missing the part how I can convert the Java object to JSON with Jackson:
public static void main(String[] args) {
// CONVERT THE JAVA OBJECT TO JSON HERE
System.out.println(json);
}
My Question is: Are my classes correct? Which instance do I have to call and how that I can achieve this JSON output?
To convert your object in JSON with Jackson:
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.ObjectWriter;
ObjectWriter ow = new ObjectMapper().writer().withDefaultPrettyPrinter();
String json = ow.writeValueAsString(object);
I know this is old (and I am new to java), but I ran into the same problem. And the answers were not as clear to me as a newbie... so I thought I would add what I learned.
I used a third-party library to aid in the endeavor: org.codehaus.jackson
All of the downloads for this can be found here.
For base JSON functionality, you need to add the following jars to your project's libraries:
jackson-mapper-asl
and
jackson-core-asl
Choose the version your project needs. (Typically you can go with the latest stable build).
Once they are imported in to your project's libraries, add the following import lines to your code:
import org.codehaus.jackson.JsonGenerationException;
import org.codehaus.jackson.map.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
With the java object defined and assigned values that you wish to convert to JSON and return as part of a RESTful web service
User u = new User();
u.firstName = "Sample";
u.lastName = "User";
u.email = "sampleU#example.com";
ObjectMapper mapper = new ObjectMapper();
try {
// convert user object to json string and return it
return mapper.writeValueAsString(u);
}
catch (JsonGenerationException | JsonMappingException e) {
// catch various errors
e.printStackTrace();
}
The result should looks like this:
{"firstName":"Sample","lastName":"User","email":"sampleU#example.com"}
Just follow any of these:
For jackson it should work:
ObjectMapper mapper = new ObjectMapper();
return mapper.writeValueAsString(object);
//will return json in string
For gson it should work:
Gson gson = new Gson();
return Response.ok(gson.toJson(yourClass)).build();
You could do this:
String json = new ObjectMapper().writeValueAsString(yourObjectHere);
This might be useful:
objectMapper.writeValue(new File("c:\\employee.json"), employee);
// display to console
Object json = objectMapper.readValue(
objectMapper.writeValueAsString(employee), Object.class);
System.out.println(objectMapper.writerWithDefaultPrettyPrinter()
.writeValueAsString(json));
You can use Google Gson like this
UserEntity user = new UserEntity();
user.setUserName("UserName");
user.setUserAge(18);
Gson gson = new Gson();
String jsonStr = gson.toJson(user);
Well, even the accepted answer does not exactly output what op has asked for. It outputs the JSON string but with " characters escaped. So, although might be a little late, I am answering hopeing it will help people! Here is how I do it:
StringWriter writer = new StringWriter();
JsonGenerator jgen = new JsonFactory().createGenerator(writer);
jgen.setCodec(new ObjectMapper());
jgen.writeObject(object);
jgen.close();
System.out.println(writer.toString());
Note: To make the most voted solution work, attributes in the POJO have to be public or have a public getter/setter:
By default, Jackson 2 will only work with fields that are either
public, or have a public getter method – serializing an entity that
has all fields private or package private will fail.
Not tested yet, but I believe that this rule also applies for other JSON libs like google Gson.
public class JSONConvector {
public static String toJSON(Object object) throws JSONException, IllegalAccessException {
String str = "";
Class c = object.getClass();
JSONObject jsonObject = new JSONObject();
for (Field field : c.getDeclaredFields()) {
field.setAccessible(true);
String name = field.getName();
String value = String.valueOf(field.get(object));
jsonObject.put(name, value);
}
System.out.println(jsonObject.toString());
return jsonObject.toString();
}
public static String toJSON(List list ) throws JSONException, IllegalAccessException {
JSONArray jsonArray = new JSONArray();
for (Object i : list) {
String jstr = toJSON(i);
JSONObject jsonObject = new JSONObject(jstr);
jsonArray.put(jsonArray);
}
return jsonArray.toString();
}
}

Categories

Resources