Java GSON Custom Deserializer versioning support

和自甴很熟 提交于 2019-12-11 09:53:39

问题


I created a custom deserializer for my Person class. This is just for demonstration purpose. My actual class is more complicated.

The json file contains the version of the format and after that an array of persons.

On version 1.0 i have a name and age for every person.
On version 2.0 i have a name, age and additionally the gender.

My problem here is that i do not have access to the version in the custom deserializer, or at least didn't figure out how to get it yet.

Is there any other way to do this without jsonObj.get("gender").has();
or if (jsonObj.get("gender") != null)?

GSON Version: 2.8.5

Deserializer:

private class PersonDeserializer implements JsonDeserializer<PersonDatapoint>
{
    @Override
    public PersonDatapoint deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException
    {
        JsonObject jsonObj = json.getAsJsonObject();

        // version 1.0
        Person person = new Person(jsonObj.get("name").getAsString());
        person.setAge(jsonObj.get("age").getAsInt());

        // version 2.0
        // how to determine version field in json File?
        // person.setGender(jsonObj.get("gender").getAsString());

        return person;
    }
}

JSON File v1.0:

{
    "version": "1.0",

    "persons": [
    {
      "name": "Alex",
      "age": 30
    },
    {
      "name": "John",
      "age": 31
    },
    {
      "name": "Elise",
      "age": 32
    }]  
}

JSON File v2.0:

{
  "version": "2.0",

  "persons": [
  {
    "name": "Alex",
    "age": 30,
    "gender": "male"
  },
  {
    "name": "John",
    "age": 31,
    "gender": "male" 
  },
  {
    "name": "Elise",
    "age": 32,
    "gender": "female"
  }]   
}

回答1:


To have access to version field do not make JsonDeserializer for person but for the whole JSON you have. So let us assume your JSON is some kind of a response that could be presented with a Java class like:

@Getter @Setter
public class Response {
    private Double version;
    private Person[] persons; // versioned stuff
}

Your class Person might be like:

@Getter @Setter
public class Person {
    @Since(1.0) // these annotations are put just for demonstrative purpose but are 
                // actually also functional, see deserializer
    private String name;
    @Since(1.0)
    private Integer age;
    @Since(2.0)
    private String gender;
}

Note: This Person is a bit bad example class since it could easily be deserialized without any custom deserializer from v1.0 or v2.0 JSON. Deserializng from v1.0 would just leave gender null. Anyway your custom deserializer - making use of JSON field version - might then look like:

public class ResponseDeserializer implements JsonDeserializer<Response> {
    @Override
    public Response deserialize(JsonElement json, Type typeOfT,
                                    JsonDeserializationContext context)
            throws JsonParseException {
        // This is how to get the version
        Double version = json.getAsJsonObject().get("version").getAsDouble();
        // and below is jsut an example what you could do with version
        Gson gson = new GsonBuilder()
                .setVersion(version) // this is where @Since might be handy
                .setPrettyPrinting()
                .create();
        return gson.fromJson(json, Response.class);
    }
}



回答2:


Put simple if condition to check the value is null or not

if (jsonObj.get("gender") != null) {
    person.setGender(jsonObj.get("gender").getAsString());
}


来源:https://stackoverflow.com/questions/54012489/java-gson-custom-deserializer-versioning-support

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!