diff --git a/src/main/java/org/json/JSONArray.java b/src/main/java/org/json/JSONArray.java index 3823598..df0b299 100644 --- a/src/main/java/org/json/JSONArray.java +++ b/src/main/java/org/json/JSONArray.java @@ -75,104 +75,55 @@ public class JSONArray implements Iterable { } /** - * Constructs a JSONArray from a JSONTokener. - *

- * This constructor reads the JSONTokener to parse a JSON array. It uses the default JSONParserConfiguration. + * Construct a JSONArray from a JSONTokener. * - * @param x A JSONTokener - * @throws JSONException If there is a syntax error. + * @param x + * A JSONTokener + * @throws JSONException + * If there is a syntax error. */ public JSONArray(JSONTokener x) throws JSONException { - this(x, new JSONParserConfiguration()); - } - - /** - * Constructs a JSONArray from a JSONTokener and a JSONParserConfiguration. - * JSONParserConfiguration contains strictMode turned off (false) by default. - * - * @param x A JSONTokener instance from which the JSONArray is constructed. - * @param jsonParserConfiguration A JSONParserConfiguration instance that controls the behavior of the parser. - * @throws JSONException If a syntax error occurs during the construction of the JSONArray. - */ - public JSONArray(JSONTokener x, JSONParserConfiguration jsonParserConfiguration) throws JSONException { this(); - char nextChar = x.nextClean(); - - // check first character, if not '[' throw JSONException - if (nextChar != '[') { + if (x.nextClean() != '[') { throw x.syntaxError("A JSONArray text must start with '['"); } - - parseTokener(x, jsonParserConfiguration); // runs recursively - - } - - private void parseTokener(JSONTokener x, JSONParserConfiguration jsonParserConfiguration) { - boolean strictMode = jsonParserConfiguration.isStrictMode(); - - char cursor = x.nextClean(); - - switch (cursor) { - case 0: - throwErrorIfEoF(x); - break; - case ',': - cursor = x.nextClean(); - - throwErrorIfEoF(x); - - if(strictMode && cursor == ']'){ - throw x.syntaxError(getInvalidCharErrorMsg(cursor)); - } - - if (cursor == ']') { - break; - } - - x.back(); - - parseTokener(x, jsonParserConfiguration); - break; - case ']': - if (strictMode) { - cursor = x.nextClean(); - boolean isEoF = x.end(); - - if (isEoF) { - break; - } - - if (x.getArrayLevel() == 0) { - throw x.syntaxError(getInvalidCharErrorMsg(cursor)); - } - - x.back(); - } - break; - default: - x.back(); - boolean currentCharIsQuote = x.getPrevious() == '"'; - boolean quoteIsNotNextToValidChar = x.getPreviousChar() != ',' && x.getPreviousChar() != '['; - - if (strictMode && currentCharIsQuote && quoteIsNotNextToValidChar) { - throw x.syntaxError(getInvalidCharErrorMsg(cursor)); - } - - this.myArrayList.add(x.nextValue(jsonParserConfiguration)); - parseTokener(x, jsonParserConfiguration); + + char nextChar = x.nextClean(); + if (nextChar == 0) { + // array is unclosed. No ']' found, instead EOF + throw x.syntaxError("Expected a ',' or ']'"); } - } - - /** - * Throws JSONException if JSONTokener has reached end of file, usually when array is unclosed. No ']' found, - * instead EoF. - * - * @param x the JSONTokener being evaluated. - * @throws JSONException if JSONTokener has reached end of file. - */ - private void throwErrorIfEoF(JSONTokener x) { - if (x.end()) { - throw x.syntaxError(String.format("Expected a ',' or ']' but instead found '%s'", x.getPrevious())); + if (nextChar != ']') { + x.back(); + for (;;) { + if (x.nextClean() == ',') { + x.back(); + this.myArrayList.add(JSONObject.NULL); + } else { + x.back(); + this.myArrayList.add(x.nextValue()); + } + switch (x.nextClean()) { + case 0: + // array is unclosed. No ']' found, instead EOF + throw x.syntaxError("Expected a ',' or ']'"); + case ',': + nextChar = x.nextClean(); + if (nextChar == 0) { + // array is unclosed. No ']' found, instead EOF + throw x.syntaxError("Expected a ',' or ']'"); + } + if (nextChar == ']') { + return; + } + x.back(); + break; + case ']': + return; + default: + throw x.syntaxError("Expected a ',' or ']'"); + } + } } } @@ -187,19 +138,7 @@ public class JSONArray implements Iterable { * If there is a syntax error. */ public JSONArray(String source) throws JSONException { - this(new JSONTokener(source), new JSONParserConfiguration()); - } - - /** - * Constructs a JSONArray from a source JSON text and a JSONParserConfiguration. - * - * @param source A string that begins with [ (left bracket) and - * ends with ]  (right bracket). - * @param jsonParserConfiguration A JSONParserConfiguration instance that controls the behavior of the parser. - * @throws JSONException If there is a syntax error. - */ - public JSONArray(String source, JSONParserConfiguration jsonParserConfiguration) throws JSONException { - this(new JSONTokener(source), jsonParserConfiguration); + this(new JSONTokener(source)); } /** @@ -428,7 +367,7 @@ public class JSONArray implements Iterable { /** * Get the enum value associated with an index. - * + * * @param * Enum Type * @param clazz @@ -616,7 +555,7 @@ public class JSONArray implements Iterable { if (len == 0) { return ""; } - + StringBuilder sb = new StringBuilder( JSONObject.valueToString(this.myArrayList.get(0))); @@ -930,7 +869,7 @@ public class JSONArray implements Iterable { /** * Get the enum value associated with a key. - * + * * @param * Enum Type * @param clazz @@ -945,7 +884,7 @@ public class JSONArray implements Iterable { /** * Get the enum value associated with a key. - * + * * @param * Enum Type * @param clazz @@ -978,8 +917,8 @@ public class JSONArray implements Iterable { } /** - * Get the optional BigInteger value associated with an index. The - * defaultValue is returned if there is no value for the index, or if the + * Get the optional BigInteger value associated with an index. The + * defaultValue is returned if there is no value for the index, or if the * value is not a number and cannot be converted to a number. * * @param index @@ -994,8 +933,8 @@ public class JSONArray implements Iterable { } /** - * Get the optional BigDecimal value associated with an index. The - * defaultValue is returned if there is no value for the index, or if the + * Get the optional BigDecimal value associated with an index. The + * defaultValue is returned if there is no value for the index, or if the * value is not a number and cannot be converted to a number. If the value * is float or double, the {@link BigDecimal#BigDecimal(double)} * constructor will be used. See notes on the constructor for conversion @@ -1164,7 +1103,7 @@ public class JSONArray implements Iterable { if (val instanceof Number){ return (Number) val; } - + if (val instanceof String) { try { return JSONObject.stringToNumber((String) val); @@ -1241,7 +1180,7 @@ public class JSONArray implements Iterable { public JSONArray put(double value) throws JSONException { return this.put(Double.valueOf(value)); } - + /** * Append a float value. This increases the array's length by one. * @@ -1496,19 +1435,19 @@ public class JSONArray implements Iterable { * * @param collection * A Collection. - * @return this. + * @return this. */ public JSONArray putAll(Collection collection) { this.addAll(collection, false); return this; } - + /** * Put an Iterable's elements in to the JSONArray. * * @param iter * An Iterable. - * @return this. + * @return this. */ public JSONArray putAll(Iterable iter) { this.addAll(iter, false); @@ -1520,7 +1459,7 @@ public class JSONArray implements Iterable { * * @param array * A JSONArray. - * @return this. + * @return this. */ public JSONArray putAll(JSONArray array) { // directly copy the elements from the source array to this one @@ -1535,7 +1474,7 @@ public class JSONArray implements Iterable { * @param array * Array. If the parameter passed is null, or not an array or Iterable, an * exception will be thrown. - * @return this. + * @return this. * * @throws JSONException * If not an array, JSONArray, Iterable or if an value is non-finite number. @@ -1546,9 +1485,9 @@ public class JSONArray implements Iterable { this.addAll(array, false); return this; } - + /** - * Creates a JSONPointer using an initialization string and tries to + * Creates a JSONPointer using an initialization string and tries to * match it to an item within this JSONArray. For example, given a * JSONArray initialized with this document: *
@@ -1556,7 +1495,7 @@ public class JSONArray implements Iterable {
      *     {"b":"c"}
      * ]
      * 
-     * and this JSONPointer string:
+     * and this JSONPointer string: 
      * 
      * "/0/b"
      * 
@@ -1569,9 +1508,9 @@ public class JSONArray implements Iterable { public Object query(String jsonPointer) { return query(new JSONPointer(jsonPointer)); } - + /** - * Uses a user initialized JSONPointer and tries to + * Uses a user initialized JSONPointer and tries to * match it to an item within this JSONArray. For example, given a * JSONArray initialized with this document: *
@@ -1579,7 +1518,7 @@ public class JSONArray implements Iterable {
      *     {"b":"c"}
      * ]
      * 
-     * and this JSONPointer:
+     * and this JSONPointer: 
      * 
      * "/0/b"
      * 
@@ -1592,11 +1531,11 @@ public class JSONArray implements Iterable { public Object query(JSONPointer jsonPointer) { return jsonPointer.queryFrom(this); } - + /** * Queries and returns a value from this object using {@code jsonPointer}, or * returns null if the query fails due to a missing key. - * + * * @param jsonPointer the string representation of the JSON pointer * @return the queried value or {@code null} * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax @@ -1604,11 +1543,11 @@ public class JSONArray implements Iterable { public Object optQuery(String jsonPointer) { return optQuery(new JSONPointer(jsonPointer)); } - + /** * Queries and returns a value from this object using {@code jsonPointer}, or * returns null if the query fails due to a missing key. - * + * * @param jsonPointer The JSON pointer * @return the queried value or {@code null} * @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax @@ -1728,11 +1667,11 @@ public class JSONArray implements Iterable { /** * Make a pretty-printed JSON text of this JSONArray. - * + * *

If

 {@code indentFactor > 0}
and the {@link JSONArray} has only * one element, then the array will be output on a single line: *
{@code [1]}
- * + * *

If an array has 2 or more elements, then it will be output across * multiple lines:

{@code
      * [
@@ -1744,7 +1683,7 @@ public class JSONArray implements Iterable {
      * 

* Warning: This method assumes that the data structure is acyclical. * - * + * * @param indentFactor * The number of spaces to add to each level of indentation. * @return a printable, displayable, transmittable representation of the @@ -1778,11 +1717,11 @@ public class JSONArray implements Iterable { /** * Write the contents of the JSONArray as JSON text to a writer. - * + * *

If

{@code indentFactor > 0}
and the {@link JSONArray} has only * one element, then the array will be output on a single line: *
{@code [1]}
- * + * *

If an array has 2 or more elements, then it will be output across * multiple lines:

{@code
      * [
@@ -1962,7 +1901,6 @@ public class JSONArray implements Iterable {
     private void addAll(Object array, boolean wrap, int recursionDepth) {
         addAll(array, wrap, recursionDepth, new JSONParserConfiguration());
     }
-
     /**
      * Add an array's elements to the JSONArray.
      *`
@@ -2009,6 +1947,7 @@ public class JSONArray implements Iterable {
                     "JSONArray initial value should be a string or collection or array.");
         }
     }
+    
     /**
      * Create a new JSONException in a common format for incorrect conversions.
      * @param idx index of the item
@@ -2037,7 +1976,4 @@ public class JSONArray implements Iterable {
                 , cause);
     }
 
-    private static String getInvalidCharErrorMsg(char cursor) {
-        return String.format("invalid character '%s' found after end of array", cursor);
-    }
 }
diff --git a/src/main/java/org/json/JSONObject.java b/src/main/java/org/json/JSONObject.java
index 642e967..26a68c6 100644
--- a/src/main/java/org/json/JSONObject.java
+++ b/src/main/java/org/json/JSONObject.java
@@ -220,12 +220,12 @@ public class JSONObject {
         for (;;) {
             c = x.nextClean();
             switch (c) {
-                case 0:
-                    throw x.syntaxError("A JSONObject text must end with '}'");
-                case '}':
-                    return;
-                default:
-                    key = x.nextSimpleValue(c, jsonParserConfiguration).toString();
+            case 0:
+                throw x.syntaxError("A JSONObject text must end with '}'");
+            case '}':
+                return;
+            default:
+                key = x.nextSimpleValue(c).toString();
             }
 
             // The key is followed by ':'.
@@ -244,7 +244,7 @@ public class JSONObject {
                     throw x.syntaxError("Duplicate key \"" + key + "\"");
                 }
 
-                Object value = x.nextValue(jsonParserConfiguration);
+                Object value = x.nextValue();
                 // Only add value if non-null
                 if (value != null) {
                     this.put(key, value);
@@ -1247,7 +1247,7 @@ public class JSONObject {
     static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue) {
         return objectToBigDecimal(val, defaultValue, true);
     }
-
+    
     /**
      * @param val value to convert
      * @param defaultValue default value to return is the conversion doesn't work or is null.
diff --git a/src/main/java/org/json/JSONParserConfiguration.java b/src/main/java/org/json/JSONParserConfiguration.java
index ad0d7fb..190daeb 100644
--- a/src/main/java/org/json/JSONParserConfiguration.java
+++ b/src/main/java/org/json/JSONParserConfiguration.java
@@ -4,25 +4,11 @@ package org.json;
  * Configuration object for the JSON parser. The configuration is immutable.
  */
 public class JSONParserConfiguration extends ParserConfiguration {
-
-    /** Original Configuration of the JSON Parser. */
-    public static final JSONParserConfiguration ORIGINAL = new JSONParserConfiguration();
-
-    /** Original configuration of the JSON Parser except that values are kept as strings. */
-    public static final JSONParserConfiguration KEEP_STRINGS = new JSONParserConfiguration().withKeepStrings(true);
-
     /**
      * Used to indicate whether to overwrite duplicate key or not.
      */
     private boolean overwriteDuplicateKey;
 
-    /**
-     * This flag, when set to true, instructs the parser to throw a JSONException if it encounters an invalid character
-     * immediately following the final ']' character in the input. This is useful for ensuring strict adherence to the
-     * JSON syntax, as any characters after the final closing bracket of a JSON array are considered invalid.
-     */
-    private boolean strictMode;
-
     /**
      * Configuration with the default values.
      */
@@ -72,24 +58,6 @@ public class JSONParserConfiguration extends ParserConfiguration {
         return clone;
     }
 
-
-    /**
-     * Sets the strict mode configuration for the JSON parser.
-     * 

- * When strict mode is enabled, the parser will throw a JSONException if it encounters an invalid character - * immediately following the final ']' character in the input. This is useful for ensuring strict adherence to the - * JSON syntax, as any characters after the final closing bracket of a JSON array are considered invalid. - * - * @param mode a boolean value indicating whether strict mode should be enabled or not - * @return a new JSONParserConfiguration instance with the updated strict mode setting - */ - public JSONParserConfiguration withStrictMode(final boolean mode) { - JSONParserConfiguration clone = this.clone(); - clone.strictMode = mode; - - return clone; - } - /** * The parser's behavior when meeting duplicate keys, controls whether the parser should * overwrite duplicate keys or not. @@ -99,18 +67,4 @@ public class JSONParserConfiguration extends ParserConfiguration { public boolean isOverwriteDuplicateKey() { return this.overwriteDuplicateKey; } - - - /** - * Retrieves the current strict mode setting of the JSON parser. - *

- * Strict mode, when enabled, instructs the parser to throw a JSONException if it encounters an invalid character - * immediately following the final ']' character in the input. This ensures strict adherence to the JSON syntax, as - * any characters after the final closing bracket of a JSON array are considered invalid. - * - * @return the current strict mode setting. True if strict mode is enabled, false otherwise. - */ - public boolean isStrictMode() { - return this.strictMode; - } } diff --git a/src/main/java/org/json/JSONTokener.java b/src/main/java/org/json/JSONTokener.java index 63effc5..b8808bb 100644 --- a/src/main/java/org/json/JSONTokener.java +++ b/src/main/java/org/json/JSONTokener.java @@ -2,8 +2,6 @@ package org.json; import java.io.*; import java.nio.charset.Charset; -import java.util.ArrayList; -import java.util.List; /* Public Domain. @@ -33,8 +31,6 @@ public class JSONTokener { private boolean usePrevious; /** the number of characters read in the previous line. */ private long characterPreviousLine; - private final List smallCharMemory; - private int arrayLevel = 0; /** @@ -53,7 +49,6 @@ public class JSONTokener { this.character = 1; this.characterPreviousLine = 0; this.line = 1; - this.smallCharMemory = new ArrayList(2); } @@ -191,46 +186,6 @@ public class JSONTokener { return this.previous; } - private void insertCharacterInCharMemory(Character c) { - boolean foundSameCharRef = checkForEqualCharRefInMicroCharMemory(c); - if(foundSameCharRef){ - return; - } - - if(smallCharMemory.size() < 2){ - smallCharMemory.add(c); - return; - } - - smallCharMemory.set(0, smallCharMemory.get(1)); - smallCharMemory.remove(1); - smallCharMemory.add(c); - } - - private boolean checkForEqualCharRefInMicroCharMemory(Character c) { - boolean isNotEmpty = !smallCharMemory.isEmpty(); - if (isNotEmpty) { - Character lastChar = smallCharMemory.get(smallCharMemory.size() - 1); - return c.compareTo(lastChar) == 0; - } - - // list is empty so there's no equal characters - return false; - } - - /** - * Retrieves the previous char from memory. - * - * @return previous char stored in memory. - */ - public char getPreviousChar() { - return smallCharMemory.get(0); - } - - public int getArrayLevel(){ - return this.arrayLevel; - } - /** * Get the last character read from the input or '\0' if nothing has been read yet. * @return the last character read from the input. @@ -308,6 +263,7 @@ public class JSONTokener { return new String(chars); } + /** * Get the next char in the string, skipping whitespace. * @throws JSONException Thrown if there is an error reading the source string. @@ -317,7 +273,6 @@ public class JSONTokener { for (;;) { char c = this.next(); if (c == 0 || c > ' ') { - insertCharacterInCharMemory(c); return c; } } @@ -325,14 +280,15 @@ public class JSONTokener { /** - * Return the characters up to the next close quote character. Backslash processing is done. The formal JSON format - * does not allow strings in single quotes, but an implementation is allowed to accept them. - * + * Return the characters up to the next close quote character. + * Backslash processing is done. The formal JSON format does not + * allow strings in single quotes, but an implementation is allowed to + * accept them. * @param quote The quoting character, either * " (double quote) or * ' (single quote). - * @return A String. - * @throws JSONException Unterminated string or unbalanced quotes if strictMode == true. + * @return A String. + * @throws JSONException Unterminated string. */ public String nextString(char quote) throws JSONException { char c; @@ -340,59 +296,58 @@ public class JSONTokener { for (;;) { c = this.next(); switch (c) { - case 0: - case '\n': - case '\r': - throw this.syntaxError("Unterminated string. " + + case 0: + case '\n': + case '\r': + throw this.syntaxError("Unterminated string. " + "Character with int code " + (int) c + " is not allowed within a quoted string."); - case '\\': - c = this.next(); - switch (c) { - case 'b': - sb.append('\b'); - break; - case 't': - sb.append('\t'); - break; - case 'n': - sb.append('\n'); - break; - case 'f': - sb.append('\f'); - break; - case 'r': - sb.append('\r'); - break; - case 'u': - String next = this.next(4); - try { - sb.append((char) Integer.parseInt(next, 16)); - } catch (NumberFormatException e) { - throw this.syntaxError("Illegal escape. " + - "\\u must be followed by a 4 digit hexadecimal number. \\" + next - + " is not valid.", - e); - } - break; - case '"': - case '\'': - case '\\': - case '/': - sb.append(c); - break; - default: - throw this.syntaxError("Illegal escape. Escape sequence \\" + c + " is not valid."); + case '\\': + c = this.next(); + switch (c) { + case 'b': + sb.append('\b'); + break; + case 't': + sb.append('\t'); + break; + case 'n': + sb.append('\n'); + break; + case 'f': + sb.append('\f'); + break; + case 'r': + sb.append('\r'); + break; + case 'u': + String next = this.next(4); + try { + sb.append((char)Integer.parseInt(next, 16)); + } catch (NumberFormatException e) { + throw this.syntaxError("Illegal escape. " + + "\\u must be followed by a 4 digit hexadecimal number. \\" + next + " is not valid.", e); } break; - default: - if (c == quote) { - return sb.toString(); - } + case '"': + case '\'': + case '\\': + case '/': sb.append(c); + break; + default: + throw this.syntaxError("Illegal escape. Escape sequence \\" + c + " is not valid."); + } + break; + default: + if (c == quote) { + return sb.toString(); + } + sb.append(c); } } } + /** * Get the text up but not including the specified character or the * end of line, whichever comes first. @@ -442,113 +397,51 @@ public class JSONTokener { /** - * Get the next value. The value can be a Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the - * JSONObject.NULL object. + * Get the next value. The value can be a Boolean, Double, Integer, + * JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object. + * @throws JSONException If syntax error. * * @return An object. - * @throws JSONException If syntax error. */ public Object nextValue() throws JSONException { - return nextValue(new JSONParserConfiguration()); - } - - /** - * Get the next value. The value can be a Boolean, Double, Integer, JSONArray, JSONObject, Long, or String, or the - * JSONObject.NULL object. The strictMode parameter controls the behavior of the method when parsing the value. - * - * @param jsonParserConfiguration which carries options such as strictMode, these methods will - * strictly adhere to the JSON syntax, throwing a JSONException for any deviations. - * @return An object. - * @throws JSONException If syntax error. - */ - public Object nextValue(JSONParserConfiguration jsonParserConfiguration) throws JSONException { char c = this.nextClean(); switch (c) { - case '{': - this.back(); - try { - return new JSONObject(this, jsonParserConfiguration); - } catch (StackOverflowError e) { - throw new JSONException("JSON Array or Object depth too large to process.", e); - } - case '[': - this.back(); - try { - this.arrayLevel++; - return new JSONArray(this, jsonParserConfiguration); - } catch (StackOverflowError e) { - throw new JSONException("JSON Array or Object depth too large to process.", e); - } - default: - return nextSimpleValue(c, jsonParserConfiguration); + case '{': + this.back(); + try { + return new JSONObject(this); + } catch (StackOverflowError e) { + throw new JSONException("JSON Array or Object depth too large to process.", e); + } + case '[': + this.back(); + try { + return new JSONArray(this); + } catch (StackOverflowError e) { + throw new JSONException("JSON Array or Object depth too large to process.", e); + } } + return nextSimpleValue(c); } - /** - * This method is used to get a JSONObject from the JSONTokener. The strictMode parameter controls the behavior of - * the method when parsing the JSONObject. - * - * @param jsonParserConfiguration which carries options such as strictMode, these methods will - * strictly adhere to the JSON syntax, throwing a JSONException for any deviations. - * deviations. - * @return A JSONObject which is the next value in the JSONTokener. - * @throws JSONException If the JSONObject or JSONArray depth is too large to process. - */ - private JSONObject getJsonObject(JSONParserConfiguration jsonParserConfiguration) { - try { - return new JSONObject(this, jsonParserConfiguration); - } catch (StackOverflowError e) { - throw new JSONException("JSON Array or Object depth too large to process.", e); - } - } + Object nextSimpleValue(char c) { + String string; - /** - * This method is used to get a JSONArray from the JSONTokener. - * - * @return A JSONArray which is the next value in the JSONTokener. - * @throws JSONException If the JSONArray depth is too large to process. - */ - private JSONArray getJsonArray() { - try { - return new JSONArray(this); - } catch (StackOverflowError e) { - throw new JSONException("JSON Array or Object depth too large to process.", e); - } - } - - /** - * Get the next simple value from the JSON input. Simple values include strings (wrapped in single or double - * quotes), numbers, booleans, and null. This method is called when the next character is not '{' or '['. - * - * @param c The starting character. - * @param jsonParserConfiguration The configuration object containing parsing options. - * @return The parsed simple value. - * @throws JSONException If there is a syntax error or the value does not adhere to the configuration rules. - */ - Object nextSimpleValue(char c, JSONParserConfiguration jsonParserConfiguration) { - boolean strictMode = jsonParserConfiguration.isStrictMode(); - - if (strictMode && c == '\'') { - throw this.syntaxError("Single quote wrap not allowed in strict mode"); - } - - if (c == '"' || c == '\'') { + switch (c) { + case '"': + case '\'': return this.nextString(c); } - return parsedUnquotedText(c, strictMode); - } + /* + * Handle unquoted text. This could be the values true, false, or + * null, or it can be a number. An implementation (such as this one) + * is allowed to also accept non-standard forms. + * + * Accumulate characters until we reach the end of the text or a + * formatting character. + */ - /** - * Parses unquoted text from the JSON input. This could be the values true, false, or null, or it can be a number. - * Non-standard forms are also accepted. Characters are accumulated until the end of the text or a formatting - * character is reached. - * - * @param c The starting character. - * @return The parsed object. - * @throws JSONException If the parsed string is empty. - */ - private Object parsedUnquotedText(char c, boolean strictMode) { StringBuilder sb = new StringBuilder(); while (c >= ' ' && ",:]}/\\\"[{;=#".indexOf(c) < 0) { sb.append(c); @@ -558,24 +451,13 @@ public class JSONTokener { this.back(); } - String string = sb.toString().trim(); - - if (string.isEmpty()) { + string = sb.toString().trim(); + if ("".equals(string)) { throw this.syntaxError("Missing value"); } - - Object stringToValue = JSONObject.stringToValue(string); - - return strictMode ? getValidNumberBooleanOrNullFromObject(stringToValue) : stringToValue; + return JSONObject.stringToValue(string); } - private Object getValidNumberBooleanOrNullFromObject(Object value) { - if (value instanceof Number || value instanceof Boolean || value.equals(JSONObject.NULL)) { - return value; - } - - throw this.syntaxError(String.format("Value '%s' is not surrounded by quotes", value)); - } /** * Skip characters until the next character is the requested character. diff --git a/src/test/java/org/json/junit/CDLTest.java b/src/test/java/org/json/junit/CDLTest.java index 511218e..cc3da29 100644 --- a/src/test/java/org/json/junit/CDLTest.java +++ b/src/test/java/org/json/junit/CDLTest.java @@ -29,7 +29,8 @@ public class CDLTest { "1, 2, 3, 4\t, 5, 6, 7\n" + "true, false, true, true, false, false, false\n" + "0.23, 57.42, 5e27, -234.879, 2.34e5, 0.0, 9e-3\n" + - "\"va\tl1\", \"v\bal2\", \"val3\", \"val\f4\", \"val5\", \"va'l6\", val7\n"; + "\"va\tl1\", \"v\bal2\", \"val3\", \"val\f4\", \"val5\", va'l6, val7\n"; + /** * CDL.toJSONArray() adds all values as strings, with no filtering or @@ -37,12 +38,11 @@ public class CDLTest { * values all must be quoted in the cases where the JSONObject parsing * might normally convert the value into a non-string. */ - private static final String EXPECTED_LINES = - "[{\"Col 1\":\"val1\", \"Col 2\":\"val2\", \"Col 3\":\"val3\", \"Col 4\":\"val4\", \"Col 5\":\"val5\", \"Col 6\":\"val6\", \"Col 7\":\"val7\"}, " + - "{\"Col 1\":\"1\", \"Col 2\":\"2\", \"Col 3\":\"3\", \"Col 4\":\"4\", \"Col 5\":\"5\", \"Col 6\":\"6\", \"Col 7\":\"7\"}, " + - "{\"Col 1\":\"true\", \"Col 2\":\"false\", \"Col 3\":\"true\", \"Col 4\":\"true\", \"Col 5\":\"false\", \"Col 6\":\"false\", \"Col 7\":\"false\"}, " + - "{\"Col 1\":\"0.23\", \"Col 2\":\"57.42\", \"Col 3\":\"5e27\", \"Col 4\":\"-234.879\", \"Col 5\":\"2.34e5\", \"Col 6\":\"0.0\", \"Col 7\":\"9e-3\"}, " + - "{\"Col 1\":\"va\tl1\", \"Col 2\":\"v\bal2\", \"Col 3\":\"val3\", \"Col 4\":\"val\f4\", \"Col 5\":\"val5\", \"Col 6\":\"va'l6\", \"Col 7\":\"val7\"}]"; + private static final String EXPECTED_LINES = "[{Col 1:val1, Col 2:val2, Col 3:val3, Col 4:val4, Col 5:val5, Col 6:val6, Col 7:val7}, " + + "{Col 1:\"1\", Col 2:\"2\", Col 3:\"3\", Col 4:\"4\", Col 5:\"5\", Col 6:\"6\", Col 7:\"7\"}, " + + "{Col 1:\"true\", Col 2:\"false\", Col 3:\"true\", Col 4:\"true\", Col 5:\"false\", Col 6:\"false\", Col 7:\"false\"}, " + + "{Col 1:\"0.23\", Col 2:\"57.42\", Col 3:\"5e27\", Col 4:\"-234.879\", Col 5:\"2.34e5\", Col 6:\"0.0\", Col 7:\"9e-3\"}, " + + "{Col 1:\"va\tl1\", Col 2:\"v\bal2\", Col 3:val3, Col 4:\"val\f4\", Col 5:val5, Col 6:va'l6, Col 7:val7}]"; /** * Attempts to create a JSONArray from a null string. @@ -283,11 +283,11 @@ public class CDLTest { */ @Test public void jsonArrayToJSONArray() { - String nameArrayStr = "[\"Col1\", \"Col2\"]"; + String nameArrayStr = "[Col1, Col2]"; String values = "V1, V2"; JSONArray nameJSONArray = new JSONArray(nameArrayStr); JSONArray jsonArray = CDL.toJSONArray(nameJSONArray, values); - JSONArray expectedJsonArray = new JSONArray("[{\"Col1\":\"V1\",\"Col2\":\"V2\"}]"); + JSONArray expectedJsonArray = new JSONArray("[{Col1:V1,Col2:V2}]"); Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray); } diff --git a/src/test/java/org/json/junit/JSONArrayTest.java b/src/test/java/org/json/junit/JSONArrayTest.java index 485d43e..fcaa8ce 100644 --- a/src/test/java/org/json/junit/JSONArrayTest.java +++ b/src/test/java/org/json/junit/JSONArrayTest.java @@ -142,7 +142,7 @@ public class JSONArrayTest { assertNull("Should throw an exception", new JSONArray("[")); } catch (JSONException e) { assertEquals("Expected an exception message", - "Expected a ',' or ']' but instead found '[' at 1 [character 2 line 1]", + "Expected a ',' or ']' at 1 [character 2 line 1]", e.getMessage()); } } @@ -157,7 +157,7 @@ public class JSONArrayTest { assertNull("Should throw an exception", new JSONArray("[\"test\"")); } catch (JSONException e) { assertEquals("Expected an exception message", - "Expected a ',' or ']' but instead found '\"' at 7 [character 8 line 1]", + "Expected a ',' or ']' at 7 [character 8 line 1]", e.getMessage()); } } @@ -172,7 +172,7 @@ public class JSONArrayTest { assertNull("Should throw an exception", new JSONArray("[\"test\",")); } catch (JSONException e) { assertEquals("Expected an exception message", - "Expected a ',' or ']' but instead found ',' at 8 [character 9 line 1]", + "Expected a ',' or ']' at 8 [character 9 line 1]", e.getMessage()); } } @@ -469,8 +469,7 @@ public class JSONArrayTest { * to the spec. However, after being parsed, toString() should emit strictly * conforming JSON text. */ - // TODO: This test will only run in non-strictMode. TBD later. - @Ignore + @Test public void unquotedText() { String str = "[value1, something!, (parens), foo@bar.com, 23, 23+45]"; JSONArray jsonArray = new JSONArray(str); @@ -686,8 +685,8 @@ public class JSONArrayTest { String jsonArrayStr = "["+ - "\"hello\","+ - "\"world\""+ + "hello,"+ + "world"+ "]"; // 2 jsonArray.put(new JSONArray(jsonArrayStr)); @@ -764,8 +763,8 @@ public class JSONArrayTest { String jsonArrayStr = "["+ - "\"hello\","+ - "\"world\""+ + "hello,"+ + "world"+ "]"; // 2 jsonArray.put(2, new JSONArray(jsonArrayStr)); diff --git a/src/test/java/org/json/junit/JSONMLTest.java b/src/test/java/org/json/junit/JSONMLTest.java index d356840..154af64 100644 --- a/src/test/java/org/json/junit/JSONMLTest.java +++ b/src/test/java/org/json/junit/JSONMLTest.java @@ -6,11 +6,6 @@ Public Domain. import static org.junit.Assert.*; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.stream.Collectors; -import java.util.stream.Stream; import org.json.*; import org.junit.Test; @@ -653,10 +648,14 @@ public class JSONMLTest { // create a JSON array from the original string and make sure it // looks as expected JSONArray jsonArray = JSONML.toJSONArray(xmlStr); + JSONArray expectedJsonArray = new JSONArray(expectedJSONArrayStr); + Util.compareActualVsExpectedJsonArrays(jsonArray,expectedJsonArray); // restore the XML, then make another JSONArray and make sure it // looks as expected String jsonArrayXmlToStr = JSONML.toString(jsonArray); + JSONArray finalJsonArray = JSONML.toJSONArray(jsonArrayXmlToStr); + Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray); // lastly, confirm the restored JSONObject XML and JSONArray XML look // reasonably similar @@ -665,31 +664,6 @@ public class JSONMLTest { Util.compareActualVsExpectedJsonObjects(jsonObjectFromObject, jsonObjectFromArray); } - @Test - public void givenXmlStr_testToJSONArray_shouldEqualExpectedArray() throws IOException { - try (Stream jsonLines = Files.lines( - Paths.get("src/test/resources/JSONArrayExpectedTestCaseForToJsonArrayTest.json")); - Stream xmlLines = Files.lines(Paths.get("src/test/resources/XmlTestCaseTestToJsonArray.xml"))) { - - String xmlStr = xmlLines.collect(Collectors.joining()); - String expectedJSONArrayStr = jsonLines.collect(Collectors.joining()); - - JSONArray jsonArray = JSONML.toJSONArray(xmlStr); - JSONArray expectedJsonArray = new JSONArray(expectedJSONArrayStr); - - assertEquals(expectedJsonArray.toString(), jsonArray.toString()); - //TODO Util.compareActualVsExpectedJsonArrays can be replaced with above assertEquals(expectedJsonArray.toString(), jsonArray.toString()) - Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray); - - String jsonArrayXmlToStr = JSONML.toString(jsonArray); - - JSONArray finalJsonArray = JSONML.toJSONArray(jsonArrayXmlToStr); - - //TODO Util.compareActualVsExpectedJsonArrays can be replaced with assertEquals(expectedJsonArray.toString(), finalJsonArray.toString()) - Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray); - } - } - /** * Convert an XML document which contains embedded comments into * a JSONArray. Use JSONML.toString() to turn it into a string, then diff --git a/src/test/java/org/json/junit/JSONObjectNumberTest.java b/src/test/java/org/json/junit/JSONObjectNumberTest.java index 739de83..43173a2 100644 --- a/src/test/java/org/json/junit/JSONObjectNumberTest.java +++ b/src/test/java/org/json/junit/JSONObjectNumberTest.java @@ -23,22 +23,22 @@ public class JSONObjectNumberTest { @Parameters(name = "{index}: {0}") public static Collection data() { return Arrays.asList(new Object[][]{ - {"{\"value\":50}", 1}, - {"{\"value\":50.0}", 1}, - {"{\"value\":5e1}", 1}, - {"{\"value\":5E1}", 1}, - {"{\"value\":5e1}", 1}, - {"{\"value\":\"50\"}", 1}, - {"{\"value\":-50}", -1}, - {"{\"value\":-50.0}", -1}, - {"{\"value\":-5e1}", -1}, - {"{\"value\":-5E1}", -1}, - {"{\"value\":-5e1}", -1}, - {"{\"value\":\"-50\"}", -1} + {"{value:50}", 1}, + {"{value:50.0}", 1}, + {"{value:5e1}", 1}, + {"{value:5E1}", 1}, + {"{value:5e1}", 1}, + {"{value:'50'}", 1}, + {"{value:-50}", -1}, + {"{value:-50.0}", -1}, + {"{value:-5e1}", -1}, + {"{value:-5E1}", -1}, + {"{value:-5e1}", -1}, + {"{value:'-50'}", -1} // JSON does not support octal or hex numbers; // see https://stackoverflow.com/a/52671839/6323312 - // "{\"value\":062}", // octal 50 - // "{\"value\":0x32}" // hex 50 + // "{value:062}", // octal 50 + // "{value:0x32}" // hex 50 }); } diff --git a/src/test/java/org/json/junit/JSONObjectTest.java b/src/test/java/org/json/junit/JSONObjectTest.java index d32a2db..fbad313 100644 --- a/src/test/java/org/json/junit/JSONObjectTest.java +++ b/src/test/java/org/json/junit/JSONObjectTest.java @@ -216,8 +216,7 @@ public class JSONObjectTest { * to the spec. However, after being parsed, toString() should emit strictly * conforming JSON text. */ - // TODO: This test will only run in non-strictMode. TBD later. - @Ignore + @Test public void unquotedText() { String str = "{key1:value1, key2:42, 1.2 : 3.4, -7e5 : something!}"; JSONObject jsonObject = new JSONObject(str); @@ -1068,8 +1067,7 @@ public class JSONObjectTest { /** * This test documents how JSON-Java handles invalid numeric input. */ - // TODO: to be restored after strictMode parsing is fixed - @Ignore + @Test public void jsonInvalidNumberValues() { // Number-notations supported by Java and invalid as JSON String str = @@ -2262,7 +2260,7 @@ public class JSONObjectTest { * Explore how JSONObject handles parsing errors. */ @SuppressWarnings({"boxing", "unused"}) - @Ignore + @Test public void jsonObjectParsingErrors() { try { // does not start with '{' @@ -2324,7 +2322,7 @@ public class JSONObjectTest { assertNull("Expected an exception",new JSONObject(str)); } catch (JSONException e) { assertEquals("Expecting an exception message", - "Value 'foo' is not surrounded by quotes at 4 [character 5] line 1]", + "Expected a ':' after a key at 5 [character 6 line 1]", e.getMessage()); } try { @@ -3817,33 +3815,27 @@ public class JSONObjectTest { // Behavior documented in #826 JSONObject parsing 0-led numeric strings as ints // After reverting the code, personId is stored as a string, and the behavior is as expected - String personId = "\"0123\""; - JSONObject j1 = new JSONObject("{\"personId\": " + personId + "}"); + String personId = "0123"; + JSONObject j1 = new JSONObject("{personId: " + personId + "}"); assertEquals(j1.getString("personId"), "0123"); // Also #826. Here is input with missing quotes. Because of the leading zero, it should not be parsed as a number. // This example was mentioned in the same ticket // After reverting the code, personId is stored as a string, and the behavior is as expected - - // TODO: the next two tests fail due to an ambiguity in parsing the value. - // non-StrictMode - it is a valid non-numeric value - // strictMode - Since it is non-numeric, quotes are required. - // This test should be extracted to its own unit test. The result should depend on the strictMode setting. - // For now it s commented out -// JSONObject j2 = new JSONObject("{\"personId\":0123}"); -// assertEquals(j2.getString("personId"), "0123"); + JSONObject j2 = new JSONObject("{\"personId\":0123}"); + assertEquals(j2.getString("personId"), "0123"); // Behavior uncovered while working on the code // All of the values are stored as strings except for hex4, which is stored as a number. This is probably incorrect -// JSONObject j3 = new JSONObject("{ " + -// "\"hex1\": \"010e4\", \"hex2\": \"00f0\", \"hex3\": \"0011\", " + -// "\"hex4\": 00e0, \"hex5\": 00f0, \"hex6\": 0011 }"); -// assertEquals(j3.getString("hex1"), "010e4"); -// assertEquals(j3.getString("hex2"), "00f0"); -// assertEquals(j3.getString("hex3"), "0011"); -// assertEquals(j3.getLong("hex4"), 0, .1); -// assertEquals(j3.getString("hex5"), "00f0"); -// assertEquals(j3.getString("hex6"), "0011"); + JSONObject j3 = new JSONObject("{ " + + "\"hex1\": \"010e4\", \"hex2\": \"00f0\", \"hex3\": \"0011\", " + + "\"hex4\": 00e0, \"hex5\": 00f0, \"hex6\": 0011 }"); + assertEquals(j3.getString("hex1"), "010e4"); + assertEquals(j3.getString("hex2"), "00f0"); + assertEquals(j3.getString("hex3"), "0011"); + assertEquals(j3.getLong("hex4"), 0, .1); + assertEquals(j3.getString("hex5"), "00f0"); + assertEquals(j3.getString("hex6"), "0011"); } /** diff --git a/src/test/java/org/json/junit/JSONParserConfigurationTest.java b/src/test/java/org/json/junit/JSONParserConfigurationTest.java index 427aad4..509b988 100644 --- a/src/test/java/org/json/junit/JSONParserConfigurationTest.java +++ b/src/test/java/org/json/junit/JSONParserConfigurationTest.java @@ -1,24 +1,14 @@ package org.json.junit; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Paths; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; import org.json.JSONParserConfiguration; import org.junit.Test; import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertThrows; import static org.junit.Assert.assertTrue; public class JSONParserConfigurationTest { - private static final String TEST_SOURCE = "{\"key\": \"value1\", \"key\": \"value2\"}"; @Test(expected = JSONException.class) @@ -29,241 +19,16 @@ public class JSONParserConfigurationTest { @Test public void testOverwrite() { JSONObject jsonObject = new JSONObject(TEST_SOURCE, - new JSONParserConfiguration().withOverwriteDuplicateKey(true)); + new JSONParserConfiguration().withOverwriteDuplicateKey(true)); assertEquals("duplicate key should be overwritten", "value2", jsonObject.getString("key")); } - @Test - public void givenInvalidInputArrays_testStrictModeTrue_shouldThrowJsonException() { - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(true); - - List strictModeInputTestCases = getNonCompliantJSONList(); - - strictModeInputTestCases.forEach( - testCase -> assertThrows("expected non-compliant array but got instead: " + testCase, JSONException.class, - () -> new JSONArray(testCase, jsonParserConfiguration))); - } - - @Test - public void givenEmptyArray_testStrictModeTrue_shouldNotThrowJsonException() { - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(true); - - String testCase = "[]"; - - JSONArray jsonArray = new JSONArray(testCase, jsonParserConfiguration); - - assertEquals(testCase, jsonArray.toString()); - } - - @Test - public void givenValidDoubleArray_testStrictModeTrue_shouldNotThrowJsonException() { - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(true); - - String testCase = "[[\"c\"], [10.2], [true, false, true]]"; - - JSONArray jsonArray = new JSONArray(testCase, jsonParserConfiguration); - JSONArray arrayShouldContainStringAt0 = jsonArray.getJSONArray(0); - JSONArray arrayShouldContainNumberAt0 = jsonArray.getJSONArray(1); - JSONArray arrayShouldContainBooleanAt0 = jsonArray.getJSONArray(2); - - assertTrue(arrayShouldContainStringAt0.get(0) instanceof String); - assertTrue(arrayShouldContainNumberAt0.get(0) instanceof Number); - assertTrue(arrayShouldContainBooleanAt0.get(0) instanceof Boolean); - } - - @Test - public void givenValidEmptyArrayInsideArray_testStrictModeTrue_shouldNotThrowJsonException(){ - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(true); - - String testCase = "[[]]"; - - JSONArray jsonArray = new JSONArray(testCase, jsonParserConfiguration); - - assertEquals(testCase, jsonArray.toString()); - } - - @Test - public void givenValidEmptyArrayInsideArray_testStrictModeFalse_shouldNotThrowJsonException(){ - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(false); - - String testCase = "[[]]"; - - JSONArray jsonArray = new JSONArray(testCase, jsonParserConfiguration); - - assertEquals(testCase, jsonArray.toString()); - } - - @Test - public void givenInvalidString_testStrictModeTrue_shouldThrowJsonException() { - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(true); - - String testCase = "[badString]"; - - JSONException je = assertThrows(JSONException.class, () -> new JSONArray(testCase, jsonParserConfiguration)); - - assertEquals("Value 'badString' is not surrounded by quotes at 10 [character 11 line 1]", je.getMessage()); - } - - @Test - public void allowNullInStrictMode() { - String expected = "[null]"; - JSONArray jsonArray = new JSONArray(expected, new JSONParserConfiguration().withStrictMode(true)); - assertEquals(expected, jsonArray.toString()); - } - - @Test - public void shouldHandleNumericArray() { - String expected = "[10]"; - JSONArray jsonArray = new JSONArray(expected, new JSONParserConfiguration().withStrictMode(true)); - assertEquals(expected, jsonArray.toString()); - } - - @Test - public void givenCompliantJSONArrayFile_testStrictModeTrue_shouldNotThrowAnyException() throws IOException { - try (Stream lines = Files.lines(Paths.get("src/test/resources/compliantJsonArray.json"))) { - String compliantJsonArrayAsString = lines.collect(Collectors.joining()); - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(true); - - new JSONArray(compliantJsonArrayAsString, jsonParserConfiguration); - } - - } - - @Test - public void givenInvalidInputArrays_testStrictModeFalse_shouldNotThrowAnyException() { - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(false); - - List strictModeInputTestCases = getNonCompliantJSONList(); - - strictModeInputTestCases.forEach(testCase -> new JSONArray(testCase, jsonParserConfiguration)); - } - - @Test - public void givenInvalidInputArray_testStrictModeTrue_shouldThrowInvalidCharacterErrorMessage() { - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(true); - - String testCase = "[1,2];[3,4]"; - - JSONException je = assertThrows("expected non-compliant array but got instead: " + testCase, - JSONException.class, () -> new JSONArray(testCase, jsonParserConfiguration)); - - assertEquals("invalid character ';' found after end of array at 6 [character 7 line 1]", je.getMessage()); - } - - @Test - public void givenInvalidInputArrayWithNumericStrings_testStrictModeTrue_shouldThrowInvalidCharacterErrorMessage() { - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(true); - - String testCase = "[\"1\",\"2\"];[3,4]"; - - JSONException je = assertThrows("expected non-compliant array but got instead: " + testCase, - JSONException.class, () -> new JSONArray(testCase, jsonParserConfiguration)); - - assertEquals("invalid character ';' found after end of array at 10 [character 11 line 1]", je.getMessage()); - } - - @Test - public void givenInvalidInputArray_testStrictModeTrue_shouldThrowValueNotSurroundedByQuotesErrorMessage() { - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(true); - - String testCase = "[{\"test\": implied}]"; - - JSONException je = assertThrows("expected non-compliant array but got instead: " + testCase, - JSONException.class, () -> new JSONArray(testCase, jsonParserConfiguration)); - - assertEquals("Value 'implied' is not surrounded by quotes at 17 [character 18 line 1]", je.getMessage()); - } - - @Test - public void givenInvalidInputArray_testStrictModeFalse_shouldNotThrowAnyException() { - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(false); - - String testCase = "[{\"test\": implied}]"; - - new JSONArray(testCase, jsonParserConfiguration); - } - - @Test - public void givenNonCompliantQuotes_testStrictModeTrue_shouldThrowJsonExceptionWithConcreteErrorDescription() { - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(true); - - String testCaseOne = "[\"abc', \"test\"]"; - String testCaseTwo = "['abc\", \"test\"]"; - String testCaseThree = "['abc']"; - String testCaseFour = "[{'testField': \"testValue\"}]"; - - JSONException jeOne = assertThrows(JSONException.class, - () -> new JSONArray(testCaseOne, jsonParserConfiguration)); - JSONException jeTwo = assertThrows(JSONException.class, - () -> new JSONArray(testCaseTwo, jsonParserConfiguration)); - JSONException jeThree = assertThrows(JSONException.class, - () -> new JSONArray(testCaseThree, jsonParserConfiguration)); - JSONException jeFour = assertThrows(JSONException.class, - () -> new JSONArray(testCaseFour, jsonParserConfiguration)); - - assertEquals( - "Value 'test' is not surrounded by quotes at 13 [character 14 line 1]", - jeOne.getMessage()); - assertEquals( - "Single quote wrap not allowed in strict mode at 2 [character 3 line 1]", - jeTwo.getMessage()); - assertEquals( - "Single quote wrap not allowed in strict mode at 2 [character 3 line 1]", - jeThree.getMessage()); - assertEquals( - "Single quote wrap not allowed in strict mode at 3 [character 4 line 1]", - jeFour.getMessage()); - } - - @Test - public void givenUnbalancedQuotes_testStrictModeFalse_shouldThrowJsonException() { - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(false); - - String testCaseOne = "[\"abc', \"test\"]"; - String testCaseTwo = "['abc\", \"test\"]"; - - JSONException jeOne = assertThrows(JSONException.class, - () -> new JSONArray(testCaseOne, jsonParserConfiguration)); - JSONException jeTwo = assertThrows(JSONException.class, - () -> new JSONArray(testCaseTwo, jsonParserConfiguration)); - - assertEquals("Unterminated string. Character with int code 0 is not allowed within a quoted string. at 15 [character 16 line 1]", jeOne.getMessage()); - assertEquals("Unterminated string. Character with int code 0 is not allowed within a quoted string. at 15 [character 16 line 1]", jeTwo.getMessage()); - } - - - @Test - public void givenInvalidInputArray_testStrictModeTrue_shouldThrowKeyNotSurroundedByQuotesErrorMessage() { - JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withStrictMode(true); - - String testCase = "[{test: implied}]"; - JSONException je = assertThrows("expected non-compliant array but got instead: " + testCase, - JSONException.class, () -> new JSONArray(testCase, jsonParserConfiguration)); - - assertEquals("Value 'test' is not surrounded by quotes at 6 [character 7 line 1]", je.getMessage()); - } - @Test public void verifyDuplicateKeyThenMaxDepth() { JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withOverwriteDuplicateKey(true) - .withMaxNestingDepth(42); + .withOverwriteDuplicateKey(true) + .withMaxNestingDepth(42); assertEquals(42, jsonParserConfiguration.getMaxNestingDepth()); assertTrue(jsonParserConfiguration.isOverwriteDuplicateKey()); @@ -272,42 +37,10 @@ public class JSONParserConfigurationTest { @Test public void verifyMaxDepthThenDuplicateKey() { JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration() - .withMaxNestingDepth(42) - .withOverwriteDuplicateKey(true); + .withMaxNestingDepth(42) + .withOverwriteDuplicateKey(true); assertTrue(jsonParserConfiguration.isOverwriteDuplicateKey()); assertEquals(42, jsonParserConfiguration.getMaxNestingDepth()); } - - /** - * This method contains short but focused use-case samples and is exclusively used to test strictMode unit tests in - * this class. - * - * @return List with JSON strings. - */ - private List getNonCompliantJSONList() { - return Arrays.asList( - "[1],", - "[1,]", - "[[1]\"sa\",[2]]a", - "[1],\"dsa\": \"test\"", - "[[a]]", - "[]asdf", - "[]]", - "[]}", - "[][", - "[]{", - "[],", - "[]:", - "[],[", - "[],{", - "[1,2];[3,4]", - "[test]", - "[{'testSingleQuote': 'testSingleQuote'}]", - "[1, 2,3]:[4,5]", - "[{test: implied}]", - "[{\"test\": implied}]", - "[{\"number\":\"7990154836330\",\"color\":'c'},{\"number\":8784148854580,\"color\":RosyBrown},{\"number\":\"5875770107113\",\"color\":\"DarkSeaGreen\"}]", - "[{test: \"implied\"}]"); - } } diff --git a/src/test/java/org/json/junit/XMLConfigurationTest.java b/src/test/java/org/json/junit/XMLConfigurationTest.java index 92a109a..e9714af 100755 --- a/src/test/java/org/json/junit/XMLConfigurationTest.java +++ b/src/test/java/org/json/junit/XMLConfigurationTest.java @@ -268,14 +268,11 @@ public class XMLConfigurationTest { " \n"+ ""; - // TODO: This test failed in strictMode due to -23x.45 not being surrounded by quotes - // It should probably be split into two tests, one of which does not run in strictMode. - // TBD. String expectedStr = "{\"addresses\":{\"address\":{\"street\":\"[CDATA[Baker street 5]\","+ - "\"name\":\"Joe Tester\",\"NothingHere\":\"\",\"TrueValue\":true,\n"+ + "\"name\":\"Joe Tester\",\"NothingHere\":\"\",TrueValue:true,\n"+ "\"FalseValue\":false,\"NullValue\":null,\"PositiveValue\":42,\n"+ - "\"NegativeValue\":-23,\"DoubleValue\":-23.45,\"Nan\":\"-23x.45\",\n"+ + "\"NegativeValue\":-23,\"DoubleValue\":-23.45,\"Nan\":-23x.45,\n"+ "\"ArrayOfNum\":\"1, 2, 3, 4.1, 5.2\"\n"+ "},\"xsi:noNamespaceSchemaLocation\":"+ "\"test.xsd\",\"xmlns:xsi\":\"http://www.w3.org/2001/"+ diff --git a/src/test/java/org/json/junit/XMLTest.java b/src/test/java/org/json/junit/XMLTest.java index be47864..3b26b22 100644 --- a/src/test/java/org/json/junit/XMLTest.java +++ b/src/test/java/org/json/junit/XMLTest.java @@ -265,13 +265,11 @@ public class XMLTest { " \n"+ ""; - // TODO: fails in strict mode because -23x.45 was not surrounded by quotes. - // Should be split into a strictMode test, and a similar non-strictMode test String expectedStr = "{\"addresses\":{\"address\":{\"street\":\"[CDATA[Baker street 5]\","+ - "\"name\":\"Joe Tester\",\"NothingHere\":\"\",\"TrueValue\":true,\n"+ + "\"name\":\"Joe Tester\",\"NothingHere\":\"\",TrueValue:true,\n"+ "\"FalseValue\":false,\"NullValue\":null,\"PositiveValue\":42,\n"+ - "\"NegativeValue\":-23,\"DoubleValue\":-23.45,\"Nan\":\"-23x.45\",\n"+ + "\"NegativeValue\":-23,\"DoubleValue\":-23.45,\"Nan\":-23x.45,\n"+ "\"ArrayOfNum\":\"1, 2, 3, 4.1, 5.2\"\n"+ "},\"xsi:noNamespaceSchemaLocation\":"+ "\"test.xsd\",\"xmlns:xsi\":\"http://www.w3.org/2001/"+ @@ -1182,7 +1180,7 @@ public class XMLTest { @Test public void shouldCreateExplicitEndTagWithEmptyValueWhenConfigured(){ - String jsonString = "{\"outer\":{\"innerOne\":\"\", \"innerTwo\":\"two\"}}"; + String jsonString = "{outer:{innerOne:\"\", innerTwo:\"two\"}}"; JSONObject jsonObject = new JSONObject(jsonString); String expectedXmlString = "two"; String xmlForm = XML.toString(jsonObject,"encloser", new XMLParserConfiguration().withCloseEmptyTag(true)); @@ -1193,7 +1191,7 @@ public class XMLTest { @Test public void shouldNotCreateExplicitEndTagWithEmptyValueWhenNotConfigured(){ - String jsonString = "{\"outer\":{\"innerOne\":\"\", \"innerTwo\":\"two\"}}"; + String jsonString = "{outer:{innerOne:\"\", innerTwo:\"two\"}}"; JSONObject jsonObject = new JSONObject(jsonString); String expectedXmlString = "two"; String xmlForm = XML.toString(jsonObject,"encloser", new XMLParserConfiguration().withCloseEmptyTag(false)); diff --git a/src/test/resources/JSONArrayExpectedTestCaseForToJsonArrayTest.json b/src/test/resources/JSONArrayExpectedTestCaseForToJsonArrayTest.json deleted file mode 100644 index 6ce0864..0000000 --- a/src/test/resources/JSONArrayExpectedTestCaseForToJsonArrayTest.json +++ /dev/null @@ -1,91 +0,0 @@ -[ - "addresses", - { - "xsi:noNamespaceSchemaLocation": "test.xsd", - "xmlns:xsi": "http://www.w3.org/2001/XMLSchema-instance" - }, - [ - "address", - { - "addrType": "my address" - }, - [ - "name", - { - "nameType": "my name" - }, - "Joe Tester" - ], - [ - "street", - "Baker street 5" - ], - [ - "NothingHere", - { - "except": "an attribute" - } - ], - [ - "TrueValue", - true - ], - [ - "FalseValue", - false - ], - [ - "NullValue", - null - ], - [ - "PositiveValue", - 42 - ], - [ - "NegativeValue", - -23 - ], - [ - "DoubleValue", - -23.45 - ], - [ - "Nan", - "-23x.45" - ], - [ - "ArrayOfNum", - [ - "value", - 1 - ], - [ - "value", - 2 - ], - [ - "value", - [ - "subValue", - { - "svAttr": "svValue" - }, - "abc" - ] - ], - [ - "value", - 3 - ], - [ - "value", - 4.1 - ], - [ - "value", - 5.2 - ] - ] - ] -] diff --git a/src/test/resources/XmlTestCaseTestToJsonArray.xml b/src/test/resources/XmlTestCaseTestToJsonArray.xml deleted file mode 100644 index dfcf9d9..0000000 --- a/src/test/resources/XmlTestCaseTestToJsonArray.xml +++ /dev/null @@ -1,27 +0,0 @@ - - - -

- Joe Tester - - - true - false - null - 42 - -23 - -23.45 - -23x.45 - - 1 - 2 - - abc - - 3 - 4.1 - 5.2 - -
- \ No newline at end of file diff --git a/src/test/resources/compliantJsonArray.json b/src/test/resources/compliantJsonArray.json deleted file mode 100644 index c373690..0000000 --- a/src/test/resources/compliantJsonArray.json +++ /dev/null @@ -1,317 +0,0 @@ -[ - { - "_id": "6606c27d2ab4a0102d49420a", - "index": 0, - "guid": "441331fb-84d1-4873-a649-3814621a0370", - "isActive": true, - "balance": "$2,691.63", - "picture": "http://example.abc/32x32", - "age": 26, - "eyeColor": "blue", - "name": "abc", - "gender": "female", - "company": "example", - "email": "abc@def.com", - "phone": "+1 (123) 456-7890", - "address": "123 Main St", - "about": "Laborum magna tempor officia irure cillum nulla incididunt Lorem dolor veniam elit cupidatat amet. Veniam veniam exercitation nulla consectetur officia esse ex sunt nulla nisi ea cillum nisi reprehenderit. Qui aliquip reprehenderit aliqua aliquip aliquip anim sit magna nostrud dolore veniam velit elit aliquip.\r\n", - "registered": "2016-07-22T03:18:11 -01:00", - "latitude": -21.544934, - "longitude": 72.765495, - "tags": [ - "consectetur", - "minim", - "sunt", - "in", - "ut", - "velit", - "anim" - ], - "friends": [ - { - "id": 0, - "name": "abc def" - }, - { - "id": 1, - "name": "ghi jkl" - }, - { - "id": 2, - "name": "mno pqr" - } - ], - "greeting": "Hello, abc! You have 10 unread messages.", - "favoriteFruit": "banana" - }, - { - "_id": "6606c27d0a45df5121fb765f", - "index": 1, - "guid": "fd774715-de85-44b9-b498-c214d8f68d9f", - "isActive": true, - "balance": "$2,713.96", - "picture": "http://placehold.it/32x32", - "age": 27, - "eyeColor": "green", - "name": "def", - "gender": "female", - "company": "sample", - "email": "def@abc.com", - "phone": "+1 (123) 456-78910", - "address": "1234 Main St", - "about": "Ea id cupidatat eiusmod culpa. Nulla consequat esse elit enim et pariatur eiusmod ipsum. Consequat eu non reprehenderit in.\r\n", - "registered": "2015-04-06T07:54:22 -01:00", - "latitude": 83.512347, - "longitude": -9.368739, - "tags": [ - "excepteur", - "non", - "nostrud", - "laboris", - "laboris", - "qui", - "aute" - ], - "friends": [ - { - "id": 0, - "name": "sample example" - }, - { - "id": 1, - "name": "test name" - }, - { - "id": 2, - "name": "aaa aaaa" - } - ], - "greeting": "Hello, test! You have 7 unread messages.", - "favoriteFruit": "apple" - }, - { - "_id": "6606c27dfb3a0e4e7e7183d3", - "index": 2, - "guid": "688b0c36-98e0-4ee7-86b8-863638d79b5f", - "isActive": false, - "balance": "$3,514.35", - "picture": "http://placehold.it/32x32", - "age": 32, - "eyeColor": "green", - "name": "test", - "gender": "female", - "company": "test", - "email": "test@test.com", - "phone": "+1 (123) 456-7890", - "address": "123 Main St", - "about": "Mollit officia adipisicing ex nisi non Lorem sunt quis est. Irure exercitation duis ipsum qui ullamco eu ea commodo occaecat minim proident. Incididunt nostrud ex cupidatat eiusmod mollit anim irure culpa. Labore voluptate voluptate labore nisi sit eu. Dolor sit proident velit dolor deserunt labore sit ipsum incididunt eiusmod reprehenderit voluptate. Duis anim velit officia laboris consequat officia dolor sint dolor nisi ex.\r\n", - "registered": "2021-11-02T12:50:05 -00:00", - "latitude": -82.969939, - "longitude": 86.415645, - "tags": [ - "aliquip", - "et", - "est", - "nulla", - "nulla", - "tempor", - "adipisicing" - ], - "friends": [ - { - "id": 0, - "name": "test" - }, - { - "id": 1, - "name": "sample" - }, - { - "id": 2, - "name": "example" - } - ], - "greeting": "Hello, test! You have 1 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "6606c27d204bc2327fc9ba23", - "index": 3, - "guid": "be970cba-306e-4cbd-be08-c265a43a61fa", - "isActive": true, - "balance": "$3,691.63", - "picture": "http://placehold.it/32x32", - "age": 35, - "eyeColor": "brown", - "name": "another test", - "gender": "male", - "company": "TEST", - "email": "anothertest@anothertest.com", - "phone": "+1 (321) 987-6543", - "address": "123 Example Main St", - "about": "Do proident consectetur minim quis. In adipisicing culpa Lorem fugiat cillum exercitation velit velit. Non voluptate laboris deserunt veniam et sint consectetur irure aliqua quis eiusmod consectetur elit id. Ex sint do anim Lorem excepteur eu nulla.\r\n", - "registered": "2020-06-25T04:55:25 -01:00", - "latitude": 63.614955, - "longitude": -109.299405, - "tags": [ - "irure", - "esse", - "non", - "mollit", - "laborum", - "adipisicing", - "ad" - ], - "friends": [ - { - "id": 0, - "name": "test" - }, - { - "id": 1, - "name": "sample" - }, - { - "id": 2, - "name": "example" - } - ], - "greeting": "Hello, another test! You have 5 unread messages.", - "favoriteFruit": "apple" - }, - { - "_id": "6606c27df63eb5f390cb9989", - "index": 4, - "guid": "2c3e5115-758d-468e-99c5-c9afa26e1f9f", - "isActive": true, - "balance": "$1,047.20", - "picture": "http://test.it/32x32", - "age": 30, - "eyeColor": "green", - "name": "Test Name", - "gender": "female", - "company": "test", - "email": "testname@testname.com", - "phone": "+1 (999) 999-9999", - "address": "999 Test Main St", - "about": "Voluptate exercitation tempor consectetur velit magna ea occaecat cupidatat consectetur anim aute. Aliquip est aute ipsum laboris non irure qui consectetur tempor quis do ea Lorem. Cupidatat exercitation ad culpa aliqua amet commodo mollit reprehenderit exercitation adipisicing amet et laborum pariatur.\r\n", - "registered": "2023-01-19T02:43:18 -00:00", - "latitude": 14.15208, - "longitude": 170.411535, - "tags": [ - "dolor", - "qui", - "cupidatat", - "aliqua", - "laboris", - "reprehenderit", - "sint" - ], - "friends": [ - { - "id": 0, - "name": "test" - }, - { - "id": 1, - "name": "sample" - }, - { - "id": 2, - "name": "example" - } - ], - "greeting": "Hello, test! You have 6 unread messages.", - "favoriteFruit": "apple" - }, - { - "_id": "6606c27d01d19fa29853d59c", - "index": 5, - "guid": "816cda74-5d4b-498f-9724-20f340d5f5bf", - "isActive": false, - "balance": "$2,628.74", - "picture": "http://testing.it/32x32", - "age": 28, - "eyeColor": "green", - "name": "Testing", - "gender": "female", - "company": "test", - "email": "testing@testing.com", - "phone": "+1 (888) 888-8888", - "address": "123 Main St", - "about": "Cupidatat non ut nulla qui excepteur in minim non et nulla fugiat. Dolor quis laborum occaecat veniam dolor ullamco deserunt amet veniam dolor quis proident tempor laboris. In cillum duis ut quis. Aliqua cupidatat magna proident velit tempor veniam et consequat laborum ex dolore qui. Incididunt deserunt magna minim Lorem consectetur.\r\n", - "registered": "2017-10-14T11:14:08 -01:00", - "latitude": -5.345728, - "longitude": -9.706491, - "tags": [ - "officia", - "velit", - "laboris", - "qui", - "cupidatat", - "cupidatat", - "ad" - ], - "friends": [ - { - "id": 0, - "name": "test" - }, - { - "id": 1, - "name": "sample" - }, - { - "id": 2, - "name": "example" - } - ], - "greeting": "Hello, testing! You have 2 unread messages.", - "favoriteFruit": "strawberry" - }, - { - "_id": "6606c27d803003cede1d6deb", - "index": 6, - "guid": "4ee550bc-0920-4104-b3ce-ebf9db6a803f", - "isActive": true, - "balance": "$1,709.31", - "picture": "http://sample.it/32x32", - "age": 31, - "eyeColor": "blue", - "name": "Sample Name", - "gender": "female", - "company": "Sample", - "email": "sample@sample.com", - "phone": "+1 (777) 777-7777", - "address": "123 Main St", - "about": "Lorem ex proident ipsum ullamco velit sit nisi eiusmod cillum. Id tempor irure culpa nisi sit non qui veniam non ut. Aliquip reprehenderit excepteur mollit quis excepteur ex sit. Quis do eu veniam do ullamco occaecat eu cupidatat nisi laborum tempor minim fugiat pariatur. Ex in nulla ex velit.\r\n", - "registered": "2019-04-08T03:54:36 -01:00", - "latitude": -70.660321, - "longitude": 71.547525, - "tags": [ - "consequat", - "veniam", - "pariatur", - "aliqua", - "cillum", - "eu", - "officia" - ], - "friends": [ - { - "id": 0, - "name": "Test" - }, - { - "id": 1, - "name": "Sample" - }, - { - "id": 2, - "name": "Example" - } - ], - "greeting": "Hello, Sample! You have 6 unread messages.", - "favoriteFruit": "apple" - } -] \ No newline at end of file