1
0
Fork 0
mirror of https://github.com/ethauvin/JSON-java.git synced 2025-06-17 16:00:51 -07:00

Merge remote-tracking branch 'tests/master' into upstream

This commit is contained in:
Benjamin Gehrels 2020-04-29 20:26:05 +02:00
commit 1265897f4e
45 changed files with 11062 additions and 1 deletions

View file

@ -0,0 +1,300 @@
package org.json.junit;
import static org.junit.Assert.*;
import org.junit.Test;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONArray;
import org.json.CDL;
/**
* Tests for CDL.java.
* CDL provides an application level API, but it is not used by the
* reference app. To test it, strings will be converted to JSON-Java classes
* and then converted back.
*/
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.
*/
String lines = new String(
"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"
);
/**
* CDL.toJSONArray() adds all values as strings, with no filtering or
* conversions. For testing, this means that the expected JSONObject
* values all must be quoted in the cases where the JSONObject parsing
* might normally convert the value into a non-string.
*/
String expectedLines = new String(
"[{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.
* Expect a NullPointerException.
*/
@Test(expected=NullPointerException.class)
public void exceptionOnNullString() {
String nullStr = null;
CDL.toJSONArray(nullStr);
}
/**
* Attempts to create a JSONArray from a string with unbalanced quotes
* in column title line. Expects a JSONException.
*/
@Test
public void unbalancedQuoteInName() {
String badLine = "Col1, \"Col2\nVal1, Val2";
try {
CDL.toJSONArray(badLine);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Missing close quote '\"'. at 12 [character 0 line 2]",
e.getMessage());
}
}
/**
* Attempts to create a JSONArray from a string with unbalanced quotes
* in value line. Expects a JSONException.
*/
@Test
public void unbalancedQuoteInValue() {
String badLine = "Col1, Col2\n\"Val1, Val2";
try {
CDL.toJSONArray(badLine);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Missing close quote '\"'. at 22 [character 11 line 2]",
e.getMessage());
}
}
/**
* Attempts to create a JSONArray from a string with null char
* in column title line. Expects a JSONException.
*/
@Test
public void nullInName() {
String badLine = "C\0ol1, Col2\nVal1, Val2";
try {
CDL.toJSONArray(badLine);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Bad character 'o' (111). at 2 [character 3 line 1]",
e.getMessage());
}
}
/**
* Attempt to create a JSONArray with unbalanced quotes and a properly escaped doubled quote.
* Expects a JSONException.
*/
@Test
public void unbalancedEscapedQuote(){
String badLine = "Col1, Col2\n\"Val1, \"\"Val2\"\"";
try {
CDL.toJSONArray(badLine);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Missing close quote '\"'. at 26 [character 15 line 2]",
e.getMessage());
}
}
/**
* Assert that there is no error for a single escaped quote within a properly embedded quote.
*/
@Test
public void singleEscapedQuote(){
String singleEscape = "Col1, Col2\nVal1, \"\"\"Val2\"";
JSONArray jsonArray = CDL.toJSONArray(singleEscape);
String cdlStr = CDL.toString(jsonArray);
assertTrue(cdlStr.contains("Col1"));
assertTrue(cdlStr.contains("Col2"));
assertTrue(cdlStr.contains("Val1"));
assertTrue(cdlStr.contains("\"Val2"));
}
/**
* Assert that there is no error for a single escaped quote within a properly
* embedded quote when not the last value.
*/
@Test
public void singleEscapedQuoteMiddleString(){
String singleEscape = "Col1, Col2\nVal1, \"\"\"Val2\"\nVal 3,Val 4";
JSONArray jsonArray = CDL.toJSONArray(singleEscape);
String cdlStr = CDL.toString(jsonArray);
assertTrue(cdlStr.contains("Col1"));
assertTrue(cdlStr.contains("Col2"));
assertTrue(cdlStr.contains("Val1"));
assertTrue(cdlStr.contains("\"Val2"));
}
/**
* Attempt to create a JSONArray with an escape quote and no enclosing quotes.
* Expects a JSONException.
*/
@Test
public void badEscapedQuote(){
String badLine = "Col1, Col2\nVal1, \"\"Val2";
try {
CDL.toJSONArray(badLine);
fail("Expecting an exception");
} catch (JSONException e) {
System.out.println("Message" + e.getMessage());
assertEquals("Expecting an exception message",
"Bad character 'V' (86). at 20 [character 9 line 2]",
e.getMessage());
}
}
/**
* call toString with a null array
*/
@Test(expected=NullPointerException.class)
public void nullJSONArrayToString() {
CDL.toString((JSONArray)null);
}
/**
* Create a JSONArray from an empty string
*/
@Test
public void emptyString() {
String emptyStr = "";
JSONArray jsonArray = CDL.toJSONArray(emptyStr);
assertTrue("CDL should return null when the input string is empty",
jsonArray == null);
}
/**
* Create a JSONArray with only 1 row
*/
@Test
public void onlyColumnNames() {
String columnNameStr = "col1, col2, col3";
JSONArray jsonArray = CDL.toJSONArray(columnNameStr);
assertNull("CDL should return null when only 1 row is given",
jsonArray);
}
/**
* Create a JSONArray from string containing only whitespace and commas
*/
@Test
public void emptyLinesToJSONArray() {
String str = " , , , \n , , , ";
JSONArray jsonArray = CDL.toJSONArray(str);
assertNull("JSONArray should be null for no content",
jsonArray);
}
/**
* call toString with a null array
*/
@Test
public void emptyJSONArrayToString() {
JSONArray jsonArray = new JSONArray();
String str = CDL.toString(jsonArray);
assertNull("CDL should return null for toString(null)",
str);
}
/**
* call toString with a null arrays for names and values
*/
@Test
public void nullJSONArraysToString() {
String str = CDL.toString(null, null);
assertNull("CDL should return null for toString(null)",
str);
}
/**
* Given a JSONArray that was not built by CDL, some chars may be
* found that would otherwise be filtered out by CDL.
*/
@Test
public void checkSpecialChars() {
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject = new JSONObject();
jsonArray.put(jsonObject);
// \r will be filtered from name
jsonObject.put("Col \r1", "V1");
// \r will be filtered from value
jsonObject.put("Col 2", "V2\r");
assertTrue("expected length should be 1",jsonArray.length() == 1);
String cdlStr = CDL.toString(jsonArray);
jsonObject = jsonArray.getJSONObject(0);
assertTrue(cdlStr.contains("\"Col 1\""));
assertTrue(cdlStr.contains("Col 2"));
assertTrue(cdlStr.contains("V1"));
assertTrue(cdlStr.contains("\"V2\""));
}
/**
* Create a JSONArray from a string of lines
*/
@Test
public void textToJSONArray() {
JSONArray jsonArray = CDL.toJSONArray(this.lines);
JSONArray expectedJsonArray = new JSONArray(this.expectedLines);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
}
/**
* Create a JSONArray from a JSONArray of titles and a
* string of value lines
*/
@Test
public void jsonArrayToJSONArray() {
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}]");
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
}
/**
* Create a JSONArray from a string of lines,
* then convert to string and then back to JSONArray
*/
@Test
public void textToJSONArrayAndBackToString() {
JSONArray jsonArray = CDL.toJSONArray(this.lines);
String jsonStr = CDL.toString(jsonArray);
JSONArray finalJsonArray = CDL.toJSONArray(jsonStr);
JSONArray expectedJsonArray = new JSONArray(this.expectedLines);
Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
}
}

View file

@ -0,0 +1,186 @@
package org.json.junit;
import static org.junit.Assert.*;
import java.util.*;
import org.json.*;
import org.junit.Test;
import com.jayway.jsonpath.*;
/**
* HTTP cookie specification RFC6265: http://tools.ietf.org/html/rfc6265
* <p>
* A cookie list is a JSONObject whose members are presumed to be cookie
* name/value pairs. Entries are unescaped while being added, and escaped in
* the toString() output.
* Unescaping means to convert %hh hex strings to the ascii equivalent
* and converting '+' to ' '.
* Escaping converts '+', '%', '=', ';' and ascii control chars to %hh hex strings.
* <p>
* CookieList should not be considered as just a list of Cookie objects:<br>
* - CookieList stores a cookie name/value pair as a single entry; Cookie stores
* it as 2 entries (key="name" and key="value").<br>
* - CookieList requires multiple name/value pairs as input; Cookie allows the
* 'secure' name with no associated value<br>
* - CookieList has no special handling for attribute name/value pairs.<br>
*/
public class CookieListTest {
/**
* Attempts to create a CookieList from a null string.
* Expects a NullPointerException.
*/
@Test(expected=NullPointerException.class)
public void nullCookieListException() {
String cookieStr = null;
CookieList.toJSONObject(cookieStr);
}
/**
* Attempts to create a CookieList from a malformed string.
* Expects a JSONException.
*/
@Test
public void malFormedCookieListException() {
String cookieStr = "thisCookieHasNoEqualsChar";
try {
CookieList.toJSONObject(cookieStr);
fail("should throw an exception");
} catch (JSONException e) {
/**
* Not sure of the missing char, but full string compare fails
*/
assertEquals("Expecting an exception message",
"Expected '=' and instead saw '' at 25 [character 26 line 1]",
e.getMessage());
}
}
/**
* Creates a CookieList from an empty string.
*/
@Test
public void emptyStringCookieList() {
String cookieStr = "";
JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
assertTrue(jsonObject.isEmpty());
}
/**
* CookieList with the simplest cookie - a name/value pair with no delimiter.
*/
@Test
public void simpleCookieList() {
String cookieStr = "SID=31d4d96e407aad42";
JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("Expected 1 top level item", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 1);
assertTrue("expected 31d4d96e407aad42", "31d4d96e407aad42".equals(jsonObject.query("/SID")));
}
/**
* CookieList with a single a cookie which has a name/value pair and delimiter.
*/
@Test
public void simpleCookieListWithDelimiter() {
String cookieStr = "SID=31d4d96e407aad42;";
JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("Expected 1 top level item", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 1);
assertTrue("expected 31d4d96e407aad42", "31d4d96e407aad42".equals(jsonObject.query("/SID")));
}
/**
* CookieList with multiple cookies consisting of name/value pairs
* with delimiters.
*/
@Test
public void multiPartCookieList() {
String cookieStr =
"name1=myCookieValue1; "+
" name2=myCookieValue2;"+
"name3=myCookieValue3;"+
" name4=myCookieValue4; "+
"name5=myCookieValue5;"+
" name6=myCookieValue6;";
JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("Expected 6 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 6);
assertTrue("expected myCookieValue1", "myCookieValue1".equals(jsonObject.query("/name1")));
assertTrue("expected myCookieValue2", "myCookieValue2".equals(jsonObject.query("/name2")));
assertTrue("expected myCookieValue3", "myCookieValue3".equals(jsonObject.query("/name3")));
assertTrue("expected myCookieValue4", "myCookieValue4".equals(jsonObject.query("/name4")));
assertTrue("expected myCookieValue5", "myCookieValue5".equals(jsonObject.query("/name5")));
assertTrue("expected myCookieValue6", "myCookieValue6".equals(jsonObject.query("/name6")));
}
/**
* CookieList from a JSONObject with valid key and null value
*/
@Test
public void convertCookieListWithNullValueToString() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("key", JSONObject.NULL);
String cookieToStr = CookieList.toString(jsonObject);
assertTrue("toString() should be empty", "".equals(cookieToStr));
}
/**
* CookieList with multiple entries converted to a JSON document.
*/
@Test
public void convertCookieListToString() {
String cookieStr =
"name1=myCookieValue1; "+
" name2=myCookieValue2;"+
"name3=myCookieValue3;"+
" name4=myCookieValue4; "+
"name5=myCookieValue5;"+
" name6=myCookieValue6;";
JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
// exercise CookieList.toString()
String cookieListString = CookieList.toString(jsonObject);
// have to convert it back for validation
jsonObject = CookieList.toJSONObject(cookieListString);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("Expected 6 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 6);
assertTrue("expected myCookieValue1", "myCookieValue1".equals(jsonObject.query("/name1")));
assertTrue("expected myCookieValue2", "myCookieValue2".equals(jsonObject.query("/name2")));
assertTrue("expected myCookieValue3", "myCookieValue3".equals(jsonObject.query("/name3")));
assertTrue("expected myCookieValue4", "myCookieValue4".equals(jsonObject.query("/name4")));
assertTrue("expected myCookieValue5", "myCookieValue5".equals(jsonObject.query("/name5")));
assertTrue("expected myCookieValue6", "myCookieValue6".equals(jsonObject.query("/name6")));
}
/**
* CookieList with multiple entries and some '+' chars and URL-encoded
* values converted to a JSON document.
*/
@Test
public void convertEncodedCookieListToString() {
String cookieStr =
"name1=myCookieValue1; "+
" name2=my+Cookie+Value+2;"+
"name3=my%2BCookie%26Value%3B3%3D;"+
" name4=my%25CookieValue4; "+
"name5=myCookieValue5;"+
" name6=myCookieValue6;";
JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("Expected 6 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 6);
assertTrue("expected myCookieValue1", "myCookieValue1".equals(jsonObject.query("/name1")));
assertTrue("expected my Cookie Value 2", "my Cookie Value 2".equals(jsonObject.query("/name2")));
assertTrue("expected my+Cookie&Value;3=", "my+Cookie&Value;3=".equals(jsonObject.query("/name3")));
assertTrue("expected my%CookieValue4", "my%CookieValue4".equals(jsonObject.query("/name4")));
assertTrue("expected my%CookieValue5", "myCookieValue5".equals(jsonObject.query("/name5")));
assertTrue("expected myCookieValue6", "myCookieValue6".equals(jsonObject.query("/name6")));
}
}

View file

@ -0,0 +1,226 @@
package org.json.junit;
import static org.junit.Assert.*;
import org.json.*;
import org.junit.Test;
/**
* HTTP cookie specification: RFC6265
* <p>
* At its most basic, a cookie is a name=value pair. The value may be subdivided
* into other cookies, but that is not tested here. The cookie may also include
* certain named attributes, delimited by semicolons.
* <p>
* The Cookie.toString() method emits certain attributes if present: expires,
* domain, path, secure. All but secure are name-value pairs. Other attributes
* are not included in the toString() output.
* <p>
* A JSON-Java encoded cookie escapes '+', '%', '=', ';' with %hh values.
*/
public class CookieTest {
/**
* Attempts to create a JSONObject from a null string.
* Expects a NullPointerException.
*/
@Test(expected=NullPointerException.class)
public void nullCookieException() {
String cookieStr = null;
Cookie.toJSONObject(cookieStr);
}
/**
* Attempts to create a JSONObject from a cookie string with
* no '=' char.
* Expects a JSONException.
*/
@Test
public void malFormedNameValueException() {
String cookieStr = "thisCookieHasNoEqualsChar";
try {
Cookie.toJSONObject(cookieStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Expected '=' and instead saw '' at 25 [character 26 line 1]",
e.getMessage());
}
}
/**
* Attempts to create a JSONObject from a cookie string
* with embedded ';' char.
* Expects a JSONException.
*/
@Test
public void malFormedAttributeException() {
String cookieStr = "this=Cookie;myAttribute";
try {
Cookie.toJSONObject(cookieStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Missing '=' in cookie parameter. at 23 [character 24 line 1]",
e.getMessage());
}
}
/**
* Attempts to create a JSONObject from an empty cookie string.<br>
* Note: Cookie throws an exception, but CookieList does not.<br>
* Expects a JSONException
*/
@Test
public void emptyStringCookieException() {
String cookieStr = "";
try {
Cookie.toJSONObject(cookieStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Expected '=' and instead saw '' at 0 [character 1 line 1]",
e.getMessage());
}
}
/**
* Cookie from a simple name/value pair with no delimiter
*/
@Test
public void simpleCookie() {
String cookieStr = "SID=31d4d96e407aad42";
String expectedCookieStr = "{\"name\":\"SID\",\"value\":\"31d4d96e407aad42\"}";
JSONObject jsonObject = Cookie.toJSONObject(cookieStr);
JSONObject expectedJsonObject = new JSONObject(expectedCookieStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Store a cookie with all of the supported attributes in a
* JSONObject. The secure attribute, which has no value, is treated
* as a boolean.
*/
@Test
public void multiPartCookie() {
String cookieStr =
"PH=deleted; "+
" expires=Wed, 19-Mar-2014 17:53:53 GMT;"+
"path=/; "+
" domain=.yahoo.com;"+
"secure";
String expectedCookieStr =
"{"+
"\"name\":\"PH\","+
"\"value\":\"deleted\","+
"\"path\":\"/\","+
"\"expires\":\"Wed, 19-Mar-2014 17:53:53 GMT\","+
"\"domain\":\".yahoo.com\","+
"\"secure\":true"+
"}";
JSONObject jsonObject = Cookie.toJSONObject(cookieStr);
JSONObject expectedJsonObject = new JSONObject(expectedCookieStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Cookie.toString() will omit the non-standard "thiswont=beIncluded"
* attribute, but the attribute is still stored in the JSONObject.
* This test confirms both behaviors.
*/
@Test
public void convertCookieToString() {
String cookieStr =
"PH=deleted; "+
" expires=Wed, 19-Mar-2014 17:53:53 GMT;"+
"path=/; "+
" domain=.yahoo.com;"+
"thisWont=beIncluded;"+
"secure";
String expectedCookieStr =
"{\"path\":\"/\","+
"\"expires\":\"Wed, 19-Mar-2014 17:53:53 GMT\","+
"\"domain\":\".yahoo.com\","+
"\"name\":\"PH\","+
"\"secure\":true,"+
"\"value\":\"deleted\"}";
// Add the nonstandard attribute to the expected cookie string
String expectedDirectCompareCookieStr =
expectedCookieStr.replaceAll("\\{", "\\{\"thisWont\":\"beIncluded\",");
// convert all strings into JSONObjects
JSONObject jsonObject = Cookie.toJSONObject(cookieStr);
JSONObject expectedJsonObject = new JSONObject(expectedCookieStr);
JSONObject expectedDirectCompareJsonObject =
new JSONObject(expectedDirectCompareCookieStr);
// emit the string
String cookieToStr = Cookie.toString(jsonObject);
// create a final JSONObject from the string
JSONObject finalJsonObject = Cookie.toJSONObject(cookieToStr);
// JSONObject should contain the nonstandard string
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedDirectCompareJsonObject);
// JSONObject -> string -> JSONObject should not contain the nonstandard string
Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
}
/**
* A string may be URL-encoded when converting to JSONObject.
* If found, '+' is converted to ' ', and %hh hex strings are converted
* to their ascii char equivalents. This test confirms the decoding
* behavior.
*/
@Test
public void convertEncodedCookieToString() {
String cookieStr =
"PH=deleted; "+
" expires=Wed,+19-Mar-2014+17:53:53+GMT;"+
"path=/%2Bthis/is%26/a/spec%3Bsegment%3D; "+
" domain=.yahoo.com;"+
"secure";
String expectedCookieStr =
"{\"path\":\"/+this/is&/a/spec;segment=\","+
"\"expires\":\"Wed, 19-Mar-2014 17:53:53 GMT\","+
"\"domain\":\".yahoo.com\","+
"\"name\":\"PH\","+
"\"secure\":true,"+
"\"value\":\"deleted\"}";
JSONObject jsonObject = Cookie.toJSONObject(cookieStr);
JSONObject expectedJsonObject = new JSONObject(expectedCookieStr);
String cookieToStr = Cookie.toString(jsonObject);
JSONObject finalJsonObject = Cookie.toJSONObject(cookieToStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
}
/**
* A public API method performs a URL encoding for selected chars
* in a string. Control chars, '+', '%', '=', ';' are all encoded
* as %hh hex strings. The string is also trimmed.
* This test confirms that behavior.
*/
@Test
public void escapeString() {
String str = " +%\r\n\t\b%=;;; ";
String expectedStr = "%2b%25%0d%0a%09%08%25%3d%3b%3b%3b";
String actualStr = Cookie.escape(str);
assertTrue("expect escape() to encode correctly. Actual: " +actualStr+
" expected: " +expectedStr, expectedStr.equals(actualStr));
}
/**
* A public API method performs URL decoding for strings.
* '+' is converted to space and %hh hex strings are converted to
* their ascii equivalent values. The string is not trimmed.
* This test confirms that behavior.
*/
@Test
public void unescapeString() {
String str = " +%2b%25%0d%0a%09%08%25%3d%3b%3b%3b+ ";
String expectedStr = " +%\r\n\t\b%=;;; ";
String actualStr = Cookie.unescape(str);
assertTrue("expect unescape() to decode correctly. Actual: " +actualStr+
" expected: " +expectedStr, expectedStr.equals(actualStr));
}
}

View file

@ -0,0 +1,429 @@
package org.json.junit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.junit.data.MyEnum;
import org.json.junit.data.MyEnumClass;
import org.json.junit.data.MyEnumField;
import org.junit.Test;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
/**
* Enums are not explicitly supported in JSON-Java. But because enums act like
* classes, all required behavior is already be present in some form.
* These tests explore how enum serialization works with JSON-Java.
*/
public class EnumTest {
/**
* To serialize an enum by its getters, use the JSONObject Object constructor.
* The JSONObject ctor handles enum like any other bean. A JSONobject
* is created whose entries are the getter name/value pairs.
*/
@Test
public void jsonObjectFromEnum() {
// If there are no getters then the object is empty.
MyEnum myEnum = MyEnum.VAL2;
JSONObject jsonObject = new JSONObject(myEnum);
assertTrue("simple enum has no getters", jsonObject.isEmpty());
// enum with a getters should create a non-empty object
MyEnumField myEnumField = MyEnumField.VAL2;
jsonObject = new JSONObject(myEnumField);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider()
.parse(jsonObject.toString());
assertTrue("expecting 2 items in top level object", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expecting val 2", "val 2".equals(jsonObject.query("/value")));
assertTrue("expecting 2", Integer.valueOf(2).equals(jsonObject.query("/intVal")));
/**
* class which contains enum instances. Each enum should be stored
* in its own JSONObject
*/
MyEnumClass myEnumClass = new MyEnumClass();
myEnumClass.setMyEnum(MyEnum.VAL1);
myEnumClass.setMyEnumField(MyEnumField.VAL3);
jsonObject = new JSONObject(myEnumClass);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 2 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected 2 myEnumField items", "VAL3".equals((JsonPath.read(doc, "$.myEnumField"))));
assertTrue("expected 0 myEnum items", "VAL1".equals((JsonPath.read(doc, "$.myEnum"))));
assertTrue("expecting MyEnumField.VAL3", MyEnumField.VAL3.equals(jsonObject.query("/myEnumField")));
assertTrue("expecting MyEnum.VAL1", MyEnum.VAL1.equals(jsonObject.query("/myEnum")));
}
/**
* To serialize an enum by its set of allowed values, use getNames()
* and the the JSONObject Object with names constructor.
*/
@Test
public void jsonObjectFromEnumWithNames() {
String [] names;
JSONObject jsonObject;
MyEnum myEnum = MyEnum.VAL1;
names = JSONObject.getNames(myEnum);
// The values will be MyEnum fields
jsonObject = new JSONObject(myEnum, names);
// validate JSON object
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 3 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 3);
assertTrue("expected VAL1", MyEnum.VAL1.equals(jsonObject.query("/VAL1")));
assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonObject.query("/VAL2")));
assertTrue("expected VAL3", MyEnum.VAL3.equals(jsonObject.query("/VAL3")));
MyEnumField myEnumField = MyEnumField.VAL3;
names = JSONObject.getNames(myEnumField);
// The values will be MyEnmField fields
jsonObject = new JSONObject(myEnumField, names);
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 3 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 3);
assertTrue("expected VAL1", MyEnumField.VAL1.equals(jsonObject.query("/VAL1")));
assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonObject.query("/VAL2")));
assertTrue("expected VAL3", MyEnumField.VAL3.equals(jsonObject.query("/VAL3")));
}
/**
* Verify that enums are handled consistently between JSONArray and JSONObject
*/
@Test
public void verifyEnumConsistency(){
JSONObject jo = new JSONObject();
jo.put("value", MyEnumField.VAL2);
String expected="{\"value\":\"VAL2\"}";
String actual = jo.toString();
assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
jo.accumulate("value", MyEnumField.VAL1);
expected="{\"value\":[\"VAL2\",\"VAL1\"]}";
actual = jo.toString();
assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
jo.remove("value");
jo.append("value", MyEnumField.VAL1);
expected="{\"value\":[\"VAL1\"]}";
actual = jo.toString();
assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
jo.put("value", EnumSet.of(MyEnumField.VAL2));
expected="{\"value\":[\"VAL2\"]}";
actual = jo.toString();
assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
JSONArray ja = new JSONArray();
ja.put(MyEnumField.VAL2);
jo.put("value", ja);
actual = jo.toString();
assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
jo.put("value", new MyEnumField[]{MyEnumField.VAL2});
actual = jo.toString();
assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
}
/**
* To serialize by assigned value, use the put() methods. The value
* will be stored as a enum type.
*/
@Test
public void enumPut() {
JSONObject jsonObject = new JSONObject();
MyEnum myEnum = MyEnum.VAL2;
jsonObject.put("myEnum", myEnum);
MyEnumField myEnumField = MyEnumField.VAL1;
jsonObject.putOnce("myEnumField", myEnumField);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 2 top level objects", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonObject.query("/myEnum")));
assertTrue("expected VAL1", MyEnumField.VAL1.equals(jsonObject.query("/myEnumField")));
JSONArray jsonArray = new JSONArray();
jsonArray.put(myEnum);
jsonArray.put(1, myEnumField);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
assertTrue("expected 2 top level objects", ((List<?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonArray.query("/0")));
assertTrue("expected VAL1", MyEnumField.VAL1.equals(jsonArray.query("/1")));
/**
* Leaving these tests because they exercise get, opt, and remove
*/
assertTrue("expecting myEnum value", MyEnum.VAL2.equals(jsonArray.get(0)));
assertTrue("expecting myEnumField value", MyEnumField.VAL1.equals(jsonArray.opt(1)));
assertTrue("expecting myEnumField value", MyEnumField.VAL1.equals(jsonArray.remove(1)));
}
/**
* The default action of valueToString() is to call object.toString().
* For enums, this means the assigned value will be returned as a string.
*/
@Test
public void enumValueToString() {
String expectedStr1 = "\"VAL1\"";
String expectedStr2 = "\"VAL1\"";
MyEnum myEnum = MyEnum.VAL1;
MyEnumField myEnumField = MyEnumField.VAL1;
MyEnumClass myEnumClass = new MyEnumClass();
String str1 = JSONObject.valueToString(myEnum);
assertTrue("actual myEnum: "+str1+" expected: "+expectedStr1,
str1.equals(expectedStr1));
String str2 = JSONObject.valueToString(myEnumField);
assertTrue("actual myEnumField: "+str2+" expected: "+expectedStr2,
str2.equals(expectedStr2));
/**
* However, an enum within another class will not be rendered
* unless that class overrides default toString()
*/
String expectedStr3 = "\"org.json.junit.data.MyEnumClass@";
myEnumClass.setMyEnum(MyEnum.VAL1);
myEnumClass.setMyEnumField(MyEnumField.VAL1);
String str3 = JSONObject.valueToString(myEnumClass);
assertTrue("actual myEnumClass: "+str3+" expected: "+expectedStr3,
str3.startsWith(expectedStr3));
}
/**
* In whatever form the enum was added to the JSONObject or JSONArray,
* json[Object|Array].toString should serialize it in a reasonable way.
*/
@Test
public void enumToString() {
MyEnum myEnum = MyEnum.VAL2;
JSONObject jsonObject = new JSONObject(myEnum);
String expectedStr = "{}";
assertTrue("myEnum toString() should be empty", expectedStr.equals(jsonObject.toString()));
MyEnumField myEnumField = MyEnumField.VAL2;
jsonObject = new JSONObject(myEnumField);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 2 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected val 2", "val 2".equals(jsonObject.query("/value")));
assertTrue("expected 2", Integer.valueOf(2).equals(jsonObject.query("/intVal")));
MyEnumClass myEnumClass = new MyEnumClass();
myEnumClass.setMyEnum(MyEnum.VAL1);
myEnumClass.setMyEnumField(MyEnumField.VAL3);
jsonObject = new JSONObject(myEnumClass);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 2 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected VAL3", "VAL3".equals((JsonPath.read(doc, "$.myEnumField"))));
assertTrue("expected VAL1", "VAL1".equals((JsonPath.read(doc, "$.myEnum"))));
String [] names = JSONObject.getNames(myEnum);
jsonObject = new JSONObject(myEnum, names);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 3 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 3);
assertTrue("expected VAL1", MyEnum.VAL1.equals(jsonObject.query("/VAL1")));
assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonObject.query("/VAL2")));
assertTrue("expected VAL3", MyEnum.VAL3.equals(jsonObject.query("/VAL3")));
names = JSONObject.getNames(myEnumField);
jsonObject = new JSONObject(myEnumField, names);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 3 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 3);
assertTrue("expected VAL1", MyEnumField.VAL1.equals(jsonObject.query("/VAL1")));
assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonObject.query("/VAL2")));
assertTrue("expected VAL3", MyEnumField.VAL3.equals(jsonObject.query("/VAL3")));
expectedStr = "{\"myEnum\":\"VAL2\", \"myEnumField\":\"VAL2\"}";
jsonObject = new JSONObject();
jsonObject.putOpt("myEnum", myEnum);
jsonObject.putOnce("myEnumField", myEnumField);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 2 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonObject.query("/myEnum")));
assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonObject.query("/myEnumField")));
JSONArray jsonArray = new JSONArray();
jsonArray.put(myEnum);
jsonArray.put(1, myEnumField);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
assertTrue("expected 2 top level items", ((List<?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonArray.query("/0")));
assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonArray.query("/1")));
}
/**
* Wrap should handle enums exactly as a value type like Integer, Boolean, or String.
*/
@Test
public void wrap() {
assertTrue("simple enum has no getters", JSONObject.wrap(MyEnum.VAL2) instanceof MyEnum);
MyEnumField myEnumField = MyEnumField.VAL2;
JSONObject jsonObject = new JSONObject();
jsonObject.put("enum",myEnumField);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 1 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 1);
assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonObject.query("/enum")));
MyEnumClass myEnumClass = new MyEnumClass();
myEnumClass.setMyEnum(MyEnum.VAL1);
myEnumClass.setMyEnumField(MyEnumField.VAL3);
jsonObject = (JSONObject)JSONObject.wrap(myEnumClass);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 2 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected VAL3", "VAL3".equals((JsonPath.read(doc, "$.myEnumField"))));
assertTrue("expected VAL1", "VAL1".equals((JsonPath.read(doc, "$.myEnum"))));
assertTrue("expecting MyEnumField.VAL3", MyEnumField.VAL3.equals(jsonObject.query("/myEnumField")));
assertTrue("expecting MyEnum.VAL1", MyEnum.VAL1.equals(jsonObject.query("/myEnum")));
}
/**
* It was determined that some API methods should be added to
* support enums:<br>
* JSONObject.getEnum(class, key)<br>
* JSONObject.optEnum(class, key)<br>
* JSONObject.optEnum(class, key, default)<br>
* JSONArray.getEnum(class, index)<br>
* JSONArray.optEnum(class, index)<br>
* JSONArray.optEnum(class, index, default)<br>
* <p>
* Exercise these enum API methods on JSONObject and JSONArray
*/
@Test
public void enumAPI() {
MyEnumClass myEnumClass = new MyEnumClass();
myEnumClass.setMyEnum(MyEnum.VAL1);
MyEnumField myEnumField = MyEnumField.VAL2;
JSONObject jsonObject = new JSONObject();
jsonObject.put("strKey", "value");
jsonObject.put("strKey2", "VAL1");
jsonObject.put("enumKey", myEnumField);
jsonObject.put("enumClassKey", myEnumClass);
// get a plain old enum
MyEnumField actualEnum = jsonObject.getEnum(MyEnumField.class, "enumKey");
assertTrue("get myEnumField", actualEnum == MyEnumField.VAL2);
// try to get the wrong value
try {
actualEnum = jsonObject.getEnum(MyEnumField.class, "strKey");
assertTrue("should throw an exception for wrong key", false);
} catch (Exception ignored) {}
// get a class that contains an enum
MyEnumClass actualEnumClass = (MyEnumClass)jsonObject.get("enumClassKey");
assertTrue("get enum", actualEnumClass.getMyEnum() == MyEnum.VAL1);
// opt a plain old enum
actualEnum = jsonObject.optEnum(MyEnumField.class, "enumKey");
assertTrue("opt myEnumField", actualEnum == MyEnumField.VAL2);
// opt the wrong value
actualEnum = jsonObject.optEnum(MyEnumField.class, "strKey");
assertTrue("opt null", actualEnum == null);
// opt a class that contains an enum
actualEnumClass = (MyEnumClass)jsonObject.opt("enumClassKey");
assertTrue("get enum", actualEnumClass.getMyEnum() == MyEnum.VAL1);
// opt with default a plain old enum
actualEnum = jsonObject.optEnum(MyEnumField.class, "enumKey", null);
assertTrue("opt myEnumField", actualEnum == MyEnumField.VAL2);
// opt with default the wrong value
actualEnum = jsonObject.optEnum(MyEnumField.class, "strKey", null);
assertNull("opt null", actualEnum);
// opt with default the string value
actualEnum = jsonObject.optEnum(MyEnumField.class, "strKey2", null);
assertEquals(MyEnumField.VAL1, actualEnum);
// opt with default an index that does not exist
actualEnum = jsonObject.optEnum(MyEnumField.class, "noKey", null);
assertNull("opt null", actualEnum);
assertNull("Expected Null when the enum class is null",
jsonObject.optEnum(null, "enumKey"));
/**
* Exercise the proposed enum API methods on JSONArray
*/
JSONArray jsonArray = new JSONArray();
jsonArray.put("value");
jsonArray.put(myEnumField);
jsonArray.put(myEnumClass);
// get a plain old enum
actualEnum = jsonArray.getEnum(MyEnumField.class, 1);
assertTrue("get myEnumField", actualEnum == MyEnumField.VAL2);
// try to get the wrong value
try {
actualEnum = jsonArray.getEnum(MyEnumField.class, 0);
assertTrue("should throw an exception for wrong index", false);
} catch (Exception ignored) {}
// get a class that contains an enum
actualEnumClass = (MyEnumClass)jsonArray.get(2);
assertTrue("get enum", actualEnumClass.getMyEnum() == MyEnum.VAL1);
// opt a plain old enum
actualEnum = jsonArray.optEnum(MyEnumField.class, 1);
assertTrue("opt myEnumField", actualEnum == MyEnumField.VAL2);
// opt the wrong value
actualEnum = jsonArray.optEnum(MyEnumField.class, 0);
assertTrue("opt null", actualEnum == null);
// opt a class that contains an enum
actualEnumClass = (MyEnumClass)jsonArray.opt(2);
assertTrue("get enum", actualEnumClass.getMyEnum() == MyEnum.VAL1);
// opt with default a plain old enum
actualEnum = jsonArray.optEnum(MyEnumField.class, 1, null);
assertTrue("opt myEnumField", actualEnum == MyEnumField.VAL2);
// opt with default the wrong value
actualEnum = jsonArray.optEnum(MyEnumField.class, 0, null);
assertTrue("opt null", actualEnum == null);
// opt with default an index that does not exist
actualEnum = jsonArray.optEnum(MyEnumField.class, 3, null);
assertTrue("opt null", actualEnum == null);
}
}

View file

@ -0,0 +1,196 @@
package org.json.junit;
import static org.junit.Assert.*;
import org.json.*;
import org.junit.Test;
/**
* Unit tests for JSON-Java HTTP.java. See RFC7230.
*/
public class HTTPTest {
/**
* Attempt to call HTTP.toJSONObject() with a null string
* Expects a NUllPointerException.
*/
@Test(expected=NullPointerException.class)
public void nullHTTPException() {
String httpStr = null;
HTTP.toJSONObject(httpStr);
}
/**
* Attempt to call HTTP.toJSONObject() with a string containing
* an empty object. Expects a JSONException.
*/
@Test
public void notEnoughHTTPException() {
String httpStr = "{}";
JSONObject jsonObject = new JSONObject(httpStr);
try {
HTTP.toString(jsonObject);
assertTrue("Expected to throw exception", false);
} catch (JSONException e) {
assertTrue("Expecting an exception message",
"Not enough material for an HTTP header.".equals(e.getMessage()));
}
}
/**
* Calling HTTP.toJSONObject() with an empty string will result in a
* populated JSONObject with keys but no values for Request-URI, Method,
* and HTTP-Version.
*/
@Test
public void emptyStringHTTPRequest() {
String httpStr = "";
String expectedHTTPStr = "{\"Request-URI\":\"\",\"Method\":\"\",\"HTTP-Version\":\"\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Call HTTP.toJSONObject() with a Request-URI, Method,
* and HTTP-Version.
*/
@Test
public void simpleHTTPRequest() {
String httpStr = "GET /hello.txt HTTP/1.1";
String expectedHTTPStr =
"{\"Request-URI\":\"/hello.txt\",\"Method\":\"GET\",\"HTTP-Version\":\"HTTP/1.1\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Call HTTP.toJSONObject() with a response string containing a
* HTTP-Version, Status-Code, and Reason.
*/
@Test
public void simpleHTTPResponse() {
String httpStr = "HTTP/1.1 200 OK";
String expectedHTTPStr =
"{\"HTTP-Version\":\"HTTP/1.1\",\"Status-Code\":\"200\",\"Reason-Phrase\":\"OK\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Call HTTP.toJSONObject() with a full request string including
* request headers.
*/
@Test
public void extendedHTTPRequest() {
String httpStr =
"POST /enlighten/calais.asmx HTTP/1.1\n"+
"Host: api.opencalais.com\n"+
"Content-Type: text/xml; charset=utf-8\n"+
"Content-Length: 100\n"+
"SOAPAction: \"http://clearforest.com/Enlighten\"";
String expectedHTTPStr =
"{"+
"\"Request-URI\":\"/enlighten/calais.asmx\","+
"\"Host\":\"api.opencalais.com\","+
"\"Method\":\"POST\","+
"\"HTTP-Version\":\"HTTP/1.1\","+
"\"Content-Length\":\"100\","+
"\"Content-Type\":\"text/xml; charset=utf-8\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
/**
* Not too easy for JSONObject to parse a string with embedded quotes.
* For the sake of the test, add it here.
*/
expectedJsonObject.put("SOAPAction","\"http://clearforest.com/Enlighten\"");
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Call HTTP.toJSONObject() with a full response string including
* response headers.
*/
@Test
public void extendedHTTPResponse() {
String httpStr =
"HTTP/1.1 200 OK\n"+
"Content-Type: text/xml; charset=utf-8\n"+
"Content-Length: 100\n";
String expectedHTTPStr =
"{\"HTTP-Version\":\"HTTP/1.1\","+
"\"Status-Code\":\"200\","+
"\"Content-Length\":\"100\","+
"\"Reason-Phrase\":\"OK\","+
"\"Content-Type\":\"text/xml; charset=utf-8\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Call HTTP.toJSONObject() with a full POST request string including
* response headers, then convert it back into an HTTP string.
*/
@Test
public void convertHTTPRequestToString() {
String httpStr =
"POST /enlighten/calais.asmx HTTP/1.1\n"+
"Host: api.opencalais.com\n"+
"Content-Type: text/xml; charset=utf-8\n"+
"Content-Length: 100";
String expectedHTTPStr =
"{"+
"\"Request-URI\":\"/enlighten/calais.asmx\","+
"\"Host\":\"api.opencalais.com\","+
"\"Method\":\"POST\","+
"\"HTTP-Version\":\"HTTP/1.1\","+
"\"Content-Length\":\"100\","+
"\"Content-Type\":\"text/xml; charset=utf-8\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
String httpToStr = HTTP.toString(jsonObject);
/**
* JSONObject objects to crlfs and any trailing chars.
* For the sake of the test, simplify the resulting string
*/
httpToStr = httpToStr.replaceAll("("+HTTP.CRLF+HTTP.CRLF+")", "");
httpToStr = httpToStr.replaceAll(HTTP.CRLF, "\n");
JSONObject finalJsonObject = HTTP.toJSONObject(httpToStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
}
/**
* Call HTTP.toJSONObject() with a full response string including
* response headers, then convert it back into an HTTP string.
*/
@Test
public void convertHTTPResponseToString() {
String httpStr =
"HTTP/1.1 200 OK\n"+
"Content-Type: text/xml; charset=utf-8\n"+
"Content-Length: 100\n";
String expectedHTTPStr =
"{\"HTTP-Version\":\"HTTP/1.1\","+
"\"Status-Code\":\"200\","+
"\"Content-Length\":\"100\","+
"\"Reason-Phrase\":\"OK\","+
"\"Content-Type\":\"text/xml; charset=utf-8\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
String httpToStr = HTTP.toString(jsonObject);
/**
* JSONObject objects to crlfs and any trailing chars.
* For the sake of the test, simplify the resulting string
*/
httpToStr = httpToStr.replaceAll("("+HTTP.CRLF+HTTP.CRLF+")", "");
httpToStr = httpToStr.replaceAll(HTTP.CRLF, "\n");
JSONObject finalJsonObject = HTTP.toJSONObject(httpToStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,832 @@
package org.json.junit;
import static org.junit.Assert.*;
import org.json.*;
import org.junit.Test;
/**
* Tests for org.json.JSONML.java
*
* Certain inputs are expected to result in exceptions. These tests are
* executed first. JSONML provides an API to:
* Convert an XML string into a JSONArray or a JSONObject.
* Convert a JSONArray or JSONObject into an XML string.
* Both fromstring and tostring operations operations should be symmetrical
* within the limits of JSONML.
* It should be possible to perform the following operations, which should
* result in the original string being recovered, within the limits of the
* underlying classes:
* Convert a string -> JSONArray -> string -> JSONObject -> string
* Convert a string -> JSONObject -> string -> JSONArray -> string
*
*/
public class JSONMLTest {
/**
* Attempts to transform a null XML string to JSON.
* Expects a NullPointerException
*/
@Test(expected=NullPointerException.class)
public void nullXMLException() {
String xmlStr = null;
JSONML.toJSONArray(xmlStr);
}
/**
* Attempts to transform an empty string to JSON.
* Expects a JSONException
*/
@Test
public void emptyXMLException() {
String xmlStr = "";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Bad XML at 0 [character 1 line 1]",
e.getMessage());
}
}
/**
* Attempts to call JSONML.toString() with a null JSONArray.
* Expects a NullPointerException.
*/
@Test(expected=NullPointerException.class)
public void nullJSONXMLException() {
/**
* Tries to convert a null JSONArray to XML.
*/
JSONArray jsonArray= null;
JSONML.toString(jsonArray);
}
/**
* Attempts to call JSONML.toString() with a null JSONArray.
* Expects a JSONException.
*/
@Test
public void emptyJSONXMLException() {
/**
* Tries to convert an empty JSONArray to XML.
*/
JSONArray jsonArray = new JSONArray();
try {
JSONML.toString(jsonArray);
assertTrue("Expecting an exception", false);
} catch (JSONException e) {
assertTrue("Expecting an exception message",
"JSONArray[0] not found.".
equals(e.getMessage()));
}
}
/**
* Attempts to transform an non-XML string to JSON.
* Expects a JSONException
*/
@Test
public void nonXMLException() {
/**
* Attempts to transform a nonXML string to JSON
*/
String xmlStr = "{ \"this is\": \"not xml\"}";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Bad XML at 23 [character 24 line 1]",
e.getMessage());
}
}
/**
* Attempts to transform a JSON document with XML content that
* does not follow JSONML conventions (element name is not first value
* in a nested JSONArray) to a JSONArray then back to string.
* Expects a JSONException
*/
@Test
public void emptyTagException() {
/**
* jsonArrayStr is used to build a JSONArray which is then
* turned into XML. For this transformation, all arrays represent
* elements and the first array entry is the name of the element.
* In this case, one of the arrays does not have a name
*/
String jsonArrayStr =
"[\"addresses\","+
"{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
// this array has no name
"["+
"[\"name\"],"+
"[\"nocontent\"],"+
"\">\""+
"]"+
"]";
JSONArray jsonArray = new JSONArray(jsonArrayStr);
try {
JSONML.toString(jsonArray);
assertTrue("Expecting an exception", false);
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"JSONArray[0] is not a String.",
e.getMessage());
}
}
/**
* Attempts to transform a JSON document with XML content that
* does not follow JSONML conventions (element tag has an embedded space)
* to a JSONArray then back to string. Expects a JSONException
*/
@Test
public void spaceInTagException() {
/**
* jsonArrayStr is used to build a JSONArray which is then
* turned into XML. For this transformation, all arrays represent
* elements and the first array entry is the name of the element.
* In this case, one of the element names has an embedded space,
* which is not allowed.
*/
String jsonArrayStr =
"[\"addresses\","+
"{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
// this array has an invalid name
"[\"addr esses\","+
"[\"name\"],"+
"[\"nocontent\"],"+
"\">\""+
"]"+
"]";
JSONArray jsonArray = new JSONArray(jsonArrayStr);
try {
JSONML.toString(jsonArray);
assertTrue("Expecting an exception", false);
} catch (JSONException e) {
assertTrue("Expecting an exception message",
"'addr esses' contains a space character.".
equals(e.getMessage()));
}
}
/**
* Attempts to transform a malformed XML document
* (element tag has a frontslash) to a JSONArray.\
* Expects a JSONException
*/
@Test
public void invalidSlashInTagException() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* In this case, the XML is invalid because the 'name' element
* contains an invalid frontslash.
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/x>\n"+
" <street>abc street</street>\n"+
" </address>\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misshaped tag at 176 [character 14 line 4]",
e.getMessage());
}
}
/**
* Malformed XML text (invalid tagname) is transformed into a JSONArray.
* Expects a JSONException.
*/
@Test
public void invalidBangInTagException() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <!>\n"+
" </address>\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misshaped meta tag at 215 [character 12 line 7]",
e.getMessage());
}
}
/**
* Malformed XML text (invalid tagname, no close bracket) is transformed\
* into a JSONArray. Expects a JSONException.
*/
@Test
public void invalidBangNoCloseInTagException() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* In this case, the XML is invalid because an element
* starts with '!' and has no closing tag
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <!\n"+
" </address>\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misshaped meta tag at 214 [character 12 line 7]",
e.getMessage());
}
}
/**
* Malformed XML text (tagname with no close bracket) is transformed\
* into a JSONArray. Expects a JSONException.
*/
@Test
public void noCloseStartTagException() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* In this case, the XML is invalid because an element
* has no closing '>'.
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <abc\n"+
" </address>\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misplaced '<' at 194 [character 5 line 6]",
e.getMessage());
}
}
/**
* Malformed XML text (endtag with no name) is transformed\
* into a JSONArray. Expects a JSONException.
*/
@Test
public void noCloseEndTagException() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* In this case, the XML is invalid because an element
* has no name after the closing tag '</'.
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <abc/>\n"+
" </>\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
assertTrue("Expecting an exception", false);
} catch (JSONException e) {
assertTrue("Expecting an exception message",
"Expected a closing name instead of '>'.".
equals(e.getMessage()));
}
}
/**
* Malformed XML text (endtag with no close bracket) is transformed\
* into a JSONArray. Expects a JSONException.
*/
@Test
public void noCloseEndBraceException() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* In this case, the XML is invalid because an element
* has '>' after the closing tag '</' and name.
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation=\"test.xsd\">\n"+
" <address>\n"+
" <name/>\n"+
" <abc/>\n"+
" </address\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misplaced '<' at 206 [character 1 line 7]",
e.getMessage());
}
}
/**
* Malformed XML text (incomplete CDATA string) is transformed\
* into a JSONArray. Expects a JSONException.
*/
@Test
public void invalidCDATABangInTagException() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* In this case, the XML is invalid because an element
* does not have a complete CDATA string.
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name>Joe Tester</name>\n"+
" <![[]>\n"+
" </address>\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Expected 'CDATA[' at 204 [character 11 line 5]",
e.getMessage());
}
}
/**
* Convert an XML document into a JSONArray, then use JSONML.toString()
* to convert it into a string. This string is then converted back into
* a JSONArray. Both JSONArrays are compared against a control to
* confirm the contents.
*/
@Test
public void toJSONArray() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* Each element becomes a JSONArray:
* 1st entry = elementname
* 2nd entry = attributes object (if present)
* 3rd entry = content (if present)
* 4th entry = child element JSONArrays (if present)
* The result is compared against an expected JSONArray.
* The transformed JSONArray is then transformed back into a string
* which is used to create a final JSONArray, which is also compared
* against the expected JSONArray.
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
"xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
"<address attr1=\"attrValue1\" attr2=\"attrValue2\" attr3=\"attrValue3\">\n"+
"<name nameType=\"mine\">myName</name>\n"+
"<nocontent/>>\n"+
"</address>\n"+
"</addresses>";
String expectedStr =
"[\"addresses\","+
"{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
"[\"address\","+
"{\"attr1\":\"attrValue1\",\"attr2\":\"attrValue2\",\"attr3\":\"attrValue3\"},"+
"[\"name\", {\"nameType\":\"mine\"},\"myName\"],"+
"[\"nocontent\"],"+
"\">\""+
"]"+
"]";
JSONArray jsonArray = JSONML.toJSONArray(xmlStr);
JSONArray expectedJsonArray = new JSONArray(expectedStr);
String xmlToStr = JSONML.toString(jsonArray);
JSONArray finalJsonArray = JSONML.toJSONArray(xmlToStr);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
}
/**
* Convert an XML document into a JSONObject. Use JSONML.toString() to
* convert it back into a string, and then re-convert it into a JSONObject.
* Both JSONObjects are compared against a control JSONObject to confirm
* the contents.
* <p>
* Next convert the XML document into a JSONArray. Use JSONML.toString() to
* convert it back into a string, and then re-convert it into a JSONArray.
* Both JSONArrays are compared against a control JSONArray to confirm
* the contents.
* <p>
* This test gives a comprehensive example of how the JSONML
* transformations work.
*/
@Test
public void toJSONObjectToJSONArray() {
/**
* xmlStr contains XML text which is transformed into a JSONObject,
* restored to XML, transformed into a JSONArray, and then restored
* to XML again. Both JSONObject and JSONArray should contain the same
* information and should produce the same XML, allowing for non-ordered
* attributes.
*
* Transformation to JSONObject:
* The elementName is stored as a string where key="tagName"
* Attributes are simply stored as key/value pairs
* If the element has either content or child elements, they are stored
* in a jsonArray with key="childNodes".
*
* Transformation to JSONArray:
* 1st entry = elementname
* 2nd entry = attributes object (if present)
* 3rd entry = content (if present)
* 4th entry = child element JSONArrays (if present)
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
"xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
"<address addrType=\"my address\">\n"+
"<name nameType=\"my name\">Joe Tester</name>\n"+
"<street><![CDATA[Baker street 5]]></street>\n"+
"<NothingHere except=\"an attribute\"/>\n"+
"<TrueValue>true</TrueValue>\n"+
"<FalseValue>false</FalseValue>\n"+
"<NullValue>null</NullValue>\n"+
"<PositiveValue>42</PositiveValue>\n"+
"<NegativeValue>-23</NegativeValue>\n"+
"<DoubleValue>-23.45</DoubleValue>\n"+
"<Nan>-23x.45</Nan>\n"+
"<ArrayOfNum>\n"+
"<value>1</value>\n"+
"<value>2</value>\n"+
"<value><subValue svAttr=\"svValue\">abc</subValue></value>\n"+
"<value>3</value>\n"+
"<value>4.1</value>\n"+
"<value>5.2</value>\n"+
"</ArrayOfNum>\n"+
"</address>\n"+
"</addresses>";
String expectedJSONObjectStr =
"{"+
"\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"childNodes\":["+
"{"+
"\"childNodes\":["+
"{"+
"\"childNodes\":[\"Joe Tester\"],"+
"\"nameType\":\"my name\","+
"\"tagName\":\"name\""+
"},"+
"{"+
"\"childNodes\":[\"Baker street 5\"],"+
"\"tagName\":\"street\""+
"},"+
"{"+
"\"tagName\":\"NothingHere\","+
"\"except\":\"an attribute\""+
"},"+
"{"+
"\"childNodes\":[true],"+
"\"tagName\":\"TrueValue\""+
"},"+
"{"+
"\"childNodes\":[false],"+
"\"tagName\":\"FalseValue\""+
"},"+
"{"+
"\"childNodes\":[null],"+
"\"tagName\":\"NullValue\""+
"},"+
"{"+
"\"childNodes\":[42],"+
"\"tagName\":\"PositiveValue\""+
"},"+
"{"+
"\"childNodes\":[-23],"+
"\"tagName\":\"NegativeValue\""+
"},"+
"{"+
"\"childNodes\":[-23.45],"+
"\"tagName\":\"DoubleValue\""+
"},"+
"{"+
"\"childNodes\":[\"-23x.45\"],"+
"\"tagName\":\"Nan\""+
"},"+
"{"+
"\"childNodes\":["+
"{"+
"\"childNodes\":[1],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":[2],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":["+
"{"+
"\"childNodes\":[\"abc\"],"+
"\"svAttr\":\"svValue\","+
"\"tagName\":\"subValue\""+
"}"+
"],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":[3],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":[4.1],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":[5.2],"+
"\"tagName\":\"value\""+
"}"+
"],"+
"\"tagName\":\"ArrayOfNum\""+
"}"+
"],"+
"\"addrType\":\"my address\","+
"\"tagName\":\"address\""+
"}"+
"],"+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\","+
"\"tagName\":\"addresses\""+
"}";
String expectedJSONArrayStr =
"["+
"\"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]"+
"]"+
"]"+
"]";
// make a JSONObject and make sure it looks as expected
JSONObject jsonObject = JSONML.toJSONObject(xmlStr);
JSONObject expectedJsonObject = new JSONObject(expectedJSONObjectStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
// restore the XML, then make another JSONObject and make sure it
// looks as expected
String jsonObjectXmlToStr = JSONML.toString(jsonObject);
JSONObject finalJsonObject = JSONML.toJSONObject(jsonObjectXmlToStr);
Util.compareActualVsExpectedJsonObjects(finalJsonObject, expectedJsonObject);
// 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
JSONObject jsonObjectFromObject = JSONML.toJSONObject(jsonObjectXmlToStr);
JSONObject jsonObjectFromArray = JSONML.toJSONObject(jsonArrayXmlToStr);
Util.compareActualVsExpectedJsonObjects(jsonObjectFromObject, jsonObjectFromArray);
}
/**
* Convert an XML document which contains embedded comments into
* a JSONArray. Use JSONML.toString() to turn it into a string, then
* reconvert it into a JSONArray. Compare both JSONArrays to a control
* JSONArray to confirm the contents.
* <p>
* This test shows how XML comments are handled.
*/
@Test
public void commentsInXML() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<!-- this is a comment -->\n"+
"<addresses>\n"+
"<address>\n"+
"<!-- <!--[CDATA[ this is -- <another> comment ]] -->\n"+
"<name>Joe Tester</name>\n"+
"<!-- this is a - multi line \n"+
"comment -->\n"+
"<street>Baker street 5</street>\n"+
"</address>\n"+
"</addresses>";
String expectedStr =
"[\"addresses\","+
"[\"address\","+
"[\"name\",\"Joe Tester\"],"+
"[\"street\",\"Baker street 5\"]"+
"]"+
"]";
JSONArray jsonArray = JSONML.toJSONArray(xmlStr);
JSONArray expectedJsonArray = new JSONArray(expectedStr);
String xmlToStr = JSONML.toString(jsonArray);
JSONArray finalJsonArray = JSONML.toJSONArray(xmlToStr);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
}
/**
* JSON string with lost leading zero and converted "True" to true. See test
* result in comment below.
*/
@Test
public void testToJSONArray_jsonOutput() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
final String expectedJsonString = "[\"root\",[\"id\",\"01\"],[\"id\",1],[\"id\",\"00\"],[\"id\",0],[\"item\",{\"id\":\"01\"}],[\"title\",true]]";
final JSONArray actualJsonOutput = JSONML.toJSONArray(originalXml, false);
assertEquals(expectedJsonString, actualJsonOutput.toString());
}
/**
* JSON string cannot be reverted to original xml when type guessing is used.
*/
@Test
public void testToJSONArray_reversibility() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
final String revertedXml = JSONML.toString(JSONML.toJSONArray(originalXml, false));
assertNotEquals(revertedXml, originalXml);
}
/**
* JSON string cannot be reverted to original xml when type guessing is used.
* When we force all the values as string, the original text comes back.
*/
@Test
public void testToJSONArray_reversibility2() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
final String expectedJsonString = "[\"root\",[\"id\",\"01\"],[\"id\",\"1\"],[\"id\",\"00\"],[\"id\",\"0\"],[\"item\",{\"id\":\"01\"}],[\"title\",\"True\"]]";
final JSONArray json = JSONML.toJSONArray(originalXml,true);
assertEquals(expectedJsonString, json.toString());
final String reverseXml = JSONML.toString(json);
assertEquals(originalXml, reverseXml);
}
/**
* JSON can be reverted to original xml.
*/
@Test
public void testToJSONArray_reversibility3() {
final String originalXml = "<readResult><errors someAttr=\"arrtValue\"><code>400</code></errors><errors><code>402</code></errors></readResult>";
final JSONArray jsonArray = JSONML.toJSONArray(originalXml, false);
final String revertedXml = JSONML.toString(jsonArray);
assertEquals(revertedXml, originalXml);
}
/**
* JSON string cannot be reverted to original xml. See test result in
* comment below.
*/
@Test
public void testToJSONObject_reversibility() {
final String originalXml = "<readResult><errors someAttr=\"arrtValue\"><code>400</code></errors><errors><code>402</code></errors></readResult>";
final JSONObject originalObject=JSONML.toJSONObject(originalXml,false);
final String originalJson = originalObject.toString();
final String xml = JSONML.toString(originalObject);
final JSONObject revertedObject = JSONML.toJSONObject(xml, false);
final String newJson = revertedObject.toString();
assertTrue("JSON Objects are not similar",originalObject.similar(revertedObject));
assertEquals("original JSON does not equal the new JSON",originalJson, newJson);
}
// these tests do not pass for the following reasons:
// 1. Our XML parser does not handle generic HTML entities, only valid XML entities. Hence &nbsp;
// or other HTML specific entities would fail on reversability
// 2. Our JSON implementation for storing the XML attributes uses the standard unordered map.
// This means that <tag attr1="v1" attr2="v2" /> can not be reversed reliably.
//
// /**
// * Test texts taken from jsonml.org. Currently our implementation FAILS this conversion but shouldn't.
// * Technically JsonML should be able to transform any valid xhtml document, but ours only supports
// * standard XML entities, not HTML entities.
// */
// @Test
// public void testAttributeConversionReversabilityHTML() {
// final String originalXml = "<table class=\"MyTable\" style=\"background-color:yellow\"><tr><td class=\"MyTD\" style=\"border:1px solid black\">#5D28D1</td><td class=\"MyTD\" style=\"background-color:red\">Example text here</td></tr><tr><td class=\"MyTD\" style=\"border:1px solid black\">#AF44EF</td><td class=\"MyTD\" style=\"background-color:green\">127310656</td></tr><tr><td class=\"MyTD\" style=\"border:1px solid black\">#AAD034</td><td class=\"MyTD\" style=\"background-color:blue\">&nbsp;<span style=\"background-color:maroon\">&copy;</span>&nbsp;</td></tr></table>";
// final String expectedJsonString = "[\"table\",{\"class\" : \"MyTable\",\"style\" : \"background-color:yellow\"},[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#550758\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:red\"},\"Example text here\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#993101\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:green\"},\"127624015\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#E33D87\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:blue\"},\"\u00A0\",[\"span\",{ \"style\" : \"background-color:maroon\" },\"\u00A9\"],\"\u00A0\"]]]";
// final JSONArray json = JSONML.toJSONArray(originalXml,true);
// final String actualJsonString = json.toString();
//
// final String reverseXml = JSONML.toString(json);
// assertNotEquals(originalXml, reverseXml);
//
// assertNotEquals(expectedJsonString, actualJsonString);
// }
//
// /**
// * Test texts taken from jsonml.org but modified to have XML entities only.
// */
// @Test
// public void testAttributeConversionReversabilityXML() {
// final String originalXml = "<table class=\"MyTable\" style=\"background-color:yellow\"><tr><td class=\"MyTD\" style=\"border:1px solid black\">#5D28D1</td><td class=\"MyTD\" style=\"background-color:red\">Example text here</td></tr><tr><td class=\"MyTD\" style=\"border:1px solid black\">#AF44EF</td><td class=\"MyTD\" style=\"background-color:green\">127310656</td></tr><tr><td class=\"MyTD\" style=\"border:1px solid black\">#AAD034</td><td class=\"MyTD\" style=\"background-color:blue\">&amp;<span style=\"background-color:maroon\">&gt;</span>&lt;</td></tr></table>";
// final String expectedJsonString = "[\"table\",{\"class\" : \"MyTable\",\"style\" : \"background-color:yellow\"},[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#550758\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:red\"},\"Example text here\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#993101\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:green\"},\"127624015\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#E33D87\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:blue\"},\"&\",[\"span\",{ \"style\" : \"background-color:maroon\" },\">\"],\"<\"]]]";
// final JSONArray jsonML = JSONML.toJSONArray(originalXml,true);
// final String actualJsonString = jsonML.toString();
//
// final String reverseXml = JSONML.toString(jsonML);
// // currently not equal because the hashing of the attribute objects makes the attribute
// // order not happen the same way twice
// assertEquals(originalXml, reverseXml);
//
// assertEquals(expectedJsonString, actualJsonString);
// }
@Test (timeout = 6000)
public void testIssue484InfinteLoop1() {
try {
JSONML.toJSONObject("??*^M??|?CglR^F??`??>?w??PIlr^E??D^X^]?$?-^R?o??O?*??{OD?^FY??`2a????NM?b^Tq?:O?>S$^K?J?^FB.gUK?m^H??zE??^??!v]?^A???^[^A??^U?c??????h???s???g^Z???`?q^Dbi??:^QZl?)?}1^??k?0??:$V?$?Ovs(}J??^V????2;^QgQ?^_^A?^D?^U?Tg?K?`?h%c?hmGA?<!C*^P^Y?^X9?~?t?)??,z^XA???S}?Q??.q?j????]");
fail("Exception expected for invalid JSON.");
} catch (JSONException ex) {
assertEquals("Exception string did not match: ",
"Unterminated string at 271 [character 272 line 1]",
ex.getMessage());
}
}
@Test (timeout = 6000)
public void testIssue484InfinteLoop2() {
try {
String input = "??*\n" +
"??|?CglR??`??>?w??PIlr??D?$?-?o??O?*??{OD?Y??`2a????NM?bq?:O?>S$ ?J?B.gUK?m\b??zE???!v]???????c??????h???s???g???`?qbi??:Zl?)?}1^??k?0??:$V?$?Ovs(}J??????2;gQ????Tg?K?`?h%c?hmGA?<!C*?9?~?t?)??,zA???S}?Q??.q?j????]";
JSONML.toJSONObject(input);
fail("Exception expected for invalid JSON.");
} catch (JSONException ex) {
assertEquals("Exception string did not match: ",
"Unterminated string at 242 [character 238 line 2]",
ex.getMessage());
}
}
}

View file

@ -0,0 +1,56 @@
package org.json.junit;
import static org.junit.Assert.*;
import java.util.*;
import org.json.*;
import org.json.junit.data.MyLocaleBean;
import org.junit.*;
/**
* Note: This file is saved as UTF-8. Do not save as ASCII or the tests will
* fail.
*
*/
public class JSONObjectLocaleTest {
/**
* JSONObject built from a bean with locale-specific keys.
* In the Turkish alphabet, there are 2 versions of the letter "i".
* 'eh' I ı (dotless i)
* 'ee' İ i (dotted i)
* A problem can occur when parsing the public get methods for a bean.
* If the method starts with getI... then the key name will be lowercased
* to 'i' in English, and 'ı' in Turkish.
* We want the keys to be consistent regardless of locale, so JSON-Java
* lowercase operations are made to be locale-neutral by specifying
* Locale.ROOT. This causes 'I' to be universally lowercased to 'i'
* regardless of the locale currently in effect.
*/
@Test
public void jsonObjectByLocaleBean() {
MyLocaleBean myLocaleBean = new MyLocaleBean();
/**
* This is just the control case which happens when the locale.ROOT
* lowercasing behavior is the same as the current locale.
*/
Locale.setDefault(new Locale("en"));
JSONObject jsonen = new JSONObject(myLocaleBean);
assertEquals("expected size 2, found: " +jsonen.length(), 2, jsonen.length());
assertEquals("expected jsonen[i] == beanI", "beanI", jsonen.getString("i"));
assertEquals("expected jsonen[id] == beanId", "beanId", jsonen.getString("id"));
/**
* Without the JSON-Java change, these keys would be stored internally as
* starting with the letter, 'ı' (dotless i), since the lowercasing of
* the getI and getId keys would be specific to the Turkish locale.
*/
Locale.setDefault(new Locale("tr"));
JSONObject jsontr = new JSONObject(myLocaleBean);
assertEquals("expected size 2, found: " +jsontr.length(), 2, jsontr.length());
assertEquals("expected jsontr[i] == beanI", "beanI", jsontr.getString("i"));
assertEquals("expected jsontr[id] == beanId", "beanId", jsontr.getString("id"));
}
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,359 @@
package org.json.junit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.IOException;
import java.io.InputStream;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONPointer;
import org.json.JSONPointerException;
import org.json.JSONTokener;
import org.junit.Test;
public class JSONPointerTest {
private static final JSONObject document;
static {
@SuppressWarnings("resource")
InputStream resourceAsStream = JSONPointerTest.class.getClassLoader().getResourceAsStream("jsonpointer-testdoc.json");
if(resourceAsStream == null) {
throw new ExceptionInInitializerError("Unable to locate test file. Please check your development environment configuration");
}
document = new JSONObject(new JSONTokener(resourceAsStream));
}
private Object query(String pointer) {
return new JSONPointer(pointer).queryFrom(document);
}
@Test
public void emptyPointer() {
assertSame(document, query(""));
}
@Test(expected = NullPointerException.class)
public void nullPointer() {
new JSONPointer((String) null);
}
@Test
public void objectPropertyQuery() {
assertSame(document.get("foo"), query("/foo"));
}
@Test
public void arrayIndexQuery() {
assertSame(document.getJSONArray("foo").get(0), query("/foo/0"));
}
@Test(expected = JSONPointerException.class)
public void stringPropOfArrayFailure() {
query("/foo/bar");
}
@Test
public void queryByEmptyKey() {
assertSame(document.get(""), query("/"));
}
@Test
public void queryByEmptyKeySubObject() {
assertSame(document.getJSONObject("obj").getJSONObject(""), query("/obj/"));
}
@Test
public void queryByEmptyKeySubObjectSubOject() {
assertSame(
document.getJSONObject("obj").getJSONObject("").get(""),
query("/obj//")
);
}
@Test
public void queryByEmptyKeySubObjectValue() {
assertSame(
document.getJSONObject("obj").getJSONObject("").get("subKey"),
query("/obj//subKey")
);
}
@Test
public void slashEscaping() {
assertSame(document.get("a/b"), query("/a~1b"));
}
@Test
public void tildeEscaping() {
assertSame(document.get("m~n"), query("/m~0n"));
}
@Test
public void backslashEscaping() {
assertSame(document.get("i\\j"), query("/i\\\\j"));
}
@Test
public void quotationEscaping() {
assertSame(document.get("k\"l"), query("/k\\\\\\\"l"));
}
@Test
public void whitespaceKey() {
assertSame(document.get(" "), query("/ "));
}
@Test
public void uriFragmentNotation() {
assertSame(document.get("foo"), query("#/foo"));
}
@Test
public void uriFragmentNotationRoot() {
assertSame(document, query("#"));
}
@Test
public void uriFragmentPercentHandling() {
assertSame(document.get("c%d"), query("#/c%25d"));
assertSame(document.get("e^f"), query("#/e%5Ef"));
assertSame(document.get("g|h"), query("#/g%7Ch"));
assertSame(document.get("m~n"), query("#/m~0n"));
}
@Test(expected = IllegalArgumentException.class)
public void syntaxError() {
new JSONPointer("key");
}
@Test(expected = JSONPointerException.class)
public void arrayIndexFailure() {
query("/foo/2");
}
@Test(expected = JSONPointerException.class)
public void primitiveFailure() {
query("/obj/key/failure");
}
@Test
public void builderTest() {
JSONPointer pointer = JSONPointer.builder()
.append("obj")
.append("other~key").append("another/key")
.append(0)
.build();
assertEquals("val", pointer.queryFrom(document));
}
@Test(expected = NullPointerException.class)
public void nullToken() {
JSONPointer.builder().append(null);
}
@Test
public void toStringEscaping() {
JSONPointer pointer = JSONPointer.builder()
.append("obj")
.append("other~key").append("another/key")
.append("\"")
.append(0)
.build();
assertEquals("/obj/other~0key/another~1key/\\\"/0", pointer.toString());
}
@Test
public void emptyPointerToString() {
assertEquals("", new JSONPointer("").toString());
}
@Test
public void toURIFragment() {
assertEquals("#/c%25d", new JSONPointer("/c%d").toURIFragment());
assertEquals("#/e%5Ef", new JSONPointer("/e^f").toURIFragment());
assertEquals("#/g%7Ch", new JSONPointer("/g|h").toURIFragment());
assertEquals("#/m%7En", new JSONPointer("/m~n").toURIFragment());
}
@Test
public void tokenListIsCopiedInConstructor() {
JSONPointer.Builder b = JSONPointer.builder().append("key1");
JSONPointer jp1 = b.build();
b.append("key2");
JSONPointer jp2 = b.build();
if(jp1.toString().equals(jp2.toString())) {
fail("Oops, my pointers are sharing a backing array");
}
}
/**
* Coverage for JSONObject query(String)
*/
@Test
public void queryFromJSONObject() {
String str = "{"+
"\"stringKey\":\"hello world!\","+
"\"arrayKey\":[0,1,2],"+
"\"objectKey\": {"+
"\"a\":\"aVal\","+
"\"b\":\"bVal\""+
"}"+
"}";
JSONObject jsonObject = new JSONObject(str);
Object obj = jsonObject.query("/stringKey");
assertTrue("Expected 'hello world!'", "hello world!".equals(obj));
obj = jsonObject.query("/arrayKey/1");
assertTrue("Expected 1", Integer.valueOf(1).equals(obj));
obj = jsonObject.query("/objectKey/b");
assertTrue("Expected bVal", "bVal".equals(obj));
try {
obj = jsonObject.query("/a/b/c");
assertTrue("Expected JSONPointerException", false);
} catch (JSONPointerException e) {
assertTrue("Expected bad key/value exception",
"value [null] is not an array or object therefore its key b cannot be resolved".
equals(e.getMessage()));
}
}
/**
* Coverage for JSONObject query(JSONPointer)
*/
@Test
public void queryFromJSONObjectUsingPointer() {
String str = "{"+
"\"stringKey\":\"hello world!\","+
"\"arrayKey\":[0,1,2],"+
"\"objectKey\": {"+
"\"a\":\"aVal\","+
"\"b\":\"bVal\""+
"}"+
"}";
JSONObject jsonObject = new JSONObject(str);
Object obj = jsonObject.query(new JSONPointer("/stringKey"));
assertTrue("Expected 'hello world!'", "hello world!".equals(obj));
obj = jsonObject.query(new JSONPointer("/arrayKey/1"));
assertTrue("Expected 1", Integer.valueOf(1).equals(obj));
obj = jsonObject.query(new JSONPointer("/objectKey/b"));
assertTrue("Expected bVal", "bVal".equals(obj));
try {
obj = jsonObject.query(new JSONPointer("/a/b/c"));
assertTrue("Expected JSONPointerException", false);
} catch (JSONPointerException e) {
assertTrue("Expected bad key/value exception",
"value [null] is not an array or object therefore its key b cannot be resolved".
equals(e.getMessage()));
}
}
/**
* Coverage for JSONObject optQuery(JSONPointer)
*/
@Test
public void optQueryFromJSONObjectUsingPointer() {
String str = "{"+
"\"stringKey\":\"hello world!\","+
"\"arrayKey\":[0,1,2],"+
"\"objectKey\": {"+
"\"a\":\"aVal\","+
"\"b\":\"bVal\""+
"}"+
"}";
JSONObject jsonObject = new JSONObject(str);
Object obj = jsonObject.optQuery(new JSONPointer("/stringKey"));
assertTrue("Expected 'hello world!'", "hello world!".equals(obj));
obj = jsonObject.optQuery(new JSONPointer("/arrayKey/1"));
assertTrue("Expected 1", Integer.valueOf(1).equals(obj));
obj = jsonObject.optQuery(new JSONPointer("/objectKey/b"));
assertTrue("Expected bVal", "bVal".equals(obj));
obj = jsonObject.optQuery(new JSONPointer("/a/b/c"));
assertTrue("Expected null", obj == null);
}
/**
* Coverage for JSONArray query(String)
*/
@Test
public void queryFromJSONArray() {
String str = "["+
"\"hello world!\","+
"[0,1,2],"+
"{"+
"\"a\":\"aVal\","+
"\"b\":\"bVal\""+
"}"+
"]";
JSONArray jsonArray = new JSONArray(str);
Object obj = jsonArray.query("/0");
assertTrue("Expected 'hello world!'", "hello world!".equals(obj));
obj = jsonArray.query("/1/1");
assertTrue("Expected 1", Integer.valueOf(1).equals(obj));
obj = jsonArray.query("/2/b");
assertTrue("Expected bVal", "bVal".equals(obj));
try {
obj = jsonArray.query("/a/b/c");
assertTrue("Expected JSONPointerException", false);
} catch (JSONPointerException e) {
assertTrue("Expected bad index exception",
"a is not an array index".equals(e.getMessage()));
}
}
/**
* Coverage for JSONArray query(JSONPointer)
*/
@Test
public void queryFromJSONArrayUsingPointer() {
String str = "["+
"\"hello world!\","+
"[0,1,2],"+
"{"+
"\"a\":\"aVal\","+
"\"b\":\"bVal\""+
"}"+
"]";
JSONArray jsonArray = new JSONArray(str);
Object obj = jsonArray.query(new JSONPointer("/0"));
assertTrue("Expected 'hello world!'", "hello world!".equals(obj));
obj = jsonArray.query(new JSONPointer("/1/1"));
assertTrue("Expected 1", Integer.valueOf(1).equals(obj));
obj = jsonArray.query(new JSONPointer("/2/b"));
assertTrue("Expected bVal", "bVal".equals(obj));
try {
obj = jsonArray.query(new JSONPointer("/a/b/c"));
assertTrue("Expected JSONPointerException", false);
} catch (JSONPointerException e) {
assertTrue("Expected bad index exception",
"a is not an array index".equals(e.getMessage()));
}
}
/**
* Coverage for JSONArray optQuery(JSONPointer)
*/
@Test
public void optQueryFromJSONArrayUsingPointer() {
String str = "["+
"\"hello world!\","+
"[0,1,2],"+
"{"+
"\"a\":\"aVal\","+
"\"b\":\"bVal\""+
"}"+
"]";
JSONArray jsonArray = new JSONArray(str);
Object obj = jsonArray.optQuery(new JSONPointer("/0"));
assertTrue("Expected 'hello world!'", "hello world!".equals(obj));
obj = jsonArray.optQuery(new JSONPointer("/1/1"));
assertTrue("Expected 1", Integer.valueOf(1).equals(obj));
obj = jsonArray.optQuery(new JSONPointer("/2/b"));
assertTrue("Expected bVal", "bVal".equals(obj));
obj = jsonArray.optQuery(new JSONPointer("/a/b/c"));
assertTrue("Expected null", obj == null);
}
}

View file

@ -0,0 +1,371 @@
package org.json.junit;
import static org.junit.Assert.*;
import java.io.IOException;
import java.io.StringWriter;
import java.util.*;
import org.json.*;
import org.junit.Test;
/**
* Tests for JSONString implementations, and the difference between
* {@link JSONObject#valueToString} and {@link JSONObject#writeValue}.
*/
public class JSONStringTest {
/**
* This tests the JSONObject.writeValue() method. We can't test directly
* due to it being a package-protected method. Instead, we can call
* JSONArray.write(), which delegates the writing of each entry to
* writeValue().
*/
@Test
public void writeValues() throws Exception {
JSONArray jsonArray = new JSONArray();
jsonArray.put((Object)null);
StringWriter writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[null]".equals(output));
jsonArray = new JSONArray();
jsonArray.put(JSONObject.NULL);
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[null]".equals(output));
jsonArray = new JSONArray();
jsonArray.put(new JSONObject());
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[{}]".equals(output));
jsonArray = new JSONArray();
jsonArray.put(new JSONArray());
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[[]]".equals(output));
jsonArray = new JSONArray();
Map<?,?> singleMap = Collections.singletonMap("key1", "value1");
jsonArray.put((Object)singleMap);
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[{\"key1\":\"value1\"}]".equals(output));
jsonArray = new JSONArray();
List<?> singleList = Collections.singletonList("entry1");
jsonArray.put((Object)singleList);
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[[\"entry1\"]]".equals(output));
jsonArray = new JSONArray();
int[] intArray = new int[] { 1, 2, 3 };
jsonArray.put(intArray);
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[[1,2,3]]".equals(output));
jsonArray = new JSONArray();
jsonArray.put(24);
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[24]".equals(output));
jsonArray = new JSONArray();
jsonArray.put("string value");
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[\"string value\"]".equals(output));
jsonArray = new JSONArray();
jsonArray.put(true);
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[true]".equals(output));
} finally {
writer.close();
}
}
/**
* This tests the JSONObject.valueToString() method. These should be
* identical to the values above, except for the enclosing [ and ].
*/
@SuppressWarnings("boxing")
@Test
public void valuesToString() throws Exception {
String output = JSONObject.valueToString(null);
assertTrue("String values should be equal", "null".equals(output));
output = JSONObject.valueToString(JSONObject.NULL);
assertTrue("String values should be equal", "null".equals(output));
output = JSONObject.valueToString(new JSONObject());
assertTrue("String values should be equal", "{}".equals(output));
output = JSONObject.valueToString(new JSONArray());
assertTrue("String values should be equal", "[]".equals(output));
Map<?,?> singleMap = Collections.singletonMap("key1", "value1");
output = JSONObject.valueToString(singleMap);
assertTrue("String values should be equal", "{\"key1\":\"value1\"}".equals(output));
List<?> singleList = Collections.singletonList("entry1");
output = JSONObject.valueToString(singleList);
assertTrue("String values should be equal", "[\"entry1\"]".equals(output));
int[] intArray = new int[] { 1, 2, 3 };
output = JSONObject.valueToString(intArray);
assertTrue("String values should be equal", "[1,2,3]".equals(output));
output = JSONObject.valueToString(24);
assertTrue("String values should be equal", "24".equals(output));
output = JSONObject.valueToString("string value");
assertTrue("String values should be equal", "\"string value\"".equals(output));
output = JSONObject.valueToString(true);
assertTrue("String values should be equal", "true".equals(output));
}
/**
* Test what happens when toJSONString() returns a well-formed JSON value.
* This is the usual case.
*/
@Test
public void testJSONStringValue() throws Exception {
JSONStringValue jsonString = new JSONStringValue();
JSONArray jsonArray = new JSONArray();
jsonArray.put(jsonString);
StringWriter writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[\"the JSON string value\"]".equals(output));
output = JSONObject.valueToString(jsonString);
assertTrue("String values should be equal", "\"the JSON string value\"".equals(output));
} finally {
writer.close();
}
}
/**
* Test what happens when toJSONString() returns null. In one case,
* use the object's toString() method. In the other, throw a JSONException.
*/
@Test
public void testJSONNullStringValue() throws Exception {
JSONNullStringValue jsonString = new JSONNullStringValue();
JSONArray jsonArray = new JSONArray();
jsonArray.put(jsonString);
StringWriter writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[\"the toString value\"]".equals(output));
// The only different between writeValue() and valueToString():
// in this case, valueToString throws a JSONException
try {
output = JSONObject.valueToString(jsonString);
fail("Expected an exception, got a String value");
} catch (Exception e) {
assertTrue("Expected JSONException", e instanceof JSONException);
assertTrue("Exception message does not match", "Bad value from toJSONString: null".equals(e.getMessage()));
}
} finally {
writer.close();
}
}
/**
* Test what happens when toJSONString() returns an exception. In both
* cases, a JSONException is thrown, with the cause and message set from
* the original exception.
*/
@Test
public void testJSONStringExceptionValue() throws IOException {
JSONStringExceptionValue jsonString = new JSONStringExceptionValue();
JSONArray jsonArray = new JSONArray();
jsonArray.put(jsonString);
StringWriter writer = new StringWriter();
try {
jsonArray.write(writer).toString();
fail("Expected an exception, got a String value");
} catch (JSONException e) {
assertEquals("Unable to write JSONArray value at index: 0", e.getMessage());
} catch(Exception e) {
fail("Expected JSONException");
} finally {
writer.close();
}
try {
JSONObject.valueToString(jsonString);
fail("Expected an exception, got a String value");
} catch (JSONException e) {
assertTrue("Exception message does not match", "the exception value".equals(e.getMessage()));
} catch(Exception e) {
fail("Expected JSONException");
}
}
/**
* Test what happens when a Java object's toString() returns a String value.
* This is the usual case.
*/
@Test
public void testStringValue() throws Exception {
StringValue nonJsonString = new StringValue();
JSONArray jsonArray = new JSONArray();
jsonArray.put(nonJsonString);
StringWriter writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[\"the toString value for StringValue\"]".equals(output));
output = JSONObject.valueToString(nonJsonString);
assertTrue("String values should be equal", "\"the toString value for StringValue\"".equals(output));
} finally {
writer.close();
}
}
/**
* Test what happens when a Java object's toString() returns null.
* Defaults to empty string.
*/
@Test
public void testNullStringValue() throws Exception {
NullStringValue nonJsonString = new NullStringValue();
JSONArray jsonArray = new JSONArray();
jsonArray.put(nonJsonString);
StringWriter writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[\"\"]".equals(output));
output = JSONObject.valueToString(nonJsonString);
assertTrue("String values should be equal", "\"\"".equals(output));
} finally {
writer.close();
}
}
/**
* A JSONString that returns a valid JSON string value.
*/
private static final class JSONStringValue implements JSONString {
@Override
public String toJSONString() {
return "\"the JSON string value\"";
}
@Override
public String toString() {
return "the toString value for JSONStringValue";
}
}
/**
* A JSONString that returns null when calling toJSONString().
*/
private static final class JSONNullStringValue implements JSONString {
@Override
public String toJSONString() {
return null;
}
@Override
public String toString() {
return "the toString value";
}
}
/**
* A JSONString that throw an exception when calling toJSONString().
*/
private static final class JSONStringExceptionValue implements JSONString {
@Override
public String toJSONString() {
throw new IllegalStateException("the exception value");
}
@Override
public String toString() {
return "the toString value for JSONStringExceptionValue";
}
}
public static final class StringValue {
@Override
public String toString() {
return "the toString value for StringValue";
}
}
public static final class NullStringValue {
@Override
public String toString() {
return null;
}
}
}

View file

@ -0,0 +1,352 @@
package org.json.junit;
import static org.junit.Assert.*;
import java.util.*;
import org.json.*;
import org.junit.Test;
import com.jayway.jsonpath.*;
/**
* Tests for JSON-Java JSONStringer and JSONWriter.
*/
public class JSONStringerTest {
/**
* Object with a null key.
* Expects a JSONException.
*/
@Test
public void nullKeyException() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.object();
try {
jsonStringer.key(null);
assertTrue("Expected an exception", false);
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Null key.".
equals(e.getMessage()));
}
}
/**
* Add a key with no object.
* Expects a JSONException.
*/
@Test
public void outOfSequenceException() {
JSONStringer jsonStringer = new JSONStringer();
try {
jsonStringer.key("hi");
assertTrue("Expected an exception", false);
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Misplaced key.".
equals(e.getMessage()));
}
}
/**
* Missplace an array.
* Expects a JSONException
*/
@Test
public void missplacedArrayException() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.object().endObject();
try {
jsonStringer.array();
assertTrue("Expected an exception", false);
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Misplaced array.".
equals(e.getMessage()));
}
}
/**
* Missplace an endErray.
* Expects a JSONException
*/
@Test
public void missplacedEndArrayException() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.object();
try {
jsonStringer.endArray();
assertTrue("Expected an exception", false);
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Misplaced endArray.".
equals(e.getMessage()));
}
}
/**
* Missplace an endObject.
* Expects a JSONException
*/
@Test
public void missplacedEndObjectException() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.array();
try {
jsonStringer.endObject();
assertTrue("Expected an exception", false);
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Misplaced endObject.".
equals(e.getMessage()));
}
}
/**
* Missplace an object.
* Expects a JSONException.
*/
@Test
public void missplacedObjectException() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.object().endObject();
try {
jsonStringer.object();
assertTrue("Expected an exception", false);
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Misplaced object.".
equals(e.getMessage()));
}
}
/**
* Exceeds implementation max nesting depth.
* Expects a JSONException
*/
@Test
public void exceedNestDepthException() {
try {
JSONStringer s = new JSONStringer();
s.object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object();
s.key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object();
fail("Expected an exception message");
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Nesting too deep.".
equals(e.getMessage()));
}
}
/**
* Build a JSON doc using JSONString API calls,
* then convert to JSONObject
*/
@Test
public void simpleObjectString() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.object();
jsonStringer.key("trueValue").value(true);
jsonStringer.key("falseValue").value(false);
jsonStringer.key("nullValue").value(null);
jsonStringer.key("stringValue").value("hello world!");
jsonStringer.key("complexStringValue").value("h\be\tllo w\u1234orld!");
jsonStringer.key("intValue").value(42);
jsonStringer.key("doubleValue").value(-23.45e67);
jsonStringer.endObject();
String str = jsonStringer.toString();
JSONObject jsonObject = new JSONObject(str);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 7 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 7);
assertTrue("expected true", Boolean.TRUE.equals(jsonObject.query("/trueValue")));
assertTrue("expected false", Boolean.FALSE.equals(jsonObject.query("/falseValue")));
assertTrue("expected null", JSONObject.NULL.equals(jsonObject.query("/nullValue")));
assertTrue("expected hello world!", "hello world!".equals(jsonObject.query("/stringValue")));
assertTrue("expected h\be\tllo w\u1234orld!", "h\be\tllo w\u1234orld!".equals(jsonObject.query("/complexStringValue")));
assertTrue("expected 42", Integer.valueOf(42).equals(jsonObject.query("/intValue")));
assertTrue("expected -23.45e67", Double.valueOf(-23.45e67).equals(jsonObject.query("/doubleValue")));
}
/**
* Build a JSON doc using JSONString API calls,
* then convert to JSONArray
*/
@Test
public void simpleArrayString() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.array();
jsonStringer.value(true);
jsonStringer.value(false);
jsonStringer.value(null);
jsonStringer.value("hello world!");
jsonStringer.value(42);
jsonStringer.value(-23.45e67);
jsonStringer.endArray();
String str = jsonStringer.toString();
JSONArray jsonArray = new JSONArray(str);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
assertTrue("expected 6 top level items", ((List<?>)(JsonPath.read(doc, "$"))).size() == 6);
assertTrue("expected true", Boolean.TRUE.equals(jsonArray.query("/0")));
assertTrue("expected false", Boolean.FALSE.equals(jsonArray.query("/1")));
assertTrue("expected null", JSONObject.NULL.equals(jsonArray.query("/2")));
assertTrue("expected hello world!", "hello world!".equals(jsonArray.query("/3")));
assertTrue("expected 42", Integer.valueOf(42).equals(jsonArray.query("/4")));
assertTrue("expected -23.45e67", Double.valueOf(-23.45e67).equals(jsonArray.query("/5")));
}
/**
* Build a nested JSON doc using JSONString API calls, then convert to
* JSONObject. Will create a long cascade of output by reusing the
* returned values..
*/
@Test
public void complexObjectString() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.object().
key("trueValue").value(true).
key("falseValue").value(false).
key("nullValue").value(null).
key("stringValue").value("hello world!").
key("object2").object().
key("k1").value("v1").
key("k2").value("v2").
key("k3").value("v3").
key("array1").array().
value(1).
value(2).
object().
key("k4").value("v4").
key("k5").value("v5").
key("k6").value("v6").
key("array2").array().
value(5).
value(6).
value(7).
value(8).
endArray().
endObject().
value(3).
value(4).
endArray().
endObject().
key("complexStringValue").value("h\be\tllo w\u1234orld!").
key("intValue").value(42).
key("doubleValue").value(-23.45e67).
endObject();
String str = jsonStringer.toString();
JSONObject jsonObject = new JSONObject(str);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 8 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 8);
assertTrue("expected 4 object2 items", ((Map<?,?>)(JsonPath.read(doc, "$.object2"))).size() == 4);
assertTrue("expected 5 array1 items", ((List<?>)(JsonPath.read(doc, "$.object2.array1"))).size() == 5);
assertTrue("expected 4 array[2] items", ((Map<?,?>)(JsonPath.read(doc, "$.object2.array1[2]"))).size() == 4);
assertTrue("expected 4 array1[2].array2 items", ((List<?>)(JsonPath.read(doc, "$.object2.array1[2].array2"))).size() == 4);
assertTrue("expected true", Boolean.TRUE.equals(jsonObject.query("/trueValue")));
assertTrue("expected false", Boolean.FALSE.equals(jsonObject.query("/falseValue")));
assertTrue("expected null", JSONObject.NULL.equals(jsonObject.query("/nullValue")));
assertTrue("expected hello world!", "hello world!".equals(jsonObject.query("/stringValue")));
assertTrue("expected 42", Integer.valueOf(42).equals(jsonObject.query("/intValue")));
assertTrue("expected -23.45e67", Double.valueOf(-23.45e67).equals(jsonObject.query("/doubleValue")));
assertTrue("expected h\be\tllo w\u1234orld!", "h\be\tllo w\u1234orld!".equals(jsonObject.query("/complexStringValue")));
assertTrue("expected v1", "v1".equals(jsonObject.query("/object2/k1")));
assertTrue("expected v2", "v2".equals(jsonObject.query("/object2/k2")));
assertTrue("expected v3", "v3".equals(jsonObject.query("/object2/k3")));
assertTrue("expected 1", Integer.valueOf(1).equals(jsonObject.query("/object2/array1/0")));
assertTrue("expected 2", Integer.valueOf(2).equals(jsonObject.query("/object2/array1/1")));
assertTrue("expected v4", "v4".equals(jsonObject.query("/object2/array1/2/k4")));
assertTrue("expected v5", "v5".equals(jsonObject.query("/object2/array1/2/k5")));
assertTrue("expected v6", "v6".equals(jsonObject.query("/object2/array1/2/k6")));
assertTrue("expected 5", Integer.valueOf(5).equals(jsonObject.query("/object2/array1/2/array2/0")));
assertTrue("expected 6", Integer.valueOf(6).equals(jsonObject.query("/object2/array1/2/array2/1")));
assertTrue("expected 7", Integer.valueOf(7).equals(jsonObject.query("/object2/array1/2/array2/2")));
assertTrue("expected 8", Integer.valueOf(8).equals(jsonObject.query("/object2/array1/2/array2/3")));
assertTrue("expected 3", Integer.valueOf(3).equals(jsonObject.query("/object2/array1/3")));
assertTrue("expected 4", Integer.valueOf(4).equals(jsonObject.query("/object2/array1/4")));
}
}

View file

@ -0,0 +1,295 @@
package org.json.junit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.junit.Test;
/**
* Test specific to the {@link org.json.JSONTokener} class.
* @author John Aylward
*
*/
public class JSONTokenerTest {
/**
* verify that back() fails as expected.
* @throws IOException thrown if something unexpected happens.
*/
@Test
public void verifyBackFailureZeroIndex() throws IOException {
try(Reader reader = new StringReader("some test string")) {
final JSONTokener tokener = new JSONTokener(reader);
try {
// this should fail since the index is 0;
tokener.back();
fail("Expected an exception");
} catch (JSONException e) {
assertEquals("Stepping back two steps is not supported", e.getMessage());
} catch (Exception e) {
fail("Unknown Exception type " + e.getClass().getCanonicalName()+" with message "+e.getMessage());
}
}
}
/**
* verify that back() fails as expected.
* @throws IOException thrown if something unexpected happens.
*/
@Test
public void verifyBackFailureDoubleBack() throws IOException {
try(Reader reader = new StringReader("some test string")) {
final JSONTokener tokener = new JSONTokener(reader);
tokener.next();
tokener.back();
try {
// this should fail since the index is 0;
tokener.back();
fail("Expected an exception");
} catch (JSONException e) {
assertEquals("Stepping back two steps is not supported", e.getMessage());
} catch (Exception e) {
fail("Unknown Exception type " + e.getClass().getCanonicalName()+" with message "+e.getMessage());
}
}
}
@Test
public void testValid() {
checkValid("0",Number.class);
checkValid(" 0 ",Number.class);
checkValid("23",Number.class);
checkValid("23.5",Number.class);
checkValid(" 23.5 ",Number.class);
checkValid("null",null);
checkValid(" null ",null);
checkValid("true",Boolean.class);
checkValid(" true\n",Boolean.class);
checkValid("false",Boolean.class);
checkValid("\nfalse ",Boolean.class);
checkValid("{}",JSONObject.class);
checkValid(" {} ",JSONObject.class);
checkValid("{\"a\":1}",JSONObject.class);
checkValid(" {\"a\":1} ",JSONObject.class);
checkValid("[]",JSONArray.class);
checkValid(" [] ",JSONArray.class);
checkValid("[1,2]",JSONArray.class);
checkValid("\n\n[1,2]\n\n",JSONArray.class);
checkValid("1 2", String.class);
}
@Test
public void testErrors() {
// Check that stream can detect that a value is found after
// the first one
checkError(" { \"a\":1 } 4 ");
checkError("null \"a\"");
checkError("{} true");
}
private Object checkValid(String testStr, Class<?> aClass) {
Object result = nextValue(testStr);
// Check class of object returned
if( null == aClass ) {
if(JSONObject.NULL.equals(result)) {
// OK
} else {
throw new JSONException("Unexpected class: "+result.getClass().getSimpleName());
}
} else {
if( null == result ) {
throw new JSONException("Unexpected null result");
} else if(!aClass.isAssignableFrom(result.getClass()) ) {
throw new JSONException("Unexpected class: "+result.getClass().getSimpleName());
}
}
return result;
}
private void checkError(String testStr) {
try {
nextValue(testStr);
fail("Error should be triggered: (\""+testStr+"\")");
} catch (JSONException e) {
// OK
}
}
/**
* Verifies that JSONTokener can read a stream that contains a value. After
* the reading is done, check that the stream is left in the correct state
* by reading the characters after. All valid cases should reach end of stream.
* @param testStr
* @return
* @throws Exception
*/
private Object nextValue(String testStr) throws JSONException {
try(StringReader sr = new StringReader(testStr);){
JSONTokener tokener = new JSONTokener(sr);
Object result = tokener.nextValue();
if( result == null ) {
throw new JSONException("Unable to find value token in JSON stream: ("+tokener+"): "+testStr);
}
char c = tokener.nextClean();
if( 0 != c ) {
throw new JSONException("Unexpected character found at end of JSON stream: "+c+ " ("+tokener+"): "+testStr);
}
return result;
}
}
/**
* Tests the failure of the skipTo method with a buffered reader. Preferably
* we'd like this not to fail but at this time we don't have a good recovery.
*
* @throws IOException thrown if something unexpected happens.
*/
@Test
public void testSkipToFailureWithBufferedReader() throws IOException {
final byte[] superLongBuffer = new byte[1000001];
// fill our buffer
for(int i=0;i<superLongBuffer.length;i++) {
superLongBuffer[i] = 'A';
}
try(Reader reader = new BufferedReader(new InputStreamReader(new ByteArrayInputStream(superLongBuffer)))) {
final JSONTokener tokener = new JSONTokener(reader);
try {
// this should fail since the internal markAhead buffer is only 1,000,000
// but 'B' doesn't exist in our buffer that is 1,000,001 in size
tokener.skipTo('B');
fail("Expected exception");
} catch (JSONException e) {
assertEquals("Mark invalid", e.getMessage());
} catch (Exception e) {
fail("Unknown Exception type " + e.getClass().getCanonicalName()+" with message "+e.getMessage());
}
}
}
/**
* Tests the success of the skipTo method with a String reader.
*
* @throws IOException thrown if something unexpected happens.
*/
@Test
public void testSkipToSuccessWithStringReader() throws IOException {
final StringBuilder superLongBuffer = new StringBuilder(1000001);
// fill our buffer
for(int i=0;i<superLongBuffer.length();i++) {
superLongBuffer.append('A');
}
try(Reader reader = new StringReader(superLongBuffer.toString())) {
final JSONTokener tokener = new JSONTokener(reader);
try {
// this should not fail since the internal markAhead is ignored for StringReaders
tokener.skipTo('B');
} catch (Exception e) {
fail("Unknown Exception type " + e.getClass().getCanonicalName()+" with message "+e.getMessage());
}
}
}
/**
* Verify that next and back are working properly and tracking the correct positions
* with different new line combinations.
*/
@Test
public void testNextBackComboWithNewLines() {
final String testString = "this is\nA test\r\nWith some different\rNew Lines";
// ^ ^ ^ ^
// index positions 0 8 16 36
final JSONTokener tokener = new JSONTokener(testString);
assertEquals(" at 0 [character 1 line 1]", tokener.toString());
assertEquals('t',tokener.next());
assertEquals(" at 1 [character 2 line 1]", tokener.toString());
tokener.skipTo('\n');
assertEquals("skipTo() improperly modifying indexes"," at 7 [character 8 line 1]", tokener.toString());
assertEquals('\n',tokener.next());
assertEquals(" at 8 [character 0 line 2]", tokener.toString());
assertEquals('A',tokener.next());
assertEquals(" at 9 [character 1 line 2]", tokener.toString());
tokener.back();
assertEquals(" at 8 [character 0 line 2]", tokener.toString());
tokener.skipTo('\r');
assertEquals("skipTo() improperly modifying indexes"," at 14 [character 6 line 2]", tokener.toString());
// verify \r\n combo doesn't increment the line twice
assertEquals('\r', tokener.next());
assertEquals(" at 15 [character 0 line 3]", tokener.toString());
assertEquals('\n', tokener.next());
assertEquals(" at 16 [character 0 line 3]", tokener.toString());
// verify stepping back after reading the \n of an \r\n combo doesn't increment the line incorrectly
tokener.back();
assertEquals(" at 15 [character 6 line 2]", tokener.toString());
assertEquals('\n', tokener.next());
assertEquals(" at 16 [character 0 line 3]", tokener.toString());
assertEquals('W', tokener.next());
assertEquals(" at 17 [character 1 line 3]", tokener.toString());
assertEquals('i', tokener.next());
assertEquals(" at 18 [character 2 line 3]", tokener.toString());
tokener.skipTo('\r');
assertEquals("skipTo() improperly modifying indexes"," at 35 [character 19 line 3]", tokener.toString());
assertEquals('\r', tokener.next());
assertEquals(" at 36 [character 0 line 4]", tokener.toString());
tokener.back();
assertEquals(" at 35 [character 19 line 3]", tokener.toString());
assertEquals('\r', tokener.next());
assertEquals(" at 36 [character 0 line 4]", tokener.toString());
assertEquals('N', tokener.next());
assertEquals(" at 37 [character 1 line 4]", tokener.toString());
// verify we get the same data just walking though, no calls to back
final JSONTokener t2 = new JSONTokener(testString);
for(int i=0; i<7; i++) {
assertTrue(t2.toString().startsWith(" at " + i + " "));
assertEquals(testString.charAt(i), t2.next());
}
assertEquals(" at 7 [character 8 line 1]", t2.toString());
assertEquals(testString.charAt(7), t2.next());
assertEquals(" at 8 [character 0 line 2]", t2.toString());
for(int i=8; i<14; i++) {
assertTrue(t2.toString().startsWith(" at " + i + " "));
assertEquals(testString.charAt(i), t2.next());
}
assertEquals(" at 14 [character 6 line 2]", t2.toString());
assertEquals('\r', t2.next());
assertEquals(" at 15 [character 0 line 3]", t2.toString());
assertEquals('\n', t2.next());
assertEquals(" at 16 [character 0 line 3]", t2.toString());
assertEquals('W', t2.next());
assertEquals(" at 17 [character 1 line 3]", t2.toString());
for(int i=17; i<37; i++) {
assertTrue(t2.toString().startsWith(" at " + i + " "));
assertEquals(testString.charAt(i), t2.next());
}
assertEquals(" at 37 [character 1 line 4]", t2.toString());
for(int i=37; i<testString.length(); i++) {
assertTrue(t2.toString().startsWith(" at " + i + " "));
assertEquals(testString.charAt(i), t2.next());
}
assertEquals(" at "+ testString.length() +" [character 9 line 4]", t2.toString());
// end of the input
assertEquals(0, t2.next());
assertFalse(t2.more());
}
}

View file

@ -0,0 +1,25 @@
package org.json.junit;
import org.junit.runner.RunWith;
import org.junit.runners.Suite;
@RunWith(Suite.class)
@Suite.SuiteClasses({
CDLTest.class,
CookieTest.class,
CookieListTest.class,
PropertyTest.class,
XMLTest.class,
JSONMLTest.class,
HTTPTest.class,
JSONStringerTest.class,
JSONObjectTest.class,
JSONObjectLocaleTest.class,
JSONArrayTest.class,
EnumTest.class,
JSONPointerTest.class,
JSONStringTest.class,
JSONTokenerTest.class,
XMLConfigurationTest.class
})
public class JunitTestSuite {
}

View file

@ -0,0 +1,98 @@
package org.json.junit;
import java.util.*;
import static org.junit.Assert.*;
import org.json.*;
import org.junit.Test;
/**
* Tests for JSON-Java Property
*/
public class PropertyTest {
/**
* JSONObject from null properties object should
* result in an empty JSONObject.
*/
@Test
public void shouldHandleNullProperties() {
Properties properties = null;
JSONObject jsonObject = Property.toJSONObject(properties);
assertTrue("jsonObject should be empty", jsonObject.isEmpty());
}
/**
* JSONObject from empty properties object should
* result in an empty JSONObject.
*/
@Test
public void shouldHandleEmptyProperties() {
Properties properties = new Properties();
JSONObject jsonObject = Property.toJSONObject(properties);
assertTrue("jsonObject should be empty", jsonObject.isEmpty());
}
/**
* JSONObject from simple properties object.
*/
@Test
public void shouldHandleProperties() {
Properties properties = new Properties();
properties.put("Illinois", "Springfield");
properties.put("Missouri", "Jefferson City");
properties.put("Washington", "Olympia");
properties.put("California", "Sacramento");
properties.put("Indiana", "Indianapolis");
JSONObject jsonObject = Property.toJSONObject(properties);
assertTrue("jsonObject should contain 5 items", jsonObject.length() == 5);
assertTrue("jsonObject should contain Illinois property",
"Springfield".equals(jsonObject.get("Illinois")));
assertTrue("jsonObject should contain Missouri property",
"Jefferson City".equals(jsonObject.get("Missouri")));
assertTrue("jsonObject should contain Washington property",
"Olympia".equals(jsonObject.get("Washington")));
assertTrue("jsonObject should contain California property",
"Sacramento".equals(jsonObject.get("California")));
assertTrue("jsonObject should contain Indiana property",
"Indianapolis".equals(jsonObject.get("Indiana")));
}
/**
* Null JSONObject toProperties() should result in an empty
* Properties object.
*/
@Test
public void shouldHandleNullJSONProperty() {
JSONObject jsonObject= null;
Properties properties = Property.toProperties(jsonObject);
assertTrue("properties should be empty",
properties.size() == 0);
}
/**
* Properties should convert to JSONObject, and back to
* Properties without changing.
*/
@Test
public void shouldHandleJSONProperty() {
Properties properties = new Properties();
properties.put("Illinois", "Springfield");
properties.put("Missouri", "Jefferson City");
properties.put("Washington", "Olympia");
properties.put("California", "Sacramento");
properties.put("Indiana", "Indianapolis");
JSONObject jsonObject = Property.toJSONObject(properties);
Properties jsonProperties = Property.toProperties(jsonObject);
assertTrue("property objects should match",
properties.equals(jsonProperties));
}
}

View file

@ -0,0 +1,19 @@
package org.json.junit;
import org.junit.runner.JUnitCore;
import org.junit.runner.Result;
import org.junit.runner.notification.Failure;
/**
* Invoke this class main method if you want to run unit tests from the
* command line. If successful, will print "true" to stdout.
*/
public class TestRunner {
public static void main(String[] args) {
Result result = JUnitCore.runClasses(JunitTestSuite.class);
for (Failure failure : result.getFailures()) {
System.out.println(failure.toString());
}
System.out.println(result.wasSuccessful());
}
}

View file

@ -0,0 +1,98 @@
package org.json.junit;
import static org.junit.Assert.*;
import java.util.*;
import org.json.*;
/**
* These are helpful utility methods that perform basic comparisons
* between various objects. In most cases, the comparisons are not
* order-dependent, or else the order is known.
*/
public class Util {
/**
* Compares two JSONArrays for equality.
* The arrays need not be in the same order.
* @param jsonArray created by the code to be tested
* @param expectedJsonArray created specifically for comparing
*/
public static void compareActualVsExpectedJsonArrays(JSONArray jsonArray,
JSONArray expectedJsonArray) {
assertTrue("jsonArray lengths should be equal",
jsonArray.length() == expectedJsonArray.length());
for (int i = 0; i < jsonArray.length(); ++i) {
Object value = jsonArray.get(i);
Object expectedValue = expectedJsonArray.get(i);
compareActualVsExpectedObjects(value, expectedValue);
}
}
/**
* Compares two JSONObjects for equality. The objects need not be
* in the same order
* @param jsonObject created by the code to be tested
* @param expectedJsonObject created specifically for comparing
*/
public static void compareActualVsExpectedJsonObjects(
JSONObject jsonObject, JSONObject expectedJsonObject) {
assertTrue("jsonObjects should have the same length",
jsonObject.length() == expectedJsonObject.length());
Iterator<String> keys = jsonObject.keys();
while (keys.hasNext()) {
String key = keys.next();
Object value = jsonObject.get(key);
Object expectedValue = expectedJsonObject.get(key);
compareActualVsExpectedObjects(value, expectedValue);
}
}
/**
* Compare two objects for equality. Might be JSONArray, JSONObject,
* or something else.
* @param value created by the code to be tested
* @param expectedValue created specifically for comparing
* @param key key to the jsonObject entry to be compared
*/
private static void compareActualVsExpectedObjects(Object value,
Object expectedValue) {
if (value instanceof JSONObject && expectedValue instanceof JSONObject) {
// Compare JSONObjects
JSONObject jsonObject = (JSONObject)value;
JSONObject expectedJsonObject = (JSONObject)expectedValue;
compareActualVsExpectedJsonObjects(
jsonObject, expectedJsonObject);
} else if (value instanceof JSONArray && expectedValue instanceof JSONArray) {
// Compare JSONArrays
JSONArray jsonArray = (JSONArray)value;
JSONArray expectedJsonArray = (JSONArray)expectedValue;
compareActualVsExpectedJsonArrays(
jsonArray, expectedJsonArray);
} else {
/**
* Compare all other types using toString(). First, the types must
* also be equal, unless both are Number type. Certain helper
* classes (e.g. XML) may create Long instead of Integer for small
* int values.
*/
if (!(value instanceof Number && expectedValue instanceof Number)) {
// Non-Number and non-matching types
assertTrue("object types should be equal for actual: "+
value.toString()+" ("+
value.getClass().toString()+") expected: "+
expectedValue.toString()+" ("+
expectedValue.getClass().toString()+")",
value.getClass().toString().equals(
expectedValue.getClass().toString()));
}
/**
* Same types or both Numbers, compare by toString()
*/
assertTrue("string values should be equal for actual: "+
value.toString()+" expected: "+expectedValue.toString(),
value.toString().equals(expectedValue.toString()));
}
}
}

View file

@ -0,0 +1,930 @@
package org.json.junit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.XML;
import org.json.XMLParserConfiguration;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
/**
* Tests for JSON-Java XML.java with XMLParserConfiguration.java
*/
public class XMLConfigurationTest {
/**
* JUnit supports temporary files and folders that are cleaned up after the test.
* https://garygregory.wordpress.com/2010/01/20/junit-tip-use-rules-to-manage-temporary-files-and-folders/
*/
@Rule
public TemporaryFolder testFolder = new TemporaryFolder();
/**
* JSONObject from a null XML string.
* Expects a NullPointerException
*/
@Test(expected=NullPointerException.class)
public void shouldHandleNullXML() {
String xmlStr = null;
JSONObject jsonObject =
XML.toJSONObject(xmlStr, XMLParserConfiguration.KEEP_STRINGS);
assertTrue("jsonObject should be empty", jsonObject.isEmpty());
}
/**
* Empty JSONObject from an empty XML string.
*/
@Test
public void shouldHandleEmptyXML() {
String xmlStr = "";
JSONObject jsonObject =
XML.toJSONObject(xmlStr, XMLParserConfiguration.KEEP_STRINGS);
assertTrue("jsonObject should be empty", jsonObject.isEmpty());
}
/**
* Empty JSONObject from a non-XML string.
*/
@Test
public void shouldHandleNonXML() {
String xmlStr = "{ \"this is\": \"not xml\"}";
JSONObject jsonObject =
XML.toJSONObject(xmlStr, XMLParserConfiguration.KEEP_STRINGS);
assertTrue("xml string should be empty", jsonObject.isEmpty());
}
/**
* Invalid XML string (tag contains a frontslash).
* Expects a JSONException
*/
@Test
public void shouldHandleInvalidSlashInTag() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/x>\n"+
" <street>abc street</street>\n"+
" </address>\n"+
"</addresses>";
try {
XML.toJSONObject(xmlStr, XMLParserConfiguration.KEEP_STRINGS);
fail("Expecting a JSONException");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misshaped tag at 176 [character 14 line 4]",
e.getMessage());
}
}
/**
* Invalid XML string ('!' char in tag)
* Expects a JSONException
*/
@Test
public void shouldHandleInvalidBangInTag() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <!>\n"+
" </address>\n"+
"</addresses>";
try {
XML.toJSONObject(xmlStr, XMLParserConfiguration.KEEP_STRINGS);
fail("Expecting a JSONException");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misshaped meta tag at 214 [character 12 line 7]",
e.getMessage());
}
}
/**
* Invalid XML string ('!' char and no closing tag brace)
* Expects a JSONException
*/
@Test
public void shouldHandleInvalidBangNoCloseInTag() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <!\n"+
" </address>\n"+
"</addresses>";
try {
XML.toJSONObject(xmlStr, XMLParserConfiguration.KEEP_STRINGS);
fail("Expecting a JSONException");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misshaped meta tag at 213 [character 12 line 7]",
e.getMessage());
}
}
/**
* Invalid XML string (no end brace for tag)
* Expects JSONException
*/
@Test
public void shouldHandleNoCloseStartTag() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <abc\n"+
" </address>\n"+
"</addresses>";
try {
XML.toJSONObject(xmlStr, XMLParserConfiguration.KEEP_STRINGS);
fail("Expecting a JSONException");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misplaced '<' at 193 [character 4 line 6]",
e.getMessage());
}
}
/**
* Invalid XML string (partial CDATA chars in tag name)
* Expects JSONException
*/
@Test
public void shouldHandleInvalidCDATABangInTag() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name>Joe Tester</name>\n"+
" <![[]>\n"+
" </address>\n"+
"</addresses>";
try {
XMLParserConfiguration config =
new XMLParserConfiguration("altContent");
XML.toJSONObject(xmlStr, config);
fail("Expecting a JSONException");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Expected 'CDATA[' at 204 [character 11 line 5]",
e.getMessage());
}
}
/**
* Null JSONObject in XML.toString()
*/
@Test
public void shouldHandleNullJSONXML() {
JSONObject jsonObject= null;
String actualXml = XML.toString(jsonObject, null,
XMLParserConfiguration.KEEP_STRINGS);
assertEquals("generated XML does not equal expected XML","\"null\"",actualXml);
}
/**
* Empty JSONObject in XML.toString()
*/
@Test
public void shouldHandleEmptyJSONXML() {
JSONObject jsonObject= new JSONObject();
String xmlStr = XML.toString(jsonObject, null,
XMLParserConfiguration.KEEP_STRINGS);
assertTrue("xml string should be empty", xmlStr.isEmpty());
}
/**
* No SML start tag. The ending tag ends up being treated as content.
*/
@Test
public void shouldHandleNoStartTag() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <nocontent/>>\n"+
" </address>\n"+
"</addresses>";
String expectedStr =
"{\"addresses\":{\"address\":{\"name\":\"\",\"nocontent\":\"\",\""+
"content\":\">\"},\"xsi:noNamespaceSchemaLocation\":\"test.xsd\",\""+
"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"}}";
JSONObject jsonObject = XML.toJSONObject(xmlStr,
XMLParserConfiguration.KEEP_STRINGS);
JSONObject expectedJsonObject = new JSONObject(expectedStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Valid XML to JSONObject
*/
@Test
public void shouldHandleSimpleXML() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name>Joe Tester</name>\n"+
" <street>[CDATA[Baker street 5]</street>\n"+
" <NothingHere/>\n"+
" <TrueValue>true</TrueValue>\n"+
" <FalseValue>false</FalseValue>\n"+
" <NullValue>null</NullValue>\n"+
" <PositiveValue>42</PositiveValue>\n"+
" <NegativeValue>-23</NegativeValue>\n"+
" <DoubleValue>-23.45</DoubleValue>\n"+
" <Nan>-23x.45</Nan>\n"+
" <ArrayOfNum>1, 2, 3, 4.1, 5.2</ArrayOfNum>\n"+
" </address>\n"+
"</addresses>";
String expectedStr =
"{\"addresses\":{\"address\":{\"street\":\"[CDATA[Baker street 5]\","+
"\"name\":\"Joe Tester\",\"NothingHere\":\"\",TrueValue:true,\n"+
"\"FalseValue\":false,\"NullValue\":null,\"PositiveValue\":42,\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/"+
"XMLSchema-instance\"}}";
XMLParserConfiguration config =
new XMLParserConfiguration("altContent");
compareStringToJSONObject(xmlStr, expectedStr, config);
compareReaderToJSONObject(xmlStr, expectedStr, config);
compareFileToJSONObject(xmlStr, expectedStr);
}
/**
* Valid XML with comments to JSONObject
*/
@Test
public void shouldHandleCommentsInXML() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<!-- this is a comment -->\n"+
"<addresses>\n"+
" <address>\n"+
" <![CDATA[ this is -- <another> comment ]]>\n"+
" <name>Joe Tester</name>\n"+
" <!-- this is a - multi line \n"+
" comment -->\n"+
" <street>Baker street 5</street>\n"+
" </address>\n"+
"</addresses>";
XMLParserConfiguration config =
new XMLParserConfiguration("altContent");
JSONObject jsonObject = XML.toJSONObject(xmlStr, config);
String expectedStr = "{\"addresses\":{\"address\":{\"street\":\"Baker "+
"street 5\",\"name\":\"Joe Tester\",\"altContent\":\" this is -- "+
"<another> comment \"}}}";
JSONObject expectedJsonObject = new JSONObject(expectedStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Valid XML to XML.toString()
*/
@Test
public void shouldHandleToString() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name>[CDATA[Joe &amp; T &gt; e &lt; s &quot; t &apos; er]]</name>\n"+
" <street>Baker street 5</street>\n"+
" <ArrayOfNum>1, 2, 3, 4.1, 5.2</ArrayOfNum>\n"+
" </address>\n"+
"</addresses>";
String expectedStr =
"{\"addresses\":{\"address\":{\"street\":\"Baker street 5\","+
"\"name\":\"[CDATA[Joe & T > e < s \\\" t \\\' er]]\","+
"\"ArrayOfNum\":\"1, 2, 3, 4.1, 5.2\"\n"+
"},\"xsi:noNamespaceSchemaLocation\":"+
"\"test.xsd\",\"xmlns:xsi\":\"http://www.w3.org/2001/"+
"XMLSchema-instance\"}}";
JSONObject jsonObject = XML.toJSONObject(xmlStr,
XMLParserConfiguration.KEEP_STRINGS);
String xmlToStr = XML.toString(jsonObject, null,
XMLParserConfiguration.KEEP_STRINGS);
JSONObject finalJsonObject = XML.toJSONObject(xmlToStr,
XMLParserConfiguration.KEEP_STRINGS);
JSONObject expectedJsonObject = new JSONObject(expectedStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
}
/**
* Converting a JSON doc containing '>' content to JSONObject, then
* XML.toString() should result in valid XML.
*/
@Test
public void shouldHandleContentNoArraytoString() {
String expectedStr =
"{\"addresses\":{\"address\":{\"name\":\"\",\"nocontent\":\"\",\""+
"altContent\":\">\"},\"xsi:noNamespaceSchemaLocation\":\"test.xsd\",\""+
"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"}}";
JSONObject expectedJsonObject = new JSONObject(expectedStr);
XMLParserConfiguration config = new XMLParserConfiguration("altContent");
String finalStr = XML.toString(expectedJsonObject, null, config);
String expectedFinalStr = "<addresses><address><name/><nocontent/>&gt;"+
"</address><xsi:noNamespaceSchemaLocation>test.xsd</xsi:noName"+
"spaceSchemaLocation><xmlns:xsi>http://www.w3.org/2001/XMLSche"+
"ma-instance</xmlns:xsi></addresses>";
assertTrue("Should handle expectedFinal: ["+expectedStr+"] final: ["+
finalStr+"]", expectedFinalStr.equals(finalStr));
}
/**
* Converting a JSON doc containing a 'content' array to JSONObject, then
* XML.toString() should result in valid XML.
* TODO: This is probably an error in how the 'content' keyword is used.
*/
@Test
public void shouldHandleContentArraytoString() {
String expectedStr =
"{\"addresses\":{\"address\":{\"name\":\"\",\"nocontent\":\"\",\""+
"altContent\":[1, 2, 3]},\"xsi:noNamespaceSchemaLocation\":\"test.xsd\",\""+
"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"}}";
JSONObject expectedJsonObject = new JSONObject(expectedStr);
XMLParserConfiguration config = new XMLParserConfiguration("altContent");
String finalStr = XML.toString(expectedJsonObject, null, config);
String expectedFinalStr = "<addresses><address><name/><nocontent/>"+
"1\n2\n3"+
"</address><xsi:noNamespaceSchemaLocation>test.xsd</xsi:noName"+
"spaceSchemaLocation><xmlns:xsi>http://www.w3.org/2001/XMLSche"+
"ma-instance</xmlns:xsi></addresses>";
assertTrue("Should handle expectedFinal: ["+expectedStr+"] final: ["+
finalStr+"]", expectedFinalStr.equals(finalStr));
}
/**
* Converting a JSON doc containing a named array to JSONObject, then
* XML.toString() should result in valid XML.
*/
@Test
public void shouldHandleArraytoString() {
String expectedStr =
"{\"addresses\":{\"address\":{\"name\":\"\",\"nocontent\":\"\","+
"\"something\":[1, 2, 3]},\"xsi:noNamespaceSchemaLocation\":\"test.xsd\",\""+
"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"}}";
JSONObject expectedJsonObject = new JSONObject(expectedStr);
String finalStr = XML.toString(expectedJsonObject, null,
XMLParserConfiguration.KEEP_STRINGS);
String expectedFinalStr = "<addresses><address><name/><nocontent/>"+
"<something>1</something><something>2</something><something>3</something>"+
"</address><xsi:noNamespaceSchemaLocation>test.xsd</xsi:noName"+
"spaceSchemaLocation><xmlns:xsi>http://www.w3.org/2001/XMLSche"+
"ma-instance</xmlns:xsi></addresses>";
assertTrue("Should handle expectedFinal: ["+expectedStr+"] final: ["+
finalStr+"]", expectedFinalStr.equals(finalStr));
}
/**
* Tests that the XML output for empty arrays is consistent.
*/
@Test
public void shouldHandleEmptyArray(){
final JSONObject jo1 = new JSONObject();
jo1.put("array",new Object[]{});
final JSONObject jo2 = new JSONObject();
jo2.put("array",new JSONArray());
final String expected = "<jo></jo>";
String output1 = XML.toString(jo1, "jo",
XMLParserConfiguration.KEEP_STRINGS);
assertEquals("Expected an empty root tag", expected, output1);
String output2 = XML.toString(jo2, "jo",
XMLParserConfiguration.KEEP_STRINGS);
assertEquals("Expected an empty root tag", expected, output2);
}
/**
* Tests that the XML output for arrays is consistent when an internal array is empty.
*/
@Test
public void shouldHandleEmptyMultiArray(){
final JSONObject jo1 = new JSONObject();
jo1.put("arr",new Object[]{"One", new String[]{}, "Four"});
final JSONObject jo2 = new JSONObject();
jo2.put("arr",new JSONArray(new Object[]{"One", new JSONArray(new String[]{}), "Four"}));
final String expected = "<jo><arr>One</arr><arr></arr><arr>Four</arr></jo>";
String output1 = XML.toString(jo1, "jo",
XMLParserConfiguration.KEEP_STRINGS);
assertEquals("Expected a matching array", expected, output1);
String output2 = XML.toString(jo2, "jo",
XMLParserConfiguration.KEEP_STRINGS);
assertEquals("Expected a matching array", expected, output2);
}
/**
* Tests that the XML output for arrays is consistent when arrays are not empty.
*/
@Test
public void shouldHandleNonEmptyArray(){
final JSONObject jo1 = new JSONObject();
jo1.put("arr",new String[]{"One", "Two", "Three"});
final JSONObject jo2 = new JSONObject();
jo2.put("arr",new JSONArray(new String[]{"One", "Two", "Three"}));
final String expected = "<jo><arr>One</arr><arr>Two</arr><arr>Three</arr></jo>";
String output1 = XML.toString(jo1, "jo",
XMLParserConfiguration.KEEP_STRINGS);
assertEquals("Expected a non empty root tag", expected, output1);
String output2 = XML.toString(jo2, "jo",
XMLParserConfiguration.KEEP_STRINGS);
assertEquals("Expected a non empty root tag", expected, output2);
}
/**
* Tests that the XML output for arrays is consistent when arrays are not empty and contain internal arrays.
*/
@Test
public void shouldHandleMultiArray(){
final JSONObject jo1 = new JSONObject();
jo1.put("arr",new Object[]{"One", new String[]{"Two", "Three"}, "Four"});
final JSONObject jo2 = new JSONObject();
jo2.put("arr",new JSONArray(new Object[]{"One", new JSONArray(new String[]{"Two", "Three"}), "Four"}));
final String expected = "<jo><arr>One</arr><arr><array>Two</array><array>Three</array></arr><arr>Four</arr></jo>";
String output1 = XML.toString(jo1, "jo",
XMLParserConfiguration.KEEP_STRINGS);
assertEquals("Expected a matching array", expected, output1);
String output2 = XML.toString(jo2, "jo",
XMLParserConfiguration.KEEP_STRINGS);
assertEquals("Expected a matching array", expected, output2);
}
/**
* Converting a JSON doc containing a named array of nested arrays to
* JSONObject, then XML.toString() should result in valid XML.
*/
@Test
public void shouldHandleNestedArraytoString() {
String xmlStr =
"{\"addresses\":{\"address\":{\"name\":\"\",\"nocontent\":\"\","+
"\"outer\":[[1], [2], [3]]},\"xsi:noNamespaceSchemaLocation\":\"test.xsd\",\""+
"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"}}";
JSONObject jsonObject = new JSONObject(xmlStr);
String finalStr = XML.toString(jsonObject, null,
XMLParserConfiguration.ORIGINAL);
JSONObject finalJsonObject = XML.toJSONObject(finalStr);
String expectedStr = "<addresses><address><name/><nocontent/>"+
"<outer><array>1</array></outer><outer><array>2</array>"+
"</outer><outer><array>3</array></outer>"+
"</address><xsi:noNamespaceSchemaLocation>test.xsd</xsi:noName"+
"spaceSchemaLocation><xmlns:xsi>http://www.w3.org/2001/XMLSche"+
"ma-instance</xmlns:xsi></addresses>";
JSONObject expectedJsonObject = XML.toJSONObject(expectedStr,
XMLParserConfiguration.ORIGINAL);
Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
}
/**
* Possible bug:
* Illegal node-names must be converted to legal XML-node-names.
* The given example shows 2 nodes which are valid for JSON, but not for XML.
* Therefore illegal arguments should be converted to e.g. an underscore (_).
*/
@Test
public void shouldHandleIllegalJSONNodeNames()
{
JSONObject inputJSON = new JSONObject();
inputJSON.append("123IllegalNode", "someValue1");
inputJSON.append("Illegal@node", "someValue2");
String result = XML.toString(inputJSON, null,
XMLParserConfiguration.KEEP_STRINGS);
/*
* This is invalid XML. Names should not begin with digits or contain
* certain values, including '@'. One possible solution is to replace
* illegal chars with '_', in which case the expected output would be:
* <___IllegalNode>someValue1</___IllegalNode><Illegal_node>someValue2</Illegal_node>
*/
String expected = "<123IllegalNode>someValue1</123IllegalNode><Illegal@node>someValue2</Illegal@node>";
assertEquals(expected, result);
}
/**
* JSONObject with NULL value, to XML.toString()
*/
@Test
public void shouldHandleNullNodeValue()
{
JSONObject inputJSON = new JSONObject();
inputJSON.put("nullValue", JSONObject.NULL);
// This is a possible preferred result
// String expectedXML = "<nullValue/>";
/**
* This is the current behavior. JSONObject.NULL is emitted as
* the string, "null".
*/
String actualXML = "<nullValue>null</nullValue>";
String resultXML = XML.toString(inputJSON, null,
XMLParserConfiguration.KEEP_STRINGS);
assertEquals(actualXML, resultXML);
}
/**
* Investigate exactly how the "content" keyword works
*/
@Test
public void contentOperations() {
/*
* When a standalone <!CDATA[...]] structure is found while parsing XML into a
* JSONObject, the contents are placed in a string value with key="content".
*/
String xmlStr = "<tag1></tag1><![CDATA[if (a < b && a > 0) then return]]><tag2></tag2>";
JSONObject jsonObject = XML.toJSONObject(xmlStr,
XMLParserConfiguration.KEEP_STRINGS);
assertTrue("1. 3 items", 3 == jsonObject.length());
assertTrue("1. empty tag1", "".equals(jsonObject.get("tag1")));
assertTrue("1. empty tag2", "".equals(jsonObject.get("tag2")));
assertTrue("1. content found", "if (a < b && a > 0) then return".equals(jsonObject.get("content")));
// multiple consecutive standalone cdatas are accumulated into an array
xmlStr = "<tag1></tag1><![CDATA[if (a < b && a > 0) then return]]><tag2></tag2><![CDATA[here is another cdata]]>";
jsonObject = XML.toJSONObject(xmlStr,
new XMLParserConfiguration(true, "altContent"));
assertTrue("2. 3 items", 3 == jsonObject.length());
assertTrue("2. empty tag1", "".equals(jsonObject.get("tag1")));
assertTrue("2. empty tag2", "".equals(jsonObject.get("tag2")));
assertTrue("2. content array found", jsonObject.get("altContent") instanceof JSONArray);
JSONArray jsonArray = jsonObject.getJSONArray("altContent");
assertTrue("2. array size", jsonArray.length() == 2);
assertTrue("2. content array entry 0", "if (a < b && a > 0) then return".equals(jsonArray.get(0)));
assertTrue("2. content array entry 1", "here is another cdata".equals(jsonArray.get(1)));
/*
* text content is accumulated in a "content" inside a local JSONObject.
* If there is only one instance, it is saved in the context (a different JSONObject
* from the calling code. and the content element is discarded.
*/
xmlStr = "<tag1>value 1</tag1>";
jsonObject = XML.toJSONObject(xmlStr,
new XMLParserConfiguration(true, "altContent"));
assertTrue("3. 2 items", 1 == jsonObject.length());
assertTrue("3. value tag1", "value 1".equals(jsonObject.get("tag1")));
/*
* array-style text content (multiple tags with the same name) is
* accumulated in a local JSONObject with key="content" and value=JSONArray,
* saved in the context, and then the local JSONObject is discarded.
*/
xmlStr = "<tag1>value 1</tag1><tag1>2</tag1><tag1>true</tag1>";
jsonObject = XML.toJSONObject(xmlStr,
new XMLParserConfiguration(true, "altContent"));
assertTrue("4. 1 item", 1 == jsonObject.length());
assertTrue("4. content array found", jsonObject.get("tag1") instanceof JSONArray);
jsonArray = jsonObject.getJSONArray("tag1");
assertTrue("4. array size", jsonArray.length() == 3);
assertTrue("4. content array entry 0", "value 1".equals(jsonArray.get(0)));
assertTrue("4. content array entry 1", jsonArray.getInt(1) == 2);
assertTrue("4. content array entry 2", jsonArray.getBoolean(2) == true);
/*
* Complex content is accumulated in a "content" field. For example, an element
* may contain a mix of child elements and text. Each text segment is
* accumulated to content.
*/
xmlStr = "<tag1>val1<tag2/>val2</tag1>";
jsonObject = XML.toJSONObject(xmlStr,
new XMLParserConfiguration(true, "altContent"));
assertTrue("5. 1 item", 1 == jsonObject.length());
assertTrue("5. jsonObject found", jsonObject.get("tag1")
instanceof JSONObject);
jsonObject = jsonObject.getJSONObject("tag1");
assertTrue("5. 2 contained items", 2 == jsonObject.length());
assertTrue("5. contained tag", "".equals(jsonObject.get("tag2")));
assertTrue("5. contained content jsonArray found",
jsonObject.get("altContent") instanceof JSONArray);
jsonArray = jsonObject.getJSONArray("altContent");
assertTrue("5. array size", jsonArray.length() == 2);
assertTrue("5. content array entry 0", "val1".equals(jsonArray.get(0)));
assertTrue("5. content array entry 1", "val2".equals(jsonArray.get(1)));
/*
* If there is only 1 complex text content, then it is accumulated in a
* "content" field as a string.
*/
xmlStr = "<tag1>val1<tag2/></tag1>";
jsonObject = XML.toJSONObject(xmlStr,
new XMLParserConfiguration(true, "altContent"));
assertTrue("6. 1 item", 1 == jsonObject.length());
assertTrue("6. jsonObject found", jsonObject.get("tag1") instanceof JSONObject);
jsonObject = jsonObject.getJSONObject("tag1");
assertTrue("6. contained content found",
"val1".equals(jsonObject.get("altContent")));
assertTrue("6. contained tag2", "".equals(jsonObject.get("tag2")));
/*
* In this corner case, the content sibling happens to have key=content
* We end up with an array within an array, and no content element.
* This is probably a bug.
*/
xmlStr = "<tag1>val1<altContent/></tag1>";
jsonObject = XML.toJSONObject(xmlStr,
new XMLParserConfiguration(true, "altContent"));
assertTrue("7. 1 item", 1 == jsonObject.length());
assertTrue("7. jsonArray found",
jsonObject.get("tag1") instanceof JSONArray);
jsonArray = jsonObject.getJSONArray("tag1");
assertTrue("array size 1", jsonArray.length() == 1);
assertTrue("7. contained array found", jsonArray.get(0)
instanceof JSONArray);
jsonArray = jsonArray.getJSONArray(0);
assertTrue("7. inner array size 2", jsonArray.length() == 2);
assertTrue("7. inner array item 0", "val1".equals(jsonArray.get(0)));
assertTrue("7. inner array item 1", "".equals(jsonArray.get(1)));
/*
* Confirm behavior of original issue
*/
String jsonStr =
"{"+
"\"Profile\": {"+
"\"list\": {"+
"\"history\": {"+
"\"entries\": ["+
"{"+
"\"deviceId\": \"id\","+
"\"altContent\": {"+
"\"material\": ["+
"{"+
"\"stuff\": false"+
"}"+
"]"+
"}"+
"}"+
"]"+
"}"+
"}"+
"}"+
"}";
jsonObject = new JSONObject(jsonStr);
xmlStr = XML.toString(jsonObject, null,
new XMLParserConfiguration(true, "altContent"));
/*
* This is the created XML. Looks like content was mistaken for
* complex (child node + text) XML.
* <Profile>
* <list>
* <history>
* <entries>
* <deviceId>id</deviceId>
* {&quot;material&quot;:[{&quot;stuff&quot;:false}]}
* </entries>
* </history>
* </list>
* </Profile>
*/
assertTrue("nothing to test here, see comment on created XML, above", true);
}
/**
* JSON string lost leading zero and converted "True" to true.
*/
@Test
public void testToJSONArray_jsonOutput() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
final String expectedJsonString = "{\"root\":{\"item\":{\"id\":\"01\"},\"id\":[\"01\",1,\"00\",0],\"title\":true}}";
final JSONObject actualJsonOutput = XML.toJSONObject(originalXml,
new XMLParserConfiguration(false));
assertEquals(expectedJsonString, actualJsonOutput.toString());
}
/**
* JSON string cannot be reverted to original xml.
*/
@Test
public void testToJSONArray_reversibility() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
XMLParserConfiguration config = new XMLParserConfiguration(false);
final String revertedXml =
XML.toString(XML.toJSONObject(originalXml, config),
null, config);
assertNotEquals(revertedXml, originalXml);
}
/**
* test passes when using the new method toJsonArray.
*/
@Test
public void testToJsonXML() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
final String expectedJsonString = "{\"root\":{\"item\":{\"id\":\"01\"},\"id\":[\"01\",\"1\",\"00\",\"0\"],\"title\":\"True\"}}";
final JSONObject json = XML.toJSONObject(originalXml,
new XMLParserConfiguration(true));
assertEquals(expectedJsonString, json.toString());
final String reverseXml = XML.toString(json);
// this reversal isn't exactly the same. use JSONML for an exact reversal
final String expectedReverseXml = "<root><item><id>01</id></item><id>01</id><id>1</id><id>00</id><id>0</id><title>True</title></root>";
assertEquals(expectedReverseXml, reverseXml);
}
/**
* test to validate certain conditions of XML unescaping.
*/
@Test
public void testUnescape() {
assertEquals("{\"xml\":\"Can cope <;\"}",
XML.toJSONObject("<xml>Can cope &lt;; </xml>",
XMLParserConfiguration.KEEP_STRINGS).toString());
assertEquals("Can cope <; ", XML.unescape("Can cope &lt;; "));
assertEquals("{\"xml\":\"Can cope & ;\"}",
XML.toJSONObject("<xml>Can cope &amp; ; </xml>",
XMLParserConfiguration.KEEP_STRINGS).toString());
assertEquals("Can cope & ; ", XML.unescape("Can cope &amp; ; "));
assertEquals("{\"xml\":\"Can cope &;\"}",
XML.toJSONObject("<xml>Can cope &amp;; </xml>",
XMLParserConfiguration.KEEP_STRINGS).toString());
assertEquals("Can cope &; ", XML.unescape("Can cope &amp;; "));
// unicode entity
assertEquals("{\"xml\":\"Can cope 4;\"}",
XML.toJSONObject("<xml>Can cope &#x34;; </xml>",
XMLParserConfiguration.KEEP_STRINGS).toString());
assertEquals("Can cope 4; ", XML.unescape("Can cope &#x34;; "));
// double escaped
assertEquals("{\"xml\":\"Can cope &lt;\"}",
XML.toJSONObject("<xml>Can cope &amp;lt; </xml>",
XMLParserConfiguration.KEEP_STRINGS).toString());
assertEquals("Can cope &lt; ", XML.unescape("Can cope &amp;lt; "));
assertEquals("{\"xml\":\"Can cope &#x34;\"}",
XML.toJSONObject("<xml>Can cope &amp;#x34; </xml>",
XMLParserConfiguration.KEEP_STRINGS).toString());
assertEquals("Can cope &#x34; ", XML.unescape("Can cope &amp;#x34; "));
}
/**
* Confirm XMLParserConfiguration functionality
*/
@Test
public void testConfig() {
/**
* 1st param is whether to keep the raw string, or call
* XML.stringToValue(), which may convert the token to
* boolean, null, or number.
* 2nd param is what JSON name to use for strings that are
* evaluated as xml content data in complex objects, e.g.
* <parent>
* <child>value</child>
* content data
* </tag>
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" content 1\n"+
" <name>Sherlock Holmes</name>\n"+
" content 2\n"+
" <street>Baker street 5</street>\n"+
" content 3\n"+
" <num>1</num>\n"+
" </address>\n"+
"</addresses>";
// keep strings, use the altContent tag
XMLParserConfiguration config =
new XMLParserConfiguration(true, "altContent");
JSONObject jsonObject = XML.toJSONObject(xmlStr, config);
// num is parsed as a string
assertEquals(jsonObject.getJSONObject("addresses").
getJSONObject("address").getString("num"), "1");
// complex content is collected in an 'altContent' array
JSONArray jsonArray = jsonObject.getJSONObject("addresses").
getJSONObject("address").getJSONArray("altContent");
String expectedStr = "[\"content 1\", \"content 2\", \"content 3\"]";
JSONArray expectedJsonArray = new JSONArray(expectedStr);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
// keepstrings only
jsonObject = XML.toJSONObject(xmlStr,
XMLParserConfiguration.KEEP_STRINGS);
// num is parsed as a string
assertEquals(jsonObject.getJSONObject("addresses").
getJSONObject("address").getString("num"), "1");
// complex content is collected in an 'content' array
jsonArray = jsonObject.getJSONObject("addresses").
getJSONObject("address").getJSONArray("content");
expectedJsonArray = new JSONArray(expectedStr);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
// use alternate content name
config = new XMLParserConfiguration("altContent");
jsonObject = XML.toJSONObject(xmlStr, config);
// num is parsed as a number
assertEquals(jsonObject.getJSONObject("addresses").
getJSONObject("address").getInt("num"), 1);
// complex content is collected in an 'altContent' array
jsonArray = jsonObject.getJSONObject("addresses").
getJSONObject("address").getJSONArray("altContent");
expectedJsonArray = new JSONArray(expectedStr);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
}
/**
* Convenience method, given an input string and expected result,
* convert to JSONObject and compare actual to expected result.
* @param xmlStr the string to parse
* @param expectedStr the expected JSON string
* @param config provides more flexible XML parsing
* flexible XML parsing.
*/
private void compareStringToJSONObject(String xmlStr, String expectedStr,
XMLParserConfiguration config) {
JSONObject expectedJsonObject = new JSONObject(expectedStr);
JSONObject jsonObject = XML.toJSONObject(xmlStr, config);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Convenience method, given an input string and expected result,
* convert to JSONObject via reader and compare actual to expected result.
* @param xmlStr the string to parse
* @param expectedStr the expected JSON string
* @param config provides more flexible XML parsing
*/
private void compareReaderToJSONObject(String xmlStr, String expectedStr,
XMLParserConfiguration config) {
/*
* Commenting out this method until the JSON-java code is updated
* to support XML.toJSONObject(reader)
JSONObject expectedJsonObject = new JSONObject(expectedStr);
Reader reader = new StringReader(xmlStr);
JSONObject jsonObject = XML.toJSONObject(reader);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
*/
}
/**
* Convenience method, given an input string and expected result, convert to
* JSONObject via file and compare actual to expected result.
*
* @param xmlStr
* the string to parse
* @param expectedStr
* the expected JSON string
* @throws IOException
*/
private void compareFileToJSONObject(String xmlStr, String expectedStr) {
/*
* Commenting out this method until the JSON-java code is updated
* to support XML.toJSONObject(reader)
try {
JSONObject expectedJsonObject = new JSONObject(expectedStr);
File tempFile = testFolder.newFile("fileToJSONObject.xml");
FileWriter fileWriter = new FileWriter(tempFile);
fileWriter.write(xmlStr);
fileWriter.close();
Reader reader = new FileReader(tempFile);
JSONObject jsonObject = XML.toJSONObject(reader);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
} catch (IOException e) {
assertTrue("file writer error: " +e.getMessage(), false);
}
*/
}
}

View file

@ -0,0 +1,883 @@
package org.json.junit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.Reader;
import java.io.StringReader;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.XML;
import org.json.XMLParserConfiguration;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
/**
* Tests for JSON-Java XML.java
* Note: noSpace() will be tested by JSONMLTest
*/
public class XMLTest {
/**
* JUnit supports temporary files and folders that are cleaned up after the test.
* https://garygregory.wordpress.com/2010/01/20/junit-tip-use-rules-to-manage-temporary-files-and-folders/
*/
@Rule
public TemporaryFolder testFolder = new TemporaryFolder();
/**
* JSONObject from a null XML string.
* Expects a NullPointerException
*/
@Test(expected=NullPointerException.class)
public void shouldHandleNullXML() {
String xmlStr = null;
JSONObject jsonObject = XML.toJSONObject(xmlStr);
assertTrue("jsonObject should be empty", jsonObject.isEmpty());
}
/**
* Empty JSONObject from an empty XML string.
*/
@Test
public void shouldHandleEmptyXML() {
String xmlStr = "";
JSONObject jsonObject = XML.toJSONObject(xmlStr);
assertTrue("jsonObject should be empty", jsonObject.isEmpty());
}
/**
* Empty JSONObject from a non-XML string.
*/
@Test
public void shouldHandleNonXML() {
String xmlStr = "{ \"this is\": \"not xml\"}";
JSONObject jsonObject = XML.toJSONObject(xmlStr);
assertTrue("xml string should be empty", jsonObject.isEmpty());
}
/**
* Invalid XML string (tag contains a frontslash).
* Expects a JSONException
*/
@Test
public void shouldHandleInvalidSlashInTag() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/x>\n"+
" <street>abc street</street>\n"+
" </address>\n"+
"</addresses>";
try {
XML.toJSONObject(xmlStr);
fail("Expecting a JSONException");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misshaped tag at 176 [character 14 line 4]",
e.getMessage());
}
}
/**
* Invalid XML string ('!' char in tag)
* Expects a JSONException
*/
@Test
public void shouldHandleInvalidBangInTag() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <!>\n"+
" </address>\n"+
"</addresses>";
try {
XML.toJSONObject(xmlStr);
fail("Expecting a JSONException");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misshaped meta tag at 214 [character 12 line 7]",
e.getMessage());
}
}
/**
* Invalid XML string ('!' char and no closing tag brace)
* Expects a JSONException
*/
@Test
public void shouldHandleInvalidBangNoCloseInTag() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <!\n"+
" </address>\n"+
"</addresses>";
try {
XML.toJSONObject(xmlStr);
fail("Expecting a JSONException");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misshaped meta tag at 213 [character 12 line 7]",
e.getMessage());
}
}
/**
* Invalid XML string (no end brace for tag)
* Expects JSONException
*/
@Test
public void shouldHandleNoCloseStartTag() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <abc\n"+
" </address>\n"+
"</addresses>";
try {
XML.toJSONObject(xmlStr);
fail("Expecting a JSONException");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misplaced '<' at 193 [character 4 line 6]",
e.getMessage());
}
}
/**
* Invalid XML string (partial CDATA chars in tag name)
* Expects JSONException
*/
@Test
public void shouldHandleInvalidCDATABangInTag() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name>Joe Tester</name>\n"+
" <![[]>\n"+
" </address>\n"+
"</addresses>";
try {
XML.toJSONObject(xmlStr);
fail("Expecting a JSONException");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Expected 'CDATA[' at 204 [character 11 line 5]",
e.getMessage());
}
}
/**
* Null JSONObject in XML.toString()
*/
@Test
public void shouldHandleNullJSONXML() {
JSONObject jsonObject= null;
String actualXml=XML.toString(jsonObject);
assertEquals("generated XML does not equal expected XML","\"null\"",actualXml);
}
/**
* Empty JSONObject in XML.toString()
*/
@Test
public void shouldHandleEmptyJSONXML() {
JSONObject jsonObject= new JSONObject();
String xmlStr = XML.toString(jsonObject);
assertTrue("xml string should be empty", xmlStr.isEmpty());
}
/**
* No SML start tag. The ending tag ends up being treated as content.
*/
@Test
public void shouldHandleNoStartTag() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <nocontent/>>\n"+
" </address>\n"+
"</addresses>";
String expectedStr =
"{\"addresses\":{\"address\":{\"name\":\"\",\"nocontent\":\"\",\""+
"content\":\">\"},\"xsi:noNamespaceSchemaLocation\":\"test.xsd\",\""+
"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"}}";
JSONObject jsonObject = XML.toJSONObject(xmlStr);
JSONObject expectedJsonObject = new JSONObject(expectedStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Valid XML to JSONObject
*/
@Test
public void shouldHandleSimpleXML() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name>Joe Tester</name>\n"+
" <street>[CDATA[Baker street 5]</street>\n"+
" <NothingHere/>\n"+
" <TrueValue>true</TrueValue>\n"+
" <FalseValue>false</FalseValue>\n"+
" <NullValue>null</NullValue>\n"+
" <PositiveValue>42</PositiveValue>\n"+
" <NegativeValue>-23</NegativeValue>\n"+
" <DoubleValue>-23.45</DoubleValue>\n"+
" <Nan>-23x.45</Nan>\n"+
" <ArrayOfNum>1, 2, 3, 4.1, 5.2</ArrayOfNum>\n"+
" </address>\n"+
"</addresses>";
String expectedStr =
"{\"addresses\":{\"address\":{\"street\":\"[CDATA[Baker street 5]\","+
"\"name\":\"Joe Tester\",\"NothingHere\":\"\",TrueValue:true,\n"+
"\"FalseValue\":false,\"NullValue\":null,\"PositiveValue\":42,\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/"+
"XMLSchema-instance\"}}";
compareStringToJSONObject(xmlStr, expectedStr);
compareReaderToJSONObject(xmlStr, expectedStr);
compareFileToJSONObject(xmlStr, expectedStr);
}
/**
* Tests to verify that supported escapes in XML are converted to actual values.
*/
@Test
public void testXmlEscapeToJson(){
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<root>"+
"<rawQuote>\"</rawQuote>"+
"<euro>A &#8364;33</euro>"+
"<euroX>A &#x20ac;22&#x20AC;</euroX>"+
"<unknown>some text &copy;</unknown>"+
"<known>&#x0022; &quot; &amp; &apos; &lt; &gt;</known>"+
"<high>&#x1D122; &#x10165;</high>" +
"</root>";
String expectedStr =
"{\"root\":{" +
"\"rawQuote\":\"\\\"\"," +
"\"euro\":\"A €33\"," +
"\"euroX\":\"A €22€\"," +
"\"unknown\":\"some text &copy;\"," +
"\"known\":\"\\\" \\\" & ' < >\"," +
"\"high\":\"𝄢 𐅥\""+
"}}";
compareStringToJSONObject(xmlStr, expectedStr);
compareReaderToJSONObject(xmlStr, expectedStr);
compareFileToJSONObject(xmlStr, expectedStr);
}
/**
* Tests that control characters are escaped.
*/
@Test
public void testJsonToXmlEscape(){
final String jsonSrc = "{\"amount\":\"10,00 €\","
+ "\"description\":\"Ação Válida\u0085\","
+ "\"xmlEntities\":\"\\\" ' & < >\""
+ "}";
JSONObject json = new JSONObject(jsonSrc);
String xml = XML.toString(json);
//test control character not existing
assertFalse("Escaping \u0085 failed. Found in XML output.", xml.contains("\u0085"));
assertTrue("Escaping \u0085 failed. Entity not found in XML output.", xml.contains("&#x85;"));
// test normal unicode existing
assertTrue("Escaping € failed. Not found in XML output.", xml.contains(""));
assertTrue("Escaping ç failed. Not found in XML output.", xml.contains("ç"));
assertTrue("Escaping ã failed. Not found in XML output.", xml.contains("ã"));
assertTrue("Escaping á failed. Not found in XML output.", xml.contains("á"));
// test XML Entities converted
assertTrue("Escaping \" failed. Not found in XML output.", xml.contains("&quot;"));
assertTrue("Escaping ' failed. Not found in XML output.", xml.contains("&apos;"));
assertTrue("Escaping & failed. Not found in XML output.", xml.contains("&amp;"));
assertTrue("Escaping < failed. Not found in XML output.", xml.contains("&lt;"));
assertTrue("Escaping > failed. Not found in XML output.", xml.contains("&gt;"));
}
/**
* Valid XML with comments to JSONObject
*/
@Test
public void shouldHandleCommentsInXML() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<!-- this is a comment -->\n"+
"<addresses>\n"+
" <address>\n"+
" <![CDATA[ this is -- <another> comment ]]>\n"+
" <name>Joe Tester</name>\n"+
" <!-- this is a - multi line \n"+
" comment -->\n"+
" <street>Baker street 5</street>\n"+
" </address>\n"+
"</addresses>";
JSONObject jsonObject = XML.toJSONObject(xmlStr);
String expectedStr = "{\"addresses\":{\"address\":{\"street\":\"Baker "+
"street 5\",\"name\":\"Joe Tester\",\"content\":\" this is -- "+
"<another> comment \"}}}";
JSONObject expectedJsonObject = new JSONObject(expectedStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Valid XML to XML.toString()
*/
@Test
public void shouldHandleToString() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name>[CDATA[Joe &amp; T &gt; e &lt; s &quot; t &apos; er]]</name>\n"+
" <street>Baker street 5</street>\n"+
" <ArrayOfNum>1, 2, 3, 4.1, 5.2</ArrayOfNum>\n"+
" </address>\n"+
"</addresses>";
String expectedStr =
"{\"addresses\":{\"address\":{\"street\":\"Baker street 5\","+
"\"name\":\"[CDATA[Joe & T > e < s \\\" t \\\' er]]\","+
"\"ArrayOfNum\":\"1, 2, 3, 4.1, 5.2\"\n"+
"},\"xsi:noNamespaceSchemaLocation\":"+
"\"test.xsd\",\"xmlns:xsi\":\"http://www.w3.org/2001/"+
"XMLSchema-instance\"}}";
JSONObject jsonObject = XML.toJSONObject(xmlStr);
String xmlToStr = XML.toString(jsonObject);
JSONObject finalJsonObject = XML.toJSONObject(xmlToStr);
JSONObject expectedJsonObject = new JSONObject(expectedStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
}
/**
* Converting a JSON doc containing '>' content to JSONObject, then
* XML.toString() should result in valid XML.
*/
@Test
public void shouldHandleContentNoArraytoString() {
String expectedStr =
"{\"addresses\":{\"address\":{\"name\":\"\",\"nocontent\":\"\",\""+
"content\":\">\"},\"xsi:noNamespaceSchemaLocation\":\"test.xsd\",\""+
"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"}}";
JSONObject expectedJsonObject = new JSONObject(expectedStr);
String finalStr = XML.toString(expectedJsonObject);
String expectedFinalStr = "<addresses><address><name/><nocontent/>&gt;"+
"</address><xsi:noNamespaceSchemaLocation>test.xsd</xsi:noName"+
"spaceSchemaLocation><xmlns:xsi>http://www.w3.org/2001/XMLSche"+
"ma-instance</xmlns:xsi></addresses>";
assertTrue("Should handle expectedFinal: ["+expectedStr+"] final: ["+
finalStr+"]", expectedFinalStr.equals(finalStr));
}
/**
* Converting a JSON doc containing a 'content' array to JSONObject, then
* XML.toString() should result in valid XML.
* TODO: This is probably an error in how the 'content' keyword is used.
*/
@Test
public void shouldHandleContentArraytoString() {
String expectedStr =
"{\"addresses\":{\"address\":{\"name\":\"\",\"nocontent\":\"\",\""+
"content\":[1, 2, 3]},\"xsi:noNamespaceSchemaLocation\":\"test.xsd\",\""+
"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"}}";
JSONObject expectedJsonObject = new JSONObject(expectedStr);
String finalStr = XML.toString(expectedJsonObject);
String expectedFinalStr = "<addresses><address><name/><nocontent/>"+
"1\n2\n3"+
"</address><xsi:noNamespaceSchemaLocation>test.xsd</xsi:noName"+
"spaceSchemaLocation><xmlns:xsi>http://www.w3.org/2001/XMLSche"+
"ma-instance</xmlns:xsi></addresses>";
assertTrue("Should handle expectedFinal: ["+expectedStr+"] final: ["+
finalStr+"]", expectedFinalStr.equals(finalStr));
}
/**
* Converting a JSON doc containing a named array to JSONObject, then
* XML.toString() should result in valid XML.
*/
@Test
public void shouldHandleArraytoString() {
String expectedStr =
"{\"addresses\":{\"address\":{\"name\":\"\",\"nocontent\":\"\","+
"\"something\":[1, 2, 3]},\"xsi:noNamespaceSchemaLocation\":\"test.xsd\",\""+
"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"}}";
JSONObject expectedJsonObject = new JSONObject(expectedStr);
String finalStr = XML.toString(expectedJsonObject);
String expectedFinalStr = "<addresses><address><name/><nocontent/>"+
"<something>1</something><something>2</something><something>3</something>"+
"</address><xsi:noNamespaceSchemaLocation>test.xsd</xsi:noName"+
"spaceSchemaLocation><xmlns:xsi>http://www.w3.org/2001/XMLSche"+
"ma-instance</xmlns:xsi></addresses>";
assertTrue("Should handle expectedFinal: ["+expectedStr+"] final: ["+
finalStr+"]", expectedFinalStr.equals(finalStr));
}
/**
* Tests that the XML output for empty arrays is consistent.
*/
@Test
public void shouldHandleEmptyArray(){
final JSONObject jo1 = new JSONObject();
jo1.put("array",new Object[]{});
final JSONObject jo2 = new JSONObject();
jo2.put("array",new JSONArray());
final String expected = "<jo></jo>";
String output1 = XML.toString(jo1,"jo");
assertEquals("Expected an empty root tag", expected, output1);
String output2 = XML.toString(jo2,"jo");
assertEquals("Expected an empty root tag", expected, output2);
}
/**
* Tests that the XML output for arrays is consistent when an internal array is empty.
*/
@Test
public void shouldHandleEmptyMultiArray(){
final JSONObject jo1 = new JSONObject();
jo1.put("arr",new Object[]{"One", new String[]{}, "Four"});
final JSONObject jo2 = new JSONObject();
jo2.put("arr",new JSONArray(new Object[]{"One", new JSONArray(new String[]{}), "Four"}));
final String expected = "<jo><arr>One</arr><arr></arr><arr>Four</arr></jo>";
String output1 = XML.toString(jo1,"jo");
assertEquals("Expected a matching array", expected, output1);
String output2 = XML.toString(jo2,"jo");
assertEquals("Expected a matching array", expected, output2);
}
/**
* Tests that the XML output for arrays is consistent when arrays are not empty.
*/
@Test
public void shouldHandleNonEmptyArray(){
final JSONObject jo1 = new JSONObject();
jo1.put("arr",new String[]{"One", "Two", "Three"});
final JSONObject jo2 = new JSONObject();
jo2.put("arr",new JSONArray(new String[]{"One", "Two", "Three"}));
final String expected = "<jo><arr>One</arr><arr>Two</arr><arr>Three</arr></jo>";
String output1 = XML.toString(jo1,"jo");
assertEquals("Expected a non empty root tag", expected, output1);
String output2 = XML.toString(jo2,"jo");
assertEquals("Expected a non empty root tag", expected, output2);
}
/**
* Tests that the XML output for arrays is consistent when arrays are not empty and contain internal arrays.
*/
@Test
public void shouldHandleMultiArray(){
final JSONObject jo1 = new JSONObject();
jo1.put("arr",new Object[]{"One", new String[]{"Two", "Three"}, "Four"});
final JSONObject jo2 = new JSONObject();
jo2.put("arr",new JSONArray(new Object[]{"One", new JSONArray(new String[]{"Two", "Three"}), "Four"}));
final String expected = "<jo><arr>One</arr><arr><array>Two</array><array>Three</array></arr><arr>Four</arr></jo>";
String output1 = XML.toString(jo1,"jo");
assertEquals("Expected a matching array", expected, output1);
String output2 = XML.toString(jo2,"jo");
assertEquals("Expected a matching array", expected, output2);
}
/**
* Converting a JSON doc containing a named array of nested arrays to
* JSONObject, then XML.toString() should result in valid XML.
*/
@Test
public void shouldHandleNestedArraytoString() {
String xmlStr =
"{\"addresses\":{\"address\":{\"name\":\"\",\"nocontent\":\"\","+
"\"outer\":[[1], [2], [3]]},\"xsi:noNamespaceSchemaLocation\":\"test.xsd\",\""+
"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"}}";
JSONObject jsonObject = new JSONObject(xmlStr);
String finalStr = XML.toString(jsonObject);
JSONObject finalJsonObject = XML.toJSONObject(finalStr);
String expectedStr = "<addresses><address><name/><nocontent/>"+
"<outer><array>1</array></outer><outer><array>2</array>"+
"</outer><outer><array>3</array></outer>"+
"</address><xsi:noNamespaceSchemaLocation>test.xsd</xsi:noName"+
"spaceSchemaLocation><xmlns:xsi>http://www.w3.org/2001/XMLSche"+
"ma-instance</xmlns:xsi></addresses>";
JSONObject expectedJsonObject = XML.toJSONObject(expectedStr);
Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
}
/**
* Possible bug:
* Illegal node-names must be converted to legal XML-node-names.
* The given example shows 2 nodes which are valid for JSON, but not for XML.
* Therefore illegal arguments should be converted to e.g. an underscore (_).
*/
@Test
public void shouldHandleIllegalJSONNodeNames()
{
JSONObject inputJSON = new JSONObject();
inputJSON.append("123IllegalNode", "someValue1");
inputJSON.append("Illegal@node", "someValue2");
String result = XML.toString(inputJSON);
/*
* This is invalid XML. Names should not begin with digits or contain
* certain values, including '@'. One possible solution is to replace
* illegal chars with '_', in which case the expected output would be:
* <___IllegalNode>someValue1</___IllegalNode><Illegal_node>someValue2</Illegal_node>
*/
String expected = "<123IllegalNode>someValue1</123IllegalNode><Illegal@node>someValue2</Illegal@node>";
assertEquals(expected, result);
}
/**
* JSONObject with NULL value, to XML.toString()
*/
@Test
public void shouldHandleNullNodeValue()
{
JSONObject inputJSON = new JSONObject();
inputJSON.put("nullValue", JSONObject.NULL);
// This is a possible preferred result
// String expectedXML = "<nullValue/>";
/**
* This is the current behavior. JSONObject.NULL is emitted as
* the string, "null".
*/
String actualXML = "<nullValue>null</nullValue>";
String resultXML = XML.toString(inputJSON);
assertEquals(actualXML, resultXML);
}
/**
* Investigate exactly how the "content" keyword works
*/
@Test
public void contentOperations() {
/*
* When a standalone <!CDATA[...]] structure is found while parsing XML into a
* JSONObject, the contents are placed in a string value with key="content".
*/
String xmlStr = "<tag1></tag1><![CDATA[if (a < b && a > 0) then return]]><tag2></tag2>";
JSONObject jsonObject = XML.toJSONObject(xmlStr);
assertTrue("1. 3 items", 3 == jsonObject.length());
assertTrue("1. empty tag1", "".equals(jsonObject.get("tag1")));
assertTrue("1. empty tag2", "".equals(jsonObject.get("tag2")));
assertTrue("1. content found", "if (a < b && a > 0) then return".equals(jsonObject.get("content")));
// multiple consecutive standalone cdatas are accumulated into an array
xmlStr = "<tag1></tag1><![CDATA[if (a < b && a > 0) then return]]><tag2></tag2><![CDATA[here is another cdata]]>";
jsonObject = XML.toJSONObject(xmlStr);
assertTrue("2. 3 items", 3 == jsonObject.length());
assertTrue("2. empty tag1", "".equals(jsonObject.get("tag1")));
assertTrue("2. empty tag2", "".equals(jsonObject.get("tag2")));
assertTrue("2. content array found", jsonObject.get("content") instanceof JSONArray);
JSONArray jsonArray = jsonObject.getJSONArray("content");
assertTrue("2. array size", jsonArray.length() == 2);
assertTrue("2. content array entry 0", "if (a < b && a > 0) then return".equals(jsonArray.get(0)));
assertTrue("2. content array entry 1", "here is another cdata".equals(jsonArray.get(1)));
/*
* text content is accumulated in a "content" inside a local JSONObject.
* If there is only one instance, it is saved in the context (a different JSONObject
* from the calling code. and the content element is discarded.
*/
xmlStr = "<tag1>value 1</tag1>";
jsonObject = XML.toJSONObject(xmlStr);
assertTrue("3. 2 items", 1 == jsonObject.length());
assertTrue("3. value tag1", "value 1".equals(jsonObject.get("tag1")));
/*
* array-style text content (multiple tags with the same name) is
* accumulated in a local JSONObject with key="content" and value=JSONArray,
* saved in the context, and then the local JSONObject is discarded.
*/
xmlStr = "<tag1>value 1</tag1><tag1>2</tag1><tag1>true</tag1>";
jsonObject = XML.toJSONObject(xmlStr);
assertTrue("4. 1 item", 1 == jsonObject.length());
assertTrue("4. content array found", jsonObject.get("tag1") instanceof JSONArray);
jsonArray = jsonObject.getJSONArray("tag1");
assertTrue("4. array size", jsonArray.length() == 3);
assertTrue("4. content array entry 0", "value 1".equals(jsonArray.get(0)));
assertTrue("4. content array entry 1", jsonArray.getInt(1) == 2);
assertTrue("4. content array entry 2", jsonArray.getBoolean(2) == true);
/*
* Complex content is accumulated in a "content" field. For example, an element
* may contain a mix of child elements and text. Each text segment is
* accumulated to content.
*/
xmlStr = "<tag1>val1<tag2/>val2</tag1>";
jsonObject = XML.toJSONObject(xmlStr);
assertTrue("5. 1 item", 1 == jsonObject.length());
assertTrue("5. jsonObject found", jsonObject.get("tag1") instanceof JSONObject);
jsonObject = jsonObject.getJSONObject("tag1");
assertTrue("5. 2 contained items", 2 == jsonObject.length());
assertTrue("5. contained tag", "".equals(jsonObject.get("tag2")));
assertTrue("5. contained content jsonArray found", jsonObject.get("content") instanceof JSONArray);
jsonArray = jsonObject.getJSONArray("content");
assertTrue("5. array size", jsonArray.length() == 2);
assertTrue("5. content array entry 0", "val1".equals(jsonArray.get(0)));
assertTrue("5. content array entry 1", "val2".equals(jsonArray.get(1)));
/*
* If there is only 1 complex text content, then it is accumulated in a
* "content" field as a string.
*/
xmlStr = "<tag1>val1<tag2/></tag1>";
jsonObject = XML.toJSONObject(xmlStr);
assertTrue("6. 1 item", 1 == jsonObject.length());
assertTrue("6. jsonObject found", jsonObject.get("tag1") instanceof JSONObject);
jsonObject = jsonObject.getJSONObject("tag1");
assertTrue("6. contained content found", "val1".equals(jsonObject.get("content")));
assertTrue("6. contained tag2", "".equals(jsonObject.get("tag2")));
/*
* In this corner case, the content sibling happens to have key=content
* We end up with an array within an array, and no content element.
* This is probably a bug.
*/
xmlStr = "<tag1>val1<content/></tag1>";
jsonObject = XML.toJSONObject(xmlStr);
assertTrue("7. 1 item", 1 == jsonObject.length());
assertTrue("7. jsonArray found", jsonObject.get("tag1") instanceof JSONArray);
jsonArray = jsonObject.getJSONArray("tag1");
assertTrue("array size 1", jsonArray.length() == 1);
assertTrue("7. contained array found", jsonArray.get(0) instanceof JSONArray);
jsonArray = jsonArray.getJSONArray(0);
assertTrue("7. inner array size 2", jsonArray.length() == 2);
assertTrue("7. inner array item 0", "val1".equals(jsonArray.get(0)));
assertTrue("7. inner array item 1", "".equals(jsonArray.get(1)));
/*
* Confirm behavior of original issue
*/
String jsonStr =
"{"+
"\"Profile\": {"+
"\"list\": {"+
"\"history\": {"+
"\"entries\": ["+
"{"+
"\"deviceId\": \"id\","+
"\"content\": {"+
"\"material\": ["+
"{"+
"\"stuff\": false"+
"}"+
"]"+
"}"+
"}"+
"]"+
"}"+
"}"+
"}"+
"}";
jsonObject = new JSONObject(jsonStr);
xmlStr = XML.toString(jsonObject);
/*
* This is the created XML. Looks like content was mistaken for
* complex (child node + text) XML.
* <Profile>
* <list>
* <history>
* <entries>
* <deviceId>id</deviceId>
* {&quot;material&quot;:[{&quot;stuff&quot;:false}]}
* </entries>
* </history>
* </list>
* </Profile>
*/
assertTrue("nothing to test here, see comment on created XML, above", true);
}
/**
* Convenience method, given an input string and expected result,
* convert to JSONObject and compare actual to expected result.
* @param xmlStr the string to parse
* @param expectedStr the expected JSON string
*/
private void compareStringToJSONObject(String xmlStr, String expectedStr) {
JSONObject jsonObject = XML.toJSONObject(xmlStr);
JSONObject expectedJsonObject = new JSONObject(expectedStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Convenience method, given an input string and expected result,
* convert to JSONObject via reader and compare actual to expected result.
* @param xmlStr the string to parse
* @param expectedStr the expected JSON string
*/
private void compareReaderToJSONObject(String xmlStr, String expectedStr) {
JSONObject expectedJsonObject = new JSONObject(expectedStr);
Reader reader = new StringReader(xmlStr);
JSONObject jsonObject = XML.toJSONObject(reader);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Convenience method, given an input string and expected result, convert to
* JSONObject via file and compare actual to expected result.
*
* @param xmlStr
* the string to parse
* @param expectedStr
* the expected JSON string
* @throws IOException
*/
private void compareFileToJSONObject(String xmlStr, String expectedStr) {
try {
JSONObject expectedJsonObject = new JSONObject(expectedStr);
File tempFile = this.testFolder.newFile("fileToJSONObject.xml");
try(FileWriter fileWriter = new FileWriter(tempFile);){
fileWriter.write(xmlStr);
}
try(Reader reader = new FileReader(tempFile);){
JSONObject jsonObject = XML.toJSONObject(reader);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
} catch (IOException e) {
fail("file writer error: " +e.getMessage());
}
}
/**
* JSON string lost leading zero and converted "True" to true.
*/
@Test
public void testToJSONArray_jsonOutput() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
final String expectedJsonString = "{\"root\":{\"item\":{\"id\":\"01\"},\"id\":[\"01\",1,\"00\",0],\"title\":true}}";
final JSONObject actualJsonOutput = XML.toJSONObject(originalXml, false);
assertEquals(expectedJsonString, actualJsonOutput.toString());
}
/**
* JSON string cannot be reverted to original xml.
*/
@Test
public void testToJSONArray_reversibility() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
final String revertedXml = XML.toString(XML.toJSONObject(originalXml, false));
assertNotEquals(revertedXml, originalXml);
}
/**
* test passes when using the new method toJsonArray.
*/
@Test
public void testToJsonXML() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
final String expectedJsonString = "{\"root\":{\"item\":{\"id\":\"01\"},\"id\":[\"01\",\"1\",\"00\",\"0\"],\"title\":\"True\"}}";
final JSONObject json = XML.toJSONObject(originalXml,true);
assertEquals(expectedJsonString, json.toString());
final String reverseXml = XML.toString(json);
// this reversal isn't exactly the same. use JSONML for an exact reversal
final String expectedReverseXml = "<root><item><id>01</id></item><id>01</id><id>1</id><id>00</id><id>0</id><title>True</title></root>";
assertEquals(expectedReverseXml, reverseXml);
}
/**
* test to validate certain conditions of XML unescaping.
*/
@Test
public void testUnescape() {
assertEquals("{\"xml\":\"Can cope <;\"}",
XML.toJSONObject("<xml>Can cope &lt;; </xml>").toString());
assertEquals("Can cope <; ", XML.unescape("Can cope &lt;; "));
assertEquals("{\"xml\":\"Can cope & ;\"}",
XML.toJSONObject("<xml>Can cope &amp; ; </xml>").toString());
assertEquals("Can cope & ; ", XML.unescape("Can cope &amp; ; "));
assertEquals("{\"xml\":\"Can cope &;\"}",
XML.toJSONObject("<xml>Can cope &amp;; </xml>").toString());
assertEquals("Can cope &; ", XML.unescape("Can cope &amp;; "));
// unicode entity
assertEquals("{\"xml\":\"Can cope 4;\"}",
XML.toJSONObject("<xml>Can cope &#x34;; </xml>").toString());
assertEquals("Can cope 4; ", XML.unescape("Can cope &#x34;; "));
// double escaped
assertEquals("{\"xml\":\"Can cope &lt;\"}",
XML.toJSONObject("<xml>Can cope &amp;lt; </xml>").toString());
assertEquals("Can cope &lt; ", XML.unescape("Can cope &amp;lt; "));
assertEquals("{\"xml\":\"Can cope &#x34;\"}",
XML.toJSONObject("<xml>Can cope &amp;#x34; </xml>").toString());
assertEquals("Can cope &#x34; ", XML.unescape("Can cope &amp;#x34; "));
}
/**
* test passes when xsi:nil="true" converting to null (JSON specification-like nil conversion enabled)
*/
@Test
public void testToJsonWithNullWhenNilConversionEnabled() {
final String originalXml = "<root><id xsi:nil=\"true\"/></root>";
final String expectedJsonString = "{\"root\":{\"id\":null}}";
final JSONObject json = XML.toJSONObject(originalXml, new XMLParserConfiguration(false, "content", true));
assertEquals(expectedJsonString, json.toString());
}
/**
* test passes when xsi:nil="true" not converting to null (JSON specification-like nil conversion disabled)
*/
@Test
public void testToJsonWithNullWhenNilConversionDisabled() {
final String originalXml = "<root><id xsi:nil=\"true\"/></root>";
final String expectedJsonString = "{\"root\":{\"id\":{\"xsi:nil\":true}}}";
final JSONObject json = XML.toJSONObject(originalXml, new XMLParserConfiguration());
assertEquals(expectedJsonString, json.toString());
}
}

