【问题标题】:How to deserialize a blank JSON string value to null for java.lang.String?如何将 java.lang.String 的空白 JSON 字符串值反序列化为 null?
【发布时间】:2015-06-15 09:42:16
【问题描述】:

我正在尝试一个简单的 JSON 来反序列化为 java 对象。但是,我得到了 java.lang.String 属性值的空 String 值。在其余属性中,空白值正在转换为 null 值(这是我想要的)。

下面列出了我的 JSON 和相关的 Java 类。

JSON 字符串:

{
  "eventId" : 1,
  "title" : "sample event",
  "location" : "" 
}

EventBean 类 POJO:

public class EventBean {

    public Long eventId;
    public String title;
    public String location;

}

我的主课代码:

ObjectMapper mapper = new ObjectMapper();
mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
mapper.enable(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT);

try {
    File file = new   File(JsonTest.class.getClassLoader().getResource("event.txt").getFile());

    JsonNode root = mapper.readTree(file);
    // find out the applicationId

    EventBean e = mapper.treeToValue(root, EventBean.class);
    System.out.println("It is " + e.location);
}

我期待打印“它是空的”。相反,我得到“它是”。显然,Jackson 在转换为我的 String 对象类型时没有将空白字符串值视为 NULL。

我在某处读到它是预期的。但是,对于 java.lang.String,我也想避免这种情况。有简单的方法吗?

【问题讨论】:

    标签: java json jackson


    【解决方案1】:

    对于其他对象,Jackson 会给你 null,但对于 String,它会给你空 String。

    但您可以使用自定义JsonDeserializer 来执行此操作:

    class CustomDeserializer extends JsonDeserializer<String> {
    
        @Override
        public String deserialize(JsonParser jsonParser, DeserializationContext context) throws IOException, JsonProcessingException {
            JsonNode node = jsonParser.readValueAsTree();
            if (node.asText().isEmpty()) {
                return null;
            }
            return node.toString();
        }
    
    }
    

    在课堂上你必须将它用于位置字段:

    class EventBean {
        public Long eventId;
        public String title;
    
        @JsonDeserialize(using = CustomDeserializer.class)
        public String location;
    }
    

    【讨论】:

    • 这对我也有用,但是使用 readValueAsTree() 将字符串包裹在额外的引号中。所以为了避免它我改用 jsonParser.readValueAs(String.class);
    • @kopelitsa 额外引号问题可以通过“return node.asText();”解决
    • 我们能不能把JsonDeserialize注解也应用到类级别,这样下面所有空字符串的字符串属性都将转换为null?
    • @AnsarSamad 你的问题有答案吗?我需要了解它是否可以在班级级别插入
    【解决方案2】:

    可以为 String 类型定义自定义反序列化器,覆盖标准的 String 反序列化器:

    this.mapper = new ObjectMapper();
    
    SimpleModule module = new SimpleModule();
    
    module.addDeserializer(String.class, new StdDeserializer<String>(String.class) {
    
        @Override
        public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
            String result = StringDeserializer.instance.deserialize(p, ctxt);
            if (StringUtils.isEmpty(result)) {
                return null;
            }
            return result;
        }
    });
    
    mapper.registerModule(module);
    

    这样所有字符串字段的行为方式都相同。

    【讨论】:

      【解决方案3】:

      您可能首先想看看the Github issue 请求此确切功能是否有任何进展。

      对于那些使用 Spring Boot 的人:jgesser 的回答对我最有帮助,但我花了一段时间试图找出在 Spring Boot 中配置它的最佳方法。

      其实the documentation 说:

      com.fasterxml.jackson.databind.Module 类型的任何 bean 都是 使用自动配置自动注册 Jackson2ObjectMapperBuilder 并应用于任何 ObjectMapper 它创建的实例。

      所以这里的 jgesser 的答案扩展为您可以复制粘贴到 Spring Boot 应用程序中的新类中的内容

      @Configuration
      public class EmptyStringAsNullJacksonConfiguration {
      
        @Bean
        SimpleModule emptyStringAsNullModule() {
          SimpleModule module = new SimpleModule();
      
          module.addDeserializer(
              String.class,
              new StdDeserializer<String>(String.class) {
      
                @Override
                public String deserialize(JsonParser parser, DeserializationContext context)
                    throws IOException {
                  String result = StringDeserializer.instance.deserialize(parser, context);
                  if (StringUtils.isEmpty(result)) {
                    return null;
                  }
                  return result;
                }
              });
      
          return module;
        }
      }
      

      【讨论】:

      • 唉,由于似乎明显缺乏兴趣,您所指的问题已被(其中一个)维护者关闭...
      【解决方案4】:

      我可以通过以下配置得到这个。

      final ObjectMapper mapper = new ObjectMapper();
      mapper.configure(DeserializationFeature.ACCEPT_EMPTY_STRING_AS_NULL_OBJECT, true);
      

      【讨论】:

      • 这不起作用 - 反序列化功能仅适用于作为整个 JSON 表达式的空字符串(由“NULL_OBJECT”表示) - 不适用于对象属性。
      【解决方案5】:

      可以使用 JsonCreator 注解。它对我有用

      public class Foo {
      private String field;
      
       @JsonCreator
       public Foo(
         @JsonProrerty("field") String field) {
           this.field = StringUtils.EMPTY.equals(field) ? null : field ;
      }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2012-06-30
        • 1970-01-01
        • 2012-08-15
        • 1970-01-01
        • 1970-01-01
        • 2011-04-17
        • 2015-03-23
        相关资源
        最近更新 更多