如何使用Jackson ObjectMapper检测尾随垃圾 [英] How to detect trailing garbage using Jackson ObjectMapper
问题描述
说我有一个班级
class A {
public int x;
}
然后可以解析有效的json,如下所示:
Then a valid json can be parsed as follows:
ObjectMapper mapper = new ObjectMapper();
A a = mapper.readValue("{\"x\" : 3}", A.class);
如果字符串包含的数据多于解析对象所需的数据,是否有办法让解析器失败?
Is there a way to have the parser fail if the string contains more data than necessary to parse the object?
例如我希望以下内容失败(成功)
For example I would like the following to fail (which succeeds)
A a = mapper.readValue("{\"x\" : 3} trailing garbage", A.class);
我尝试使用带有JsonParser.Feature.AUTO_CLOSE_SOURCE = false的InputStream并检查流是否已经过完全消耗,但不起作用:
I tried it using an InputStream with JsonParser.Feature.AUTO_CLOSE_SOURCE=false and checking whether the stream has been consumed completely, but that does not work:
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");
仍然成功,可能是因为解析器从流中消耗的数量超过了严格必要的数量。
still succeeds, probably because the parser consumes more from the stream than strictly necessary.
一个有效的解决方案是在从字符串中删除最后一个字符串时验证解析失败:
One solution that works is to verify that the parsing fails when dropping the last charachter from the string:
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;
}
但我正在寻找更有效的解决方案。
but I'm looking for a more efficient solution.
推荐答案
要做的主要是首先单独创建一个 JsonParser
然后调用 ObjectMapper.readValue()
传递该解析器,然后再次调用 nextToken()
并验证它是否返回null(而不是非空值,或抛出异常)。
The main thing to do is to create a JsonParser
first, separately, then call ObjectMapper.readValue()
passing that parser, and THEN call nextToken()
once more and verify it returns null (instead of non-null value, or throw exception).
所以,像
JsonParser jp = mapper.getFactory().createParser(jsonSource);
try {
Value v = mapper.readValue(jp, Value.class);
if (jp.nextToken() != null) {
//throw some exception: trailing garbage detected
}
return v;
} finally {
jp.close();
}
注意:这是杰克逊2.x.对于Jackson 1.x,使用 getJsonFactory()。createJsonParser()
而不是 getFactory()。createParser()
。
这篇关于如何使用Jackson ObjectMapper检测尾随垃圾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!