转载

Jackson 反序列化 "Y"/"N" 为相应的布尔值

JSON 表示布尔值标准的形式是 true 和  false ,如果 Java 对应的类型是对象  Boolean,那么在 JSON 中也可以是  null 。如果收到 JSON 数据是用 'Y'/'N', 或 'Yes'/'No' 来表示布尔值的,那么使用 Java 的 Jackson 库如何把它们反序列化为相应的布尔属性值呢?

如果按照 JSON 规范必须把内容中的布尔值全部转换为 truefalse , 然而再反序列化,否则需要定制 Boolean 类型的反序列化类,可应用到全局的 boolean 类型,或指派给特定的 boolean 类型属性。

如果尝试反序列化 Y , 或 N 为 Java 的 boolean 值,会有只接受  true 或 false 的异常:

com.fasterxml.jackson.databind.exc.InvalidFormatException: Can not deserialize value of type java.lang.Boolean from String "Y": only "true" or "false" recognized

具体步骤是:

先创建一个 YNBooleanDeserializer 类

package blog.yanbin.jsonutils;
 
import com.fasterxml.jackson.core.*;
import com.fasterxml.jackson.databind.*;
import java.io.IOException;
 
public class YNBooleanDeserializer extends JsonDeserializer<Boolean> {
 
    @Override
    public Boolean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
        JsonToken currentToken = jp.getCurrentToken();
 
        if (currentToken.equals(JsonToken.VALUE_STRING)) {
            String text = jp.getText();
 
            if ("Y".equals(text)) {
                return Boolean.TRUE;
            } else if ("N".equals(text)) {
                return Boolean.FALSE;
            }
 
            throw ctxt.weirdStringException(text, Boolean.class,
                "Only /"" + YES + "/" or /"" + NO + "/" values supported");
        } else if (currentToken.equals(JsonToken.VALUE_NULL)) {
            return Boolean.FALSE;
            //return null
        }
 
        throw ctxt.mappingException("Can't parse boolean value: " + jp.getText());
    }
}

应用到相应的 Boolean 属性上

class User {
 
    @JsonDeserialize(using = YNBooleanDeserializer.class)
    public Boolean isAlive;
}

测试代码

ObjectMapper objectMapper = new ObjectMapper() ;
String json = "{/"isAlive/":/"Y/"}";
User user = objectMapper.readValue(json, User.class);
System.out.println(user.isAlive);

可以得到 user.isAlive 属性值为 true

其他问题引申

上面代码只是给某些个别的属性使用 YNBooleanDeserializer 来反序列化 JSON 中的 boolean 值,如果 JSON 中全部的 boolean 值都是用  Y / N 来表示的,那么可以为 ObjectMapper 注册一个模块,完整代码如下:

ObjectMapper objectMapper = new ObjectMapper() ;
        
SimpleModule boolModule = new SimpleModule();
boolModule.addDeserializer(Boolean.class, new YNBooleanDeserializer());
objectMapper.registerModule(boolModule);
 
String json = "{/"isAlive/":/"Y/"}";
User user = objectMapper.readValue(json, User.class);
System.out.println(user.isAlive);

这时候在 User 中就不需要 JsonDeserialize(using = YNBooleanDeserializer.class) 注解了。

再一步引申,如果希望序列化时也用 Y / N 来表示 boolean 值,可用的方法与上面差不多,只是反着方向来的。比如特定属性上用

@JsonSerialize(using = YBNooleanSerializer.class)

或是全局的模块中设定

booleanModule.addSerializer(Boolean.class, new YNBooleanSerializer());

具体代码不再一一列出了,请参考上面的代码实现。

原文  https://yanbin.blog/jackson-yn-boolean-value-deserialization/
正文到此结束
Loading...