Help me to parse this kind of json for android - java

I have this type of json from api:
[
{
"id": "12",
"name": "elo2",
"status": "ok",
"vulumes": [
{
"id": 17592,
"name": "vol1",
"status": "ok"
}
]
},
{
"id": "13",
"name": "elo",
"status": "ok",
"vulumes": [
{
"id": "17596",
"name": "vol2",
"status": "ok"
}
]
}
]
ID 12 and 13 its shelf, volumes is a part of shelf with id 17592 and 17596
I cannot to parse it with json, i trying to use gson or json, but i can't understand how to get sime block, for e.g. block with id 12 for parse info about shelf and existing volumes at this shelf.
Can you help me? In other apis i can see named objects vith k/v, but there is nothing.

With Gson, here's one simple approach you could take. This demonstrates a Java data structure that matches the JSON example, along with how to deserialize and serialize it using Gson.
public class Foo
{
public static void main(String[] args) throws Exception
{
Gson gson = new Gson();
Type thingsType = new TypeToken<List<Thing>>() {}.getType();
List<Thing> things = gson.fromJson(new FileReader("input.json"), thingsType);
System.out.println(gson.toJson(things));
}
}
class Thing
{
String id;
String name;
String status;
List<Vulume> vulumes;
}
class Vulume
{
String id;
String name;
String status;
}
Since the attributes of the two object types are almost identical, then maybe the intention was that there be only one object type, with a reference to a collection of objects of the same type. Here's what that would look like.
public class Foo
{
public static void main(String[] args) throws Exception
{
Gson gson = new Gson();
Type thingsType = new TypeToken<List<Vulume>>() {}.getType();
List<Vulume> things = gson.fromJson(new FileReader("input.json"), thingsType);
System.out.println(gson.toJson(things));
}
}
class Vulume
{
String id;
String name;
String status;
List<Vulume> vulumes;
}

Related

how to iterate through this json object and format it

