使用Jackson处理@RequestBody中的Null和Default值

时间:2016-08-10 20:09:41

标签: java spring hibernate jpa jackson

我的时区POJO如下:

@Entity
public class TimeZoneDto implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @Column(name = "id", nullable = false)
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "timezone_sequence")
    @SequenceGenerator(name = "timezone_sequence", sequenceName = "t_timeZone_master_id_seq", initialValue = 1, allocationSize = 1)
    private Long id;
    @Column
    private String timeZone;
    @Column
    private String name;
    @Column
    private double hourDifference;
    /* all gettet/setter */
}

我在Spring Controller中有updateTimeZone方法,如下所示:

@RequestMapping(value = "updateTimezone", consumes = "application/json", produces = "application/json", method = RequestMethod.POST)

    public ResponseEntity<Object> updateTimezone(@RequestBody TimeZoneDto timeZoneDto){

}

当我通过以下请求时:

{"id":14,"name":"America/Los_Angeles -7:00 GMT"}

然后,当使用POJO映射时,它会自动使用默认值转换其他值,并且它变为:

id=14, timeZone=null, name=America/Los_Angeles -7:00 GMT, hourDifference=0.0

因为这个当我更新这个POJO时如下

getEntityManager().merge(timezoneDto);

它会自动覆盖TimeZone = null和hourDifference = 0.0,

所以@RequestBody中的TimeZoneDto只有那些我在请求JSON中传递的列。

修改

我在课堂上使用过以下但是没有用

  @JsonInclude(value=Include.NON_EMPTY)
                 OR  
  @JsonInclude(value=Include.NON_DEFAULT)

2 个答案:

答案 0 :(得分:1)

我认为问题出在你的设计上。您将实体与DTO混合在一起。最常用的解决方案是分离这两层。你可以有一个公共接口说TimeZoneInfo然后有两个实现

  • TimeZoneDto - 负责在客户端和服务器之间传输数据,您只需在此对象中声明所需内容。 (例如:没有timeZone字段)
  • TimeZoneEntity - 表示持久性实体(JPA / Hibernate)

然后,您可以将TimeZoneDto作为请求主体,并将该对象作为TimeZoneEntity进行调整(即获取所需的值并设置为实体)。在调整此DTO之前,您可能需要从DB中获取TimeZoneEntity。我最好在服务/委托类中说不在休息控制器中。

答案 1 :(得分:0)

这是您首先需要从存储库中获取TimeZone实体,然后将传入的JSON数据与现有记录数据合并的经典模式。

public ResponseEntity<Object> updateTimeZone(@RequestBody TimeZoneDto dto) {
  final TimeZone timeZone = timeZoneRepository.findById( dto.getId() );
  // use object mapper or whatever and merge dto onto timeZone
  timeZoneRepository.saveOrUpdate( timeZone );
  return timeZone;
}