Skip to content

Commit

Permalink
Relax JSON parser, ensure duplicate keys are overridden
Browse files Browse the repository at this point in the history
Resolves #15605

Closes #17645.

PiperOrigin-RevId: 514491743
Change-Id: I17ea9fb57682b668bff02bc64fefd75edb2cf2ee
  • Loading branch information
LavaToaster authored and copybara-github committed Mar 6, 2023
1 parent 3d8ccd8 commit 8548e20
Show file tree
Hide file tree
Showing 2 changed files with 5 additions and 6 deletions.
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"
+ "<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

0 comments on commit 8548e20

Please sign in to comment.