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
具体步骤是:
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()); } }
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());
具体代码不再一一列出了,请参考上面的代码实现。