【问题标题】:Jackson: deserializing null Strings as empty Strings杰克逊:将空字符串反序列化为空字符串
【发布时间】:2023-03-04 01:28:01
【问题描述】:

我有以下由 Jackson 映射的类(简化版):

public class POI {
    @JsonProperty("name")
    private String name;
}

在某些情况下,服务器返回 "name": null,然后我想将 name 设置为空 Java 字符串。

是否有任何 Jackson 注释,或者如果属性是 null,我应该只检查我的 getter 中的 null 并返回空字符串?

【问题讨论】:

标签: java null jackson


【解决方案1】:

一个不使用 Jackson 特长的简单解决方案:为 name 编写一个 Getter,它返回一个空 String 而不是 null,因为 Jackson 使用它们来序列化。

public String getName() {
  return name != null ? name : "";
}

另一种方法是编写自定义反序列化程序。看这里:http://wiki.fasterxml.com/JacksonHowToCustomSerializers

【讨论】:

    【解决方案2】:

    您可以在默认构造函数中设置它,也可以在声明中设置它:

    public class POI {
        @JsonProperty("name")
        private String name; 
    
        public POI() {
            name = "";
        }
    }
    

    public class POI {
        @JsonProperty("name")
        private String name = "";
    } 
    

    【讨论】:

    • 很好的答案。 ¿ 无参数构造函数由 Lombok 管理时的任何解决方案?
    【解决方案3】:

    同样,此答案适用于偶然发现此线程的 SO 用户

    虽然接受的答案在所有意义上都被接受并且有效 - 但在我们将服务提供给 @987654323 之后才决定将 null 字符串值设置为 empty 字符串的决定对我没有帮助@客户。

    因此,大约 30-40 个 pojo(增加)并在实例化相关对象或在声明时初始化它们太多了。

    我们是这样做的。

    public class CustomSerializerProvider extends DefaultSerializerProvider {
    
        public CustomSerializerProvider() {
            super();
        }
    
        public CustomSerializerProvider(CustomSerializerProvider provider, SerializationConfig config,
                SerializerFactory jsf) {
            super(provider, config, jsf);
        }
    
        @Override
        public CustomSerializerProvider createInstance(SerializationConfig config, SerializerFactory jsf) {
            return new CustomSerializerProvider(this, config, jsf);
        }
    
        @Override
        public JsonSerializer<Object> findNullValueSerializer(BeanProperty property) throws JsonMappingException {
            if (property.getType().getRawClass().equals(String.class))
                return Serializers.EMPTY_STRING_SERIALIZER_INSTANCE;
            else
                return super.findNullValueSerializer(property);
        }
    }
    

    还有,序列化器

    public class Serializers extends JsonSerializer<Object> {
        public static final JsonSerializer<Object> EMPTY_STRING_SERIALIZER_INSTANCE = new EmptyStringSerializer();
    
        public Serializers() {}
    
        @Override
        public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
                throws IOException, JsonProcessingException {
            jsonGenerator.writeString("");
        }
    
        private static class EmptyStringSerializer extends JsonSerializer<Object> {
            public EmptyStringSerializer() {}
    
            @Override
            public void serialize(Object o, JsonGenerator jsonGenerator, SerializerProvider serializerProvider)
                    throws IOException, JsonProcessingException {
                jsonGenerator.writeString("");
            }
        }
    }
    

    然后,在 ObjectMapper 中设置序列化器。 (杰克逊 2.7.4

    ObjectMapper nullMapper = new ObjectMapper();
    nullMapper.setSerializerProvider(new CustomSerializerProvider());
    

    希望,这可以节省一些时间。

    【讨论】:

    • SO users 是什么意思?
    • stackoverflow -> SO
    • 我明白了,谢谢你的回答
    【解决方案4】:

    Jackson 2.9 实际上提供了一种尚未提及的新机制:将@JsonSetter 用于属性,并将其等效的“配置覆盖”用于String.class 等类型。 更长的解释包含在

    https://medium.com/@cowtowncoder/jackson-2-9-features-b2a19029e9ff

    但要点是您可以像这样标记字段(或设置器):

    @JsonSetter(nulls=Nulls.AS_EMPTY) public String stringValue;
    

    或将映射器配置为对所有 String 值属性执行相同操作:

    mapper.configOverride(String.class)
     .setSetterInfo(JsonSetter.Value.forValueNulls(Nulls.AS_EMPTY));
    

    这两者都会将传入的null 转换为空值,对于字符串来说是“”。

    这同样适用于Collections 和Maps。

    【讨论】:

    • 当 API 可以发送“null”作为值或根本不发送字段时,设置 @JsonSetter(nulls = Nulls.AS_EMPTY) 对我有用。在这两种情况下,它都被映射到一个空字符串。正是我需要的,谢谢!
    • 对于集合:这不适用于 missing 属性,至少在 Jackson 2.11.3 中是这样。当反序列化显式空值缺少属性时,最终集合字段初始化为空集合,仅使用getter,并指定Nulls.SKIP - 在字段本身或通过配置此答案中指定的映射器。
    • @YanivNahoum 正确,不处理没有传入值的属性,但必须提供某些值的构造函数传递 (@JsonCreator) 情况除外。所以你是正确的,这是解决限制的一种方法。
    猜你喜欢
    • 2018-10-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-22
    相关资源
    最近更新 更多