I had a similar problem and solved it with a specialized serializer / deserializer
This is how I handle it (please adapt it to your own code):
Childseerializer
public class ChildSerializer extends StdSerializer<Child> { private static final long serialVersionUID = -265706839304575646L; public ChildSerializer(Class<Child> t) { super(t); } public ChildSerializer() { this(null); } @Override public void serialize(Child child, JsonGenerator jg, SerializerProvider sp) throws IOException, JsonGenerationException { jg.writeStartObject(); jg.writeStringField("name", child.getName()); jg.writeStringField("surname", child.getSurname()); Parent parent = child.getParent(); jg.writeObjectFieldStart("parent"); jg.writeStringField("name", parent.getName()); jg.writeStringField("surname", parent.getSurname()); jg.writeEndObject(); } }
Child
@JsonSerialize(using = ChildSerializer.class) public class Child implements Serializable { private static final long serialVersionUID = 7902561110976676934L; private String name; private String surname; private Parent parent; public Child(String name, String surname, Parent parent) { this(name, surname); this.parent = parent; } public Child(String name, String surname) { this(); this.name = name; this.surname = surname; } public Child() { super(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSurname() { return surname; } public void setSurname(String surname) { this.surname = surname; } public Parent getParent() { return parent; } public void setParent(Parent parent) { this.parent = parent; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((parent == null) ? 0 : parent.hashCode()); result = prime * result + ((surname == null) ? 0 : surname.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Child other = (Child) obj; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (parent == null) { if (other.parent != null) return false; } else if (!parent.equals(other.parent)) return false; if (surname == null) { if (other.surname != null) return false; } else if (!surname.equals(other.surname)) return false; return true; } }
Parent
public class Parent implements Serializable { private static final long serialVersionUID = -5604725691780073247L; private String name; private String surname; private List<Child> childs; public Parent(String name, String surname) { this(); this.name = name; this.surname = surname; } public Parent(String name, String surname, List<Child> childs) { this(name, surname); this.childs = childs; } public Parent() { super(); childs = new ArrayList<Child>(); } public String getName() { return name; } public void setName(String name) { this.name = name; } public String getSurname() { return surname; } public void setSurname(String surname) { this.surname = surname; } public void addChild( Child child ) { if( !childs.contains(child) ) { child.setParent(this); childs.add(child); } } public List<Child> getChilds() { return childs; } public void setChilds(List<Child> childs) { this.childs = childs; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + ((childs == null) ? 0 : childs.hashCode()); result = prime * result + ((name == null) ? 0 : name.hashCode()); result = prime * result + ((surname == null) ? 0 : surname.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Parent other = (Parent) obj; if (childs == null) { if (other.childs != null) return false; } else if (!childs.equals(other.childs)) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; if (surname == null) { if (other.surname != null) return false; } else if (!surname.equals(other.surname)) return false; return true; } }
My testing method:
@Test public void testJson() { try { Parent p = new Parent(UUID.randomUUID().toString(), UUID.randomUUID().toString()); for (int i = 0; i < 10; i++) { p.addChild(new Child(UUID.randomUUID().toString(), UUID.randomUUID().toString())); } ObjectMapper om = new ObjectMapper(); String childJson = om.writeValueAsString(p.getChilds().get(0)); System.out.println(childJson); } catch (Exception e) { e.printStackTrace(); } }
Final result:
{"name":"b86eab86-9858-4536-9c5c-d44d22810fc1","surname":"9a6249f0-58df-44e5-a1b9-31fbad6e9f49","parent":{"name":"74b0cd97-64a1-4547-ab22-4e4eedd0759b","surname":"a33c79f3-6f26-478b-9e24-7df96b3b1f68"}}
A sad annotation is important, but does not always allow you to get what you need, and therefore you need to do it "on your own"
I hope this can be useful