greywolf82
greywolf82

Reputation: 22173

Gson nested objects

I'm using a library with a class to map a json message and I'm using Gson to serialized the classes over json. The message contains a data field. The field is generic and it contains anything. The class provided by the library is:

public class Api {
....
@SerializedName("data")
Map<String, JsonElement> data;
....
}

Now I'd like to extend the class but I have my own root object to map the data sub field, so to do a summary the json is something like:

{...., "data": {"myownroot":"aaaa"}}

How can I do? I could create my own classes of course but I would prefer to extend the library if possible. If I extend the class I would have:

public class MyOwnRoot extends Api {
@SerializedName("myownroot")
public String root;
}

but in this case when I serialize it doesn't work because myownroot must be a child of data but how can I say to Gson "put MyOwnRoot in the data map"??

Upvotes: 0

Views: 357

Answers (1)

minus
minus

Reputation: 2786

I can't really understand why you would need to extend the Api class. I guess the class name is a bit of a misnomer, since API are (generally speaking) interfaces, and they get implemented.

I guess you could do this by using getters to your advantages, while letting Gson do its work on fields.

EDIT: To serialize also

public class Api {
    @SerializedName("data")
    protected Map<String, JsonElement> data;
}

public class RootEntity extends Api {
    transient StructuredRootImpl _cached;
    transient Gson _gson = new Gson();

    public class StructuredRootImpl {
        Integer v;
        String name;
    }

    public Integer getV() {
        synch();
        return _cached.v;
    }

    public void setV(Integer v) {
        _cached.v=v;
        synch();
    }

    private void synch() {
        if(_cached==null){
            if(data==null){
                data = new LinkedHashMap<>();
            }
            JsonElement jsonElement = data.get("myroot");
            _cached = _gson.fromJson(jsonElement, StructuredRootImpl.class);
        }
        JsonElement jsonTree = _gson.toJsonTree(_cached);
        data.put("myroot", jsonTree);
    }

    public String getName() {
        synch();
        return _cached.name;
    }

    public void setName(String name) {
        _cached.name = name;
        synch();
    }

    @Override
    public String toString() {
        return "RootEntity [v=" + getV() + ", n=" + getName() + "]";
    }

}

Running the main you can both serialize and deserialize your entity.

public class TestGson {

    public static void main(String[] args) {
        String jsonText = "{data:{\"myroot\":{\"v\":123,\"name\":\"mario\"}}}";
        Gson gson = new Gson();
        RootEntity entity = gson.fromJson(jsonText, RootEntity.class);
        System.out.println(entity);
        entity.setName("Alex");
        entity.setV(150);
        String thenBack = gson.toJson(entity);
        System.out.println(thenBack);

    }
}

This will result in :

so.alpha.TestGson$Foo@4b85612c
StructuredRoot [v=123, name=mario]

Still I don't understand why you would extend the Api class.

Upvotes: 1

Related Questions