2

I have a question on how to perform this kind of deserialization with retrofit.

I have a complicated Json to parse :

{
  "key":"value",
  "rows" : [
    {  //type 1 object
      "type" : "the_type_1",
      "self" :{
          //type 1 subobject
      }
    },
    {  //type 2 object
      "type" : "the_type_2",
      "self" : {
          //type 2 subobject
      }
    },
    { //type 3 object
      "type" : "the_type_3",
      "self" : {  //type 2 object with different key
        "type" : "the_type_2",
         "target":{
            //type 2 subobject
         }
      }
    }
  ]
}

Each of my rows can have very different content shemes, I have simplified it, but you can see that I have nested objects that have some key changed in function of how deep it is in the json.

So my first solution was to build enormous Gson models that contain each keys of each possibility, and test later the "type" kinds of fields to know what to access. But It's pretty unmaintainable, and so not elegant.

I suppose I could do something with Gson Stream mode and a custom retrofit converter, but I don't know exactly where to start nor if it's the right approach.

what would you do ?

also, the title of my post is bad as I didn't come up with better, please make suggestions.

Thanks,

Renaud Favier
  • 1,645
  • 1
  • 17
  • 33

1 Answers1

0

Updated

make this class

public class Target {

}

make this Self.java

import com.google.gson.annotations.SerializedName;

public class Self {

    @SerializedName("type")
    private String type;

    @SerializedName("target")
    private Target target;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Target getTarget() {
        return target;
    }

    public void setTarget(Target target) {
        this.target = target;
    }
}

make a Row.java

import com.google.gson.annotations.SerializedName;

public class Row {

    @SerializedName("type")
    private String type;

    @SerializedName("self")
    private Self self;

    public String getType() {
        return type;
    }

    public void setType(String type) {
        this.type = type;
    }

    public Self getSelf() {
        return self;
    }

    public void setSelf(Self self) {
        this.self = self;
    }
}

this is Respones.java which will be serialized using gson

import java.util.ArrayList;

import com.google.gson.annotations.SerializedName;

public class Respones {

    @SerializedName("key")
    private String key;

    @SerializedName("rows")
    private ArrayList<Row> rows;

    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public ArrayList<Row> getRows() {
        return rows;
    }

    public void setRows(ArrayList<Row> rows) {
        this.rows = rows;
    }
}

following is the test code to check if the classes are working,

you can use above model classes in your code but following code is strictly made to match your data by no means that is a standard way of generating JSON data, it is up to you how do you want to populate your object

import java.util.ArrayList;

import com.google.gson.Gson;

public class TestDrive {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Respones respones = new Respones();
        respones.setKey("value");
        ArrayList<Row> rows = new ArrayList<>();
        Row one = new Row();
        one.setType("the_type_1");
        one.setSelf(new Self());

        Row two = new Row();
        two.setType("the_type_2");
        two.setSelf(new Self());

        Row three = new Row();
        three.setType("the_type_3");
        Self self = new Self();
        self.setTarget(new Target());
        self.setType("the_type_2");
        three.setSelf(self);
        rows.add(one);
        rows.add(two);
        rows.add(three);
        respones.setRows(rows);

    /**
     * This code will convert your ArrayList object to a equivalent JSON
     * String
     */
    String result = (new Gson()).toJson(respones);
    System.out.println(""+result);


    /**
     * This code will convert your JSON String to a equivalent Response
     * Object
     */
    Respones respones2 = (new Gson()).fromJson(result, Respones.class);
    System.out.println(""+respones2.getKey());
    System.out.println(""+respones2.getRows().get(0).getType());
    System.out.println(""+respones2.getRows().get(2).getSelf().getType());
    }
}

output

{
  "key": "value",
  "rows": [
    {
      "type": "the_type_1",
      "self": {

      }
    },
    {
      "type": "the_type_2",
      "self": {

      }
    },
    {
      "type": "the_type_3",
      "self": {
        "type": "the_type_2",
        "target": {

        }
      }
    }
  ]
}

value
the_type_1
the_type_2
Pankaj Nimgade
  • 4,529
  • 3
  • 20
  • 30
  • Hi, thank you for taking the time to answer me this precisly. I can't do that with Retrofit, I don't have access to the raw json. Please also note that I'm tring to create pojo from json not the other way around. – Renaud Favier Nov 23 '15 at 12:31
  • @RenaudFavier, hmm I understand, with above code which i posted actually needs programmer to know the structure of the **JSON** where key's will be represented by the properties in the Java class, I do not know how does Pojo works but would like to know as see many people are using it, Actually this code can be used to read the following **JSON** posted by you which will populate your object , I will update the answer so you can see it – Pankaj Nimgade Nov 23 '15 at 17:41
  • @RenaudFavier, I checked What **POJO** is and what I can say is you are better off with the code I have presented. But if you want to have **POJO** you can make all instance variables of the class public remove getters and setters as you wont need them and remove annotations and you will get **POJO** what you want out of the classes which I wrote. – Pankaj Nimgade Nov 23 '15 at 19:11
  • Hi, by POJO i just meant Java objects. I have already done a custom parser, It works ok (i use gson stream mode), the problem is the integration with retrofit. And your code is doing the opposit of what I want (from json to java objects) – Renaud Favier Nov 24 '15 at 09:36
  • @RenaudFavier, do you mean you want something like Java object to **JSON** – Pankaj Nimgade Nov 24 '15 at 09:56
  • no the other way around, from json to java object (and with retrofit, I don't have access to raw json) – Renaud Favier Nov 24 '15 at 10:20
  • @RenaudFavier, wish i could you, http://stackoverflow.com/questions/21815008/using-retrofit-to-access-json-arrays, this link talks about retrofit, i hope you find it useful – Pankaj Nimgade Nov 24 '15 at 10:44