Gson中的STRICT_DUPLICATE_DETECTION的类似物

时间:2018-12-17 17:36:36

标签: java json gson deserialization json-deserialization

在反序列化JSON数据时,我想防止“ json注入”。 默认情况下,JSON解析器不关心对象中的重复键,而只是覆盖它们。

我花了一些时间来找到可以逆转此行为的功能。 我在杰克逊任职,但在格森却不行。 问题在于项目中有很多代码基于Gson。 因此,切换到杰克逊并不容易。

在杰克逊,此功能称为“ STRICT_DUPLICATE_DETECTION”

{"x": true, "x": false} 

1 个答案:

答案 0 :(得分:0)

排序。 由于某种原因,Gson在反序列化Map实例时会检测到名称冲突,但不会对数据包或JsonElement及其子代进行检查(因此,您无法编写基于树的JSON反序列化器来检测它们) )。

给出

{
    "x": true,
    "x": false
}
final class Foo {

    @SuppressWarnings("UnnecessaryBoxing")
    final boolean x = Boolean.valueOf(false);

}
final Foo foo = gson.fromJson(jsonReader, Foo.class);
if ( !foo.x ) {
    throw new AssertionError();
}

对于标准JsonReader,此操作失败。 但是,您可以在最低级别上解决该问题。 这有点棘手,但优化程度不高,但涵盖了所有可能的解串器(这可能解释了Gson在不同的解串器中表现不同的原因:每个这样的解串器都应自己进行此项检查,而只会错过工作)。

final class StrictNamesJsonReader
        extends JsonReader {

    private final Stack<Set<String>> nameStack = new Stack<>();

    private Set<String> names;

    private StrictNamesJsonReader(final Reader reader) {
        super(reader);
    }

    static JsonReader of(final Reader reader) {
        return new StrictNamesJsonReader(reader);
    }

    @Override
    public void beginObject()
            throws IOException {
        super.beginObject();
        names = new HashSet<>();
        nameStack.add(names);
    }

    @Override
    public String nextName()
            throws IOException {
        final String name = super.nextName();
        if ( !names.add(name) ) {
            throw new JsonSyntaxException("Detected duplicate property name " + name + " in " + names + " at " + this);
        }
        return name;
    }

    @Override
    public void endObject()
            throws IOException {
        super.endObject();
        nameStack.pop();
        names = !nameStack.isEmpty() ? nameStack.peek() : null;
    }

}

如您所见,此JsonReader实现实现名称重复检测本身的管理,并引发类似以下异常的情况

Exception in thread "main" com.google.gson.JsonSyntaxException: Detected duplicate property name x in [x] at StrictNamesJsonReader at line 3 column 5 path $.x

如果检测到重复。

不过,您可以在https://github.com/google/gson/pull/649上要求修改您的问题。 我确实认为反序列化器是检测重复项的错误方法,与该PR中的建议不同,应该增强JsonReader