你提到的所有主要JSON库都没有提供解析你所说的JSON文档的方法:它们只能处理格式正确的JSON文档,其他任何情况都不能处理,这是它们的唯一责任。你提到了一个无效的JSON文档,所以这就是它们无法解析的唯一原因。然而,你在问题中提到的所有库都可以透明地使用Reader,并且只需删除那五个字符,你就可以修复损坏的JSON文档(对于JSON标准或任何JSON工具来说,它都是损坏的),从而可以被任何一个库使用。请注意,你不需要任何“特殊”的库(好吧,假设这样的库存在,但如果它缺少你可以与你喜欢的JSON库一起使用的任何功能,那么你会很失望?),因为你可以使其适用于任何一个库。性能提示:为了节省内存并能够处理巨大的JSON文档,你不需要使用字符串。
考虑以下“JSON”文档:
)]}',{"foo":"bar"}
知道最前面的五个字符会阻止任何JSON解析器解析它,你可以轻松地将它们剥离:
private static final char[] protectingCharacters = {
')', ']', '}', '\'', ','
};
static Reader stripProtection(final Reader reader)
throws IOException {
final char[] buffer = new char[protectingCharacters.length];
final Reader normalizedReader = reader.markSupported() ? reader : new BufferedReader(reader);
normalizedReader.mark(protectingCharacters.length);
normalizedReader.read(buffer, 0, protectingCharacters.length);
if ( !Arrays.equals(protectingCharacters, buffer) ) {
normalizedReader.reset();
}
return normalizedReader;
}
以下示例使用
stripProtection
方法解析给定的输入流,以创建其各自的 JSON 树模型,使示例更加简洁。其中涉及 Gson、Jackson 和 org.json 库。
static void testWithGson()
throws IOException {
try ( final Reader reader = stripProtection(getPackageResourceReader(Q42971905.class, "no-hijacking.json")) ) {
final JsonParser parser = new JsonParser();
final JsonElement jsonElement = parser.parse(reader);
System.out.println(jsonElement);
}
}
static void testWithJackson()
throws IOException {
try ( final Reader reader = stripProtection(getPackageResourceReader(Q42971905.class, "no-hijacking.json")) ) {
final ObjectMapper objectMapper = new ObjectMapper();
final JsonNode jsonNode = objectMapper.readTree(reader);
System.out.println(jsonNode);
}
}
static void testWithOrgJson()
throws IOException {
try ( final Reader reader = stripProtection(getPackageResourceReader(Q42971905.class, "no-hijacking.json")) ) {
final JSONTokener jsonTokener = new JSONTokener(reader);
final Object value = jsonTokener.nextValue();
System.out.println(value);
}
}
所有三种方法都会产生以下输出:
{"foo":"bar"}
如果出于某些原因,您需要生成这样的文档,只需编写如下方法即可:
static Writer coverWithProtection(final Writer writer)
throws IOException {
writer.write(protectingCharacters);
return writer;
}
将编写器传递给您正在使用的相应 JSON 库。此方法只会在编写器输出前添加
)]}',
。
)]}'
。 - Sachin Gupta