Reputation: 2224
JSON
{
"schools": [
{
"id": 1,
"name": "School A"
},
{
"id": 2,
"name": "School B"
}
],
"students": [
{
"id": 1,
"name": "Bobby",
"school": 1
}
]
}
How would I map the JSON into the following classes such that Bobby's school is mapped to the already instantiated School A.
public class School {
private Integer id;
private String name;
}
public class Student {
private Integer id;
private String name;
private School school;
}
I've tried some weird stuff with the Student class...
public class Student {
private Integer id;
private String name;
private School school;
@JsonProperty("school")
public void setSchool(Integer sid) {
for (School school : getSchools()) {
if (school.id == sid) {
this.school = school;
break;
}
}
}
}
The problem I'm having is that both the schools and the students are being parsed from the JSON at the same time, so I'm not sure how to get a list of the schools. Maybe I should parse these separately so I have the list of schools first?
Upvotes: 14
Views: 6336
Reputation: 8510
With classes defined as below:
@JsonIdentityInfo(property = "id", generator = ObjectIdGenerators.PropertyGenerator.class)
class School {
public Integer id;
public String name;
}
class Student {
public Integer id;
public String name;
@JsonIdentityReference(alwaysAsId = true)
public School school;
}
class All {
public List<School> schools;
public List<Student> students;
}
This works exactly as You intended:
@Test
public void test() throws JsonProcessingException {
var json = "{" +
"\"schools\":[" +
"{\"id\":1,\"name\":\"School A\"}," +
"{\"id\":2,\"name\":\"School B\"}" +
"]," +
"\"students\":[" +
"{\"id\":1,\"name\":\"Bobby\",\"school\":1}" +
"]" +
"}";
var mapper = new ObjectMapper();
var all = mapper.readValue(json, All.class);
Assertions.assertThat(all.students.get(0).school).isSameAs(all.schools.get(0));
}
Upvotes: 3
Reputation: 7286
Jackson will do it for you. Just annotate your objects with @JsonIdentityInfo
:
@JsonIdentityInfo(scope=School.class, generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class School {
private Integer id;
private String name;
public School() {
}
public School(Integer id, String name) {
this.id = id;
this.name = name;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@JsonIdentityInfo(scope=Student.class, generator=ObjectIdGenerators.PropertyGenerator.class, property="id")
public class Student {
private Integer id;
private String name;
private School school;
public Student() {
}
public Student(Integer id, String name, School school) {
this.id = id;
this.name = name;
this.school = school;
}
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public School getSchool() {
return school;
}
public void setSchool(School school) {
this.school = school;
}
}
public static void main(String[] args) throws IOException {
School school = new School(1, "St Magdalene's");
Student mary = new Student(1, "Mary", school);
Student bob = new Student(2, "Bob", school);
Student[] students = new Student[] {mary, bob};
// Write out
String serialized = mapper.writeValueAsString(students);
System.out.println("Serialized: " + serialized);
// Read in
Student[] deserialized = mapper.readValue(serialized, Student[].class);
}
Upvotes: 6