我正在使用第三方JSON API,它会返回如下数据:
{details: {...}, ...}
我使用Java Jackson将此JSON字符串反序列化为POJO对象,字段声明为:
@JsonProperty("details")
public Details getDetails(){...}
和Details
是另一个类。
一切都很好,直到我发现API可能返回这样的数据:
{details: false, ...}
如果详细信息为空,则返回false
!!!杰克逊给了我这个例外:
com.fasterxml.jackson.databind.JsonMappingException: Can not instantiate value of type [simple type, class Details] from Boolean value; no single-boolean/Boolean-arg constructor/factory method (through reference chain: ...["details"])
那么,如何处理这种JSON字符串?如果为空,我只需要将此字段设置为null。
答案 0 :(得分:2)
来自Jackson的错误消息暗示该库具有支持静态工厂方法的功能。这可能是一个比自定义反序列化器更简单的解决方案:
我创建了这个示例POJO,使用静态工厂方法,注释以便Jackson使用它:
public class Details {
public String name; // example property
@JsonCreator
public static Details factory(Map<String,Object> props) {
if (props.get("details") instanceof Boolean) return null;
Details details = new Details();
Map<String,Object> detailsProps = (Map<String,Object>)props.get("details");
details.name = (String)detailsProps.get("name");
return details;
}
}
测试方法:
public static void main(String[] args)
{
String fullDetailsJson = "{\"details\": {\"name\":\"My Details\"}} ";
String emptyDetailsJson = "{\"details\": false} ";
ObjectMapper mapper = new ObjectMapper();
try {
Details details = mapper.readValue(fullDetailsJson, Details.class);
System.out.println(details.name);
details = mapper.readValue(emptyDetailsJson, Details.class);
System.out.println(details);
} catch (Exception e) {
e.printStackTrace();
}
}
结果如预期:
My Details
null
答案 1 :(得分:1)
创建一个自定义JsonDeserializer来处理反序列化你的Details
对象,如果你得到false则返回null,或者如果它是一个实际的对象,则将对象传递给默认的反序列化器。伪代码:
public class CustomDeserializer extends JsonDeserializer<Details>{
@Override
public Details deserialize(JsonParser jsonParser, DeserializationContext ctx){
//if object use default deserializer else return null
}
}
您还必须编写一个ObjectMapperProvider来注册您的反序列化器,如下所示:
@Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper>{
private ObjectMapper mapper;
public ObjectMapperProvider(){
mapper = new ObjectMapper();
SimpleModule sm = new SimpleModule();
sm.addDeserializer(Details.class, new CustomDeserializer());
mapper.registerModule(sm);
}
public ObjectMapper getContext(Class<?> arg0){
return mapper;
}
}