I
I
Ivan Kurnakov2016-03-11 11:36:23
Java
Ivan Kurnakov, 2016-03-11 11:36:23

How to make a class for working with JSON, which can contain objects of different types?

From the server API comes a JSON of the form

{  
    'field1':'<string>',
    'field2':'string','
     list':[{
               'id':'123',
               'uid':'123',
               'date':'<datetime dd.mm.yyyy hh:mi:ss>',
               'msg':{<message в json формате>}},...
             ], ...}

msg attribute formats:
Message 1: {'txt':''}
Message 2: {'txt':'','btns':[{'cap':'','val':''},... ]}
Message 3: {'clst':[{'cap':'','val':''},...]}"
As you can see from the JSON, the problem is that I don't know what type the me data.And how do I interact with the server in such a situation?
What should the class look like to receive a response from the server?
An example of how I get a class for a simpler JSON: www.jsonschema2pojo.org
ps I use the retrofit2 library to communicate with the server.Sorry for crooked JSON formatting.

Answer the question

In order to leave comments, you need to log in

2 answer(s)
D
Denis Zagaevsky, 2016-03-11
@Skinner2170

With retrofit, you are probably using some kind of ConverterFactory to convert the response to an object. For example, GsonConverterFactory (GSON). Consider the situation on his example:
You describe all objects as usual, except for msg. You describe it as the Message interface. Register:

class MessageDeserializer implements JsonDeserializer<Message>{ ... }
...
Gson gson = new GsonBuilder()
                .registerTypeAdapter(Message.class, new MessageDeserializer())
                .create();
GsonConverterFactory.create(gson);

In method
public Message deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { ... }

Deserialize msg based on the data that you have (you need to learn to distinguish between different types of msg). You put data in different Message implementations, for example, for {'txt':''} you make the following implementation:
class MessageTxt implements Message {
    private final String txt;
    public MessageTxt(String txt){
        this.txt = txt;
    }
    String getTxt() { return txt; }
}

The Message interface itself may contain no methods at all (marker interface), or contain methods common to all msg types, or additionally contain a method for returning the type. This is how I would do it, apparently. Different implementations of Message can then simply check instaceof and cast.

J
j7sx, 2016-03-11
@j7sx

Isn't the entire response in json format just a string?
Well, depending on how you process, you already extract the data of the desired format.
I don't know how in java, but in python it looks like this:

import sys
import json

response = json.loads(sys.stdin.read())
field1 = response['field1'] #'строка'
lst = response['list']['id'] # '123' - по сути это тоже строка, ибо числа в python без кавычек
если нужно получить число, то можно явно преобразовать в число 
lst = int(lst)
или так, если не знаешь число или не число:
try:
    lst = int(lst)
except ValueError:
    print "преобразовать не получилось"

I must say that strings, if they are in the form of numbers, say 123 or 1.23, are converted without problems.
And if the json has an embedded json then it can be loaded twice. first you load and get a pointer to the second json, then you load this pointer (loads) again and get it and already work with it the same way as before.

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question