我有一个webservice,它将“null”打印为任何属性的字符串,而不是null literal。它适用于几乎所有数据类型(String或Date)。例如,在理想情况下,它返回
{
"item" : {
"title": "Some title",
"expires": "2014-11-02 00:00:00"
}
}
但有时它会返回:
{
"item" : {
"title": "null",
"expires": "2014-11-02 00:00:00"
}
}
这使得title属性值为“null”,而不是将其设置为null。 或者有时候这个:
{
"item" : {
"title": "Some title",
"expires": "null"
}
}
这使得反序列化失败,因为dateformat不匹配。 如何配置objectmapper或注释我的模型类以在反序列化期间解决这些问题?
我的模型类看起来像:
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Item {
public String title;
@JsonFormat(shape= JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
public Date expires;
}
这是一个Android应用程序,所以我无法控制webservice。提前致谢
答案 0 :(得分:1)
如果您使用自定义Deserializer
,则可以执行此操作,但我认为无法使用标准注释。
借用和修改http://www.baeldung.com/jackson-deserialization中的一些代码:
public class ItemDeserializer extends JsonDeserializer<Item> {
@Override
public Item deserialize(JsonParser jp, DeserializationContext ctxt)
throws IOException, JsonProcessingException {
JsonNode node = jp.getCodec().readTree(jp);
String title = null;
TextNode titleNode = (TextNode)node.get("title");
if ( ! titleNode.toString().equals("null")) {
title = titleNode.toString();
}
Date expires = null;
// similar logic for expires
return new Item(title, expires);
}
}
答案 1 :(得分:1)
不确定是否需要,但如果您使用的是ObjectMapper,则可以执行以下操作:
1)删除@JsonFormat(shape= JsonFormat.Shape.STRING, pattern="yyyy-MM-dd HH:mm:ss")
。我还为您显示输入数据的方式添加了@JsonRootName
。
@JsonRootName("item")
@JsonInclude(JsonInclude.Include.NON_NULL)
public class Item {
public String title;
public Date expires;
@Override
public String toString() {
return "Item{" +
"title='" + title + '\'' +
", expires=" + expires +
'}';
}
}
2)并使用您要使用的DateFormat
配置ObjectMapper:
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:s"));
以下是我测试的完整示例:
public class Test {
private static final String T1 = "{\n"+
" \"item\" : {\n"+
" \"title\": \"Some title\",\n"+
" \"expires\": \"2014-11-02 00:00:00\"\n"+
" }\n"+
"}";
private static final String T2 = "{\n" +
" \"item\" : {\n" +
" \"title\": \"null\",\n" +
" \"expires\": \"2014-11-02 00:00:00\"\n" +
" }\n" +
"}";
private static final String T3 = "{\n" +
" \"item\" : {\n" +
" \"title\": \"Some title\",\n" +
" \"expires\": \"null\"\n" +
" }\n" +
"}";
public static void main(String[] args) throws IOException {
ObjectMapper mapper = new ObjectMapper();
mapper.configure(DeserializationFeature.UNWRAP_ROOT_VALUE, true);
mapper.setDateFormat(new SimpleDateFormat("yyyy-MM-dd HH:mm:s"));
Item t1 = mapper.readValue(T1, Item.class);
Item t2 = mapper.readValue(T2, Item.class);
Item t3 = mapper.readValue(T3, Item.class);
System.out.println(t1);
System.out.println(t2);
System.out.println(t3);
System.out.println(mapper.writeValueAsString(t1));
System.out.println(mapper.writeValueAsString(t2));
System.out.println(mapper.writeValueAsString(t3));
}
}
结果。上次打印输出显示@JsonInclude
如何影响输出,以及如何使用此配置完成输入字符串&#39; null&#39; 的序列化:
Item{title='Some title', expires=Sun Nov 02 00:00:00 PDT 2014}
Item{title='null', expires=Sun Nov 02 00:00:00 PDT 2014}
Item{title='Some title', expires=null}
{"title":"Some title","expires":"2014-11-02 00:00:0"}
{"title":"null","expires":"2014-11-02 00:00:0"}
{"title":"Some title"}
答案 2 :(得分:1)
自someone asked this question again几分钟以来,我进行了一些研究,认为我找到了一个很好的解决此问题的方法(在处理字符串时)。
您必须创建一个自定义JsonDeserializer类,如下所示:
class NullStringJsonDeserializer extends JsonDeserializer<String> {
@Override
public String deserialize(JsonParser p, DeserializationContext ctxt) throws IOException {
String result = StringDeserializer.instance.deserialize(p, ctxt);
return result!=null && result.toLowerCase().equals(null+"") ? null : result;
}
}
最后但并非最不重要的,您要做的就是告诉您的ObjectMapper它应该使用自定义的json字符串反序列化器。 这取决于您使用ObjectMapper的方式和位置,但是看起来像这样:
ObjectMapper objectMapper = new ObjectMapper();
SimpleModule module = new SimpleModule();
module.addDeserializer(String.class, new NullStringJsonDeserializer());
objectMapper.registerModule(module);