When serializing a Java object which has other object references, I need to serialize only one attribute of the nested object(usual case of foreign key, so serialize the "id" attribute of the object reference). Ingore everything else.
For example, I have two classes which I need to serialize to JSON & XML(removed JPA annotations for clarity):
Relationship: User ->(one-to-many) AddressInformation; Also: AddressInformation ->(one-to-one) User
@XmlRootElement
public class User {
private String id;
private String firstName;
private String lastName;
private String email;
private AddressInformation defaultAddress;
private Set<AddressInformation> addressInformation;
public User() {
}
@JsonProperty(value = "id")
@XmlAttribute(name = "id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@JsonProperty(value = "firstname")
@XmlAttribute(name = "firstname")
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
@JsonProperty(value = "lastname")
@XmlAttribute(name = "lastname")
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@JsonProperty(value = "email")
@XmlAttribute(name = "email")
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
@JsonIgnore
public Set<AddressInformation> getAddressInformation() {
return addressInformation;
}
public void setAddressInformation(Set<AddressInformation> addressInformation) {
this.addressInformation = addressInformation;
}
@JsonProperty(value = "defaultaddress")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public AddressInformation getDefaultAddress() {
return defaultAddress;
}
public void setDefaultAddress(AddressInformation defaultAddress) {
this.defaultAddress = defaultAddress;
}
}
AddressInformation:
@XmlRootElement
public class AddressInformation {
private String id;
private String address;
private String details;
private User user;
@JsonProperty(value = "id")
@XmlAttribute(name = "id")
public String getId() {
return id;
}
public void setId(String id) {
this.id = id;
}
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
public User getUser() {
return user;
}
public void setUser(User user) {
this.user = user;
}
@JsonProperty(value = "details")
@XmlAttribute(name = "details")
public String getDetails() {
return details;
}
public void setDetails(String details) {
this.details = details;
}
@JsonProperty(value = "address")
@XmlAttribute(name = "address")
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
public AddressInformation() {
super();
}
}
enter code here
When serializing User for example, I need:
{
"id" : "idofuser01",
"email" : "[email protected]",
"status" : "OK",
"firstname" : "Filan",
"lastname" : "Ovni",
"defaultaddressid" : "idofaddress01",
}
enter code here
When serializing AddressInformation:
{
"id" : "idofaddress01",
"address" : "R.8. adn",
"details" : "blah blah",
"userid" : "idofuser01",
}
I have tried @JsonManageReference
& @JsonBackReference
with no success. As you can see I also tried @JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
Just Found a way using Jackson 2.1+ .
Annotate object references with(this will pick only the id
attribute of AddressInformation
):
@JsonProperty(value = "defaultaddressid")
@JsonIdentityInfo(generator = ObjectIdGenerators.PropertyGenerator.class, property = "id")
@JsonIdentityReference(alwaysAsId = true)
public AddressInformation getDefaultAddress() {
return defaultAddress;
}
Serialization works very well.
You can implement custom deserializer for this class and use it in User
class. Example implementation:
class AddressInformationIdJsonSerializer extends JsonSerializer<AddressInformation> {
@Override
public void serialize(AddressInformation value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeString(value.getId());
}
}
And configuration in User
class:
@JsonProperty(value = "defaultaddress")
@JsonSerialize(using = AddressInformationIdJsonSerializer.class)
public AddressInformation getDefaultAddress() {
return defaultAddress;
}
### Generic solution for all classes which implement one interface ###
You can create interface which contains String getId()
method:
interface Identifiable {
String getId();
}
Serializer for this interface could look like that:
class IdentifiableJsonSerializer extends JsonSerializer<Identifiable> {
@Override
public void serialize(Identifiable value, JsonGenerator jgen, SerializerProvider provider) throws IOException, JsonProcessingException {
jgen.writeString(value.getId());
}
}
And now, you can use this serializer for all Identifiable
implementations. For example:
@JsonProperty(value = "defaultaddress")
@JsonSerialize(using = IdentifiableJsonSerializer.class)
public AddressInformation getDefaultAddress() {
return defaultAddress;
}
of course: AddressInformation
have to implement this interface:
class AddressInformation implements Identifiable {
....
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With