【问题标题】:Unable to get Empty String set to null via Jackson2ObjectMapperBuilder DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT无法通过 Jackson2ObjectMapperBuilder DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT 将空字符串设置为空
【发布时间】:2017-05-07 10:40:38
【问题描述】:

问题

我试图让Jackson 将任何Empty String 设置为null 这是在Spring-boot 应用程序中。我们向 POJO 添加了验证,以检查该值是否在 1 到 255 IFF 之间。

@Size(min = 1, max = 255)
@Column(length = 255)
private String businessTitle;

问题在于,当 Empty String 被传递给验证时,它将失败并出现 javax.validation.ConstraintViolationException 异常,因为它正在检查空字符串。

我尝试在Jackson2ObjectMapperBuilder 上设置DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT,以便将这些空字符串设置为null,并且验证不会失败。但是这并没有发生,它继续将Empty String 传递给对象的save()

问题

保存对象时出现什么问题或需要调整以将Empty String 正确设置为null

代码

对象

@Size(min = 1, max = 255)
@Column(length = 255)
private String businessTitle;

杰克逊配置

@Configuration
public class JacksonConfiguration {


  @Bean
  public Jackson2ObjectMapperBuilder filteringObjectMapperBuilder() {
    Jackson2ObjectMapperBuilder builder = new Jackson2ObjectMapperBuilder();
    builder.featuresToDisable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
    builder.featuresToEnable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

    return builder;
  }
}

例外

Caused by: javax.validation.ConstraintViolationException: Validation failed for classes [com..model.User] during update time for groups [javax.validation.groups.Default, ]
List of constraint violations:[
      ConstraintViolationImpl{interpolatedMessage='size must be between 1 and 255', propertyPath=businessTitle, rootBeanClass=class com..model.User, messageTemplate='{javax.validation.constraints.Size.message}'}
]
        at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.validate(BeanValidationEventListener.java:138)
        at org.hibernate.cfg.beanvalidation.BeanValidationEventListener.onPreUpdate(BeanValidationEventListener.java:86)
        at org.hibernate.action.internal.EntityUpdateAction.preUpdate(EntityUpdateAction.java:244)
        at org.hibernate.action.internal.EntityUpdateAction.execute(EntityUpdateAction.java:118)
        at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:582)
        at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:456)
        at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:337)
        at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:39)
        at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1282)
        at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:465)
        at org.hibernate.internal.SessionImpl.flushBeforeTransactionCompletion(SessionImpl.java:2963)
        at org.hibernate.internal.SessionImpl.beforeTransactionCompletion(SessionImpl.java:2339)
        at org.hibernate.engine.jdbc.internal.JdbcCoordinatorImpl.beforeTransactionCompletion(JdbcCoordinatorImpl.java:485)
        at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.beforeCompletionCallback(JdbcResourceLocalTransactionCoordinatorImpl.java:147)
        at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl.access$100(JdbcResourceLocalTransactionCoordinatorImpl.java:38)
        at org.hibernate.resource.transaction.backend.jdbc.internal.JdbcResourceLocalTransactionCoordinatorImpl$TransactionDriverControlImpl.commit(JdbcResourceLocalTransactionCoordinatorImpl.java:231)
        at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:65)
        at org.hibernate.jpa.internal.TransactionImpl.commit(TransactionImpl.java:61)
        ... 127 common frames omitted

【问题讨论】:

标签: java spring rest spring-boot jackson


【解决方案1】:

实际上有一个更好的解决方案,然后必须将它放在每个属性上。创建一个自定义反序列化器EmptyToNullStringDeserializer,用于将“”更改为空。这是基于同事的解决方案。

builder
  .deserializerByType(String.class, new EmptyToNullStringDeserializer());

【讨论】:

    【解决方案2】:

    DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT 不会帮助您,因为它意味着“将空字符串 JSON 值反序列化为对象字段的 null”,不幸的是,您的字符串字段是标量而不是 JSON 对象。 我认为没有方便的方法来获得你想要的行为。可以覆盖 String 类型的所有字段的反序列化行为,但您可能不想要它。您也可以定义自定义解串器,但您需要像这样注释每个字段:

    @JsonDeserialize(using = MyStringDeseralizer.class)
    private String businessTitle;
    

    class MyStringDeseralizer extends JsonDeserializer<String> 并实现你需要的转换逻辑。

    【讨论】:

    • 谢谢。在搜索解决方案时,我确实在其他一些帖子中阅读了有关设置自定义 JsonDeserialize 的内容。我会研究一下。
    • 一位同事找到了比将其放在每个属性上更好的解决方案,并允许您在反序列化时在每个 String.class 类型上创建它。我在上面发布了解决方案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2016-01-31
    • 2017-11-05
    • 1970-01-01
    • 1970-01-01
    • 2018-08-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多