mirror of
https://github.com/stleary/JSON-java.git
synced 2025-08-03 03:15:32 -04:00
Merge pull request #911 from stleary/revert-strict-mode-for-now
Revert strict mode
This commit is contained in:
commit
39ee5e092f
@ -75,104 +75,55 @@ public class JSONArray implements Iterable<Object> {
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a JSONArray from a JSONTokener.
|
||||
* <p>
|
||||
* 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<Object> {
|
||||
* 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 <code>[</code> <small>(left bracket)</small> and
|
||||
* ends with <code>]</code> <small>(right bracket)</small>.
|
||||
* @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));
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1962,7 +1901,6 @@ public class JSONArray implements Iterable<Object> {
|
||||
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<Object> {
|
||||
"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<Object> {
|
||||
, cause);
|
||||
}
|
||||
|
||||
private static String getInvalidCharErrorMsg(char cursor) {
|
||||
return String.format("invalid character '%s' found after end of array", cursor);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
@ -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<Character> 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<Character>(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
|
||||
* <code>"</code> <small>(double quote)</small> or
|
||||
* <code>'</code> <small>(single quote)</small>.
|
||||
* @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.
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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<String> jsonLines = Files.lines(
|
||||
Paths.get("src/test/resources/JSONArrayExpectedTestCaseForToJsonArrayTest.json"));
|
||||
Stream<String> 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
|
||||
|
@ -23,22 +23,22 @@ public class JSONObjectNumberTest {
|
||||
@Parameters(name = "{index}: {0}")
|
||||
public static Collection<Object[]> 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
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -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");
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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<String> 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<String> 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<String> 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<String> 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\"}]");
|
||||
}
|
||||
}
|
||||
|
@ -268,14 +268,11 @@ public class XMLConfigurationTest {
|
||||
" </address>\n"+
|
||||
"</addresses>";
|
||||
|
||||
// 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/"+
|
||||
|
@ -265,13 +265,11 @@ public class XMLTest {
|
||||
" </address>\n"+
|
||||
"</addresses>";
|
||||
|
||||
// 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 = "<encloser><outer><innerOne></innerOne><innerTwo>two</innerTwo></outer></encloser>";
|
||||
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 = "<encloser><outer><innerOne/><innerTwo>two</innerTwo></outer></encloser>";
|
||||
String xmlForm = XML.toString(jsonObject,"encloser", new XMLParserConfiguration().withCloseEmptyTag(false));
|
||||
|
@ -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
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
@ -1,27 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
|
||||
<addresses xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:noNamespaceSchemaLocation='test.xsd'>
|
||||
<address addrType="my address">
|
||||
<name nameType="my name">Joe Tester</name>
|
||||
<street><![CDATA[Baker street 5]]></street>
|
||||
<NothingHere except="an attribute"/>
|
||||
<TrueValue>true</TrueValue>
|
||||
<FalseValue>false</FalseValue>
|
||||
<NullValue>null</NullValue>
|
||||
<PositiveValue>42</PositiveValue>
|
||||
<NegativeValue>-23</NegativeValue>
|
||||
<DoubleValue>-23.45</DoubleValue>
|
||||
<Nan>-23x.45</Nan>
|
||||
<ArrayOfNum>
|
||||
<value>1</value>
|
||||
<value>2</value>
|
||||
<value>
|
||||
<subValue svAttr="svValue">abc</subValue>
|
||||
</value>
|
||||
<value>3</value>
|
||||
<value>4.1</value>
|
||||
<value>5.2</value>
|
||||
</ArrayOfNum>
|
||||
</address>
|
||||
</addresses>
|
@ -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"
|
||||
}
|
||||
]
|
Loading…
x
Reference in New Issue
Block a user