mirror of
https://github.com/stleary/JSON-java.git
synced 2025-08-03 03:15:32 -04:00
Merge pull request #772 from eamonnmcmanus/complexkey
Disallow nested objects and arrays as keys in objects.
This commit is contained in:
commit
beb2fb5706
@ -208,22 +208,14 @@ public class JSONObject {
|
|||||||
throw x.syntaxError("A JSONObject text must begin with '{'");
|
throw x.syntaxError("A JSONObject text must begin with '{'");
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (;;) {
|
||||||
char prev = x.getPrevious();
|
|
||||||
c = x.nextClean();
|
c = x.nextClean();
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0:
|
case 0:
|
||||||
throw x.syntaxError("A JSONObject text must end with '}'");
|
throw x.syntaxError("A JSONObject text must end with '}'");
|
||||||
case '}':
|
case '}':
|
||||||
return;
|
return;
|
||||||
case '{':
|
|
||||||
case '[':
|
|
||||||
if(prev=='{') {
|
|
||||||
throw x.syntaxError("A JSON Object can not directly nest another JSON Object or JSON Array.");
|
|
||||||
}
|
|
||||||
// fall through
|
|
||||||
default:
|
default:
|
||||||
x.back();
|
key = x.nextSimpleValue(c).toString();
|
||||||
key = x.nextValue().toString();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// The key is followed by ':'.
|
// The key is followed by ':'.
|
||||||
@ -1726,12 +1718,12 @@ public class JSONObject {
|
|||||||
final Object result = method.invoke(bean);
|
final Object result = method.invoke(bean);
|
||||||
if (result != null) {
|
if (result != null) {
|
||||||
// check cyclic dependency and throw error if needed
|
// check cyclic dependency and throw error if needed
|
||||||
// the wrap and populateMap combination method is
|
// the wrap and populateMap combination method is
|
||||||
// itself DFS recursive
|
// itself DFS recursive
|
||||||
if (objectsRecord.contains(result)) {
|
if (objectsRecord.contains(result)) {
|
||||||
throw recursivelyDefinedObjectException(key);
|
throw recursivelyDefinedObjectException(key);
|
||||||
}
|
}
|
||||||
|
|
||||||
objectsRecord.add(result);
|
objectsRecord.add(result);
|
||||||
|
|
||||||
this.map.put(key, wrap(result, objectsRecord));
|
this.map.put(key, wrap(result, objectsRecord));
|
||||||
@ -1740,7 +1732,7 @@ public class JSONObject {
|
|||||||
|
|
||||||
// we don't use the result anywhere outside of wrap
|
// we don't use the result anywhere outside of wrap
|
||||||
// if it's a resource we should be sure to close it
|
// if it's a resource we should be sure to close it
|
||||||
// after calling toString
|
// after calling toString
|
||||||
if (result instanceof Closeable) {
|
if (result instanceof Closeable) {
|
||||||
try {
|
try {
|
||||||
((Closeable) result).close();
|
((Closeable) result).close();
|
||||||
|
@ -402,12 +402,7 @@ public class JSONTokener {
|
|||||||
*/
|
*/
|
||||||
public Object nextValue() throws JSONException {
|
public Object nextValue() throws JSONException {
|
||||||
char c = this.nextClean();
|
char c = this.nextClean();
|
||||||
String string;
|
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '"':
|
|
||||||
case '\'':
|
|
||||||
return this.nextString(c);
|
|
||||||
case '{':
|
case '{':
|
||||||
this.back();
|
this.back();
|
||||||
try {
|
try {
|
||||||
@ -423,6 +418,17 @@ public class JSONTokener {
|
|||||||
throw new JSONException("JSON Array or Object depth too large to process.", e);
|
throw new JSONException("JSON Array or Object depth too large to process.", e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
return nextSimpleValue(c);
|
||||||
|
}
|
||||||
|
|
||||||
|
Object nextSimpleValue(char c) {
|
||||||
|
String string;
|
||||||
|
|
||||||
|
switch (c) {
|
||||||
|
case '"':
|
||||||
|
case '\'':
|
||||||
|
return this.nextString(c);
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Handle unquoted text. This could be the values true, false, or
|
* Handle unquoted text. This could be the values true, false, or
|
||||||
|
@ -118,7 +118,7 @@ public class JSONArrayTest {
|
|||||||
* Expects a JSONException.
|
* Expects a JSONException.
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void emptStr() {
|
public void emptyStr() {
|
||||||
String str = "";
|
String str = "";
|
||||||
try {
|
try {
|
||||||
assertNull("Should throw an exception", new JSONArray(str));
|
assertNull("Should throw an exception", new JSONArray(str));
|
||||||
@ -460,6 +460,20 @@ public class JSONArrayTest {
|
|||||||
Util.checkJSONArrayMaps(jsonArray);
|
Util.checkJSONArrayMaps(jsonArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The JSON parser is permissive of unambiguous unquoted keys and values.
|
||||||
|
* Such JSON text should be allowed, even if it does not strictly conform
|
||||||
|
* to the spec. However, after being parsed, toString() should emit strictly
|
||||||
|
* conforming JSON text.
|
||||||
|
*/
|
||||||
|
@Test
|
||||||
|
public void unquotedText() {
|
||||||
|
String str = "[value1, something!, (parens), foo@bar.com, 23, 23+45]";
|
||||||
|
JSONArray jsonArray = new JSONArray(str);
|
||||||
|
List<Object> expected = Arrays.asList("value1", "something!", "(parens)", "foo@bar.com", 23, "23+45");
|
||||||
|
assertEquals(expected, jsonArray.toList());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Exercise JSONArray.join() by converting a JSONArray into a
|
* Exercise JSONArray.join() by converting a JSONArray into a
|
||||||
* comma-separated string. Since this is very nearly a JSON document,
|
* comma-separated string. Since this is very nearly a JSON document,
|
||||||
|
@ -205,13 +205,17 @@ public class JSONObjectTest {
|
|||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void unquotedText() {
|
public void unquotedText() {
|
||||||
String str = "{key1:value1, key2:42}";
|
String str = "{key1:value1, key2:42, 1.2 : 3.4, -7e5 : something!}";
|
||||||
JSONObject jsonObject = new JSONObject(str);
|
JSONObject jsonObject = new JSONObject(str);
|
||||||
String textStr = jsonObject.toString();
|
String textStr = jsonObject.toString();
|
||||||
assertTrue("expected key1", textStr.contains("\"key1\""));
|
assertTrue("expected key1", textStr.contains("\"key1\""));
|
||||||
assertTrue("expected value1", textStr.contains("\"value1\""));
|
assertTrue("expected value1", textStr.contains("\"value1\""));
|
||||||
assertTrue("expected key2", textStr.contains("\"key2\""));
|
assertTrue("expected key2", textStr.contains("\"key2\""));
|
||||||
assertTrue("expected 42", textStr.contains("42"));
|
assertTrue("expected 42", textStr.contains("42"));
|
||||||
|
assertTrue("expected 1.2", textStr.contains("\"1.2\""));
|
||||||
|
assertTrue("expected 3.4", textStr.contains("3.4"));
|
||||||
|
assertTrue("expected -7E+5", textStr.contains("\"-7E+5\""));
|
||||||
|
assertTrue("expected something!", textStr.contains("\"something!\""));
|
||||||
Util.checkJSONObjectMaps(jsonObject);
|
Util.checkJSONObjectMaps(jsonObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2224,6 +2228,42 @@ public class JSONObjectTest {
|
|||||||
"Expected a ',' or '}' at 15 [character 16 line 1]",
|
"Expected a ',' or '}' at 15 [character 16 line 1]",
|
||||||
e.getMessage());
|
e.getMessage());
|
||||||
}
|
}
|
||||||
|
try {
|
||||||
|
// key is a nested map
|
||||||
|
String str = "{{\"foo\": \"bar\"}: \"baz\"}";
|
||||||
|
assertNull("Expected an exception",new JSONObject(str));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
assertEquals("Expecting an exception message",
|
||||||
|
"Missing value at 1 [character 2 line 1]",
|
||||||
|
e.getMessage());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// key is a nested array containing a map
|
||||||
|
String str = "{\"a\": 1, [{\"foo\": \"bar\"}]: \"baz\"}";
|
||||||
|
assertNull("Expected an exception",new JSONObject(str));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
assertEquals("Expecting an exception message",
|
||||||
|
"Missing value at 9 [character 10 line 1]",
|
||||||
|
e.getMessage());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// key contains }
|
||||||
|
String str = "{foo}: 2}";
|
||||||
|
assertNull("Expected an exception",new JSONObject(str));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
assertEquals("Expecting an exception message",
|
||||||
|
"Expected a ':' after a key at 5 [character 6 line 1]",
|
||||||
|
e.getMessage());
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
// key contains ]
|
||||||
|
String str = "{foo]: 2}";
|
||||||
|
assertNull("Expected an exception",new JSONObject(str));
|
||||||
|
} catch (JSONException e) {
|
||||||
|
assertEquals("Expecting an exception message",
|
||||||
|
"Expected a ':' after a key at 5 [character 6 line 1]",
|
||||||
|
e.getMessage());
|
||||||
|
}
|
||||||
try {
|
try {
|
||||||
// \0 after ,
|
// \0 after ,
|
||||||
String str = "{\"myKey\":true, \0\"myOtherKey\":false}";
|
String str = "{\"myKey\":true, \0\"myOtherKey\":false}";
|
||||||
|
Loading…
x
Reference in New Issue
Block a user