diff --git a/src/main/java/org/json/JSONObject.java b/src/main/java/org/json/JSONObject.java index b504519..10fed95 100644 --- a/src/main/java/org/json/JSONObject.java +++ b/src/main/java/org/json/JSONObject.java @@ -213,6 +213,7 @@ public class JSONObject { this(); char c; String key; + Object obj; boolean isInitial = x.getPrevious() == 0; @@ -230,7 +231,20 @@ public class JSONObject { } return; default: - key = x.nextSimpleValue(c).toString(); + obj = x.nextSimpleValue(c); + key = obj.toString(); + } + + if (jsonParserConfiguration != null && jsonParserConfiguration.isStrictMode()) { + if(obj instanceof Boolean) { + throw x.syntaxError(String.format("Strict mode error: key '%s' cannot be boolean", key)); + } + if(obj == JSONObject.NULL) { + throw x.syntaxError(String.format("Strict mode error: key '%s' cannot be null", key)); + } + if(obj instanceof Number) { + throw x.syntaxError(String.format("Strict mode error: key '%s' cannot be number", key)); + } } // The key is followed by ':'. diff --git a/src/main/java/org/json/JSONTokener.java b/src/main/java/org/json/JSONTokener.java index a90d51a..ffe12d6 100644 --- a/src/main/java/org/json/JSONTokener.java +++ b/src/main/java/org/json/JSONTokener.java @@ -511,6 +511,15 @@ public class JSONTokener { throw this.syntaxError("Missing value"); } Object obj = JSONObject.stringToValue(string); + // if obj is a boolean, look at string + if (jsonParserConfiguration != null && + jsonParserConfiguration.isStrictMode() && obj instanceof Boolean) { + if (!"true".equals(string) && !"false".equals(string)) { + throw this.syntaxError(String.format("Strict mode error: Value '%s' is not lowercase boolean", obj)); + } + } + + // Strict mode only allows strings with explicit double quotes if (jsonParserConfiguration != null && jsonParserConfiguration.isStrictMode() && diff --git a/src/test/java/org/json/junit/JSONObjectTest.java b/src/test/java/org/json/junit/JSONObjectTest.java index 061f185..50319a8 100644 --- a/src/test/java/org/json/junit/JSONObjectTest.java +++ b/src/test/java/org/json/junit/JSONObjectTest.java @@ -3997,6 +3997,41 @@ public class JSONObjectTest { assertThrows(JSONException.class, () -> { new JSONObject(tokener); }); } + @Test + public void test_strictModeWithMisCasedBooleanValue(){ + JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration().withStrictMode(); + + try{ + JSONObject j1 = new JSONObject("{\"a\":True}", jsonParserConfiguration); + fail("Expected an exception"); + } catch (JSONException e) { } + try{ + JSONObject j2 = new JSONObject("{\"a\":TRUE}", jsonParserConfiguration); + fail("Expected an exception"); + } catch (JSONException e) { } + } + + @Test + public void test_strictModeWithInappropriateKey(){ + JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration().withStrictMode(); + + // Parsing the following objects should fail + try{ + JSONObject j3 = new JSONObject("{true : 3}", jsonParserConfiguration); + fail("Expected an exception"); + } catch (JSONException e) { } + try{ + JSONObject j4 = new JSONObject("{TRUE : 3}", jsonParserConfiguration); + fail("Expected an exception"); + } catch (JSONException e) { } + try{ + JSONObject j5 = new JSONObject("{1 : 3}", jsonParserConfiguration); + fail("Expected an exception"); + } catch (JSONException e) { } + + } + + /** * Method to build nested map of max maxDepth *