Reputation: 107
I have a JSON response that I try to parse with Jackson, and type of one of fields is unknown.
Exapmle:
{"name" : "Catalina"}
OR
{"name" : {"First" : "Catalina", "Last" : "Kyle"}}
How I can deserialize that object into POJO:
class NamesHolder {
public String singleName;
public Map<String, String> nameMap;
}
This is synthetic example but I hope it clear for understanding.
In first case I want to have object with singleName == "Catalina" and nameMap == null, and vice versa in other case.
UPDATE
I am really sorry, at the end of day I misspelled the property name. In both cases they are the same: name.
Upvotes: 1
Views: 2631
Reputation: 38655
The easiest way is to rename your POJO
properties to the same which you have in JSON
. See below example:
class NamesHolder {
public String name;
public Map<String, String> names;
@Override
public String toString() {
return "NamesHolder{" +
"name='" + name + '\'' +
", names=" + names +
'}';
}
}
If you do not want to rename properties you can use @JsonProperty
annotation. See below example:
class NamesHolder {
@JsonProperty("name")
public String singleName;
@JsonProperty("names")
public Map<String, String> nameMap;
@Override
public String toString() {
return "NamesHolder{" +
"name='" + singleName + '\'' +
", names=" + nameMap +
'}';
}
}
Two above classes work for your JSON
examples. See below program:
ObjectMapper mapper = new ObjectMapper();
System.out.println(mapper.readValue("{\"names\" : {\"First\" : \"Catalina\", \"Last\" : \"Kyle\"}}", NamesHolder.class));
System.out.println(mapper.readValue("{\"name\" : \"Catalina\"}", NamesHolder.class));
which prints:
NamesHolder{name='null', names={First=Catalina, Last=Kyle}}
NamesHolder{name='Catalina', names=null}
EDIT 1
In this case you have to handle it manually using Object
type. See below example:
public class JacksonTest {
public static void main(String[] args) throws Exception {
String json = "{\"name\" : \"Catalina\"}";
ObjectMapper deserializerMapper = new ObjectMapper();
NamesHolder namesHolder = deserializerMapper.readValue(json, NamesHolder.class);
System.out.println(toString(namesHolder));
json = "{\"name\" : {\"First\" : \"Catalina\", \"Last\" : \"Kyle\"}}";
namesHolder = deserializerMapper.readValue(json, NamesHolder.class);
System.out.println(toString(namesHolder));
}
private static String toString(NamesHolder namesHolder) {
if (namesHolder.hasStringName()) {
return "Type: String, Value: " + namesHolder.getStringName();
} else if (namesHolder.hasMapNames()) {
return "Type: Map, Value: " + namesHolder.getMapNames();
}
return "Type: Unknown, Value: " + namesHolder;
}
}
class NamesHolder {
public Object name;
public boolean hasStringName() {
return name instanceof String;
}
public String getStringName() {
return name.toString();
}
public boolean hasMapNames() {
return name instanceof Map;
}
public Map<String, String> getMapNames() {
return (Map<String, String>) name;
}
@Override
public String toString() {
return String.valueOf(name);
}
}
Above example prints:
Type: String, Value: Catalina
Type: Map, Value: {First=Catalina, Last=Kyle}
Upvotes: 0
Reputation: 15799
Try making your name field an object:
class MyPojo {
public Object name;
}
The you'll have to check at runtime to see if it deserialized as a String or as a Map.
Upvotes: 2