Skip to content

Commit 8548e20

Browse files
LavaToastercopybara-github
authored andcommitted
Relax JSON parser, ensure duplicate keys are overridden
Resolves #15605 Closes #17645. PiperOrigin-RevId: 514491743 Change-Id: I17ea9fb57682b668bff02bc64fefd75edb2cf2ee
1 parent 3d8ccd8 commit 8548e20

File tree

2 files changed

+5
-6
lines changed
  • src
    • main/java/net/starlark/java/lib/json
    • test/java/net/starlark/java/eval/testdata

2 files changed

+5
-6
lines changed

src/main/java/net/starlark/java/lib/json/Json.java

+2-5
Original file line numberDiff line numberDiff line change
@@ -287,7 +287,8 @@ private void appendQuoted(String s) {
287287
+ " a decimal point or an exponent. Although JSON has no syntax "
288288
+ " for non-finite values, very large values may be decoded as infinity.\n"
289289
+ "<li>a JSON object is parsed as a new unfrozen Starlark dict."
290-
+ " Keys must be unique strings.\n"
290+
+ " If the same key string occurs more than once in the object, the last"
291+
+ " value for the key is kept.\n"
291292
+ "<li>a JSON array is parsed as new unfrozen Starlark list.\n"
292293
+ "</ul>\n"
293294
+ "Decoding fails if x is not a valid JSON encoding.\n",
@@ -398,11 +399,7 @@ private Object parse() throws EvalException {
398399
}
399400
i++; // ':'
400401
Object value = parse();
401-
int sz = dict.size();
402402
dict.putEntry((String) key, value); // can't fail
403-
if (dict.size() == sz) {
404-
throw Starlark.errorf("object has duplicate key: %s", Starlark.repr(key));
405-
}
406403
c = next();
407404
if (c != ',') {
408405
if (c != '}') {

src/test/java/net/starlark/java/eval/testdata/json.star

+3-1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,9 @@ assert_eq(json.decode('"\\u0123"'), 'ģ')
8080
assert_eq(json.decode('\t[\t1,\r2,\n3]\n'), [1, 2, 3]) # whitespace other than ' '
8181
assert_eq(json.decode('\n{\t"a":\r1\t}\n'), {'a': 1}) # same, with dict
8282
assert_eq(json.decode(r'"\\\/\"\n\r\t"'), "\\/\"\n\r\t") # TODO(adonovan): test \b\f when Starlark/Java supports them
83+
assert_eq(json.decode('{"x": 1, "x": 2}'), {"x": 2})
84+
assert_eq(json.decode('{"x": {"y": 1, "y": 2}}'), {"x": {"y": 2}})
85+
assert_eq(json.decode('{"x": {"y": 1, "z": 1}, "x": {"y": 2}}'), {"x": {"y": 2}})
8386

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

0 commit comments

Comments
 (0)