简体   繁体   中英

Unable to get Empty String set to null via Jackson2ObjectMapperBuilder DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT

Problem

I am trying to have Jackson set any Empty String to null this is within a Spring-boot Application. We have added validation to our POJO to check to see that the value is between 1 and 255 IFF the value is being set.

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

The problem is that when a Empty String is passed to the validation it will fail with a javax.validation.ConstraintViolationException exception because it is checking the empty string.

I tried to setup DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT on the Jackson2ObjectMapperBuilder so it would set these empty strings as null and the validation would not fail. This is not happening though, it continues to pass the Empty String into the save() for the Object.

Question

What is going wrong or needs to be adjusted to have the Empty String set correctly to null when saving the Ojbject?

Code

Object

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

JacksonConfiguration

@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;
  }
}

Exception

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

DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT is not going to help you because it means "deserialise empty string JSON value as null for object field" and unfortunately your String fields are scalars not JSON objects. I think there is no convenient way to get behaviour you want. It is possible to override deserializaton behaviour for all fields with type String but you may not want it. Also you can define custom deserialzer but you will need to annotate every field like this:

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

where class MyStringDeseralizer extends JsonDeserializer<String> and implement conversion logic you need.

Actually there is a better solution then having to put it on each attribute. Create a custom deserializer, EmptyToNullStringDeserializer , for changing '' to null. This is based on a co-workers solution.

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM