mirror of
https://github.com/stleary/JSON-java.git
synced 2025-08-02 11:05:28 -04:00
fix(#887): regressions, unit tests
- JSONArray now evaluates EOF accordingly for empty Array inputs. - JSONTokener fixed indentation - externalized two JSONMLTest cases
This commit is contained in:
parent
cf00ef3e8a
commit
1ae43bdb90
@ -136,9 +136,13 @@ public class JSONArray implements Iterable<Object> {
|
||||
case ']':
|
||||
if (strictMode) {
|
||||
cursor = x.nextClean();
|
||||
boolean isNotEoF = !x.end();
|
||||
boolean isEoF = x.end();
|
||||
|
||||
if (isNotEoF && x.getArrayLevel() == 0) {
|
||||
if (isEoF) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (x.getArrayLevel() == 0) {
|
||||
throw x.syntaxError(getInvalidCharErrorMsg(cursor));
|
||||
}
|
||||
|
||||
|
@ -325,77 +325,66 @@ 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.
|
||||
* If strictMode is true, this implementation will not accept unbalanced quotes (e.g will not accept <code>"test'</code>).
|
||||
* 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>.
|
||||
* @param strictMode If true, this implementation will not accept unbalanced quotes (e.g will not accept <code>"test'</code>).
|
||||
* @return A String.
|
||||
* @throws JSONException Unterminated string or unbalanced quotes if strictMode == true.
|
||||
*/
|
||||
public String nextString(char quote, boolean strictMode) throws JSONException {
|
||||
public String nextString(char quote) throws JSONException {
|
||||
char c;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
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);
|
||||
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.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw this.syntaxError("Illegal escape. Escape sequence \\" + c + " is not valid.");
|
||||
}
|
||||
break;
|
||||
default:
|
||||
if (strictMode && c == '\"' && quote != c) {
|
||||
throw this.syntaxError(String.format(
|
||||
"Field contains unbalanced quotes. Starts with %s but ends with double quote.", quote));
|
||||
}
|
||||
|
||||
if (strictMode && c == '\'' && quote != c) {
|
||||
throw this.syntaxError(String.format(
|
||||
"Field contains unbalanced quotes. Starts with %s but ends with single quote.", quote));
|
||||
}
|
||||
|
||||
if (c == quote) {
|
||||
return sb.toString();
|
||||
}
|
||||
@ -404,7 +393,6 @@ public class JSONTokener {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the text up but not including the specified character or the
|
||||
* end of line, whichever comes first.
|
||||
@ -528,15 +516,24 @@ public class JSONTokener {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 == '\''){
|
||||
if (strictMode && c == '\'') {
|
||||
throw this.syntaxError("Single quote wrap not allowed in strict mode");
|
||||
}
|
||||
|
||||
if (c == '"' || c == '\'') {
|
||||
return this.nextString(c, strictMode);
|
||||
return this.nextString(c);
|
||||
}
|
||||
|
||||
return parsedUnquotedText(c, strictMode);
|
||||
|
@ -24,16 +24,12 @@ public class CDLTest {
|
||||
* String of lines where the column names are in the first row,
|
||||
* and all subsequent rows are values. All keys and values should be legal.
|
||||
*/
|
||||
// TODO: This regression causes several unit tests to fail in strictMode.
|
||||
// a single quote embedded in a valid st ring value should be allowed.
|
||||
// This probably needs to be fixed in the strictMode parser.
|
||||
private static final String LINES = "Col 1, Col 2, \tCol 3, Col 4, Col 5, Col 6, Col 7\n" +
|
||||
"val1, val2, val3, val4, val5, val6, val7\n" +
|
||||
"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\", \"val6\", 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
|
||||
@ -46,8 +42,7 @@ public class CDLTest {
|
||||
"{\"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\"}]";
|
||||
"{\"Col 1\":\"va\tl1\", \"Col 2\":\"v\bal2\", \"Col 3\":\"val3\", \"Col 4\":\"val\f4\", \"Col 5\":\"val5\", \"Col 6\":\"val6\", \"Col 7\":\"val7\"}]";
|
||||
"{\"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.
|
||||
|
@ -6,6 +6,11 @@ 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;
|
||||
|
||||
@ -648,16 +653,10 @@ public class JSONMLTest {
|
||||
// create a JSON array from the original string and make sure it
|
||||
// looks as expected
|
||||
JSONArray jsonArray = JSONML.toJSONArray(xmlStr);
|
||||
// TODO: The next 2 test cases fail due to a strictMode regression. They should be isolated in separate
|
||||
// test cases and fixed.
|
||||
// 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
|
||||
@ -666,6 +665,31 @@ 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
|
||||
|
@ -47,14 +47,15 @@ public class JSONParserConfigurationTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenEmptyArray_testStrictModeTrue_shouldNotThrowJsonException(){
|
||||
public void givenEmptyArray_testStrictModeTrue_shouldNotThrowJsonException() {
|
||||
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
|
||||
.withStrictMode(true);
|
||||
|
||||
String testCase = "[]";
|
||||
|
||||
JSONArray jsonArray = new JSONArray(testCase, jsonParserConfiguration);
|
||||
System.out.println(jsonArray);
|
||||
|
||||
assertEquals(testCase, jsonArray.toString());
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -215,7 +216,7 @@ public class JSONParserConfigurationTest {
|
||||
() -> new JSONArray(testCaseFour, jsonParserConfiguration));
|
||||
|
||||
assertEquals(
|
||||
"Field contains unbalanced quotes. Starts with \" but ends with single quote. at 6 [character 7 line 1]",
|
||||
"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]",
|
||||
|
@ -94,11 +94,9 @@ public class JSONTokenerTest {
|
||||
checkValid(" {} ",JSONObject.class);
|
||||
checkValid("{\"a\":1}",JSONObject.class);
|
||||
checkValid(" {\"a\":1} ",JSONObject.class);
|
||||
// TODO: strictMode regression, needs to be fixed.
|
||||
// checkValid("[]",JSONArray.class);
|
||||
checkValid("[]",JSONArray.class);
|
||||
checkValid(" [] ",JSONArray.class);
|
||||
// TODO: strictMode regression, needs to be fixed
|
||||
// checkValid("[1,2]",JSONArray.class);
|
||||
checkValid("[1,2]",JSONArray.class);
|
||||
checkValid("\n\n[1,2]\n\n",JSONArray.class);
|
||||
// TODO: strictMode regression, needs to be fixed
|
||||
// checkValid("1 2", String.class);
|
||||
|
@ -0,0 +1,91 @@
|
||||
[
|
||||
"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
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
27
src/test/resources/XmlTestCaseTestToJsonArray.xml
Normal file
27
src/test/resources/XmlTestCaseTestToJsonArray.xml
Normal file
@ -0,0 +1,27 @@
|
||||
<?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>
|
Loading…
x
Reference in New Issue
Block a user