Reputation: 4501
I have this class:
class Address {
int id;
String address;
// ... other fields
}
I have many other classes that embed Address
, one example:
class Person {
int id;
String name;
Address address;
// ... other fields
}
I receive a json representing a person such as:
{
"id": 10,
"name": "John",
"addressId": 50,
// ... other fields
}
I can deserialize the above into
class PersonJson {
int id;
String name;
int addressId;
// ... other fields
}
and then convert PersonJson
into Person
.
However, this can happen deeper in the hierarchy. I have Organization
that has a List<Person>
, so I'd need to have OrganizationJson
and List<PersonJson>
that I then need to convert to Organization
and List<Person>
.
Alternatively, I can make a custom deserializer for Person
, but since Address
is embedded in many other objects I'd have to make a deserializer for each of these. I don't think I can reuse much of this and most other fields would be deserialized by default (i.e. primitives, etc.) by ObjectMapper
.
Both are doable, but both are a duplication of the work ObjectMapper
already does and require maintenance in multiple places, which is a pain. Is there a way to configure ObjectMapper
to custom-deserialize a field (including within a collection such as List<Address>
) or some other way to avoid duplication?
Upvotes: 0
Views: 89
Reputation: 100
The first atempt that occour me is to combine the @JsonProperty with @JsonCreator annotations to instruct de object mapper to address (no pun intended) the deserialize to the correct nested object.
For sake of simplicity, and knowing your immutablility by you comment, there is an example below using lombok.
import java.io.IOException;
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.core.JsonParseException;
import com.fasterxml.jackson.databind.JsonMappingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonPOJOBuilder;
import lombok.Builder;
import lombok.Data;
import lombok.Getter;
import lombok.NonNull;
import lombok.ToString;
public class JsonTest {
@Data
@Builder(toBuilder = true)
@ToString
@Getter
static class Address {
int id;
@NonNull
String address;
@JsonCreator
public static Address factory(int id) {
return new AddressBuilder().id(id).address("getAddressLogicHere").build();
}
}
@Data
@JsonDeserialize(builder = Person.PersonBuilder.class)
@Builder(toBuilder = true)
@ToString
@Getter
static class Person {
private final int id;
@NonNull
private final String name;
@JsonProperty("addressId")
private final Address address;
@JsonPOJOBuilder(withPrefix = "")
public static class PersonBuilder {
}
}
public static void main(String[] args) throws JsonParseException, JsonMappingException, IOException {
String json = "{\n" +
" \"id\": 10,\n" +
" \"name\": \"John\",\n" +
" \"addressId\": 50\n" +
"}";
Person person = new ObjectMapper().readValue(json, Person.class);
System.out.println(person);
//JsonTest.Person(id=10, name=John, address=JsonTest.Address(id=50, address=getAddressLogicHere))
}
}
Upvotes: 1