Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relax JSON parser, ensure duplicate keys are overridden #17645

Closed
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 2 additions & 5 deletions src/main/java/net/starlark/java/lib/json/Json.java
Original file line number Diff line number Diff line change
Expand Up @@ -287,7 +287,8 @@ private void appendQuoted(String s) {
+ " a decimal point or an exponent. Although JSON has no syntax "
+ " for non-finite values, very large values may be decoded as infinity.\n"
+ "<li>a JSON object is parsed as a new unfrozen Starlark dict."
+ " Keys must be unique strings.\n"
+ " If the same key string occurs more than once in the object, the last"
+ " value for the key is kept.\n"
LavaToaster marked this conversation as resolved.
Show resolved Hide resolved
+ "<li>a JSON array is parsed as new unfrozen Starlark list.\n"
+ "</ul>\n"
+ "Decoding fails if x is not a valid JSON encoding.\n",
Expand Down Expand Up @@ -398,11 +399,7 @@ private Object parse() throws EvalException {
}
i++; // ':'
Object value = parse();
int sz = dict.size();
dict.putEntry((String) key, value); // can't fail
if (dict.size() == sz) {
throw Starlark.errorf("object has duplicate key: %s", Starlark.repr(key));
}
c = next();
if (c != ',') {
if (c != '}') {
Expand Down
4 changes: 3 additions & 1 deletion src/test/java/net/starlark/java/eval/testdata/json.star
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@ assert_eq(json.decode('"\\u0123"'), 'ģ')
assert_eq(json.decode('\t[\t1,\r2,\n3]\n'), [1, 2, 3]) # whitespace other than ' '
assert_eq(json.decode('\n{\t"a":\r1\t}\n'), {'a': 1}) # same, with dict
assert_eq(json.decode(r'"\\\/\"\n\r\t"'), "\\/\"\n\r\t") # TODO(adonovan): test \b\f when Starlark/Java supports them
assert_eq(json.decode('{"x": 1, "x": 2}'), {"x": 2})
assert_eq(json.decode('{"x": {"y": 1, "y": 2}}'), {"x": {"y": 2}})
assert_eq(json.decode('{"x": {"y": 1, "z": 1}, "x": {"y": 2}}'), {"x": {"y": 2}})

# We accept UTF-16 strings that have been arbitrarily truncated,
# as many Java and JavaScript programs emit them.
Expand Down Expand Up @@ -123,7 +126,6 @@ assert_fails(lambda: json.decode('[1, 2}'), "got \"}\", want ',' or ']'")
assert_fails(lambda: json.decode('{"one": 1'), "unexpected end of file")
assert_fails(lambda: json.decode('{"one" 1'), 'after object key, got "1", want \':\'')
assert_fails(lambda: json.decode('{"one": 1 "two": 2'), "in object, got ..\"., want ',' or '}'")
assert_fails(lambda: json.decode('{"x": 1, "x": 2}'), 'object has duplicate key: "x"')
assert_fails(lambda: json.decode('{1:2}'), "got int for object key, want string")
assert_fails(lambda: json.decode('{"one": 1,'), "unexpected end of file")
assert_fails(lambda: json.decode('{"one": 1, }'), 'unexpected character "}"')
Expand Down