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

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

如果按照 JSON 规范必须把内容中的布尔值全部转换为 true 或 false, 然而再反序列化,否则需要定制 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 类

 1package blog.yanbin.jsonutils;
 2
 3import com.fasterxml.jackson.core.*;
 4import com.fasterxml.jackson.databind.*;
 5import java.io.IOException;
 6
 7public class YNBooleanDeserializer extends JsonDeserializer<Boolean> {
 8
 9    @Override
10    public Boolean deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException {
11        JsonToken currentToken = jp.getCurrentToken();
12
13        if (currentToken.equals(JsonToken.VALUE_STRING)) {
14            String text = jp.getText();
15
16            if ("Y".equals(text)) {
17                return Boolean.TRUE;
18            } else if ("N".equals(text)) {
19                return Boolean.FALSE;
20            }
21
22            throw ctxt.weirdStringException(text, Boolean.class,
23                "Only \"" + YES + "\" or \"" + NO + "\" values supported");
24        } else if (currentToken.equals(JsonToken.VALUE_NULL)) {
25            return Boolean.FALSE;
26            //return null
27        }
28
29        throw ctxt.mappingException("Can't parse boolean value: " + jp.getText());
30    }
31}

应用到相应的 Boolean 属性上

1class User {
2
3    @JsonDeserialize(using = YNBooleanDeserializer.class)
4    public Boolean isAlive;
5}

测试代码

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

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

其他问题引申

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

1ObjectMapper objectMapper = new ObjectMapper() ;
2
3SimpleModule boolModule = new SimpleModule();
4boolModule.addDeserializer(Boolean.class, new YNBooleanDeserializer());
5objectMapper.registerModule(boolModule);
6
7String json = "{\"isAlive\":\"Y\"}";
8User user = objectMapper.readValue(json, User.class);
9System.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/, 来自 隔叶黄莺 Yanbin's Blog
[版权声明] 本文采用 署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0) 进行许可。