View file

@ -0,0 +1,13 @@
package org.json.junit.data;
/**
* test class for verifying write errors.
* @author John Aylward
*
*/
public class BrokenToString {
@Override
public String toString() {
throw new IllegalStateException("Something went horribly wrong!");
}
}

View file

@ -0,0 +1,69 @@
/**
*
*/
package org.json.junit.data;
import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import org.json.JSONObject;
/**
* Object for testing the exception handling in {@link JSONObject#populateMap}.
*
* @author John Aylward
*/
public class ExceptionalBean {
/**
* @return a closeable.
*/
public Closeable getCloseable() {
// anonymous inner class did not work...
return new MyCloseable();
}
/**
* @return Nothing really. Just can't be void.
* @throws IllegalAccessException
* always thrown
*/
public int getIllegalAccessException() throws IllegalAccessException {
throw new IllegalAccessException("Yup, it's illegal");
}
/**
* @return Nothing really. Just can't be void.
* @throws IllegalArgumentException
* always thrown
*/
public int getIllegalArgumentException() throws IllegalArgumentException {
throw new IllegalArgumentException("Yup, it's illegal");
}
/**
* @return Nothing really. Just can't be void.
* @throws InvocationTargetException
* always thrown
*/
public int getInvocationTargetException() throws InvocationTargetException {
throw new InvocationTargetException(new Exception("Yup, it's illegal"));
}
/** My closeable class. */
public static final class MyCloseable implements Closeable {
/**
* @return a string
*/
@SuppressWarnings("unused")
public String getString() {
return "Yup, it's closeable";
}
@Override
public void close() throws IOException {
throw new IOException("Closing is too hard!");
}
}
}