I have multiple JSON files, but they all look similar to this one (some much longer):
{
"$id": "http://example.com/myURI.schema.json",
"$schema": "http://json-schema.org/draft-07/schema#",
"additionalProperties": false,
"description": "Sample Procedure schema.",
"properties": {
"prop1": {
"description": "",
"type": "string"
},
"prop2": {
"description": "",
"type": "number"
}
"prop3": {
"description": "",
"type": "string"
}
}
}
I want to extract the names (ex. "prop1","prop2") along with their types (ex. "string,"number") and format it to look something like the following:
public static class Whatever {
#JsonProperty
public String prop1;
#JsonProperty
public Integer prop2;
#JsonProperty
public String prop3;
public Whatever() {}
public Whatever(String prop1, Integer prop2, String prop3){
this(prop1, prop2, prop3);
}
}
I've never used Java before so I'm not sure where to begin in creating this script. Mainly I'm concerned with how I will iterate through the json object.
I would Approach this this way:
Create a main class that holds all the information of the JSON and a Secondary class that keeps the information of the prop properties of the JSON:
public class MainJsonObject
{
private int $id;
private int $schema;
// All the other objects that you find relevant...
private List<SecondaryJsonObject> propsList = new ArrayList<>(); // This will keep all your other props with description and type
// Getter and setter, do not forget them as they are needed by the JSON library!!
}
public class SecondaryJsonObject
{
private String description;
private String type;
// Getter and setter, do not forget them !!
}
You could iterate through your JSON Object this way:
First of all include the JSON Library in your project.
Then iterate through your JSON like this:
JSONObject jsonObject = new JSONObject(jsonString);
MainJsonObject mjo = new MainJsonObject();
mjo.set$id(jsonObject.getInt("$id")); // Do this for all other "normal" attributes
// Then we start with your properties array and iterate through it this way:
JSONArray jsonArrayWithProps = jsonObject.getJSONArray("properties");
for(int i = 0 ; i < jsonArrayWithProps.length(); i++)
{
JSONObject propJsonObject = jsonArrayWithProps.getJSONObject(i); // We get the prop object
SecondaryJsonObject sjo = new SecondaryJsonObject();
sjo.setDescription(propJsonObject.getString("description"));
sjo.setTyoe(propJsonObject.getString("type"));
mjo.getPropsList().add(sjo); // We fill our main object's list.
}

Retrofit2: convert JSON with dynamic keys to a Map<String, Model> with Model also containing those keys

I'm using Retrofit 2 in combination with Gson and RxJava. My JSON data looks something like this:
{
"groups": {
"1": {
"name": "First group",
"type": "some data",
// ... more data
},
"2": {
"name": "Second group",
"type": "some data",
// ... more data
},
"3": {
"name": "Third group",
"type": "some data",
// ... more data
}
// 4, 5, 6, etc...
},
// ... more data
}
In the example above the "keys" 1, 2, 3 are integers but they can also be unique strings. I want to map this JSON data to something like this:
public class MyData {
#SerializedName("groups")
private Map<String, Group> mGroups;
// ... more data
}
public class Group {
// TODO: This should be "1", "2", "3", etc.
#SerializedName(???)
private String mId;
// This should be "First group", "Second group", "Third group", etc.
#SerializedName("name")
private String mName;
// This should be "some data"
#SerializedName("type")
private String mType;
// ... more data
}
What's the best way to put the dynamic key (1, 2, 3) in the Group object as well? I'm not hosting the JSON data myself so it cannot be changed to another format.
Step A - Create a group class:
public class Group {
String name;
String type;
}
Step B - Create a groups class:
public class Groups {
List<Group> userList;
}
Step C - Create a GSON Deserializer class
public class MyDeserializer implements JsonDeserializer<Groups> {
private final String groups_key = "groups";
#Override
public Groups deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
Groups groups = new Groups();
JsonObject object = json.getAsJsonObject().getAsJsonObject(groups_key);
Map<String, Group> retMap = new Gson().fromJson(object, new TypeToken<HashMap<String, Group>>() {}.getType());
List<Group> list = new ArrayList<Group>(retMap.values());
groups.userList = list;
return groups;
}
}
Step D - Register your Deserializer when you create your Gson object
Gson gson = new GsonBuilder()
.registerTypeAdapter(Groups.class, new MyDeserializer()).create();
Step E - Convert your JSON object via. Gson
Groups groups = gson.fromJson(jsonExmple, Groups.class);
Notes:
When your JSON object gets bigger you can expand your Group/Groups
classes and add more variables. Keep in mind that you will need to reflect everything in your Deserializer class. :)
Use #SerializedName annotation when your variable got a different name from your JSON key

Create JSON object in Java8 using com.google.code.gson

I am trying to create a JSON Object using com.google.code.jso in JAVA 8. I have a list of objects and i am iterating through them. The object is as:
public class MyObject {
private String name, status, cause, id;
public String getName() {
return name;
}
public String getStatus() {
return status;
}
public String getCause() {
return cause;
}
public String getId() {
return id;
}
}
I have a list of above objects and i am trying to convert them to JSON using the below (the relevant code):
import com.google.gson.JsonObject;
JsonObject status = new JsonObject();
for (MyObject obj : objectLists){
status.add(obj.getId(),
new JsonObject()
.add("Name: ", obj.getName())
.add("Status: ", obj.getStatus())
.add("Cause: ", obj.getCause())
);
}
I was hoping to get a JSON of the following form:
{
"0 (this is the id i get from myObject.getId())": {
"name": The name i get from myObject.getName(),
"Status": The status from myobject.getStatus(),
"cause": The status from myobject.getCause()
},
"1": {
"name": "myname",
"Status": "mystatus",
"cause": "cause"
}
}
So I have 2 question.
I am getting an error in creating the Json object. Wrong 2nd
argument type. Found: 'java.lang.String', required:
'com.google.gson.JsonElement' I understand that i have to change
the second parameter but i could not find in the docs how to do
that.
How can i pretty print this.
Thanks
You used wrong method:
JsonObject.addProperty(), not JsonObject.add()
JsonObject.add(String, JsonElement) - adds nested json element to your object:
{
"root": {
"nested": {}
}
}
JsonObject.addProperty(String, String) - adds property to your object (it may be any primitive or String):
{
"root": {
"property": "some string"
}
}
Why not using this instead.
Gson.toJson(obj);
You should wrap your strings in JsonPrimitive objects, for example:
new JsonObject().add("Name: ", new JsonPrimitive(obj.getName()));
To enable pretty printing, you have to use GsonBuilder.setPrettyPrinting():
Gson gson = new GsonBuilder().setPrettyPrinting().create();
System.out.println(gson.toJson(obj));

