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}}