eoinzy
eoinzy

Reputation: 2242

Use GSON to map changing field name to POJO

I am writing an Android app, and using RetroFit to communicate with the REST API. I have all the classes/POJO's written, except one.

Here is the Java for the specific class. This is the parent class, which is the root of the problem. I need to be able to map the userNameResponse variable to the users name in the JSON below

public class DiTopicStats {

    private UserNameResponse userNameResponse;

    public UserNameResponse getUserNameResponse() {
        return userNameResponse;
    }

    public void setUserNameResponse(UserNameResponse userNameResponse) {
        this.userNameResponse = userNameResponse;
    }
}

and the child class, which should be fine as long as I can map to it from the above parent class:

public class UserNameResponse {

    //Fields
    //Getters and Setters
}

The JSON that is returned contains a field which changes per response. The field is the users name. For example:

{
    "sMessage": "",
    "diStatus": {
        "diTopicWrongAns": {
            //Some fields
        },
        "diOverallStats": {
            //Some more fields
        },
        "diUserStats": {
            "John Smith": { //PROBLEM: This name changes
                //some other fields
            }
        }
    }
}

So in this case, the name "John Smith" has a dynamic field name. Realistically, it could be any string with letters, numbers, a - or a . in it.

My question is, using RetroFit, how can I create a Java class that lets RetroFit map a field to a variable?

I'm aware you can specify a SerialisedName but can this be done programatically at runtime, because I will have the name or the user at this stage.

Thanks.

Upvotes: 2

Views: 1249

Answers (1)

John Fontaine
John Fontaine

Reputation: 1019

Create a pojo called DiUserStats and then define a custom GsonTypeAdapter e.g.

public class DiUserStatsTypeAdapter implements JsonDeserializer<DiUserStats>, JsonSerializer<DiUserStats> {

    @Override
    public DiUserStats deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        DiUserStats target = new DiUserStats();
        JsonObject jsonObject = json.getAsJsonObject();
        Map.Entry<String,JsonElement> object =(Map.Entry<String,JsonElement>)jsonObject.entrySet().toArray()[0];
        target.setName(object.getKey());
        JsonObject targetValues = object.getValue().getAsJsonObject();
        /*parse values to your DiUserStats as documented using targetValues.get("fooProperty").getAsString(), etc */
        return target;
    }

    @Override
    public JsonElement serialize(DiUserStats src, Type typeOfSrc, JsonSerializationContext context) {
        JsonObject obj = new JsonObject();
        JsonObject values = new JsonObject();
        values.addProperty("foo", src.getFoo);
        obj.addProperty(target.getName(), values);
        return obj;
    }

} 

Then when you setup Gson use a builder and add your custom type adapter e.g.

Gson gson = new GsonBuilder().registerTypeAdapter(DiUserStats.class, new DiUserStatsTypeAdapter()).create();

Upvotes: 2

Related Questions