retrofit gson converter for nested json with different objects

I've JSON structure like follows -
{
"status": true,
"message": "Registration Complete.",
"data": {
"user": {
"username": "user88",
"email": "user#domain.com",
"created_on": "1426171225",
"last_login": null,
"active": "1",
"first_name": "User",
"last_name": "",
"company": null,
"phone": null,
"sign_up_mode": "GOOGLE_PLUS"
}
}
}
Above format is common . Only data key can hold different types of information like user, product, invoice etc.
I want to keep status, message and data keys same in every rest response. data will be treated according to status and message will be displayed to user.
So basically, above format is desired in all apis. Only information inside data key will be different each time.
And I've setup a following class and set it up as gson converter - MyResponse.java
public class MyResponse<T> implements Serializable{
private boolean status ;
private String message ;
private T data;
public boolean isStatus() {
return status;
}
public void setStatus(boolean status) {
this.status = status;
}
public String getMessage() {
return message;
}
public void setMessage(String message) {
this.message = message;
}
public T getData() {
return data;
}
public void setData(T data) {
this.data = data;
}
}
Deserializer.java
class Deserializer<T> implements JsonDeserializer<T>{
#Override
public T deserialize(JsonElement je, Type type, JsonDeserializationContext jdc) throws JsonParseException{
JsonElement content = je.getAsJsonObject();
// Deserialize it. You use a new instance of Gson to avoid infinite recursion to this deserializer
return new Gson().fromJson(content, type);
}
}
And used it as follows -
GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES);
gsonBuilder.registerTypeAdapter(MyResponse.class, new Deserializer<MyResponse>());
...... ..... ....
restBuilder.setConverter(new GsonConverter(gsonBuilder.create()));
Service interface is as follows -
#POST("/register")
public void test1(#Body MeUser meUser, Callback<MyResponse<MeUser>> apiResponseCallback);
#POST("/other")
public void test2(Callback<MyResponse<Product>> apiResponseCallback);
Problem
I can access status and message fields from inside callback. But information inside data key is not parsed and model like MeUser and Product always returns as empty.
If I change json structure to following above code works perfectly -
{
"status": true,
"message": "Registration Complete.",
"data": {
"username": "user88",
"email": "user#domain.com",
"created_on": "1426171225",
"last_login": null,
"active": "1",
"first_name": "User",
"last_name": "",
"company": null,
"phone": null,
"sign_up_mode": "GOOGLE_PLUS"
}
}
How can I have it worked with specifying separate key inside data object and parse it successfully ?
If I can suggest to change something in json is that you have to add at one new field that defines the type of data, so json should look like below:
{
"status": true,
"message": "Registration Complete.",
"dataType" : "user",
"data": {
"username": "user88",
"email": "user#domain.com",
"created_on": "1426171225",
"last_login": null,
"active": "1",
"first_name": "User",
"last_name": "",
"company": null,
"phone": null,
"sign_up_mode": "GOOGLE_PLUS"
}
}
The MyResponse class has to have new filed DataType so it should look like below:
public class MyResponse<T> implements Serializable{
private boolean status ;
private String message ;
private DataType dataType ;
private T data;
public DataType getDataType() {
return dataType;
}
//... other getters and setters
}
The DataType is an enum which defines type of data. You have to pass Data.class as param in constructor. For all data types you have to create new classes. DataType enum should look like below:
public enum DataType {
#SerializedName("user")
USER(MeUser.class),
#SerializedName("product")
Product(Product.class),
//other types in the same way, the important think is that
//the SerializedName value should be the same as dataType value from json
;
Type type;
DataType(Type type) {
this.type = type;
}
public Type getType(){
return type;
}
}
The desarializator for Json should looks like below:
public class DeserializerJson implements JsonDeserializer<MyResponse> {
#Override
public MyResponse deserialize(JsonElement je, Type type, JsonDeserializationContext jdc)
throws JsonParseException {
JsonObject content = je.getAsJsonObject();
MyResponse message = new Gson().fromJson(je, type);
JsonElement data = content.get("data");
message.setData(new Gson().fromJson(data, message.getDataType().getType()));
return message;
}
}
And when you create RestAdapter, in the line where you register Deserializator, you should use this :
.registerTypeAdapter(MyResponse.class, new DeserializerJson())
Other classes (types of data) you define like standard POJO for Gson in separated classes.
Your issue is because the data attribute is defined as T which you expect to be of types MeUser, Product, etc, but is actually of an object which has inner attribute like user. To resolve this, you need to introduce another level of classes which has the required attributes user, product, invoice etc. This can be easily achieved using static inner classes.
public class MeUser{
private User user;
public static class User{
private String username;
//add other attributes of the User class
}
}
Might be a little bit off-topic, but what happens if the inner object contains a Date property? My TypeAdapter looks like this:
.registerTypeAdapter(Date.class, new DateDeserializer())
.registerTypeAdapter(GenericNotificationResponse.class, new NotificationDeserializer())
.setDateFormat("yyyy-MM-dd'T'HH:mm:ss")
.create();
But due to the parsing which is done by this : message.setData(new Gson().fromJson(data, message.getDataType().getType()));
It will throw an error whenever it will try to deserialize the Date property. Is there a quick fix for this?
EDIT: Marked the answer as accepted, definitely :) it helped me fix my issue. But now there's this problem with the date deserializer.

