I use fasterxml in 2.6.4 and getting the following JSON by an external service on which I have no influence on the given output:
{
"name": "dunnosName",
"widthValue": 46.1,
"heightValue": 56.1,
"depthValue": 66.1,
"unit": "mm"
}
and want to map it to the following POJOs:
public class Dunno {
private String name;
private ValueWithUnit width;
private ValueWithUnit height;
private ValueWithUnit depth;
}
public class ValueWithUnit {
private Float value;
private String unit;
}
My excepted mapping should look something like this:
name -> Dunno.name
widthValue -> Dunno.width.value
heightValue -> Dunno.height.value
depthValue -> Dunno.depth.value
unit -> Dunno.width.unit
unit -> Dunno.height.unit
unit -> Dunno.depth.unit
Is it possible to realize the expected mapping using fasterxml? And if so which fasterxml annotations or classes do I have to implement to realize this mapping?
You don't need a transitional TempDunno
. You need a Custom Deserializer. This is a textbook example where you would use one. Add the following annotation to Dunno
class:
@JsonDeserialize(using = DunnoDeserializer.class)
and here it is, and with input validation as well:
@SuppressWarnings("serial")
public class DunnoDeserializer extends StdDeserializer<Dunno>
{
public DunnoDeserializer()
{
this(null);
}
public DunnoDeserializer(Class<?> vc)
{
super(vc);
}
@Override
public Dunno deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException
{
Dunno dunno = new Dunno();
// first parse the input into a map, which is more convenient to work with
@SuppressWarnings("unchecked")
Map<String, Object> values = jp.getCodec().readValue(jp, Map.class);
dunno.name = values.containsKey("name") ? values.get("name").toString() : "empty";
String unit = values.containsKey("unit") ? values.get("unit").toString() : "default-units";
if (values.containsKey("widthValue")) {
dunno.width = new ValueWithUnit();
dunno.width.value = ((Number)values.get("widthValue")).floatValue();
dunno.width.unit = unit;
}
if (values.containsKey("heightValue")) {
dunno.height = new ValueWithUnit();
dunno.height.value = ((Number)values.get("heightValue")).floatValue();
dunno.height.unit = unit;
}
if (values.containsKey("depthValue")) {
dunno.depth = new ValueWithUnit();
dunno.depth.value = ((Number)values.get("depthValue")).floatValue();
dunno.depth.unit = unit;
}
System.out.println(values);
values.values().forEach(v -> System.out.println(v.getClass()));
return dunno;
}
}
test method:
public static void main(String[] args)
{
String jsonString = "{ \"name\": \"dunnosName\"," + "\"widthValue\": 46.1," + "\"heightValue\": 56.1,"
+ "\"depthValue\": 66.1," + "\"unit\": \"mm\"}";
ObjectMapper mapper = new ObjectMapper();
try {
Dunno d = (Dunno)mapper.readValue(jsonString, Dunno.class);
System.out.format("%s: %.2f(%s) %.2f(%s) %.2f(%s)",
d.name, d.width.value, d.width.unit, d.height.value, d.height.unit, d.depth.value, d.depth.unit);
} catch (IOException e) {
e.printStackTrace();
}
}
which gives expected output:
dunnosName: 46.10(mm) 56.10(mm) 66.10(mm)