Home > Back-end >  Is there a way to deserialize a member object in Java based on the type of JSON String passed in Jac
Is there a way to deserialize a member object in Java based on the type of JSON String passed in Jac

Time:06-25

I have a Java class as follows,

public class User {
    Integer id;
    UserDetails details;
}

The class user details is as follows,

public class UserDetails {
    String name;
    Integer age;
}

The json String can be defined in both of the following ways,

String jsonString1 = "{\"id\" : 100,\"details\" : {\"name\" : \"ABC\", \"age\": 25}}";

//Here the details object is passed as a string instead as a JSON object in JSON string
String jsonString2 = "{\"id\" : 100,\"details\" : \"{\\\"name\\\" : \\\"ABC\\\", \\\"age\\\": 25}\"}"

I need ObjectMapper.readValue to work on both the strings, i.e.

ObjectMapper mapper = new ObjectMapper();
User user1 = mapper.readValue(jsonString1, User.class);
User user2 = mapper.readValue(jsonString2, User.class);

Is there a way to achieve this in Jackson? Through introducing annotations on UserDetails member and defining some custom Deserializer?

CodePudding user response:

have you tried gson library?

new Gson().fromJson(jsonString1 , MyJSON.class);

CodePudding user response:

This works, but i'm not sure if creating a new ObjectMapper is the most performant solution.

Custom deserializer:

public class UserDetailsSerializer extends JsonDeserializer<UserDetails> {

    @Override
    public UserDetails deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
        JsonNode node = jsonParser.readValueAsTree();
        JsonNodeType nodeType = node.getNodeType();
        if (nodeType == JsonNodeType.OBJECT) {
            return new ObjectMapper().treeToValue(node, UserDetails.class);
        } else if (nodeType == JsonNodeType.STRING) {
            return new ObjectMapper().readValue(node.asText(), UserDetails.class);
        }
        throw new IllegalArgumentException("Invalid node type: "   nodeType);
    }
}

User class:

    @JsonDeserialize(using = UserDetailsSerializer.class)
    public UserDetails details;

Given your example two JSON strings:

        ObjectMapper mapper = new ObjectMapper();
        User user1 = mapper.readValue(jsonString1, User.class);
        User user2 = mapper.readValue(jsonString2, User.class);
        
        System.out.println(user1);
        System.out.println(user2);

Output (i have added toStrings on both objects to print the fields)

User{id=100, details=UserDetails{name='ABC', age=25}}
User{id=100, details=UserDetails{name='ABC', age=25}}
  • Related