'JSON: use deserializing name different than serializing name json

I have one class User, I received JSON (for User class) from system1 and I should read info , validate then forward to system2, I can't touch these 2 systems, the problem is the names of keys are different, I want to differentiate between deserialized and serialized name received JSON is :

{"userId":"user1","pwd":"123456","country":"US"}

"{"username":"user1","password":"123456","country":"US"}"

But the sent should be like this

I am using Gson lib, and this is my code:

User class:

class User implements Cloneable {

    @SerializedName("username")
    private String username ;
    
    @SerializedName("password")
    private String password ;
    
    @SerializedName("country")
    private String country ;

}

TestJson class

class TestJson {

    private static GsonBuilder gsonBuilder;
    private static Gson gson;

    public static Object fromJson(String json, Class clz) {
        gson = new Gson();
        return gson.fromJson(json, clz);
    }

    public static String toJson(Object obj) {
        gsonBuilder = new GsonBuilder();
        gson = gsonBuilder.create();
        String json = gson.toJson(obj);
        return json;
    }
    
    public static void main(String[] args) {
        
        String json2 = "{\"userId\":\"user1\",\"pwd\":\"123456\",\"country\":\"US\"}";
        User user = (User) TestJson.fromJson(json2, User.class); 
        System.out.println(user.getPassword());
        User u = new User("user1","123456","US");
        String json1 = TestJson.toJson(u);
        System.out.println(json1);
        
    }
}


Solution 1:[1]

If there are alternative names of field just use alternate param of @SerializedName

public class User {

   @SerializedName(value="username", alternate={"userId", "useriD"})
   private String username ;
   ...
}

Solution 2:[2]

You can create custom serializer/deserializer for this purpose.

Serializer:

public class UserSerializer implements JsonSerializer<User> {
    @Override public JsonElement serialize(User obj, Type type, JsonSerializationContext jsonSerializationContext) {
        ..........
    }
}

Deserializer:

public class UserDeserializer implements JsonDeserializer<User> {
    @Override public User deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        ...........
    }
}

and to create Gson instance:

GsonBuilder gsonBuilder = new GsonBuilder();
gsonBuilder.registerTypeAdapter(User.class, new UserSerializer());
gsonBuilder.registerTypeAdapter(User.class, new UserDeserializer());
Gson gson = gsonBuilder.create();

Example

Edit: this is an example of a custom deserializer which might fit into your need. We don't need a custom serializer in this case.

Add this UserDeserializer.java:

public class UserDeserializer implements JsonDeserializer<User> {
    @Override
    public User deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException {
        JsonObject obj = json.getAsJsonObject();
        User user = new User(obj.get("userId").getAsString(), obj.get("pwd").getAsString(), obj.get("country").getAsString());
        return user;
    }
}

Replace your fromJson implementation with this (I use generic to avoid the need for casting when calling fromJson):

public static <T> T fromJson(String json, Class<T> clz) {
    gsonBuilder = new GsonBuilder();
    gsonBuilder.registerTypeAdapter(User.class, new UserDeserializer());
    gson = gsonBuilder.create();
    return gson.fromJson(json, clz);
}

Solution 3:[3]

The only way I can think of would be to have a custom Adapter or deser to a JsonObject and then map it to your User.

With Genson you can create two instances of Genson, one for deserialization and another one for serializaiton. The one used in deserialization could be configured with renamed properties like that.

// you can also precise that you want to rename only the properties from User class
Genson genson = new GensonBuilder()
  .rename("username", "userId")
  .rename("password", "pwd")
  .create();

User user = genson.deserialize(json, User.class);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 PrimosK
Solution 2
Solution 3 eugen