Spring 引导 Java 将实体映射到 DTO:对象数组的数组文字(字符串)INSTEAD

Spring Boot Java map Entity to DTO: array literal (strings) INSTEAD of array of objects

示例获取请求:http://localhost:3000/contact/1

我得到的:

{
  "id": 1,
  "firstname": "First Name",
  "lastname": "Last Name",
  "emailaddresses": [
    {
      "emailaddress": "email@gmail.com"
    },
    {
      "emailaddress": "email@g.c"
    }
  ]
}

我想要的:

{
  "id": 1,
  "firstname": "First Name",
  "lastname": "Last Name",
  "emailaddresses": ["email@gmail.com","email@g.c"]
}

代码如下:

PersonDto

public class PersonDto {
    
    private Long id;
    private String firstname;
    private String lastname;
    private List<EmailAddressDto> emailaddresses;
    //getters setters
}

EmailAddressDto

public class EmailAddressDto {

    private String emailaddress;
    //getters and setters
}

服务class

public PersonDto getPerson(Long personId) { //this is the method inside the class

        Optional<PersonEntity> p = peopleRepository.findById(personId);
        var dto = modelMapper.map(p.get(), PersonDto.class);
        return dto;
}

我还有一个 PersonEntity class 一对多映射到 EmailAddressesEntity class.

我真的是 spring/java 的新手 - 我不知道如何获得我想要的 JSON 结构。

如果你能改变你的 PersonDto 那将是最简单和最干净的方法。

public class PersonDto {
    
    private Long id;
    private String firstname;
    private String lastname;
    private List<String> emailaddresses;
    //getters setters
}

在映射您的实体时,您需要将 EmailAddressesEntity 映射到代表它的 String (emailaddress)。


如果这不可能,您将需要一个用于 EmailAddressDto 的自定义转换器,如下所示:

public class ListEmailAddressDtoConverter extends StdConverter<List<EmailAddressDto>, List<String>> {
    @Override
    public List<String> convert(List<EmailAddressDto> emailAddresses) {
        return emailAddresses.stream().map(EmailAddressDto::getEmailaddress).collect(Collectors.toList());
    }
}

然后你需要告诉杰克逊使用它:

public class PersonDto {
    
    private Long id;
    private String firstname;
    private String lastname;
    
    @JsonSerialize(converter = ListEmailAddressDtoConverter.class)
    private List<EmailAddressDto> emailaddresses;
    //getters setters
}

我建议您使用字符串列表而不是 EmailAddressDto 列表。

以下原因:

  • 由于您的 Dto 中只有一个属性,因此您可以轻松地直接使用字符串列表。
  • 您获得第二个 JSON-Layout 作为对您的 GET-Request 的响应。

当使用变体编号 1(使用 EmailAddressDto 列表)时,您将实现 JSON-对不同电子邮件地址的多个对象的响应。 否则,当您使用变体编号 2(带有字符串列表)时,您将获得一个看起来像您想要的 JSON-Response。

所以别忘了更改您的实体。

public class PersonDto {

private Long id;
private String firstname;
private String lastname;
private List<String> emailAddresses;
//getters setters
}

您可以只用 @JsonValue 注释 EmailAddressDtoemailaddress 字段并保持原样。

public class EmailAddressDto {
    
    @JsonValue
    private String emailaddress;
    //getters and setters
}

使用上面的示例输出:

    PersonDto personDto = new PersonDto();
    personDto.setId(1L);
    personDto.setFirstname("John");
    personDto.setLastname("Doe");
    personDto.setEmailaddresses(Arrays.asList(new EmailAddressDto("john@doe.com"), new EmailAddressDto("foo@bar.com")));

    ObjectMapper mapper = new ObjectMapper();
    String json = mapper.writeValueAsString(personDto);
    System.out.println(json);

是:

{"id":1,"firstname":"John","lastname":"Doe","emailaddresses":["john@doe.com","foo@bar.com"]}