View file

@ -0,0 +1,180 @@
package org.json.junit.data;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
/**
* basic fraction class, no frills.
* @author John Aylward
*
*/
public class Fraction extends Number implements Comparable<Fraction> {
/**
* serial id.
*/
private static final long serialVersionUID = 1L;
/**
* value as a big decimal.
*/
private final BigDecimal bigDecimal;
/**
* value of the denominator.
*/
private final BigInteger denominator;
/**
* value of the numerator.
*/
private final BigInteger numerator;
/**
* @param numerator
* numerator
* @param denominator
* denominator
*/
public Fraction(final BigInteger numerator, final BigInteger denominator) {
super();
if (numerator == null || denominator == null) {
throw new IllegalArgumentException("All values must be non-null");
}
if (denominator.compareTo(BigInteger.ZERO)==0) {
throw new IllegalArgumentException("Divide by zero");
}
final BigInteger n;
final BigInteger d;
// normalize fraction
if (denominator.signum()<0) {
n = numerator.negate();
d = denominator.negate();
} else {
n = numerator;
d = denominator;
}
this.numerator = n;
this.denominator = d;
if (n.compareTo(BigInteger.ZERO)==0) {
this.bigDecimal = BigDecimal.ZERO;
} else if (n.compareTo(d)==0) {// i.e. 4/4, 10/10
this.bigDecimal = BigDecimal.ONE;
} else {
this.bigDecimal = new BigDecimal(this.numerator).divide(new BigDecimal(this.denominator),
RoundingMode.HALF_EVEN);
}
}
/**
* @param numerator
* numerator
* @param denominator
* denominator
*/
public Fraction(final long numerator, final long denominator) {
this(BigInteger.valueOf(numerator),BigInteger.valueOf(denominator));
}
/**
* @return the decimal
*/
public BigDecimal bigDecimalValue() {
return this.bigDecimal;
}
@Override
public int compareTo(final Fraction o) {
// .equals call this, so no .equals compare allowed
// if they are the same reference, just return equals
if (this == o) {
return 0;
}
// if my denominators are already equal, just compare the numerators
if (this.denominator.compareTo(o.denominator)==0) {
return this.numerator.compareTo(o.numerator);
}
// get numerators of common denominators
// a x ay xb
// --- --- = ---- ----
// b y by yb
final BigInteger thisN = this.numerator.multiply(o.denominator);
final BigInteger otherN = o.numerator.multiply(this.denominator);
return thisN.compareTo(otherN);
}
@Override
public double doubleValue() {
return this.bigDecimal.doubleValue();
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final Fraction other = (Fraction) obj;
return this.compareTo(other) == 0;
}
@Override
public float floatValue() {
return this.bigDecimal.floatValue();
}
/**
* @return the denominator
*/
public BigInteger getDenominator() {
return this.denominator;
}
/**
* @return the numerator
*/
public BigInteger getNumerator() {
return this.numerator;
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (this.bigDecimal == null ? 0 : this.bigDecimal.hashCode());
return result;
}
@Override
public int intValue() {
return this.bigDecimal.intValue();
}
@Override
public long longValue() {
return this.bigDecimal.longValue();
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return this.numerator + "/" + this.denominator;
}
}

View file

@ -0,0 +1,79 @@
package org.json.junit.data;
import java.io.StringReader;
/**
*
* @author John Aylward
*
* @param <T>
* generic number value
*/
public class GenericBean<T extends Number & Comparable<T>> implements MyBean {
/**
* @param genericValue
* value to initiate with
*/
public GenericBean(T genericValue) {
super();
this.genericValue = genericValue;
}
/** */
protected T genericValue;
/** to be used by the calling test to see how often the getter is called */
public int genericGetCounter;
/** to be used by the calling test to see how often the setter is called */
public int genericSetCounter;
/** @return the genericValue */
public T getGenericValue() {
this.genericGetCounter++;
return this.genericValue;
}
/**
* @param genericValue
* generic value to set
*/
public void setGenericValue(T genericValue) {
this.genericSetCounter++;
this.genericValue = genericValue;
}
@Override
public Integer getIntKey() {
return Integer.valueOf(42);
}
@Override
public Double getDoubleKey() {
return Double.valueOf(4.2);
}
@Override
public String getStringKey() {
return "MyString Key";
}
@Override
public String getEscapeStringKey() {
return "\"My String with \"s";
}
@Override
public Boolean isTrueKey() {
return Boolean.TRUE;
}
@Override
public Boolean isFalseKey() {
return Boolean.FALSE;
}
@Override
public StringReader getStringReaderKey() {
return new StringReader("Some String Value in a reader");
}
}

View file

@ -0,0 +1,69 @@
/**
*
*/
package org.json.junit.data;
/**
* @author john
*
*/
public class GenericBeanInt extends GenericBean<Integer> {
/** */
final char a = 'A';
/** @return the a */
public char getA() {
return this.a;
}
/**
* Should not be beanable
*
* @return false
*/
public boolean getable() {
return false;
}
/**
* Should not be beanable
*
* @return false
*/
public boolean get() {
return false;
}
/**
* Should not be beanable
*
* @return false
*/
public boolean is() {
return false;
}
/**
* Should be beanable
*
* @return false
*/
public boolean isB() {
return this.genericValue.equals((Integer.valueOf(this.a+1)));
}
/**
* @param genericValue
* the value to initiate with.
*/
public GenericBeanInt(Integer genericValue) {
super(genericValue);
}
/** override to generate a bridge method */
@Override
public Integer getGenericValue() {
return super.getGenericValue();
}
}

View file

@ -0,0 +1,16 @@
package org.json.junit.data;
import java.io.*;
/**
* Used in testing when Bean behavior is needed
*/
public interface MyBean {
public Integer getIntKey();
public Double getDoubleKey();
public String getStringKey();
public String getEscapeStringKey();
public Boolean isTrueKey();
public Boolean isFalseKey();
public StringReader getStringReaderKey();
}

View file

@ -0,0 +1,20 @@
package org.json.junit.data;
import org.json.JSONPropertyName;
/**
* Test bean for the {@link JSONPropertyName} annotation.
*/
public class MyBeanCustomName implements MyBeanCustomNameInterface {
public int getSomeInt() { return 42; }
@JSONPropertyName("")
public long getSomeLong() { return 42L; }
@JSONPropertyName("myStringField")
public String getSomeString() { return "someStringValue"; }
@JSONPropertyName("Some Weird NAme that Normally Wouldn't be possible!")
public double getMyDouble() { return 0.0d; }
@Override
public float getSomeFloat() { return 2.0f; }
@Override
public int getIgnoredInt() { return 40; }
}

View file

@ -0,0 +1,11 @@
package org.json.junit.data;
import org.json.JSONPropertyIgnore;
import org.json.JSONPropertyName;
public interface MyBeanCustomNameInterface {
@JSONPropertyName("InterfaceField")
float getSomeFloat();
@JSONPropertyIgnore
int getIgnoredInt();
}

View file

@ -0,0 +1,32 @@
/**
*
*/
package org.json.junit.data;
import org.json.JSONPropertyIgnore;
import org.json.JSONPropertyName;
/**
* Test bean to verify that the {@link org.json.JSONPropertyName} annotation
* is inherited.
*/
public class MyBeanCustomNameSubClass extends MyBeanCustomName {
@Override
@JSONPropertyName("forcedInt")
public int getIgnoredInt() { return 42*42; }
@Override
@JSONPropertyName("newIntFieldName")
public int getSomeInt() { return 43; }
@Override
public String getSomeString() { return "subClassString"; }
@Override
@JSONPropertyName("AMoreNormalName")
public double getMyDouble() { return 1.0d; }
@Override
public float getSomeFloat() { return 3.0f; }
@JSONPropertyIgnore
@JSONPropertyName("ShouldBeIgnored")
public boolean getShouldNotBeJSON() { return true; }
@JSONPropertyName("Getable")
public boolean getable() { return true; }
}

View file

@ -0,0 +1,11 @@
package org.json.junit.data;
import java.math.*;
/**
* Used in testing when a Bean containing big numbers is needed
*/
public interface MyBigNumberBean {
public BigInteger getBigInteger();
public BigDecimal getBigDecimal();
}

View file

@ -0,0 +1,10 @@
package org.json.junit.data;
/**
* An enum with no methods or data
*/
public enum MyEnum {
VAL1,
VAL2,
VAL3;
}

View file

@ -0,0 +1,22 @@
package org.json.junit.data;
/**
* this is simply a class that contains some enum instances
*/
public class MyEnumClass {
private MyEnum myEnum;
private MyEnumField myEnumField;
public MyEnum getMyEnum() {
return myEnum;
}
public void setMyEnum(MyEnum myEnum) {
this.myEnum = myEnum;
}
public MyEnumField getMyEnumField() {
return myEnumField;
}
public void setMyEnumField(MyEnumField myEnumField) {
this.myEnumField = myEnumField;
}
}

View file

@ -0,0 +1,28 @@
package org.json.junit.data;
/**
* An enum that contains getters and some internal fields
*/
@SuppressWarnings("boxing")
public enum MyEnumField {
VAL1(1, "val 1"),
VAL2(2, "val 2"),
VAL3(3, "val 3");
private String value;
private Integer intVal;
private MyEnumField(Integer intVal, String value) {
this.value = value;
this.intVal = intVal;
}
public String getValue() {
return this.value;
}
public Integer getIntVal() {
return this.intVal;
}
@Override
public String toString(){
return this.value;
}
}

View file

@ -0,0 +1,14 @@
package org.json.junit.data;
import org.json.*;
/**
* Used in testing when a JSONString is needed
*/
public class MyJsonString implements JSONString {
@Override
public String toJSONString() {
return "my string";
}
}

View file

@ -0,0 +1,12 @@
package org.json.junit.data;
public class MyLocaleBean {
private final String id = "beanId";
private final String i = "beanI";
public String getId() {
return id;
}
public String getI() {
return i;
}
}

View file

@ -0,0 +1,97 @@
package org.json.junit.data;
import java.math.BigDecimal;
/**
* Number override for testing. Number overrides should always override
* toString, hashCode, and Equals.
*
* @see <a
* href="https://docs.oracle.com/javase/tutorial/java/data/numberclasses.html">The
* Numbers Classes</a>
* @see <a
* href="https://docs.oracle.com/javase/tutorial/java/data/numberformat.html">Formatting
* Numeric Print Output</a>
*
* @author John Aylward
*/
public class MyNumber extends Number {
private Number number = BigDecimal.valueOf(42);
/**
*/
private static final long serialVersionUID = 1L;
/**
* @return number!
*/
public Number getNumber() {
return this.number;
}
@Override
public int intValue() {
return getNumber().intValue();
}
@Override
public long longValue() {
return getNumber().longValue();
}
@Override
public float floatValue() {
return getNumber().floatValue();
}
@Override
public double doubleValue() {
return getNumber().doubleValue();
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*
* Number overrides should in general always override the toString method.
*/
@Override
public String toString() {
return getNumber().toString();
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.number == null) ? 0 : this.number.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof MyNumber)) {
return false;
}
MyNumber other = (MyNumber) obj;
if (this.number == null) {
if (other.number != null) {
return false;
}
} else if (!this.number.equals(other.number)) {
return false;
}
return true;
}
}

View file

@ -0,0 +1,13 @@
package org.json.junit.data;
/**
* Class that holds our MyNumber override as a property.
* @author John Aylward
*/
public class MyNumberContainer {
private MyNumber myNumber = new MyNumber();
/**
* @return a MyNumber.
*/
public Number getMyNumber() {return this.myNumber;}
}

View file

@ -0,0 +1,10 @@
package org.json.junit.data;
/**
* Need a class with some public data members for testing
*/
@SuppressWarnings("boxing")
public class MyPublicClass {
public Integer publicInt = 42;
public String publicString = "abc";
}

View file

@ -0,0 +1,91 @@
package org.json.junit.data;
/**
* Sample singleton for use with bean testing.
*
* @author John Aylward
*
*/
public final class Singleton {
/** */
private int someInt;
/** */
private String someString;
/** single instance. */
private static final Singleton INSTANCE = new Singleton();
/** @return the singleton instance. */
public static final Singleton getInstance() {
return INSTANCE;
}
/** */
private Singleton() {
if (INSTANCE != null) {
throw new IllegalStateException("Already instantiated");
}
}
@Override
protected Object clone() throws CloneNotSupportedException {
return INSTANCE;
}
/** @return someInt */
public int getSomeInt() {
return someInt;
}
/**
* sets someInt.
*
* @param someInt
* the someInt to set
*/
public void setSomeInt(int someInt) {
this.someInt = someInt;
}
/** @return someString */
public String getSomeString() {
return someString;
}
/**
* sets someString.
*
* @param someString
* the someString to set
*/
public void setSomeString(String someString) {
this.someString = someString;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + someInt;
result = prime * result + ((someString == null) ? 0 : someString.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Singleton other = (Singleton) obj;
if (someInt != other.someInt)
return false;
if (someString == null) {
if (other.someString != null)
return false;
} else if (!someString.equals(other.someString))
return false;
return true;
}
}

View file

@ -0,0 +1,62 @@
package org.json.junit.data;
/**
* Sample singleton done as an Enum for use with bean testing.
*
* @author John Aylward
*
*/
public enum SingletonEnum {
/**
* the singleton instance.
*/
INSTANCE;
/** */
private int someInt;
/** */
private String someString;
/** single instance. */
/**
* @return the singleton instance. I a real application, I'd hope no one did
* this to an enum singleton.
*/
public static final SingletonEnum getInstance() {
return INSTANCE;
}
/** */
private SingletonEnum() {
}
/** @return someInt */
public int getSomeInt() {
return someInt;
}
/**
* sets someInt.
*
* @param someInt
* the someInt to set
*/
public void setSomeInt(int someInt) {
this.someInt = someInt;
}
/** @return someString */
public String getSomeString() {
return someString;
}
/**
* sets someString.
*
* @param someString
* the someString to set
*/
public void setSomeString(String someString) {
this.someString = someString;
}
}

View file

@ -0,0 +1,19 @@
package org.json.junit.data;
import java.util.*;
/**
* A resource bundle class
*/
public class StringsResourceBundle extends ListResourceBundle {
@Override
public Object[][] getContents() {
return contents;
}
static final Object[][] contents = {
{"greetings.hello", "Hello, "},
{"greetings.world", "World!"},
{"farewells.later", "Later, "},
{"farewells.gator", "Alligator!"}
};
}

View file

@ -0,0 +1,67 @@
/**
*
*/
package org.json.junit.data;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author John Aylward
*/
public class WeirdList {
/** */
private final List<Integer> list = new ArrayList<>();
/**
* @param vals
*/
public WeirdList(Integer... vals) {
this.list.addAll(Arrays.asList(vals));
}
/**
* @return a copy of the list
*/
public List<Integer> get() {
return new ArrayList<>(this.list);
}
/**
* @return a copy of the list
*/
public List<Integer> getALL() {
return new ArrayList<>(this.list);
}
/**
* get a value at an index.
*
* @param i
* index to get
* @return the value at the index
*/
public Integer get(int i) {
return this.list.get(i);
}
/**
* get a value at an index.
*
* @param i
* index to get
* @return the value at the index
*/
public int getInt(int i) {
return this.list.get(i);
}
/**
* @param value
* new value to add to the end of the list
*/
public void add(Integer value) {
this.list.add(value);
}
}

View file

@ -0,0 +1,28 @@
{
"foo":
[
"bar",
"baz"
],
"": 0,
"a/b": 1,
"c%d": 2,
"e^f": 3,
"g|h": 4,
"i\\j": 5,
"k\"l": 6,
" ": 7,
"m~n": 8,
"obj" : {
"key" : "value",
"other~key" : {
"another/key" : [
"val"
]
},
"" : {
"" : "empty key of an object with an empty key",
"subKey" : "Some other value"
}
}
}