在Spring Data REST Lombok数据模型中,如何在不创建并行实体或DTO的情况下将数据导出和导入自引用JSON?
例如,对于简单的音乐管理器,使用JSONPath的自引用JSON可能如下所示:
{ "id" : 1,
"albums" : [ {
"id" : 1,
"title" : "Kind Of Blue",
"artist" : "$..artists[?(@.id=1)]",
"tracks" : [ {
"id" : 1,
"title" : "So What",
"duration" : "PT9M5S",
"musicians" : [ {
"musician" : "$..artists[?(@.id=1)]",
}, {
"musician" : "$..artists[?(@.id=2)]",
} ]
}, {
"id" : 3,
"title" : "Blue in Green",
"duration" : "PT5M29S",
"musicians" : [ {
"musician" : "$..artists[?(@.id=1)]",
}, {
"musician" : "$..artists[?(@.id=2)]",
} ]
} ]
} ],
"artists" : [ {
"id" : 1,
"firstName" : "Miles",
"lastName" : "Davis",
"birthDate" : "1926-05-26"
}, {
"id" : 2,
"firstName" : "Bill",
"lastName" : "Evans",
"birthDate" : "1929-09-16"
} ]
}
如何在保留Spring Data REST HATEOAS功能的同时为此表示创建导入和导出功能?导出/导入中的musicians
容器具有字符串JSONPath表达式数组,而在REST API中musicians
是Person
个对象的数组(见下文) - 所以杰克逊怎么办?配置为选择正确的序列化程序和反序列化导出和导入操作?
这里是Spring Boot 1.5,Spring Data Rest,Lombok和Jackson实现(GitHub)。
音乐
@Data
@NoArgsConstructor
@Entity
public class Music {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@OneToMany(cascade = { CascadeType.ALL }, orphanRemoval = true)
private List<Album> albums;
@OneToMany(cascade = { CascadeType.ALL }, orphanRemoval = true)
private List<Person> artists;
}
相册
@Data
@NoArgsConstructor
@Entity
public class Album {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String title;
@ManyToOne(cascade = { CascadeType.ALL })
private Person artist;
@OneToMany(cascade = { CascadeType.ALL }, orphanRemoval = true)
private List<Track> tracks;
}
轨道
@Data
@NoArgsConstructor
@Entity
public class Track {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String title;
@JsonSerialize(using = MyDurationSerializer.class)
private Duration duration;
@ManyToMany(cascade = { CascadeType.ALL })
private List<Person> musicians;
public Track(String title, String duration, List<Person> musicians) {
this.title = title;
this.duration = Duration.parse(duration);
this.musicians = musicians;
}
}
人
@Data
@NoArgsConstructor
@Entity
public class Person {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
private String firstName;
private String lastName;
@JsonSerialize(using = MyLocalDateSerializer.class)
private LocalDate birthDate;
public Person(String firstName, String lastName, String birthDate) {
this.firstName = firstName;
this.lastName = lastName;
this.birthDate = LocalDate.parse(birthDate);
}
}
MyDurationSerializer
public class MyDurationSerializer extends StdSerializer<Duration> {
private static final long serialVersionUID = 1L;
protected MyDurationSerializer() {
super(Duration.class);
}
@Override
public void serialize(Duration value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString(value.toString());
}
}
MyLocalDateSerializer
public class MyLocalDateSerializer extends StdSerializer<LocalDate> {
private static final long serialVersionUID = 1L;
private DateTimeFormatter FORMATTER = ofPattern("yyyy-MM-dd");
protected MyLocalDateSerializer() {
super(LocalDate.class);
}
@Override
public void serialize(LocalDate value, JsonGenerator gen, SerializerProvider provider) throws IOException {
gen.writeString(value.format(FORMATTER));
}
}
curl http://localhost:4000/albums/1/tracks
{ "id" : 1,
"albums" : [ {
"id" : 1,
"title" : "Kind Of Blue",
"artist" : "@{
"id" : 1,
"firstName" : "Miles",
"lastName" : "Davis",
"birthDate" : "1926-05-26"
},
"tracks" : [ {
"id" : 1,
"title" : "So What",
"duration" : "PT9M5S",
"musicians" : [ {
"id" : 1,
"firstName" : "Miles",
"lastName" : "Davis",
"birthDate" : "1926-05-26"
}, {
"id" : 2,
"firstName" : "Bill",
"lastName" : "Evans",
"birthDate" : "1929-09-16"
} ]
}, {
"id" : 3,
"title" : "Blue in Green",
"duration" : "PT5M29S",
"musicians" : [ {
"id" : 1,
"firstName" : "Miles",
"lastName" : "Davis",
"birthDate" : "1926-05-26"
}, {
"id" : 2,
"firstName" : "Bill",
"lastName" : "Evans",
"birthDate" : "1929-09-16"
} ]
} ]
} ],
"artists" : [ {
"id" : 15,
"firstName" : "Miles",
"lastName" : "Davis",
"birthDate" : "1926-05-26"
}, {
"id" : 16,
"firstName" : "Bill",
"lastName" : "Evans",
"birthDate" : "1929-09-16"
} ]
}