Reputation: 1309
I want to map some fields of json to inner fields of a class. e.g
{
values:[{
"name":"Abc",
"age":18,
"street":"test",
"postalcoad":"1231412"
},
{
"name":"ccvb",
"age":20,
"street":"test2",
"postalcoad":"123"
}
]}
Following i my java class
@JsonIgnoreProperties(ignoreUnknown = true)
public class Customer{
@JsonProperty("name")
private string name;
@JsonProperty("age")
private int age;
private Address address;
}
@JsonIgnoreProperties(ignoreUnknown = true)
public class Address{
@JsonProperty("street")
private string street;
@JsonProperty("postalcode")
private string postalcode;
}
ObjectMapper mapper = new ObjectMapper();
Customer[] c = mapper.readValue(mapper.readTree(json).get("values").toString(), Customer[].class);
It returns me Customer object without Address. Any idea how can i create Address object from this json.
Upvotes: 3
Views: 5365
Reputation: 961
I would create a custom deserializer and inside of it call the default deserializer for Customer and then call the default deseriazlier for Address. Then you add the address to the customer object. This way they both look at the same json but you get two different objects out and you can connect them the way you want.
To call a standard deserializer from a custom deseriazlier see this answer: How do I call the default deserializer from a custom deserializer in Jackson.
Upvotes: 1
Reputation: 3082
One of the options is to use @JsonCreator
annotation:
@JsonCreator
public Customer(
@JsonProperty("name") String name,
@JsonProperty("age") int age,
@JsonProperty("street") String street,
@JsonProperty("postalcode") String postalcode
) {
this.name = name;
this.age = age;
this.address = new Address();
this.address.street = street;
this.address.postalcode = postalcode;
}
Second option is create custom deserializer and bind your class with deserializer using @JsonDeserialize
annotation
@JsonDeserialize(using = CustomerDeserializer.class)
public static class Customer{
....
}
public class CustomerDeserializer extends StdDeserializer<Customer> {
public CustomerDeserializer() {
super(Customer.class);
}
@Override
public Customer deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
Customer customer = new Customer();
JsonNode treeNode = p.readValueAsTree();
if (treeNode == null) {
return null;
}
customer.setName(treeNode.get("name").asText());
customer.setAge(treeNode.get("age").asInt());
Address address = new Address();
address.setStreet(treeNode.get("street").asText());
address.setPostalcode(treeNode.get("postalcode").asText());
customer.setAddress(address);
return customer;
}
}
As third option, you can use @JsonAnySetter
with some kind of post construct processing:
public interface PostConstruct {
void postConstruct();
}
public class Customer implements PostConstruct {
//mapping
private Map<String, Object> additionalFields = new HashMap<>();
@JsonAnySetter
public void setAdditionalValue(String key, Object value) {
additionalFields.put(key, value);
}
@Override
public void postConstruct() {
address = new Address();
address.setStreet(String.valueOf(additionalFields.get("street")));
address.setPostalcode(String.valueOf(additionalFields.get("postalcode")));
}
}
public static class PostConstructDeserializer extends DelegatingDeserializer {
private final JsonDeserializer<?> deserializer;
public PostConstructDeserializer(JsonDeserializer<?> deserializer) {
super(deserializer);
this.deserializer = deserializer;
}
@Override
protected JsonDeserializer<?> newDelegatingInstance(JsonDeserializer<?> newDelegatee) {
return deserializer;
}
@Override
public Object deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
Object result = _delegatee.deserialize(jp, ctxt);
if (result instanceof PostConstruct) {
((PostConstruct) result).postConstruct();
}
return result;
}
}
//using of post construct deserializer
ObjectMapper mapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.setDeserializerModifier(new BeanDeserializerModifier() {
@Override
public JsonDeserializer<?> modifyDeserializer(DeserializationConfig config,
BeanDescription beanDesc,
final JsonDeserializer<?> deserializer) {
return new PostConstructDeserializer(deserializer);
}
});
mapper.registerModule(module);
Upvotes: 4