假设我有课
class A {
public int x;
}
那么一个有效的json可以被解析如下:
ObjectMapper mapper = new ObjectMapper();
A a = mapper.readValue("{\"x\" : 3}", A.class);
如果字符串包含的数据超过解析对象所需的数据,是否有办法让解析器失败?
例如,我希望以下操作失败(成功)
A a = mapper.readValue("{\"x\" : 3} trailing garbage", A.class);
我尝试使用InputStream和JsonParser.Feature.AUTO_CLOSE_SOURCE = false并检查流是否已被完全消耗,但这不起作用:
A read(String s) throws JsonParseException, JsonMappingException, IOException {
JsonFactory f = new MappingJsonFactory();
f.configure(JsonParser.Feature.AUTO_CLOSE_SOURCE, false);
ObjectMapper mapper = new ObjectMapper(f);
InputStream is = new ByteArrayInputStream(s.getBytes(StandardCharsets.UTF_8));
try {
A a = mapper.readValue(is, A.class);
if(is.available() > 0) {
throw new RuntimeException();
}
return a;
} finally {
is.close();
}
}
即,
read("{\"x\" : 3} trailing garbage");
仍然成功,可能是因为解析器从流中消耗的比严格需要的更多。
一个可行的解决方案是验证在删除字符串中的最后一个字符时解析是否失败:
A read(String s) throws JsonParseException, JsonMappingException, IOException {
ObjectMapper mapper = new ObjectMapper();
A a = mapper.readValue(s, A.class);
if (s.length() > 0) {
try {
mapper.readValue(s.substring(0, s.length()-1), A.class);
throw new RuntimeException();
} catch (JsonParseException e) {
}
}
return a;
}
但我在寻找更有效的解决方案。
3条答案
按热度按时间wydwbb8l1#
从Jackson版本2.9开始,现在有反序列化功能. FAIL_ON_TRAILING_TOKENS,可用于实现以下目的:
参见https://github.com/FasterXML/jackson/wiki/Jackson-Release-2.9和https://medium.com/@cowtowncoder/jackson-2-9-features-b2a19029e9ff
vjhs03f72#
要做的主要事情是首先单独创建一个
JsonParser
,然后调用ObjectMapper.readValue()
传递该解析器,然后再次调用nextToken()
并验证它是否返回null(而不是非null值,或者抛出异常)。所以,就像
注:这是针对Jackson2.x的。对于Jackson 1.x,请使用
getJsonFactory().createJsonParser()
而不是getFactory().createParser()
。goqiplq23#
基本上,在
readValue
.JsonParser #nextToken()验证String是否为正确的JSON之前,循环遍历令牌。下面是代码:
控制台输出: