英文:
Recreate DTO class without field property instead of having it null using Gson/Jackson and Spring Boot
问题
我有一个DTO类,返回如下:
{
"id": "fdbfb1ec-1f1e-4867-9cc8-73929fbcc07e",
"title": "My another category",
"reports": null
}
实际上,我希望我的一些API调用不包括"reports"键,如下所示,而不是将其设置为null:
{
"id": "fdbfb1ec-1f1e-4867-9cc8-73929fbcc07e",
"title": "My another category"
}
我尝试使用Gson和Expose注解,相信这将删除我的键,但似乎只是将其变为null。我尝试过使用@Expose(serialize = false, deserialize = false)
,也尝试过不使用注解,因为我的Gson对象使用了excludeFieldsWithoutExposeAnnotation()
方法,但两者都给我带来了相同的结果。然而,我可以看到我的字符串转换器排除了"reports"键,并给我了这个{"id":"fdbfb1ec-1f1e-4867-9cc8-73929fbcc07e","title":"My another category"}
,但不确定为什么在重新创建对象时该属性仍然存在,如果唯一的解决方案是不通过Gson而是使用两个完全不同的DTOs,一个包含该属性,另一个不包含该属性?
谢谢。
更新
这是我的Github上的代码:https://github.com/francislainy/gatling_tool_backend
尝试使用Jackson而不是Gson,但出现了相同的问题。
英文:
I have a DTO class that returns this:
{
"id": "fdbfb1ec-1f1e-4867-9cc8-73929fbcc07e",
"title": "My another category",
"reports": null
}
When I actually would like for some of my api calls to have the reports key as not part of it as per the below, rather than being set to null.
{
"id": "fdbfb1ec-1f1e-4867-9cc8-73929fbcc07e",
"title": "My another category",
}
I tried to use Gson and Expose annotation believing this would remove my key, but it just seems to be turning it to null instead. I tried both using @Expose(serialize = false, deserialize = false)
or leaving it without the annotation since my Gson object uses the excludeFieldsWithoutExposeAnnotation()
piece but both give me the same outcome. However, I can see my string converter excludes the reports key and gives me this {"id":"fdbfb1ec-1f1e-4867-9cc8-73929fbcc07e","title":"My another category"}
but not sure why the property is still there when the object is recreated and if the only solution for this scenario would not be through Gson but have two complete different DTOs instead, one with that property and the other without it?
@AllArgsConstructor
@NoArgsConstructor
@Data
public class CategoryQueryDto {
@Expose()
private UUID id;
@Expose()
private String title;
@Expose(serialize = false, deserialize = false)
private List<ReportQueryDto> reports;
public CategoryQueryDto(String title) {
this.title = title;
}
public CategoryQueryDto(UUID id, String title) {
this.id = id;
this.title = title;
}
}
@Override
public CategoryQueryDto getCategory(UUID id) {
if (categoryRepository.findById(id).isPresent()) {
Category category = categoryRepository.findById(id).get();
CategoryQueryDto categoryQueryDto = new CategoryQueryDto(category.getId(), category.getTitle());
Gson gson = new GsonBuilder().excludeFieldsWithoutExposeAnnotation().create();
String converter = gson.toJson(categoryQueryDto);
categoryQueryDto = gson.fromJson(converter, CategoryQueryDto.class);
return categoryQueryDto;
} else {
return null;
}
}
Thank you very much.
UPDATE
Here is my code on Github https://github.com/francislainy/gatling_tool_backend
Tried with Jackson rather than Gson and got the same issue.
答案1
得分: 1
Used `@JsonInclude(JsonInclude.Include.NON_NULL)` on the field I wanted to show only if not null and it worked.
@AllArgsConstructor
@NoArgsConstructor
@Data
public class CategoryQueryDto {
@Expose()
private UUID id;
@Expose()
private String title;
@JsonInclude(JsonInclude.Include.NON_NULL)
private List<ReportQueryDto> reports = null;
public CategoryQueryDto(String title) {
this.title = title;
}
public CategoryQueryDto(UUID id, String title) {
this.id = id;
this.title = title;
}
}
And here my controller with Jackson
@Service
public class CategoryQueryServiceImpl implements CategoryQueryService {
@Autowired
private CategoryRepository categoryRepository;
@Autowired
private ReportRepository reportRepository;
ObjectMapper mapper = new ObjectMapper();
@Override
public CategoryQueryDto getCategory(UUID id) throws JsonProcessingException {
if (categoryRepository.findById(id).isPresent()) {
Category category = categoryRepository.findById(id).get();
CategoryQueryDto categoryQueryDto = new CategoryQueryDto(category.getId(), category.getTitle());
String converter = mapper.writeValueAsString(categoryQueryDto);
categoryQueryDto = mapper.readValue(converter, CategoryQueryDto.class);
return categoryQueryDto;
} else {
return null;
}
}
POM
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
<scope>test</scope>
</dependency>
<details>
<summary>英文:</summary>
Used `@JsonInclude(JsonInclude.Include.NON_NULL)` on the field I wanted to show only if not null and it worked.
@AllArgsConstructor
@NoArgsConstructor
@Data
public class CategoryQueryDto {
@Expose()
private UUID id;
@Expose()
private String title;
@JsonInclude(JsonInclude.Include.NON_NULL)
private List<ReportQueryDto> reports = null;
public CategoryQueryDto(String title) {
this.title = title;
}
public CategoryQueryDto(UUID id, String title) {
this.id = id;
this.title = title;
}
}
And here my controller with Jackson
@Service
public class CategoryQueryServiceImpl implements CategoryQueryService {
@Autowired
private CategoryRepository categoryRepository;
@Autowired
private ReportRepository reportRepository;
ObjectMapper mapper = new ObjectMapper();
@Override
public CategoryQueryDto getCategory(UUID id) throws JsonProcessingException {
if (categoryRepository.findById(id).isPresent()) {
Category category = categoryRepository.findById(id).get();
CategoryQueryDto categoryQueryDto = new CategoryQueryDto(category.getId(), category.getTitle());
String converter = mapper.writeValueAsString(categoryQueryDto);
categoryQueryDto = mapper.readValue(converter, CategoryQueryDto.class);
return categoryQueryDto;
} else {
return null;
}
}
POM
<dependency>
<groupId>org.codehaus.jackson</groupId>
<artifactId>jackson-core-asl</artifactId>
<version>1.9.13</version>
<scope>test</scope>
</dependency>
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论