Gson json getting the result

I have a json string like this:
{
"d": {
"results": [
{
"__metadata": {
"uri": "http://localhost:2000",
"key_fields": "Accountnum",
"rows_affected": 0,
"last_autoinc": 0
},
"Accountnum": "9999999",
"workphone": null,
"name": "Smith",
"address": "33 Main St",
"city": "Anytown",
"state": "FL",
"zip": "33333",
}
]
}
}
and I tried to deserialize it according to diffrent questions here on stackoverflow, but I can't get it right.
Here is what I did I created a class, I only need the accountnum and name.
public class Result {
#SerializedName("Accountnum")
public String accountnumStr;
#SerializedName("name")
public String nameStr;
}
I have a string with the json myresult.
Gson gson = new Gson();
Result result = gson.fromJson(myresult,Result.class);
myName.setText(result.nameStr);
I receive an empty string.
Thanks
Since there is a object holding the result object your trying to create, you have make the result class an inner class. You're Result class would have to look like this:
public class ResultParent {
public class Result {
#SerializedName("Accountnum")
public String accountnumStr;
#SerializedName("name")
public String nameStr;
}
}
If you visualize your JSON in terms of class objects then it will be no problem at all. Imagine that your root object contains a property named "d" of type "D". And type "D" contains a list of "results" of another type "Result". The result contains its properties as above. Here's the picture of it:
class RootObj {
D d;
}
class D {
List<Result> results;
}
class Result {
#SerializedName("Accountnum")
public String accountnumStr;
#SerializedName("name")
public String nameStr;
}
To get the objects from a JSON, you would do the following:
Gson g = new Gson();
RootObj ro = g.fromJson(jsonString, RootObj.class);

Categories