使用Spring Data REST自引用JSON

时间:2017-04-25 22:05:22

标签: java spring spring-boot jackson spring-data-rest

使用Spring Data REST自引用JSON

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中musiciansPerson个对象的数组(见下文) - 所以杰克逊怎么办?配置为选择正确的序列化程序和反序列化导出和导入操作?

详情:音乐经理示例

这里是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));
    }
}

Spring Data REST HATEOAS表示

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"
  } ]
}

0 个答案:

没有答案