使用 Json 反序列化在 Java 中自动将空字符串转换为 null

Posted

技术标签:

【中文标题】使用 Json 反序列化在 Java 中自动将空字符串转换为 null【英文标题】:Automaticaly convert empty strings to null in Java using JsonB deserialization 【发布时间】:2021-07-06 18:15:56 【问题描述】:

有没有人试图找到一个好的解决方案,在使用 JsonB (Yasson) 进行反序列化时自动将所有空字符串转换为空对象?

我在从 Jackson 迁移到 Jsonb 时遇到了这个问题,其中请求中的空字符串值会产生反序列化异常,因为它无法解析为对象。

HTTP 请求负载:


   fieldNameUid: '', // Java property is UUID type

杰克逊有以下配置:

public void customize(ObjectMapper mapper) 
        mapper.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES);
        mapper.enable(DeserializationFeature.READ_UNKNOWN_ENUM_VALUES_AS_NULL);

        SimpleModule module = new SimpleModule();
        module.addDeserializer(
                String.class,
                new StdDeserializer<>(String.class) 

                    @Override
                    public String deserialize(JsonParser parser, DeserializationContext context)
                            throws IOException 
                        String result = StringDeserializer.instance.deserialize(parser, context);
                        if (result == null || result.isBlank()) 
                            return null;
                        
                        return result;
                    
                );
        module.addDeserializer(byte[].class,
                new StdDeserializer<>(byte[].class) 

                    @Override
                    public byte[] deserialize(JsonParser parser, DeserializationContext context)
                            throws IOException 
                        String result = StringDeserializer.instance.deserialize(parser, context);
                        if (result == null || result.isBlank()) 
                            return null;
                        
                        return result.getBytes(StandardCharsets.UTF_8);
                    
                );

        mapper.registerModule(module);
    

和当前的 Jsonb 配置:

public class JsonbObjectMapper implements JsonbConfigCustomizer 

    @Override
    public void customize(JsonbConfig jsonbConfig) 

        jsonbConfig
                .withDeserializers(new StringDeserializer(), new ByteArrayDeserializer(), new EnumDeserializer())
                .withSerializers(new EnumSerializer());

    

    public static class StringDeserializer implements JsonbDeserializer<String> 

        @Override
        public String deserialize(javax.json.stream.JsonParser jsonParser, javax.json.bind.serializer.DeserializationContext deserializationContext, Type type) 
            final String str = jsonParser.getString();
            return str == null || str.isBlank() ? null : str;
        
    

    public static class ByteArrayDeserializer implements JsonbDeserializer<byte[]> 

        @Override
        public byte[] deserialize(javax.json.stream.JsonParser jsonParser, javax.json.bind.serializer.DeserializationContext deserializationContext, Type type) 
            final String str = jsonParser.getString();
            return str == null || str.isBlank() ? null : str.getBytes(StandardCharsets.UTF_8);
        
    

    public static class EnumDeserializer implements JsonbDeserializer<Enum> 

        @Override
        public Enum deserialize(javax.json.stream.JsonParser jsonParser, javax.json.bind.serializer.DeserializationContext deserializationContext, Type type) 

            final String str = jsonParser.getString();
            if (str == null || str.isBlank()) 
                return null;
            
            for (final Enum en : ((Class<Enum>) type).getEnumConstants()) 
                if (en.toString().equals(str)) 
                    return en;
                
            

            return null;
        
    

    public static class EnumSerializer implements JsonbSerializer<Enum> 

        @Override
        public void serialize(Enum anEnum, JsonGenerator jsonGenerator, SerializationContext serializationContext) 
            jsonGenerator.write(anEnum == null ? null : anEnum.toString());
        
    

【问题讨论】:

【参考方案1】:

由于 JsonB 没有替代属性,我最终为 UUID 类型编写了自定义反序列化器。

【讨论】:

以上是关于使用 Json 反序列化在 Java 中自动将空字符串转换为 null的主要内容,如果未能解决你的问题,请参考以下文章

SrpingMVC/SpringBoot中restful接口序列化json的时候使用Jackson将空字段,空字符串不传递给前端

Java Jackson将空字段反序列化为POJO中的默认空列表

如何用杰克逊反序列化空字符串?

将空 XML 元素反序列化为 Guid.Empty

使用 XmlSerializer 将空 xml 属性值反序列化为可为空的 int 属性

反序列化 null 值以使用 Jackson 枚举