mirror of
https://github.com/stleary/JSON-java.git
synced 2026-05-20 00:00:59 -04:00
2076 lines
94 KiB
Java
2076 lines
94 KiB
Java
package org.json.junit;
|
|
|
|
import static org.junit.Assert.assertFalse;
|
|
import static org.junit.Assert.assertTrue;
|
|
import static org.mockito.Mockito.mock;
|
|
import static org.mockito.Mockito.when;
|
|
|
|
import java.io.StringReader;
|
|
import java.io.StringWriter;
|
|
import java.io.Writer;
|
|
import java.math.BigDecimal;
|
|
import java.math.BigInteger;
|
|
import java.util.ArrayList;
|
|
import java.util.Arrays;
|
|
import java.util.Collection;
|
|
import java.util.Collections;
|
|
import java.util.HashMap;
|
|
import java.util.List;
|
|
import java.util.Locale;
|
|
import java.util.Map;
|
|
|
|
import org.json.CDL;
|
|
import org.json.JSONArray;
|
|
import org.json.JSONException;
|
|
import org.json.JSONObject;
|
|
import org.json.XML;
|
|
import org.junit.Test;
|
|
|
|
import com.jayway.jsonpath.Configuration;
|
|
import com.jayway.jsonpath.JsonPath;
|
|
|
|
/**
|
|
* JSONObject, along with JSONArray, are the central classes of the reference
|
|
* app. All of the other classes interact with them, and JSON functionality
|
|
* would otherwise be impossible.
|
|
*/
|
|
public class JSONObjectTest {
|
|
|
|
/**
|
|
* Document behaviors of big numbers. Includes both JSONObject and JSONArray
|
|
* tests
|
|
*/
|
|
@Test
|
|
public void bigNumberOperations() {
|
|
/**
|
|
* JSONObject tries to parse BigInteger as a bean, but it only has one
|
|
* getter, getLowestBitSet(). The value is lost and an unhelpful value
|
|
* is stored. This should be fixed.
|
|
*/
|
|
final BigInteger bigInteger = new BigInteger(
|
|
"123456789012345678901234567890");
|
|
JSONObject jsonObject = new JSONObject(bigInteger);
|
|
Object obj = jsonObject.get("lowestSetBit");
|
|
assertTrue("JSONObject only has 1 value", jsonObject.length() == 1);
|
|
assertTrue("JSONObject parses BigInteger as the Integer lowestBitSet",
|
|
obj instanceof Integer);
|
|
assertTrue("this bigInteger lowestBitSet happens to be 1",
|
|
obj.equals(1));
|
|
|
|
/**
|
|
* JSONObject tries to parse BigDecimal as a bean, but it has no
|
|
* getters, The value is lost and no value is stored. This should be
|
|
* fixed.
|
|
*/
|
|
final BigDecimal bigDecimal = new BigDecimal(
|
|
"123456789012345678901234567890.12345678901234567890123456789");
|
|
jsonObject = new JSONObject(bigDecimal);
|
|
assertTrue("large bigDecimal is not stored", jsonObject.length() == 0);
|
|
|
|
/**
|
|
* JSONObject put(String, Object) method stores and serializes bigInt
|
|
* and bigDec correctly. Nothing needs to change.
|
|
*/
|
|
jsonObject = new JSONObject();
|
|
jsonObject.put("bigInt", bigInteger);
|
|
assertTrue("jsonObject.put() handles bigInt correctly",
|
|
jsonObject.get("bigInt").equals(bigInteger));
|
|
assertTrue("jsonObject.getBigInteger() handles bigInt correctly",
|
|
jsonObject.getBigInteger("bigInt").equals(bigInteger));
|
|
assertTrue(
|
|
"jsonObject.optBigInteger() handles bigInt correctly",
|
|
jsonObject.optBigInteger("bigInt", BigInteger.ONE).equals(
|
|
bigInteger));
|
|
assertTrue(
|
|
"jsonObject serializes bigInt correctly",
|
|
jsonObject.toString().equals(
|
|
"{\"bigInt\":123456789012345678901234567890}"));
|
|
jsonObject = new JSONObject();
|
|
jsonObject.put("bigDec", bigDecimal);
|
|
assertTrue("jsonObject.put() handles bigDec correctly",
|
|
jsonObject.get("bigDec").equals(bigDecimal));
|
|
assertTrue("jsonObject.getBigDecimal() handles bigDec correctly",
|
|
jsonObject.getBigDecimal("bigDec").equals(bigDecimal));
|
|
assertTrue(
|
|
"jsonObject.optBigDecimal() handles bigDec correctly",
|
|
jsonObject.optBigDecimal("bigDec", BigDecimal.ONE).equals(
|
|
bigDecimal));
|
|
assertTrue(
|
|
"jsonObject serializes bigDec correctly",
|
|
jsonObject
|
|
.toString()
|
|
.equals("{\"bigDec\":123456789012345678901234567890.12345678901234567890123456789}"));
|
|
|
|
/**
|
|
* exercise some exceptions
|
|
*/
|
|
try {
|
|
jsonObject.getBigDecimal("bigInt");
|
|
assertTrue("expected an exeption", false);
|
|
} catch (final JSONException ignored) {
|
|
}
|
|
obj = jsonObject.optBigDecimal("bigInt", BigDecimal.ONE);
|
|
assertTrue("expected BigDecimal", obj.equals(BigDecimal.ONE));
|
|
try {
|
|
jsonObject.getBigInteger("bigDec");
|
|
assertTrue("expected an exeption", false);
|
|
} catch (final JSONException ignored) {
|
|
}
|
|
jsonObject.put("stringKey", "abc");
|
|
try {
|
|
jsonObject.getBigDecimal("stringKey");
|
|
assertTrue("expected an exeption", false);
|
|
} catch (final JSONException ignored) {
|
|
}
|
|
obj = jsonObject.optBigInteger("bigDec", BigInteger.ONE);
|
|
assertTrue("expected BigInteger", obj.equals(BigInteger.ONE));
|
|
|
|
/**
|
|
* JSONObject.numberToString() works correctly, nothing to change.
|
|
*/
|
|
String str = JSONObject.numberToString(bigInteger);
|
|
assertTrue("numberToString() handles bigInteger correctly",
|
|
str.equals("123456789012345678901234567890"));
|
|
str = JSONObject.numberToString(bigDecimal);
|
|
assertTrue(
|
|
"numberToString() handles bigDecimal correctly",
|
|
str.equals("123456789012345678901234567890.12345678901234567890123456789"));
|
|
|
|
/**
|
|
* JSONObject.stringToValue() turns bigInt into an accurate string, and
|
|
* rounds bigDec. This incorrect, but users may have come to expect this
|
|
* behavior. Change would be marginally better, but might inconvenience
|
|
* users.
|
|
*/
|
|
obj = JSONObject.stringToValue(bigInteger.toString());
|
|
assertTrue("stringToValue() turns bigInteger string into string",
|
|
obj instanceof String);
|
|
obj = JSONObject.stringToValue(bigDecimal.toString());
|
|
assertTrue("stringToValue() changes bigDecimal string", !obj.toString()
|
|
.equals(bigDecimal.toString()));
|
|
|
|
/**
|
|
* wrap() vs put() big number behavior is now the same.
|
|
*/
|
|
// bigInt map ctor
|
|
Map<String, Object> map = new HashMap<String, Object>();
|
|
map.put("bigInt", bigInteger);
|
|
jsonObject = new JSONObject(map);
|
|
String actualFromMapStr = jsonObject.toString();
|
|
assertTrue("bigInt in map (or array or bean) is a string",
|
|
actualFromMapStr
|
|
.equals("{\"bigInt\":123456789012345678901234567890}"));
|
|
// bigInt put
|
|
jsonObject = new JSONObject();
|
|
jsonObject.put("bigInt", bigInteger);
|
|
String actualFromPutStr = jsonObject.toString();
|
|
assertTrue("bigInt from put is a number",
|
|
actualFromPutStr
|
|
.equals("{\"bigInt\":123456789012345678901234567890}"));
|
|
// bigDec map ctor
|
|
map = new HashMap<String, Object>();
|
|
map.put("bigDec", bigDecimal);
|
|
jsonObject = new JSONObject(map);
|
|
actualFromMapStr = jsonObject.toString();
|
|
assertTrue(
|
|
"bigDec in map (or array or bean) is a bigDec",
|
|
actualFromMapStr
|
|
.equals("{\"bigDec\":123456789012345678901234567890.12345678901234567890123456789}"));
|
|
// bigDec put
|
|
jsonObject = new JSONObject();
|
|
jsonObject.put("bigDec", bigDecimal);
|
|
actualFromPutStr = jsonObject.toString();
|
|
assertTrue(
|
|
"bigDec from put is a number",
|
|
actualFromPutStr
|
|
.equals("{\"bigDec\":123456789012345678901234567890.12345678901234567890123456789}"));
|
|
// bigInt,bigDec put
|
|
JSONArray jsonArray = new JSONArray();
|
|
jsonArray.put(bigInteger);
|
|
jsonArray.put(bigDecimal);
|
|
actualFromPutStr = jsonArray.toString();
|
|
assertTrue(
|
|
"bigInt, bigDec from put is a number",
|
|
actualFromPutStr
|
|
.equals("[123456789012345678901234567890,123456789012345678901234567890.12345678901234567890123456789]"));
|
|
assertTrue("getBigInt is bigInt",
|
|
jsonArray.getBigInteger(0).equals(bigInteger));
|
|
assertTrue("getBigDec is bigDec",
|
|
jsonArray.getBigDecimal(1).equals(bigDecimal));
|
|
assertTrue("optBigInt is bigInt",
|
|
jsonArray.optBigInteger(0, BigInteger.ONE).equals(bigInteger));
|
|
assertTrue("optBigDec is bigDec",
|
|
jsonArray.optBigDecimal(1, BigDecimal.ONE).equals(bigDecimal));
|
|
jsonArray.put(Boolean.TRUE);
|
|
try {
|
|
jsonArray.getBigInteger(2);
|
|
assertTrue("should not be able to get big int", false);
|
|
} catch (final Exception ignored) {
|
|
}
|
|
try {
|
|
jsonArray.getBigDecimal(2);
|
|
assertTrue("should not be able to get big dec", false);
|
|
} catch (final Exception ignored) {
|
|
}
|
|
assertTrue(
|
|
"optBigInt is default",
|
|
jsonArray.optBigInteger(2, BigInteger.ONE).equals(
|
|
BigInteger.ONE));
|
|
assertTrue(
|
|
"optBigDec is default",
|
|
jsonArray.optBigDecimal(2, BigDecimal.ONE).equals(
|
|
BigDecimal.ONE));
|
|
|
|
// bigInt,bigDec list ctor
|
|
final List<Object> list = new ArrayList<Object>();
|
|
list.add(bigInteger);
|
|
list.add(bigDecimal);
|
|
jsonArray = new JSONArray(list);
|
|
final String actualFromListStr = jsonArray.toString();
|
|
assertTrue(
|
|
"bigInt, bigDec in list is a bigInt, bigDec",
|
|
actualFromListStr
|
|
.equals("[123456789012345678901234567890,123456789012345678901234567890.12345678901234567890123456789]"));
|
|
// bigInt bean ctor
|
|
MyBigNumberBean myBigNumberBean = mock(MyBigNumberBean.class);
|
|
when(myBigNumberBean.getBigInteger()).thenReturn(
|
|
new BigInteger("123456789012345678901234567890"));
|
|
jsonObject = new JSONObject(myBigNumberBean);
|
|
String actualFromBeanStr = jsonObject.toString();
|
|
// can't do a full string compare because mockery adds an extra
|
|
// key/value
|
|
assertTrue("bigInt from bean ctor is a bigInt",
|
|
actualFromBeanStr.contains("123456789012345678901234567890"));
|
|
// bigDec bean ctor
|
|
myBigNumberBean = mock(MyBigNumberBean.class);
|
|
when(myBigNumberBean.getBigDecimal())
|
|
.thenReturn(
|
|
new BigDecimal(
|
|
"123456789012345678901234567890.12345678901234567890123456789"));
|
|
jsonObject = new JSONObject(myBigNumberBean);
|
|
actualFromBeanStr = jsonObject.toString();
|
|
// can't do a full string compare because mockery adds an extra
|
|
// key/value
|
|
assertTrue(
|
|
"bigDec from bean ctor is a bigDec",
|
|
actualFromBeanStr
|
|
.contains("123456789012345678901234567890.12345678901234567890123456789"));
|
|
// bigInt,bigDec wrap()
|
|
obj = JSONObject.wrap(bigInteger);
|
|
assertTrue("wrap() returns big num", obj.equals(bigInteger));
|
|
obj = JSONObject.wrap(bigDecimal);
|
|
assertTrue("wrap() returns string", obj.equals(bigDecimal));
|
|
|
|
}
|
|
|
|
/**
|
|
* A JSONObject can be created with no content
|
|
*/
|
|
@Test
|
|
public void emptyJsonObject() {
|
|
final JSONObject jsonObject = new JSONObject();
|
|
assertTrue("jsonObject should be empty", jsonObject.length() == 0);
|
|
}
|
|
|
|
/**
|
|
* Populate a JSONArray from an empty JSONObject names() method. It should
|
|
* be empty.
|
|
*/
|
|
@Test
|
|
public void emptyJsonObjectNamesToJsonAray() {
|
|
final JSONObject jsonObject = new JSONObject();
|
|
final JSONArray jsonArray = jsonObject.names();
|
|
assertTrue("jsonArray should be null", jsonArray == null);
|
|
}
|
|
|
|
/**
|
|
* Exercise the JSONObject equals() method
|
|
*/
|
|
@Test
|
|
public void equals() {
|
|
final String str = "{\"key\":\"value\"}";
|
|
final JSONObject aJsonObject = new JSONObject(str);
|
|
assertTrue("Same JSONObject should be equal to itself",
|
|
aJsonObject.equals(aJsonObject));
|
|
}
|
|
|
|
/**
|
|
* This test documents how JSON-Java handles invalid numeric input.
|
|
*/
|
|
@Test
|
|
public void jsonInvalidNumberValues() {
|
|
// Number-notations supported by Java and invalid as JSON
|
|
final String str = "{" + "\"hexNumber\":-0x123,"
|
|
+ "\"tooManyZeros\":00," + "\"negativeInfinite\":-Infinity,"
|
|
+ "\"negativeNaN\":-NaN," + "\"negativeFraction\":-.01,"
|
|
+ "\"tooManyZerosFraction\":00.001,"
|
|
+ "\"negativeHexFloat\":-0x1.fffp1,"
|
|
+ "\"hexFloat\":0x1.0P-1074," + "\"floatIdentifier\":0.1f,"
|
|
+ "\"doubleIdentifier\":0.1d" + "}";
|
|
final JSONObject jsonObject = new JSONObject(str);
|
|
Object obj;
|
|
obj = jsonObject.get("hexNumber");
|
|
assertFalse(
|
|
"hexNumber must not be a number (should throw exception!?)",
|
|
obj instanceof Number);
|
|
assertTrue("hexNumber currently evaluates to string",
|
|
obj.equals("-0x123"));
|
|
assertTrue("tooManyZeros currently evaluates to string", jsonObject
|
|
.get("tooManyZeros").equals("00"));
|
|
obj = jsonObject.get("negativeInfinite");
|
|
assertTrue("negativeInfinite currently evaluates to string",
|
|
obj.equals("-Infinity"));
|
|
obj = jsonObject.get("negativeNaN");
|
|
assertTrue("negativeNaN currently evaluates to string",
|
|
obj.equals("-NaN"));
|
|
assertTrue("negativeFraction currently evaluates to double -0.01",
|
|
jsonObject.get("negativeFraction").equals(new Double(-0.01)));
|
|
assertTrue("tooManyZerosFraction currently evaluates to double 0.001",
|
|
jsonObject.get("tooManyZerosFraction")
|
|
.equals(new Double(0.001)));
|
|
assertTrue(
|
|
"negativeHexFloat currently evaluates to double -3.99951171875",
|
|
jsonObject.get("negativeHexFloat").equals(
|
|
new Double(-3.99951171875)));
|
|
assertTrue("hexFloat currently evaluates to double 4.9E-324",
|
|
jsonObject.get("hexFloat").equals(new Double(4.9E-324)));
|
|
assertTrue("floatIdentifier currently evaluates to double 0.1",
|
|
jsonObject.get("floatIdentifier").equals(new Double(0.1)));
|
|
assertTrue("doubleIdentifier currently evaluates to double 0.1",
|
|
jsonObject.get("doubleIdentifier").equals(new Double(0.1)));
|
|
}
|
|
|
|
/**
|
|
* Exercise the JSONObject.accumulate() method
|
|
*/
|
|
@Test
|
|
public void jsonObjectAccumulate() {
|
|
|
|
final JSONObject jsonObject = new JSONObject();
|
|
jsonObject.accumulate("myArray", true);
|
|
jsonObject.accumulate("myArray", false);
|
|
jsonObject.accumulate("myArray", "hello world!");
|
|
jsonObject.accumulate("myArray", "h\be\tllo w\u1234orld!");
|
|
jsonObject.accumulate("myArray", 42);
|
|
jsonObject.accumulate("myArray", -23.45e7);
|
|
// include an unsupported object for coverage
|
|
try {
|
|
jsonObject.accumulate("myArray", Double.NaN);
|
|
assertTrue("Expected exception", false);
|
|
} catch (final JSONException ignored) {
|
|
}
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObject.toString());
|
|
assertTrue("expected 1 top level item",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 1);
|
|
assertTrue("expected 6 myArray items",
|
|
((List<?>) JsonPath.read(doc, "$.myArray")).size() == 6);
|
|
assertTrue("expected true",
|
|
Boolean.TRUE.equals(JsonPath.read(doc, "$.myArray[0]")));
|
|
assertTrue("expected false",
|
|
Boolean.FALSE.equals(JsonPath.read(doc, "$.myArray[1]")));
|
|
assertTrue("expected hello world!",
|
|
"hello world!".equals(JsonPath.read(doc, "$.myArray[2]")));
|
|
assertTrue("expected h\be\tllo w\u1234orld!",
|
|
"h\be\tllo w\u1234orld!".equals(JsonPath.read(doc,
|
|
"$.myArray[3]")));
|
|
assertTrue("expected 42",
|
|
Integer.valueOf(42).equals(JsonPath.read(doc, "$.myArray[4]")));
|
|
assertTrue(
|
|
"expected -23.45e7",
|
|
Double.valueOf(-23.45e7).equals(
|
|
JsonPath.read(doc, "$.myArray[5]")));
|
|
}
|
|
|
|
/**
|
|
* Exercise the JSONObject append() functionality
|
|
*/
|
|
@Test
|
|
public void jsonObjectAppend() {
|
|
final JSONObject jsonObject = new JSONObject();
|
|
jsonObject.append("myArray", true);
|
|
jsonObject.append("myArray", false);
|
|
jsonObject.append("myArray", "hello world!");
|
|
jsonObject.append("myArray", "h\be\tllo w\u1234orld!");
|
|
jsonObject.append("myArray", 42);
|
|
jsonObject.append("myArray", -23.45e7);
|
|
// include an unsupported object for coverage
|
|
try {
|
|
jsonObject.append("myArray", Double.NaN);
|
|
assertTrue("Expected exception", false);
|
|
} catch (final JSONException ignored) {
|
|
}
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObject.toString());
|
|
assertTrue("expected 1 top level item",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 1);
|
|
assertTrue("expected 6 myArray items",
|
|
((List<?>) JsonPath.read(doc, "$.myArray")).size() == 6);
|
|
assertTrue("expected true",
|
|
Boolean.TRUE.equals(JsonPath.read(doc, "$.myArray[0]")));
|
|
assertTrue("expected false",
|
|
Boolean.FALSE.equals(JsonPath.read(doc, "$.myArray[1]")));
|
|
assertTrue("expected hello world!",
|
|
"hello world!".equals(JsonPath.read(doc, "$.myArray[2]")));
|
|
assertTrue("expected h\be\tllo w\u1234orld!",
|
|
"h\be\tllo w\u1234orld!".equals(JsonPath.read(doc,
|
|
"$.myArray[3]")));
|
|
assertTrue("expected 42",
|
|
Integer.valueOf(42).equals(JsonPath.read(doc, "$.myArray[4]")));
|
|
assertTrue(
|
|
"expected -23.45e7",
|
|
Double.valueOf(-23.45e7).equals(
|
|
JsonPath.read(doc, "$.myArray[5]")));
|
|
}
|
|
|
|
/**
|
|
* JSONObject built from a bean. In this case all but one of the bean
|
|
* getters return valid JSON types
|
|
*/
|
|
@Test
|
|
public void jsonObjectByBean() {
|
|
/**
|
|
* Default access classes have to be mocked since JSONObject, which is
|
|
* not in the same package, cannot call MyBean methods by reflection.
|
|
*/
|
|
final MyBean myBean = mock(MyBean.class);
|
|
when(myBean.getDoubleKey()).thenReturn(-23.45e7);
|
|
when(myBean.getIntKey()).thenReturn(42);
|
|
when(myBean.getStringKey()).thenReturn("hello world!");
|
|
when(myBean.getEscapeStringKey()).thenReturn("h\be\tllo w\u1234orld!");
|
|
when(myBean.isTrueKey()).thenReturn(true);
|
|
when(myBean.isFalseKey()).thenReturn(false);
|
|
when(myBean.getStringReaderKey()).thenReturn(new StringReader("") {
|
|
});
|
|
|
|
final JSONObject jsonObject = new JSONObject(myBean);
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObject.toString());
|
|
assertTrue("expected 8 top level items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 8);
|
|
assertTrue("expected true",
|
|
Boolean.TRUE.equals(JsonPath.read(doc, "$.trueKey")));
|
|
assertTrue("expected false",
|
|
Boolean.FALSE.equals(JsonPath.read(doc, "$.falseKey")));
|
|
assertTrue("expected hello world!",
|
|
"hello world!".equals(JsonPath.read(doc, "$.stringKey")));
|
|
assertTrue("expected h\be\tllo w\u1234orld!",
|
|
"h\be\tllo w\u1234orld!".equals(JsonPath.read(doc,
|
|
"$.escapeStringKey")));
|
|
assertTrue("expected 42",
|
|
Integer.valueOf("42").equals(JsonPath.read(doc, "$.intKey")));
|
|
assertTrue(
|
|
"expected -23.45e7",
|
|
Double.valueOf("-23.45e7").equals(
|
|
JsonPath.read(doc, "$.doubleKey")));
|
|
assertTrue(
|
|
"expected 0 items in stringReaderKey",
|
|
((Map<?, ?>) JsonPath.read(doc, "$.stringReaderKey")).size() == 0);
|
|
// sorry, mockito artifact
|
|
assertTrue("expected 2 callbacks items",
|
|
((List<?>) JsonPath.read(doc, "$.callbacks")).size() == 2);
|
|
assertTrue("expected 0 handler items", ((Map<?, ?>) JsonPath.read(doc,
|
|
"$.callbacks[0].handler")).size() == 0);
|
|
assertTrue("expected 0 callbacks[1] items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$.callbacks[1]")).size() == 0);
|
|
}
|
|
|
|
/**
|
|
* JSONObjects can be built from a Map<String, Object>. In this test all of
|
|
* the map entries are valid JSON types.
|
|
*/
|
|
@Test
|
|
public void jsonObjectByMap() {
|
|
final Map<String, Object> map = new HashMap<String, Object>();
|
|
map.put("trueKey", new Boolean(true));
|
|
map.put("falseKey", new Boolean(false));
|
|
map.put("stringKey", "hello world!");
|
|
map.put("escapeStringKey", "h\be\tllo w\u1234orld!");
|
|
map.put("intKey", new Long(42));
|
|
map.put("doubleKey", new Double(-23.45e67));
|
|
final JSONObject jsonObject = new JSONObject(map);
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObject.toString());
|
|
assertTrue("expected 6 top level items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 6);
|
|
assertTrue("expected \"trueKey\":true",
|
|
Boolean.TRUE.equals(JsonPath.read(doc, "$.trueKey")));
|
|
assertTrue("expected \"falseKey\":false",
|
|
Boolean.FALSE.equals(JsonPath.read(doc, "$.falseKey")));
|
|
assertTrue("expected \"stringKey\":\"hello world!\"",
|
|
"hello world!".equals(JsonPath.read(doc, "$.stringKey")));
|
|
assertTrue("expected \"escapeStringKey\":\"h\be\tllo w\u1234orld!\"",
|
|
"h\be\tllo w\u1234orld!".equals(JsonPath.read(doc,
|
|
"$.escapeStringKey")));
|
|
assertTrue(
|
|
"expected \"doubleKey\":-23.45e67",
|
|
Double.valueOf("-23.45e67").equals(
|
|
JsonPath.read(doc, "$.doubleKey")));
|
|
}
|
|
|
|
/**
|
|
* JSONObjects can be built from a Map<String, Object>. In this test one of
|
|
* the map values is null
|
|
*/
|
|
@Test
|
|
public void jsonObjectByMapWithNullValue() {
|
|
final Map<String, Object> map = new HashMap<String, Object>();
|
|
map.put("trueKey", new Boolean(true));
|
|
map.put("falseKey", new Boolean(false));
|
|
map.put("stringKey", "hello world!");
|
|
map.put("nullKey", null);
|
|
map.put("escapeStringKey", "h\be\tllo w\u1234orld!");
|
|
map.put("intKey", new Long(42));
|
|
map.put("doubleKey", new Double(-23.45e67));
|
|
final JSONObject jsonObject = new JSONObject(map);
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObject.toString());
|
|
assertTrue("expected 6 top level items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 6);
|
|
assertTrue("expected \"trueKey\":true",
|
|
Boolean.TRUE.equals(JsonPath.read(doc, "$.trueKey")));
|
|
assertTrue("expected \"falseKey\":false",
|
|
Boolean.FALSE.equals(JsonPath.read(doc, "$.falseKey")));
|
|
assertTrue("expected \"stringKey\":\"hello world!\"",
|
|
"hello world!".equals(JsonPath.read(doc, "$.stringKey")));
|
|
assertTrue("expected \"escapeStringKey\":\"h\be\tllo w\u1234orld!\"",
|
|
"h\be\tllo w\u1234orld!".equals(JsonPath.read(doc,
|
|
"$.escapeStringKey")));
|
|
assertTrue("expected \"intKey\":42",
|
|
Integer.valueOf("42").equals(JsonPath.read(doc, "$.intKey")));
|
|
assertTrue(
|
|
"expected \"doubleKey\":-23.45e67",
|
|
Double.valueOf("-23.45e67").equals(
|
|
JsonPath.read(doc, "$.doubleKey")));
|
|
}
|
|
|
|
/**
|
|
* JSONObjects can be built from a Map<String, Object>. In this test the map
|
|
* entries are not valid JSON types. The actual conversion is kind of
|
|
* interesting.
|
|
*/
|
|
@Test
|
|
public void jsonObjectByMapWithUnsupportedValues() {
|
|
final Map<String, Object> jsonMap = new HashMap<String, Object>();
|
|
// Just insert some random objects
|
|
jsonMap.put("key1", new CDL());
|
|
jsonMap.put("key2", new Exception());
|
|
|
|
final JSONObject jsonObject = new JSONObject(jsonMap);
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObject.toString());
|
|
assertTrue("expected 2 top level items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 2);
|
|
assertTrue("expected \"key2\":java.lang.Exception",
|
|
"java.lang.Exception".equals(JsonPath.read(doc, "$.key2")));
|
|
assertTrue("expected 0 key1 items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$.key1")).size() == 0);
|
|
}
|
|
|
|
/**
|
|
* A JSONObject can be created from another JSONObject plus a list of names.
|
|
* In this test, some of the starting JSONObject keys are not in the names
|
|
* list.
|
|
*/
|
|
@Test
|
|
public void jsonObjectByNames() {
|
|
final String str = "{" + "\"trueKey\":true," + "\"falseKey\":false,"
|
|
+ "\"nullKey\":null," + "\"stringKey\":\"hello world!\","
|
|
+ "\"escapeStringKey\":\"h\be\tllo w\u1234orld!\","
|
|
+ "\"intKey\":42," + "\"doubleKey\":-23.45e67" + "}";
|
|
final String[] keys = { "falseKey", "stringKey", "nullKey", "doubleKey" };
|
|
final JSONObject jsonObject = new JSONObject(str);
|
|
|
|
// validate JSON
|
|
final JSONObject jsonObjectByName = new JSONObject(jsonObject, keys);
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObjectByName.toString());
|
|
assertTrue("expected 4 top level items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 4);
|
|
assertTrue("expected \"falseKey\":false",
|
|
Boolean.FALSE.equals(JsonPath.read(doc, "$.falseKey")));
|
|
assertTrue("expected \"nullKey\":null",
|
|
null == JsonPath.read(doc, "$.nullKey"));
|
|
assertTrue("expected \"stringKey\":\"hello world!\"",
|
|
"hello world!".equals(JsonPath.read(doc, "$.stringKey")));
|
|
assertTrue(
|
|
"expected \"doubleKey\":-23.45e67",
|
|
Double.valueOf("-23.45e67").equals(
|
|
JsonPath.read(doc, "$.doubleKey")));
|
|
}
|
|
|
|
/**
|
|
* JSONObject built from a bean, but only using a null value. Nothing good
|
|
* is expected to happen. Expects NullPointerException
|
|
*/
|
|
@Test(expected = NullPointerException.class)
|
|
public void jsonObjectByNullBean() {
|
|
final MyBean myBean = null;
|
|
new JSONObject(myBean);
|
|
}
|
|
|
|
/**
|
|
* JSONObjects can be built from a Map<String, Object>. In this test the map
|
|
* is null. the JSONObject(JsonTokener) ctor is not tested directly since it
|
|
* already has full coverage from other tests.
|
|
*/
|
|
@Test
|
|
public void jsonObjectByNullMap() {
|
|
final Map<String, Object> map = null;
|
|
final JSONObject jsonObject = new JSONObject(map);
|
|
assertTrue("jsonObject should be empty", jsonObject.length() == 0);
|
|
}
|
|
|
|
/**
|
|
* A bean is also an object. But in order to test the JSONObject ctor that
|
|
* takes an object and a list of names, this particular bean needs some
|
|
* public data members, which have been added to the class.
|
|
*/
|
|
@Test
|
|
public void jsonObjectByObjectAndNames() {
|
|
final String[] keys = { "publicString", "publicInt" };
|
|
// just need a class that has public data members
|
|
final MyPublicClass myPublicClass = new MyPublicClass();
|
|
final JSONObject jsonObject = new JSONObject(myPublicClass, keys);
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObject.toString());
|
|
assertTrue("expected 2 top level items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 2);
|
|
assertTrue("expected \"publicString\":\"abc\"",
|
|
"abc".equals(JsonPath.read(doc, "$.publicString")));
|
|
assertTrue("expected \"publicInt\":42",
|
|
Integer.valueOf(42).equals(JsonPath.read(doc, "$.publicInt")));
|
|
}
|
|
|
|
/**
|
|
* Exercise the JSONObject from resource bundle functionality. The test
|
|
* resource bundle is uncomplicated, but provides adequate test coverage.
|
|
*/
|
|
@Test
|
|
public void jsonObjectByResourceBundle() {
|
|
final JSONObject jsonObject = new JSONObject(
|
|
"org.json.junit.StringsResourceBundle", Locale.getDefault());
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObject.toString());
|
|
assertTrue("expected 2 top level items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 2);
|
|
assertTrue("expected 2 greetings items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$.greetings")).size() == 2);
|
|
assertTrue("expected \"hello\":\"Hello, \"",
|
|
"Hello, ".equals(JsonPath.read(doc, "$.greetings.hello")));
|
|
assertTrue("expected \"world\":\"World!\"",
|
|
"World!".equals(JsonPath.read(doc, "$.greetings.world")));
|
|
assertTrue("expected 2 farewells items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$.farewells")).size() == 2);
|
|
assertTrue("expected \"later\":\"Later, \"",
|
|
"Later, ".equals(JsonPath.read(doc, "$.farewells.later")));
|
|
assertTrue("expected \"world\":\"World!\"",
|
|
"Alligator!".equals(JsonPath.read(doc, "$.farewells.gator")));
|
|
}
|
|
|
|
/**
|
|
* Exercise the JSONObject doubleToString() method
|
|
*/
|
|
@Test
|
|
public void jsonObjectDoubleToString() {
|
|
final String[] expectedStrs = { "1", "1", "-23.4", "-2.345E68", "null",
|
|
"null" };
|
|
final Double[] doubles = { 1.0, 00001.00000, -23.4, -23.45e67,
|
|
Double.NaN, Double.NEGATIVE_INFINITY };
|
|
for (int i = 0; i < expectedStrs.length; ++i) {
|
|
final String actualStr = JSONObject.doubleToString(doubles[i]);
|
|
assertTrue("value expected [" + expectedStrs[i] + "] found ["
|
|
+ actualStr + "]", expectedStrs[i].equals(actualStr));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Exercise the JSONObject increment() method.
|
|
*/
|
|
@Test
|
|
public void jsonObjectIncrement() {
|
|
final String str = "{" + "\"keyLong\":9999999991,"
|
|
+ "\"keyDouble\":1.1" + "}";
|
|
final JSONObject jsonObject = new JSONObject(str);
|
|
jsonObject.increment("keyInt");
|
|
jsonObject.increment("keyInt");
|
|
jsonObject.increment("keyLong");
|
|
jsonObject.increment("keyDouble");
|
|
jsonObject.increment("keyInt");
|
|
jsonObject.increment("keyLong");
|
|
jsonObject.increment("keyDouble");
|
|
/**
|
|
* JSONObject constructor won't handle these types correctly, but adding
|
|
* them via put works.
|
|
*/
|
|
jsonObject.put("keyFloat", new Float(1.1));
|
|
jsonObject.put("keyBigInt", new BigInteger(
|
|
"123456789123456789123456789123456780"));
|
|
jsonObject.put("keyBigDec", new BigDecimal(
|
|
"123456789123456789123456789123456780.1"));
|
|
jsonObject.increment("keyFloat");
|
|
jsonObject.increment("keyFloat");
|
|
jsonObject.increment("keyBigInt");
|
|
jsonObject.increment("keyBigDec");
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObject.toString());
|
|
assertTrue("expected 6 top level items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 6);
|
|
assertTrue("expected 3",
|
|
Integer.valueOf(3).equals(JsonPath.read(doc, "$.keyInt")));
|
|
assertTrue(
|
|
"expected 9999999993",
|
|
Long.valueOf(9999999993L).equals(
|
|
JsonPath.read(doc, "$.keyLong")));
|
|
assertTrue("expected 3.1",
|
|
Double.valueOf(3.1).equals(JsonPath.read(doc, "$.keyDouble")));
|
|
assertTrue("expected 123456789123456789123456789123456781",
|
|
new BigInteger("123456789123456789123456789123456781")
|
|
.equals(JsonPath.read(doc, "$.keyBigInt")));
|
|
assertTrue("expected 123456789123456789123456789123456781.1",
|
|
new BigDecimal("123456789123456789123456789123456781.1")
|
|
.equals(JsonPath.read(doc, "$.keyBigDec")));
|
|
|
|
/**
|
|
* Should work the same way on any platform! @see https://docs.oracle
|
|
* .com/javase/specs/jls/se7/html/jls-4.html#jls-4.2.3 This is the
|
|
* effect of a float to double conversion and is inherent to the
|
|
* shortcomings of the IEEE 754 format, when converting 32-bit into
|
|
* double-precision 64-bit. Java type-casts float to double. A 32 bit
|
|
* float is type-casted to 64 bit double by simply appending zero-bits
|
|
* to the mantissa (and extended the signed exponent by 3 bits.) and
|
|
* there is no way to obtain more information than it is stored in the
|
|
* 32-bits float.
|
|
*
|
|
* Like 1/3 cannot be represented as base10 number because it is
|
|
* periodically, 1/5 (for example) cannot be represented as base2 number
|
|
* since it is periodically in base2 (take a look at
|
|
* http://www.h-schmidt.net/FloatConverter/) The same happens to 3.1,
|
|
* that decimal number (base10 representation) is periodic in base2
|
|
* representation, therefore appending zero-bits is inaccurate. Only
|
|
* repeating the periodically occuring bits (0110) would be a proper
|
|
* conversion. However one cannot detect from a 32 bit IEE754
|
|
* representation which bits would "repeat infinitely", since the
|
|
* missing bits would not fit into the 32 bit float, i.e. the
|
|
* information needed simply is not there!
|
|
*/
|
|
assertTrue(
|
|
"expected 3.0999999046325684",
|
|
Double.valueOf(3.0999999046325684).equals(
|
|
JsonPath.read(doc, "$.keyFloat")));
|
|
|
|
/**
|
|
* float f = 3.1f; double df = (double) f; double d = 3.1d;
|
|
* System.out.println
|
|
* (Integer.toBinaryString(Float.floatToRawIntBits(f)));
|
|
* System.out.println
|
|
* (Long.toBinaryString(Double.doubleToRawLongBits(df)));
|
|
* System.out.println
|
|
* (Long.toBinaryString(Double.doubleToRawLongBits(d)));
|
|
*
|
|
* - Float: seeeeeeeemmmmmmmmmmmmmmmmmmmmmmm
|
|
* 1000000010001100110011001100110 - Double
|
|
* seeeeeeeeeeemmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm
|
|
* 10000000 10001100110011001100110
|
|
* 100000000001000110011001100110011000000000000000000000000000000
|
|
* 100000000001000110011001100110011001100110011001100110011001101
|
|
*/
|
|
|
|
/**
|
|
* Examples of well documented but probably unexpected behavior in java
|
|
* / with 32-bit float to 64-bit float conversion.
|
|
*/
|
|
assertFalse(
|
|
"Document unexpected behaviour with explicit type-casting float as double!",
|
|
0.2f == 0.2d);
|
|
assertFalse("Document unexpected behaviour with implicit type-cast!",
|
|
0.2f == 0.2d);
|
|
final Double d1 = new Double(1.1f);
|
|
final Double d2 = new Double("1.1f");
|
|
assertFalse(
|
|
"Document implicit type cast from float to double before calling Double(double d) constructor",
|
|
d1.equals(d2));
|
|
|
|
assertTrue(
|
|
"Correctly converting float to double via base10 (string) representation!",
|
|
new Double(3.1d).equals(new Double(new Float(3.1f).toString())));
|
|
|
|
// Pinpointing the not so obvious "buggy" conversion from float to
|
|
// double in JSONObject
|
|
final JSONObject jo = new JSONObject();
|
|
jo.put("bug", 3.1f); // will call put( String key, double value ) with
|
|
// implicit and "buggy" type-cast from float to
|
|
// double
|
|
assertFalse(
|
|
"The java-compiler did add some zero bits for you to the mantissa (unexpected, but well documented)",
|
|
jo.get("bug").equals(new Double(3.1d)));
|
|
|
|
final JSONObject inc = new JSONObject();
|
|
inc.put("bug", new Float(3.1f)); // This will put in instance of Float
|
|
// into JSONObject, i.e. call put(
|
|
// String key, Object value )
|
|
assertTrue("Everything is ok here!", inc.get("bug") instanceof Float);
|
|
inc.increment("bug"); // after adding 1, increment will call put( String
|
|
// key, double value ) with implicit and "buggy"
|
|
// type-cast from float to double!
|
|
// this.put(key, (Float) value + 1);
|
|
// 1. The (Object)value will be typecasted to (Float)value since it is
|
|
// an instanceof Float actually nothing is done.
|
|
// 2. Float instance will be autoboxed into float because the + operator
|
|
// will work on primitives not Objects!
|
|
// 3. A float+float operation will be performed and results into a float
|
|
// primitive.
|
|
// 4. There is no method that matches the signature put( String key,
|
|
// float value), java-compiler will choose the method
|
|
// put( String key, double value) and does an implicit type-cast(!) by
|
|
// appending zero-bits to the mantissa
|
|
assertTrue("JSONObject increment converts Float to Double",
|
|
jo.get("bug") instanceof Double);
|
|
// correct implementation (with change of behavior) would be:
|
|
// this.put(key, new Float((Float) value + 1));
|
|
// Probably it would be better to deprecate the method and remove some
|
|
// day, while convenient processing the "payload" is not
|
|
// really in the the scope of a JSON-library (IMHO.)
|
|
|
|
}
|
|
|
|
/**
|
|
* The purpose for the static method getNames() methods are not clear. This
|
|
* method is not called from within JSON-Java. Most likely uses are to prep
|
|
* names arrays for: JSONObject(JSONObject jo, String[] names)
|
|
* JSONObject(Object object, String names[]),
|
|
*/
|
|
@Test
|
|
public void jsonObjectNames() {
|
|
JSONObject jsonObject;
|
|
|
|
// getNames() from null JSONObject
|
|
assertTrue("null names from null Object",
|
|
null == JSONObject.getNames((Object) null));
|
|
|
|
// getNames() from object with no fields
|
|
assertTrue("null names from Object with no fields",
|
|
null == JSONObject.getNames(new MyJsonString()));
|
|
|
|
// getNames from new JSONOjbect
|
|
jsonObject = new JSONObject();
|
|
String[] names = JSONObject.getNames(jsonObject);
|
|
assertTrue("names should be null", names == null);
|
|
|
|
// getNames() from empty JSONObject
|
|
final String emptyStr = "{}";
|
|
jsonObject = new JSONObject(emptyStr);
|
|
assertTrue("empty JSONObject should have null names",
|
|
null == JSONObject.getNames(jsonObject));
|
|
|
|
// getNames() from JSONObject
|
|
final String str = "{" + "\"trueKey\":true," + "\"falseKey\":false,"
|
|
+ "\"stringKey\":\"hello world!\"," + "}";
|
|
jsonObject = new JSONObject(str);
|
|
names = JSONObject.getNames(jsonObject);
|
|
JSONArray jsonArray = new JSONArray(names);
|
|
|
|
// validate JSON
|
|
Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonArray.toString());
|
|
List<?> docList = JsonPath.read(doc, "$");
|
|
assertTrue("expected 3 items", docList.size() == 3);
|
|
assertTrue(
|
|
"expected to find trueKey",
|
|
((List<?>) JsonPath.read(doc, "$[?(@=='trueKey')]")).size() == 1);
|
|
assertTrue(
|
|
"expected to find falseKey",
|
|
((List<?>) JsonPath.read(doc, "$[?(@=='falseKey')]")).size() == 1);
|
|
assertTrue(
|
|
"expected to find stringKey",
|
|
((List<?>) JsonPath.read(doc, "$[?(@=='stringKey')]")).size() == 1);
|
|
|
|
/**
|
|
* getNames() from an enum with properties has an interesting result. It
|
|
* returns the enum values, not the selected enum properties
|
|
*/
|
|
final MyEnumField myEnumField = MyEnumField.VAL1;
|
|
names = JSONObject.getNames(myEnumField);
|
|
|
|
// validate JSON
|
|
jsonArray = new JSONArray(names);
|
|
doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonArray.toString());
|
|
docList = JsonPath.read(doc, "$");
|
|
assertTrue("expected 3 items", docList.size() == 3);
|
|
assertTrue("expected to find VAL1",
|
|
((List<?>) JsonPath.read(doc, "$[?(@=='VAL1')]")).size() == 1);
|
|
assertTrue("expected to find VAL2",
|
|
((List<?>) JsonPath.read(doc, "$[?(@=='VAL2')]")).size() == 1);
|
|
assertTrue("expected to find VAL3",
|
|
((List<?>) JsonPath.read(doc, "$[?(@=='VAL3')]")).size() == 1);
|
|
|
|
/**
|
|
* A bean is also an object. But in order to test the static method
|
|
* getNames(), this particular bean needs some public data members.
|
|
*/
|
|
final MyPublicClass myPublicClass = new MyPublicClass();
|
|
names = JSONObject.getNames(myPublicClass);
|
|
|
|
// validate JSON
|
|
jsonArray = new JSONArray(names);
|
|
doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonArray.toString());
|
|
docList = JsonPath.read(doc, "$");
|
|
assertTrue("expected 2 items", docList.size() == 2);
|
|
assertTrue("expected to find publicString", ((List<?>) JsonPath.read(
|
|
doc, "$[?(@=='publicString')]")).size() == 1);
|
|
assertTrue(
|
|
"expected to find publicInt",
|
|
((List<?>) JsonPath.read(doc, "$[?(@=='publicInt')]")).size() == 1);
|
|
}
|
|
|
|
/**
|
|
* Populate a JSONArray from a JSONObject names() method. Confirm that it
|
|
* contains the expected names.
|
|
*/
|
|
@Test
|
|
public void jsonObjectNamesToJsonAray() {
|
|
final String str = "{" + "\"trueKey\":true," + "\"falseKey\":false,"
|
|
+ "\"stringKey\":\"hello world!\"," + "}";
|
|
|
|
final JSONObject jsonObject = new JSONObject(str);
|
|
final JSONArray jsonArray = jsonObject.names();
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonArray.toString());
|
|
assertTrue("expected 3 top level items",
|
|
((List<?>) JsonPath.read(doc, "$")).size() == 3);
|
|
assertTrue(
|
|
"expected to find trueKey",
|
|
((List<?>) JsonPath.read(doc, "$[?(@=='trueKey')]")).size() == 1);
|
|
assertTrue(
|
|
"expected to find falseKey",
|
|
((List<?>) JsonPath.read(doc, "$[?(@=='falseKey')]")).size() == 1);
|
|
assertTrue(
|
|
"expected to find stringKey",
|
|
((List<?>) JsonPath.read(doc, "$[?(@=='stringKey')]")).size() == 1);
|
|
}
|
|
|
|
/**
|
|
* Tests how JSONObject get[type] handles incorrect types
|
|
*/
|
|
@Test
|
|
public void jsonObjectNonAndWrongValues() {
|
|
final String str = "{" + "\"trueKey\":true," + "\"falseKey\":false,"
|
|
+ "\"trueStrKey\":\"true\"," + "\"falseStrKey\":\"false\","
|
|
+ "\"stringKey\":\"hello world!\"," + "\"intKey\":42,"
|
|
+ "\"intStrKey\":\"43\"," + "\"longKey\":1234567890123456789,"
|
|
+ "\"longStrKey\":\"987654321098765432\","
|
|
+ "\"doubleKey\":-23.45e7," + "\"doubleStrKey\":\"00001.000\","
|
|
+ "\"arrayKey\":[0,1,2],"
|
|
+ "\"objectKey\":{\"myKey\":\"myVal\"}" + "}";
|
|
final JSONObject jsonObject = new JSONObject(str);
|
|
try {
|
|
jsonObject.getBoolean("nonKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("expecting an exception message",
|
|
"JSONObject[\"nonKey\"] not found.".equals(e.getMessage()));
|
|
}
|
|
try {
|
|
jsonObject.getBoolean("stringKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[\"stringKey\"] is not a Boolean.".equals(e
|
|
.getMessage()));
|
|
}
|
|
try {
|
|
jsonObject.getString("nonKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[\"nonKey\"] not found.".equals(e.getMessage()));
|
|
}
|
|
try {
|
|
jsonObject.getString("trueKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[\"trueKey\"] not a string.".equals(e
|
|
.getMessage()));
|
|
}
|
|
try {
|
|
jsonObject.getDouble("nonKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[\"nonKey\"] not found.".equals(e.getMessage()));
|
|
}
|
|
try {
|
|
jsonObject.getDouble("stringKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[\"stringKey\"] is not a number.".equals(e
|
|
.getMessage()));
|
|
}
|
|
try {
|
|
jsonObject.getInt("nonKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[\"nonKey\"] not found.".equals(e.getMessage()));
|
|
}
|
|
try {
|
|
jsonObject.getInt("stringKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[\"stringKey\"] is not an int.".equals(e
|
|
.getMessage()));
|
|
}
|
|
try {
|
|
jsonObject.getLong("nonKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[\"nonKey\"] not found.".equals(e.getMessage()));
|
|
}
|
|
try {
|
|
jsonObject.getLong("stringKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[\"stringKey\"] is not a long.".equals(e
|
|
.getMessage()));
|
|
}
|
|
try {
|
|
jsonObject.getJSONArray("nonKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[\"nonKey\"] not found.".equals(e.getMessage()));
|
|
}
|
|
try {
|
|
jsonObject.getJSONArray("stringKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[\"stringKey\"] is not a JSONArray.".equals(e
|
|
.getMessage()));
|
|
}
|
|
try {
|
|
jsonObject.getJSONObject("nonKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[\"nonKey\"] not found.".equals(e.getMessage()));
|
|
}
|
|
try {
|
|
jsonObject.getJSONObject("stringKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[\"stringKey\"] is not a JSONObject.".equals(e
|
|
.getMessage()));
|
|
}
|
|
}
|
|
|
|
/**
|
|
* JSON null is not the same as Java null. This test examines the
|
|
* differences in how they are handled by JSON-java.
|
|
*/
|
|
@Test
|
|
public void jsonObjectNullOperations() {
|
|
/**
|
|
* The Javadoc for JSONObject.NULL states: "JSONObject.NULL is
|
|
* equivalent to the value that JavaScript calls null, whilst Java's
|
|
* null is equivalent to the value that JavaScript calls undefined."
|
|
*
|
|
* Standard ECMA-262 6th Edition / June 2015 (included to help explain
|
|
* the javadoc): undefined value: primitive value used when a variable
|
|
* has not been assigned a value Undefined type: type whose sole value
|
|
* is the undefined value null value: primitive value that represents
|
|
* the intentional absence of any object value Null type: type whose
|
|
* sole value is the null value Java SE8 language spec (included to help
|
|
* explain the javadoc): The Kinds of Types and Values ... There is also
|
|
* a special null type, the type of the expression null, which has no
|
|
* name. Because the null type has no name, it is impossible to declare
|
|
* a variable of the null type or to cast to the null type. The null
|
|
* reference is the only possible value of an expression of null type.
|
|
* The null reference can always be assigned or cast to any reference
|
|
* type. In practice, the programmer can ignore the null type and just
|
|
* pretend that null is merely a special literal that can be of any
|
|
* reference type. Extensible Markup Language (XML) 1.0 Fifth Edition /
|
|
* 26 November 2008 No mention of null ECMA-404 1st Edition / October
|
|
* 2013: JSON Text ... These are three literal name tokens: ... null
|
|
*
|
|
* There seems to be no best practice to follow, it's all about what we
|
|
* want the code to do.
|
|
*/
|
|
|
|
// add JSONObject.NULL then convert to string in the manner of
|
|
// XML.toString()
|
|
final JSONObject jsonObjectJONull = new JSONObject();
|
|
Object obj = JSONObject.NULL;
|
|
jsonObjectJONull.put("key", obj);
|
|
Object value = jsonObjectJONull.opt("key");
|
|
assertTrue("opt() JSONObject.NULL should find JSONObject.NULL",
|
|
obj.equals(value));
|
|
value = jsonObjectJONull.get("key");
|
|
assertTrue("get() JSONObject.NULL should find JSONObject.NULL",
|
|
obj.equals(value));
|
|
if (value == null) {
|
|
value = "";
|
|
}
|
|
String string = value instanceof String ? (String) value : null;
|
|
assertTrue("XML toString() should convert JSONObject.NULL to null",
|
|
string == null);
|
|
|
|
// now try it with null
|
|
final JSONObject jsonObjectNull = new JSONObject();
|
|
obj = null;
|
|
jsonObjectNull.put("key", obj);
|
|
value = jsonObjectNull.opt("key");
|
|
assertTrue("opt() null should find null", value == null);
|
|
if (value == null) {
|
|
value = "";
|
|
}
|
|
string = value instanceof String ? (String) value : null;
|
|
assertTrue("should convert null to empty string", "".equals(string));
|
|
try {
|
|
value = jsonObjectNull.get("key");
|
|
assertTrue("get() null should throw exception", false);
|
|
} catch (final Exception ignored) {
|
|
}
|
|
|
|
/**
|
|
* XML.toString() then goes on to do something with the value if the key
|
|
* val is "content", then value.toString() will be called. This will
|
|
* evaluate to "null" for JSONObject.NULL, and the empty string for
|
|
* null. But if the key is anything else, then JSONObject.NULL will be
|
|
* emitted as <key>null</key> and null will be emitted as ""
|
|
*/
|
|
final String sJONull = XML.toString(jsonObjectJONull);
|
|
assertTrue("JSONObject.NULL should emit a null value",
|
|
"<key>null</key>".equals(sJONull));
|
|
final String sNull = XML.toString(jsonObjectNull);
|
|
assertTrue("null should emit an empty string", "".equals(sNull));
|
|
}
|
|
|
|
/**
|
|
* Exercise JSONObject numberToString() method
|
|
*/
|
|
@Test
|
|
public void jsonObjectNumberToString() {
|
|
String str;
|
|
Double dVal;
|
|
final Integer iVal = 1;
|
|
str = JSONObject.numberToString(iVal);
|
|
assertTrue("expected " + iVal + " actual " + str, iVal.toString()
|
|
.equals(str));
|
|
dVal = 12.34;
|
|
str = JSONObject.numberToString(dVal);
|
|
assertTrue("expected " + dVal + " actual " + str, dVal.toString()
|
|
.equals(str));
|
|
dVal = 12.34e27;
|
|
str = JSONObject.numberToString(dVal);
|
|
assertTrue("expected " + dVal + " actual " + str, dVal.toString()
|
|
.equals(str));
|
|
// trailing .0 is truncated, so it doesn't quite match toString()
|
|
dVal = 5000000.0000000;
|
|
str = JSONObject.numberToString(dVal);
|
|
assertTrue("expected 5000000 actual " + str, str.equals("5000000"));
|
|
}
|
|
|
|
/**
|
|
* Exercise JSONObject opt(key, default) method
|
|
*/
|
|
@Test
|
|
public void jsonObjectOptDefault() {
|
|
|
|
final String str = "{\"myKey\": \"myval\"}";
|
|
final JSONObject jsonObject = new JSONObject(str);
|
|
|
|
assertTrue("optBoolean() should return default boolean",
|
|
Boolean.TRUE == jsonObject.optBoolean("myKey", Boolean.TRUE));
|
|
assertTrue("optInt() should return default int",
|
|
42 == jsonObject.optInt("myKey", 42));
|
|
assertTrue("optInt() should return default int",
|
|
42 == jsonObject.optInt("myKey", 42));
|
|
assertTrue("optLong() should return default long",
|
|
42 == jsonObject.optLong("myKey", 42));
|
|
assertTrue("optDouble() should return default double",
|
|
42.3 == jsonObject.optDouble("myKey", 42.3));
|
|
assertTrue("optString() should return default string",
|
|
"hi".equals(jsonObject.optString("hiKey", "hi")));
|
|
}
|
|
|
|
/**
|
|
* Explore how JSONObject handles parsing errors.
|
|
*/
|
|
@Test
|
|
public void jsonObjectParsingErrors() {
|
|
try {
|
|
// does not start with '{'
|
|
final String str = "abc";
|
|
new JSONObject(str);
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"A JSONObject text must begin with '{' at 1 [character 2 line 1]"
|
|
.equals(e.getMessage()));
|
|
}
|
|
try {
|
|
// does not end with '}'
|
|
final String str = "{";
|
|
new JSONObject(str);
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"A JSONObject text must end with '}' at 2 [character 3 line 1]"
|
|
.equals(e.getMessage()));
|
|
}
|
|
try {
|
|
// key with no ':'
|
|
final String str = "{\"myKey\" = true}";
|
|
new JSONObject(str);
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"Expected a ':' after a key at 10 [character 11 line 1]"
|
|
.equals(e.getMessage()));
|
|
}
|
|
try {
|
|
// entries with no ',' separator
|
|
final String str = "{\"myKey\":true \"myOtherKey\":false}";
|
|
new JSONObject(str);
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"Expected a ',' or '}' at 15 [character 16 line 1]"
|
|
.equals(e.getMessage()));
|
|
}
|
|
try {
|
|
// append to wrong key
|
|
final String str = "{\"myKey\":true, \"myOtherKey\":false}";
|
|
final JSONObject jsonObject = new JSONObject(str);
|
|
jsonObject.append("myKey", "hello");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"JSONObject[myKey] is not a JSONArray.".equals(e
|
|
.getMessage()));
|
|
}
|
|
try {
|
|
// increment wrong key
|
|
final String str = "{\"myKey\":true, \"myOtherKey\":false}";
|
|
final JSONObject jsonObject = new JSONObject(str);
|
|
jsonObject.increment("myKey");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"Unable to increment [\"myKey\"].".equals(e.getMessage()));
|
|
}
|
|
try {
|
|
// invalid key
|
|
final String str = "{\"myKey\":true, \"myOtherKey\":false}";
|
|
final JSONObject jsonObject = new JSONObject(str);
|
|
jsonObject.get(null);
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"Null key.".equals(e.getMessage()));
|
|
}
|
|
try {
|
|
// invalid numberToString()
|
|
JSONObject.numberToString((Number) null);
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("Expecting an exception message",
|
|
"Null pointer".equals(e.getMessage()));
|
|
}
|
|
try {
|
|
// null put key
|
|
final JSONObject jsonObject = new JSONObject("{}");
|
|
jsonObject.put(null, 0);
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final NullPointerException ignored) {
|
|
}
|
|
try {
|
|
// multiple putOnce key
|
|
final JSONObject jsonObject = new JSONObject("{}");
|
|
jsonObject.putOnce("hello", "world");
|
|
jsonObject.putOnce("hello", "world!");
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("", true);
|
|
}
|
|
try {
|
|
// test validity of invalid double
|
|
JSONObject.testValidity(Double.NaN);
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("", true);
|
|
}
|
|
try {
|
|
// test validity of invalid float
|
|
JSONObject.testValidity(Float.NEGATIVE_INFINITY);
|
|
assertTrue("Expected an exception", false);
|
|
} catch (final JSONException e) {
|
|
assertTrue("", true);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Exercise JSONObject put() and similar() methods
|
|
*/
|
|
@Test
|
|
public void jsonObjectPut() {
|
|
final String expectedStr = "{" + "\"trueKey\":true,"
|
|
+ "\"falseKey\":false," + "\"arrayKey\":[0,1,2],"
|
|
+ "\"objectKey\":{" + "\"myKey1\":\"myVal1\","
|
|
+ "\"myKey2\":\"myVal2\"," + "\"myKey3\":\"myVal3\","
|
|
+ "\"myKey4\":\"myVal4\"" + "}" + "}";
|
|
final JSONObject jsonObject = new JSONObject();
|
|
jsonObject.put("trueKey", true);
|
|
jsonObject.put("falseKey", false);
|
|
final Integer[] intArray = { 0, 1, 2 };
|
|
jsonObject.put("arrayKey", Arrays.asList(intArray));
|
|
final Map<String, Object> myMap = new HashMap<String, Object>();
|
|
myMap.put("myKey1", "myVal1");
|
|
myMap.put("myKey2", "myVal2");
|
|
myMap.put("myKey3", "myVal3");
|
|
myMap.put("myKey4", "myVal4");
|
|
jsonObject.put("objectKey", myMap);
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObject.toString());
|
|
assertTrue("expected 4 top level items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 4);
|
|
assertTrue("expected true",
|
|
Boolean.TRUE.equals(JsonPath.read(doc, "$.trueKey")));
|
|
assertTrue("expected false",
|
|
Boolean.FALSE.equals(JsonPath.read(doc, "$.falseKey")));
|
|
assertTrue("expected 3 arrayKey items",
|
|
((List<?>) JsonPath.read(doc, "$.arrayKey")).size() == 3);
|
|
assertTrue("expected 0",
|
|
Integer.valueOf(0).equals(JsonPath.read(doc, "$.arrayKey[0]")));
|
|
assertTrue("expected 1",
|
|
Integer.valueOf(1).equals(JsonPath.read(doc, "$.arrayKey[1]")));
|
|
assertTrue("expected 2",
|
|
Integer.valueOf(2).equals(JsonPath.read(doc, "$.arrayKey[2]")));
|
|
assertTrue("expected 4 objectKey items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$.objectKey")).size() == 4);
|
|
assertTrue("expected myVal1",
|
|
"myVal1".equals(JsonPath.read(doc, "$.objectKey.myKey1")));
|
|
assertTrue("expected myVal2",
|
|
"myVal2".equals(JsonPath.read(doc, "$.objectKey.myKey2")));
|
|
assertTrue("expected myVal3",
|
|
"myVal3".equals(JsonPath.read(doc, "$.objectKey.myKey3")));
|
|
assertTrue("expected myVal4",
|
|
"myVal4".equals(JsonPath.read(doc, "$.objectKey.myKey4")));
|
|
|
|
jsonObject.remove("trueKey");
|
|
final JSONObject expectedJsonObject = new JSONObject(expectedStr);
|
|
assertTrue("unequal jsonObjects should not be similar",
|
|
!jsonObject.similar(expectedJsonObject));
|
|
assertTrue("jsonObject should not be similar to jsonArray",
|
|
!jsonObject.similar(new JSONArray()));
|
|
|
|
final String aCompareValueStr = "{\"a\":\"aval\",\"b\":true}";
|
|
final String bCompareValueStr = "{\"a\":\"notAval\",\"b\":true}";
|
|
final JSONObject aCompareValueJsonObject = new JSONObject(
|
|
aCompareValueStr);
|
|
final JSONObject bCompareValueJsonObject = new JSONObject(
|
|
bCompareValueStr);
|
|
assertTrue("different values should not be similar",
|
|
!aCompareValueJsonObject.similar(bCompareValueJsonObject));
|
|
|
|
final String aCompareObjectStr = "{\"a\":\"aval\",\"b\":{}}";
|
|
final String bCompareObjectStr = "{\"a\":\"aval\",\"b\":true}";
|
|
final JSONObject aCompareObjectJsonObject = new JSONObject(
|
|
aCompareObjectStr);
|
|
final JSONObject bCompareObjectJsonObject = new JSONObject(
|
|
bCompareObjectStr);
|
|
assertTrue("different nested JSONObjects should not be similar",
|
|
!aCompareObjectJsonObject.similar(bCompareObjectJsonObject));
|
|
|
|
final String aCompareArrayStr = "{\"a\":\"aval\",\"b\":[]}";
|
|
final String bCompareArrayStr = "{\"a\":\"aval\",\"b\":true}";
|
|
final JSONObject aCompareArrayJsonObject = new JSONObject(
|
|
aCompareArrayStr);
|
|
final JSONObject bCompareArrayJsonObject = new JSONObject(
|
|
bCompareArrayStr);
|
|
assertTrue("different nested JSONArrays should not be similar",
|
|
!aCompareArrayJsonObject.similar(bCompareArrayJsonObject));
|
|
}
|
|
|
|
/**
|
|
* Confirm behavior when JSONObject put(key, null object) is called
|
|
*/
|
|
@Test
|
|
public void jsonObjectputNull() {
|
|
|
|
// put null should remove the item.
|
|
final String str = "{\"myKey\": \"myval\"}";
|
|
final JSONObject jsonObjectRemove = new JSONObject(str);
|
|
jsonObjectRemove.remove("myKey");
|
|
|
|
final JSONObject jsonObjectPutNull = new JSONObject(str);
|
|
jsonObjectPutNull.put("myKey", (Object) null);
|
|
|
|
// validate JSON
|
|
assertTrue("jsonObject should be empty", jsonObjectRemove.length() == 0
|
|
&& jsonObjectPutNull.length() == 0);
|
|
}
|
|
|
|
/**
|
|
* Confirm behavior when putOnce() is called with null parameters
|
|
*/
|
|
@Test
|
|
public void jsonObjectPutOnceNull() {
|
|
final JSONObject jsonObject = new JSONObject();
|
|
jsonObject.putOnce(null, null);
|
|
assertTrue("jsonObject should be empty", jsonObject.length() == 0);
|
|
}
|
|
|
|
/**
|
|
* Exercise JSONObject quote() method This purpose of quote() is to ensure
|
|
* that for strings with embedded quotes, the quotes are properly escaped.
|
|
*/
|
|
@Test
|
|
public void jsonObjectQuote() {
|
|
String str;
|
|
str = "";
|
|
String quotedStr;
|
|
quotedStr = JSONObject.quote(str);
|
|
assertTrue("quote() expected escaped quotes, found " + quotedStr,
|
|
"\"\"".equals(quotedStr));
|
|
str = "\"\"";
|
|
quotedStr = JSONObject.quote(str);
|
|
assertTrue("quote() expected escaped quotes, found " + quotedStr,
|
|
"\"\\\"\\\"\"".equals(quotedStr));
|
|
str = "</";
|
|
quotedStr = JSONObject.quote(str);
|
|
assertTrue("quote() expected escaped frontslash, found " + quotedStr,
|
|
"\"<\\/\"".equals(quotedStr));
|
|
str = "AB\bC";
|
|
quotedStr = JSONObject.quote(str);
|
|
assertTrue("quote() expected escaped backspace, found " + quotedStr,
|
|
"\"AB\\bC\"".equals(quotedStr));
|
|
str = "ABC\n";
|
|
quotedStr = JSONObject.quote(str);
|
|
assertTrue("quote() expected escaped newline, found " + quotedStr,
|
|
"\"ABC\\n\"".equals(quotedStr));
|
|
str = "AB\fC";
|
|
quotedStr = JSONObject.quote(str);
|
|
assertTrue("quote() expected escaped formfeed, found " + quotedStr,
|
|
"\"AB\\fC\"".equals(quotedStr));
|
|
str = "\r";
|
|
quotedStr = JSONObject.quote(str);
|
|
assertTrue("quote() expected escaped return, found " + quotedStr,
|
|
"\"\\r\"".equals(quotedStr));
|
|
str = "\u1234\u0088";
|
|
quotedStr = JSONObject.quote(str);
|
|
assertTrue("quote() expected escaped unicode, found " + quotedStr,
|
|
"\"\u1234\\u0088\"".equals(quotedStr));
|
|
}
|
|
|
|
/**
|
|
* Exercise JSONObject toString() method
|
|
*/
|
|
@Test
|
|
public void jsonObjectToString() {
|
|
final String str = "{" + "\"trueKey\":true," + "\"falseKey\":false,"
|
|
+ "\"arrayKey\":[0,1,2]," + "\"objectKey\":{"
|
|
+ "\"myKey1\":\"myVal1\"," + "\"myKey2\":\"myVal2\","
|
|
+ "\"myKey3\":\"myVal3\"," + "\"myKey4\":\"myVal4\"" + "}"
|
|
+ "}";
|
|
final JSONObject jsonObject = new JSONObject(str);
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObject.toString());
|
|
assertTrue("expected 4 top level items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 4);
|
|
assertTrue("expected true",
|
|
Boolean.TRUE.equals(JsonPath.read(doc, "$.trueKey")));
|
|
assertTrue("expected false",
|
|
Boolean.FALSE.equals(JsonPath.read(doc, "$.falseKey")));
|
|
assertTrue("expected 3 arrayKey items",
|
|
((List<?>) JsonPath.read(doc, "$.arrayKey")).size() == 3);
|
|
assertTrue("expected 0",
|
|
Integer.valueOf(0).equals(JsonPath.read(doc, "$.arrayKey[0]")));
|
|
assertTrue("expected 1",
|
|
Integer.valueOf(1).equals(JsonPath.read(doc, "$.arrayKey[1]")));
|
|
assertTrue("expected 2",
|
|
Integer.valueOf(2).equals(JsonPath.read(doc, "$.arrayKey[2]")));
|
|
assertTrue("expected 4 objectKey items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$.objectKey")).size() == 4);
|
|
assertTrue("expected myVal1",
|
|
"myVal1".equals(JsonPath.read(doc, "$.objectKey.myKey1")));
|
|
assertTrue("expected myVal2",
|
|
"myVal2".equals(JsonPath.read(doc, "$.objectKey.myKey2")));
|
|
assertTrue("expected myVal3",
|
|
"myVal3".equals(JsonPath.read(doc, "$.objectKey.myKey3")));
|
|
assertTrue("expected myVal4",
|
|
"myVal4".equals(JsonPath.read(doc, "$.objectKey.myKey4")));
|
|
}
|
|
|
|
/**
|
|
* Explores how JSONObject handles collections. Insert a string collection
|
|
* as a value in a JSONObject. It will remain a collection. Convert the
|
|
* JSONObject to string, then create a new JSONObject from the string. In
|
|
* the new JSONObject, the value will be stored as a nested JSONArray.
|
|
* Confirm that collection and nested JSONArray have the same contents.
|
|
*/
|
|
@Test
|
|
public void jsonObjectToStringSuppressWarningOnCastToCollection() {
|
|
final JSONObject jsonObject = new JSONObject();
|
|
final Collection<String> collection = new ArrayList<String>();
|
|
collection.add("abc");
|
|
// ArrayList will be added as an object
|
|
jsonObject.put("key", collection);
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObject.toString());
|
|
assertTrue("expected 1 top level item",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 1);
|
|
assertTrue("expected 1 key item",
|
|
((List<?>) JsonPath.read(doc, "$.key")).size() == 1);
|
|
assertTrue("expected abc", "abc".equals(JsonPath.read(doc, "$.key[0]")));
|
|
}
|
|
|
|
/**
|
|
* Explores how JSONObject handles maps. Insert a string/string map as a
|
|
* value in a JSONObject. It will remain a map. Convert the JSONObject to
|
|
* string, then create a new JSONObject from the string. In the new
|
|
* JSONObject, the value will be stored as a nested JSONObject. Confirm that
|
|
* map and nested JSONObject have the same contents.
|
|
*/
|
|
@Test
|
|
public void jsonObjectToStringSuppressWarningOnCastToMap() {
|
|
final JSONObject jsonObject = new JSONObject();
|
|
final Map<String, String> map = new HashMap<>();
|
|
map.put("abc", "def");
|
|
jsonObject.put("key", map);
|
|
|
|
// validate JSON
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonObject.toString());
|
|
assertTrue("expected 1 top level item",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 1);
|
|
assertTrue("expected 1 key item",
|
|
((Map<?, ?>) JsonPath.read(doc, "$.key")).size() == 1);
|
|
assertTrue("expected def",
|
|
"def".equals(JsonPath.read(doc, "$.key.abc")));
|
|
}
|
|
|
|
/**
|
|
* Exercise some JSONObject get[type] and opt[type] methods
|
|
*/
|
|
@Test
|
|
public void jsonObjectValues() {
|
|
final String str = "{" + "\"trueKey\":true," + "\"falseKey\":false,"
|
|
+ "\"trueStrKey\":\"true\"," + "\"falseStrKey\":\"false\","
|
|
+ "\"stringKey\":\"hello world!\"," + "\"intKey\":42,"
|
|
+ "\"intStrKey\":\"43\"," + "\"longKey\":1234567890123456789,"
|
|
+ "\"longStrKey\":\"987654321098765432\","
|
|
+ "\"doubleKey\":-23.45e7," + "\"doubleStrKey\":\"00001.000\","
|
|
+ "\"arrayKey\":[0,1,2],"
|
|
+ "\"objectKey\":{\"myKey\":\"myVal\"}" + "}";
|
|
final JSONObject jsonObject = new JSONObject(str);
|
|
assertTrue("trueKey should be true", jsonObject.getBoolean("trueKey"));
|
|
assertTrue("opt trueKey should be true",
|
|
jsonObject.optBoolean("trueKey"));
|
|
assertTrue("falseKey should be false",
|
|
!jsonObject.getBoolean("falseKey"));
|
|
assertTrue("trueStrKey should be true",
|
|
jsonObject.getBoolean("trueStrKey"));
|
|
assertTrue("trueStrKey should be true",
|
|
jsonObject.optBoolean("trueStrKey"));
|
|
assertTrue("falseStrKey should be false",
|
|
!jsonObject.getBoolean("falseStrKey"));
|
|
assertTrue("stringKey should be string",
|
|
jsonObject.getString("stringKey").equals("hello world!"));
|
|
assertTrue("doubleKey should be double",
|
|
jsonObject.getDouble("doubleKey") == -23.45e7);
|
|
assertTrue("doubleStrKey should be double",
|
|
jsonObject.getDouble("doubleStrKey") == 1);
|
|
assertTrue("opt doubleKey should be double",
|
|
jsonObject.optDouble("doubleKey") == -23.45e7);
|
|
assertTrue("opt doubleKey with Default should be double",
|
|
jsonObject.optDouble("doubleStrKey", Double.NaN) == 1);
|
|
assertTrue("intKey should be int", jsonObject.optInt("intKey") == 42);
|
|
assertTrue("opt intKey should be int",
|
|
jsonObject.optInt("intKey", 0) == 42);
|
|
assertTrue("opt intKey with default should be int",
|
|
jsonObject.getInt("intKey") == 42);
|
|
assertTrue("intStrKey should be int",
|
|
jsonObject.getInt("intStrKey") == 43);
|
|
assertTrue("longKey should be long",
|
|
jsonObject.getLong("longKey") == 1234567890123456789L);
|
|
assertTrue("opt longKey should be long",
|
|
jsonObject.optLong("longKey") == 1234567890123456789L);
|
|
assertTrue("opt longKey with default should be long",
|
|
jsonObject.optLong("longKey", 0) == 1234567890123456789L);
|
|
assertTrue("longStrKey should be long",
|
|
jsonObject.getLong("longStrKey") == 987654321098765432L);
|
|
assertTrue("xKey should not exist", jsonObject.isNull("xKey"));
|
|
assertTrue("stringKey should exist", jsonObject.has("stringKey"));
|
|
assertTrue("opt stringKey should string",
|
|
jsonObject.optString("stringKey").equals("hello world!"));
|
|
assertTrue("opt stringKey with default should string", jsonObject
|
|
.optString("stringKey", "not found").equals("hello world!"));
|
|
JSONArray jsonArray = jsonObject.getJSONArray("arrayKey");
|
|
assertTrue("arrayKey should be JSONArray", jsonArray.getInt(0) == 0
|
|
&& jsonArray.getInt(1) == 1 && jsonArray.getInt(2) == 2);
|
|
jsonArray = jsonObject.optJSONArray("arrayKey");
|
|
assertTrue("opt arrayKey should be JSONArray", jsonArray.getInt(0) == 0
|
|
&& jsonArray.getInt(1) == 1 && jsonArray.getInt(2) == 2);
|
|
final JSONObject jsonObjectInner = jsonObject
|
|
.getJSONObject("objectKey");
|
|
assertTrue("objectKey should be JSONObject",
|
|
jsonObjectInner.get("myKey").equals("myVal"));
|
|
}
|
|
|
|
/**
|
|
* This test documents numeric values which could be numerically handled as
|
|
* BigDecimal or BigInteger. It helps determine what outputs will change if
|
|
* those types are supported.
|
|
*/
|
|
@Test
|
|
public void jsonValidNumberValuesNeitherLongNorIEEE754Compatible() {
|
|
// Valid JSON Numbers, probably should return BigDecimal or BigInteger
|
|
// objects
|
|
final String str = "{" + "\"numberWithDecimals\":299792.457999999984,"
|
|
+ "\"largeNumber\":12345678901234567890,"
|
|
+ "\"preciseNumber\":0.2000000000000000111,"
|
|
+ "\"largeExponent\":-23.45e2327" + "}";
|
|
final JSONObject jsonObject = new JSONObject(str);
|
|
// Comes back as a double, but loses precision
|
|
assertTrue(
|
|
"numberWithDecimals currently evaluates to double 299792.458",
|
|
jsonObject.get("numberWithDecimals").equals(
|
|
new Double("299792.458")));
|
|
Object obj = jsonObject.get("largeNumber");
|
|
assertTrue("largeNumber currently evaluates to string",
|
|
"12345678901234567890".equals(obj));
|
|
// comes back as a double but loses precision
|
|
assertTrue("preciseNumber currently evaluates to double 0.2",
|
|
jsonObject.get("preciseNumber").equals(new Double(0.2)));
|
|
obj = jsonObject.get("largeExponent");
|
|
assertTrue("largeExponent should currently evaluates as a string",
|
|
"-23.45e2327".equals(obj));
|
|
}
|
|
|
|
/**
|
|
* Confirm behavior when JSONObject stringToValue() is called for an empty
|
|
* string
|
|
*/
|
|
@Test
|
|
public void stringToValue() {
|
|
final String str = "";
|
|
final String valueStr = (String) JSONObject.stringToValue(str);
|
|
assertTrue("stringToValue() expected empty String, found " + valueStr,
|
|
"".equals(valueStr));
|
|
}
|
|
|
|
/**
|
|
* Check whether JSONObject handles large or high precision numbers
|
|
* correctly
|
|
*/
|
|
@Test
|
|
public void stringToValueNumbersTest() {
|
|
assertTrue("-0 Should be a Double!",
|
|
JSONObject.stringToValue("-0") instanceof Double);
|
|
assertTrue("-0 Should be a Double!",
|
|
JSONObject.stringToValue("-0.0") instanceof Double);
|
|
assertTrue("'-' Should be a String!",
|
|
JSONObject.stringToValue("-") instanceof String);
|
|
assertTrue("0.2 should be a Double!",
|
|
JSONObject.stringToValue("0.2") instanceof Double);
|
|
assertTrue(
|
|
"Doubles should be Doubles, even when incorrectly converting floats!",
|
|
JSONObject.stringToValue(new Double("0.2f").toString()) instanceof Double);
|
|
/**
|
|
* This test documents a need for BigDecimal conversion.
|
|
*/
|
|
final Object obj = JSONObject.stringToValue("299792.457999999984");
|
|
assertTrue(
|
|
"evaluates to 299792.458 doubld instead of 299792.457999999984 BigDecimal!",
|
|
obj.equals(new Double(299792.458)));
|
|
assertTrue("1 should be an Integer!",
|
|
JSONObject.stringToValue("1") instanceof Integer);
|
|
assertTrue("Integer.MAX_VALUE should still be an Integer!",
|
|
JSONObject.stringToValue(new Integer(Integer.MAX_VALUE)
|
|
.toString()) instanceof Integer);
|
|
assertTrue("Large integers should be a Long!",
|
|
JSONObject.stringToValue(new Long(Long
|
|
.sum(Integer.MAX_VALUE, 1)).toString()) instanceof Long);
|
|
assertTrue(
|
|
"Long.MAX_VALUE should still be an Integer!",
|
|
JSONObject.stringToValue(new Long(Long.MAX_VALUE).toString()) instanceof Long);
|
|
|
|
final String str = new BigInteger(new Long(Long.MAX_VALUE).toString())
|
|
.add(BigInteger.ONE).toString();
|
|
assertTrue("Really large integers currently evaluate to string",
|
|
JSONObject.stringToValue(str).equals("9223372036854775808"));
|
|
}
|
|
|
|
/**
|
|
* Confirm behavior when toJSONArray is called with a null value
|
|
*/
|
|
@Test
|
|
public void toJSONArray() {
|
|
assertTrue("toJSONArray() with null names should be null",
|
|
null == new JSONObject().toJSONArray(null));
|
|
}
|
|
|
|
/**
|
|
* This test documents an unexpected numeric behavior. A double that ends
|
|
* with .0 is parsed, serialized, then parsed again. On the second parse, it
|
|
* has become an int.
|
|
*/
|
|
@Test
|
|
public void unexpectedDoubleToIntConversion() {
|
|
final String key30 = "key30";
|
|
final String key31 = "key31";
|
|
final JSONObject jsonObject = new JSONObject();
|
|
jsonObject.put(key30, new Double(3.0));
|
|
jsonObject.put(key31, new Double(3.1));
|
|
|
|
assertTrue("3.0 should remain a double",
|
|
jsonObject.getDouble(key30) == 3);
|
|
assertTrue("3.1 should remain a double",
|
|
jsonObject.getDouble(key31) == 3.1);
|
|
|
|
// turns 3.0 into 3.
|
|
final String serializedString = jsonObject.toString();
|
|
final JSONObject deserialized = new JSONObject(serializedString);
|
|
assertTrue("3.0 is now an int",
|
|
deserialized.get(key30) instanceof Integer);
|
|
assertTrue("3.0 can still be interpreted as a double",
|
|
deserialized.getDouble(key30) == 3.0);
|
|
assertTrue("3.1 remains a double", deserialized.getDouble(key31) == 3.1);
|
|
}
|
|
|
|
/**
|
|
* Exercises the JSONObject.valueToString() method for various types
|
|
*/
|
|
@Test
|
|
public void valueToString() {
|
|
|
|
assertTrue("null valueToString() incorrect",
|
|
"null".equals(JSONObject.valueToString(null)));
|
|
final MyJsonString jsonString = new MyJsonString();
|
|
assertTrue("jsonstring valueToString() incorrect",
|
|
"my string".equals(JSONObject.valueToString(jsonString)));
|
|
assertTrue("boolean valueToString() incorrect",
|
|
"true".equals(JSONObject.valueToString(Boolean.TRUE)));
|
|
assertTrue("non-numeric double", "null".equals(JSONObject
|
|
.doubleToString(Double.POSITIVE_INFINITY)));
|
|
final String jsonObjectStr = "{" + "\"key1\":\"val1\","
|
|
+ "\"key2\":\"val2\"," + "\"key3\":\"val3\"" + "}";
|
|
final JSONObject jsonObject = new JSONObject(jsonObjectStr);
|
|
assertTrue("jsonObject valueToString() incorrect", JSONObject
|
|
.valueToString(jsonObject).equals(jsonObject.toString()));
|
|
final String jsonArrayStr = "[1,2,3]";
|
|
final JSONArray jsonArray = new JSONArray(jsonArrayStr);
|
|
assertTrue("jsonArra valueToString() incorrect", JSONObject
|
|
.valueToString(jsonArray).equals(jsonArray.toString()));
|
|
final Map<String, String> map = new HashMap<String, String>();
|
|
map.put("key1", "val1");
|
|
map.put("key2", "val2");
|
|
map.put("key3", "val3");
|
|
assertTrue("map valueToString() incorrect", jsonObject.toString()
|
|
.equals(JSONObject.valueToString(map)));
|
|
final Collection<Integer> collection = new ArrayList<Integer>();
|
|
collection.add(new Integer(1));
|
|
collection.add(new Integer(2));
|
|
collection.add(new Integer(3));
|
|
assertTrue(
|
|
"collection valueToString() expected: " + jsonArray.toString()
|
|
+ " actual: " + JSONObject.valueToString(collection),
|
|
jsonArray.toString().equals(
|
|
JSONObject.valueToString(collection)));
|
|
final Integer[] array = { new Integer(1), new Integer(2),
|
|
new Integer(3) };
|
|
assertTrue("array valueToString() incorrect", jsonArray.toString()
|
|
.equals(JSONObject.valueToString(array)));
|
|
}
|
|
|
|
/**
|
|
* Confirm that https://github.com/douglascrockford/JSON-java/issues/167 is
|
|
* fixed. The following code was throwing a ClassCastException in the
|
|
* JSONObject(Map<String, Object>) constructor
|
|
*/
|
|
@Test
|
|
public void valueToStringConfirmException() {
|
|
final Map<Integer, String> myMap = new HashMap<Integer, String>();
|
|
myMap.put(1, "myValue");
|
|
// this is the test, it should not throw an exception
|
|
final String str = JSONObject.valueToString(myMap);
|
|
// confirm result, just in case
|
|
final Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(str);
|
|
assertTrue("expected 1 top level item",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 1);
|
|
assertTrue("expected myValue",
|
|
"myValue".equals(JsonPath.read(doc, "$.1")));
|
|
}
|
|
|
|
/**
|
|
* Verifies that the constructor has backwards compatability with RAW types
|
|
* pre-java5.
|
|
*/
|
|
@Test
|
|
public void verifyConstructor() {
|
|
|
|
final JSONObject expected = new JSONObject("{\"myKey\":10}");
|
|
|
|
@SuppressWarnings("rawtypes")
|
|
final Map myRawC = Collections.singletonMap("myKey",
|
|
Integer.valueOf(10));
|
|
final JSONObject jaRaw = new JSONObject(myRawC);
|
|
|
|
final Map<String, Object> myCStrObj = Collections.singletonMap("myKey",
|
|
(Object) Integer.valueOf(10));
|
|
final JSONObject jaStrObj = new JSONObject(myCStrObj);
|
|
|
|
final Map<String, Integer> myCStrInt = Collections.singletonMap(
|
|
"myKey", Integer.valueOf(10));
|
|
final JSONObject jaStrInt = new JSONObject(myCStrInt);
|
|
|
|
final Map<?, ?> myCObjObj = Collections.singletonMap((Object) "myKey",
|
|
(Object) Integer.valueOf(10));
|
|
final JSONObject jaObjObj = new JSONObject(myCObjObj);
|
|
|
|
assertTrue(
|
|
"The RAW Collection should give me the same as the Typed Collection",
|
|
expected.similar(jaRaw));
|
|
assertTrue(
|
|
"The RAW Collection should give me the same as the Typed Collection",
|
|
expected.similar(jaStrObj));
|
|
assertTrue(
|
|
"The RAW Collection should give me the same as the Typed Collection",
|
|
expected.similar(jaStrInt));
|
|
assertTrue(
|
|
"The RAW Collection should give me the same as the Typed Collection",
|
|
expected.similar(jaObjObj));
|
|
}
|
|
|
|
/**
|
|
* Verifies that the put Collection has backwards compatability with RAW
|
|
* types pre-java5.
|
|
*/
|
|
@Test
|
|
public void verifyPutCollection() {
|
|
|
|
final JSONObject expected = new JSONObject("{\"myCollection\":[10]}");
|
|
|
|
@SuppressWarnings("rawtypes")
|
|
final Collection myRawC = Collections.singleton(Integer.valueOf(10));
|
|
final JSONObject jaRaw = new JSONObject();
|
|
jaRaw.put("myCollection", myRawC);
|
|
|
|
final Collection<Object> myCObj = Collections
|
|
.singleton((Object) Integer.valueOf(10));
|
|
final JSONObject jaObj = new JSONObject();
|
|
jaObj.put("myCollection", myCObj);
|
|
|
|
final Collection<Integer> myCInt = Collections.singleton(Integer
|
|
.valueOf(10));
|
|
final JSONObject jaInt = new JSONObject();
|
|
jaInt.put("myCollection", myCInt);
|
|
|
|
assertTrue(
|
|
"The RAW Collection should give me the same as the Typed Collection",
|
|
expected.similar(jaRaw));
|
|
assertTrue(
|
|
"The RAW Collection should give me the same as the Typed Collection",
|
|
expected.similar(jaObj));
|
|
assertTrue(
|
|
"The RAW Collection should give me the same as the Typed Collection",
|
|
expected.similar(jaInt));
|
|
}
|
|
|
|
/**
|
|
* Verifies that the put Map has backwards compatability with RAW types
|
|
* pre-java5.
|
|
*/
|
|
@Test
|
|
public void verifyPutMap() {
|
|
|
|
final JSONObject expected = new JSONObject("{\"myMap\":{\"myKey\":10}}");
|
|
|
|
@SuppressWarnings("rawtypes")
|
|
final Map myRawC = Collections.singletonMap("myKey",
|
|
Integer.valueOf(10));
|
|
final JSONObject jaRaw = new JSONObject();
|
|
jaRaw.put("myMap", myRawC);
|
|
|
|
final Map<String, Object> myCStrObj = Collections.singletonMap("myKey",
|
|
(Object) Integer.valueOf(10));
|
|
final JSONObject jaStrObj = new JSONObject();
|
|
jaStrObj.put("myMap", myCStrObj);
|
|
|
|
final Map<String, Integer> myCStrInt = Collections.singletonMap(
|
|
"myKey", Integer.valueOf(10));
|
|
final JSONObject jaStrInt = new JSONObject();
|
|
jaStrInt.put("myMap", myCStrInt);
|
|
|
|
final Map<?, ?> myCObjObj = Collections.singletonMap((Object) "myKey",
|
|
(Object) Integer.valueOf(10));
|
|
final JSONObject jaObjObj = new JSONObject();
|
|
jaObjObj.put("myMap", myCObjObj);
|
|
|
|
assertTrue(
|
|
"The RAW Collection should give me the same as the Typed Collection",
|
|
expected.similar(jaRaw));
|
|
assertTrue(
|
|
"The RAW Collection should give me the same as the Typed Collection",
|
|
expected.similar(jaStrObj));
|
|
assertTrue(
|
|
"The RAW Collection should give me the same as the Typed Collection",
|
|
expected.similar(jaStrInt));
|
|
assertTrue(
|
|
"The RAW Collection should give me the same as the Typed Collection",
|
|
expected.similar(jaObjObj));
|
|
}
|
|
|
|
/**
|
|
* Exercise the JSONObject wrap() method. Sometimes wrap() will change the
|
|
* object being wrapped, other times not. The purpose of wrap() is to ensure
|
|
* the value is packaged in a way that is compatible with how a JSONObject
|
|
* value or JSONArray value is supposed to be stored.
|
|
*/
|
|
@Test
|
|
public void wrapObject() {
|
|
// wrap(null) returns NULL
|
|
assertTrue("null wrap() incorrect",
|
|
JSONObject.NULL == JSONObject.wrap(null));
|
|
|
|
// wrap(Integer) returns Integer
|
|
final Integer in = new Integer(1);
|
|
assertTrue("Integer wrap() incorrect", in == JSONObject.wrap(in));
|
|
|
|
/**
|
|
* This test is to document the preferred behavior if BigDecimal is
|
|
* supported. Previously bd returned as a string, since it is recognized
|
|
* as being a Java package class. Now with explicit support for big
|
|
* numbers, it remains a BigDecimal
|
|
*/
|
|
final Object bdWrap = JSONObject.wrap(BigDecimal.ONE);
|
|
assertTrue("BigDecimal.ONE evaluates to ONE",
|
|
bdWrap.equals(BigDecimal.ONE));
|
|
|
|
// wrap JSONObject returns JSONObject
|
|
final String jsonObjectStr = "{" + "\"key1\":\"val1\","
|
|
+ "\"key2\":\"val2\"," + "\"key3\":\"val3\"" + "}";
|
|
final JSONObject jsonObject = new JSONObject(jsonObjectStr);
|
|
assertTrue("JSONObject wrap() incorrect",
|
|
jsonObject == JSONObject.wrap(jsonObject));
|
|
|
|
// wrap collection returns JSONArray
|
|
final Collection<Integer> collection = new ArrayList<Integer>();
|
|
collection.add(new Integer(1));
|
|
collection.add(new Integer(2));
|
|
collection.add(new Integer(3));
|
|
final JSONArray jsonArray = (JSONArray) JSONObject.wrap(collection);
|
|
|
|
// validate JSON
|
|
Object doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonArray.toString());
|
|
assertTrue("expected 3 top level items",
|
|
((List<?>) JsonPath.read(doc, "$")).size() == 3);
|
|
assertTrue("expected 1",
|
|
Integer.valueOf(1).equals(JsonPath.read(doc, "$[0]")));
|
|
assertTrue("expected 2",
|
|
Integer.valueOf(2).equals(JsonPath.read(doc, "$[1]")));
|
|
assertTrue("expected 3",
|
|
Integer.valueOf(3).equals(JsonPath.read(doc, "$[2]")));
|
|
|
|
// wrap Array returns JSONArray
|
|
final Integer[] array = { new Integer(1), new Integer(2),
|
|
new Integer(3) };
|
|
final JSONArray integerArrayJsonArray = (JSONArray) JSONObject
|
|
.wrap(array);
|
|
|
|
// validate JSON
|
|
doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(jsonArray.toString());
|
|
assertTrue("expected 3 top level items",
|
|
((List<?>) JsonPath.read(doc, "$")).size() == 3);
|
|
assertTrue("expected 1",
|
|
Integer.valueOf(1).equals(JsonPath.read(doc, "$[0]")));
|
|
assertTrue("expected 2",
|
|
Integer.valueOf(2).equals(JsonPath.read(doc, "$[1]")));
|
|
assertTrue("expected 3",
|
|
Integer.valueOf(3).equals(JsonPath.read(doc, "$[2]")));
|
|
|
|
// validate JSON
|
|
doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(integerArrayJsonArray.toString());
|
|
assertTrue("expected 3 top level items",
|
|
((List<?>) JsonPath.read(doc, "$")).size() == 3);
|
|
assertTrue("expected 1",
|
|
Integer.valueOf(1).equals(JsonPath.read(doc, "$[0]")));
|
|
assertTrue("expected 2",
|
|
Integer.valueOf(2).equals(JsonPath.read(doc, "$[1]")));
|
|
assertTrue("expected 3",
|
|
Integer.valueOf(3).equals(JsonPath.read(doc, "$[2]")));
|
|
|
|
// wrap map returns JSONObject
|
|
final Map<String, String> map = new HashMap<String, String>();
|
|
map.put("key1", "val1");
|
|
map.put("key2", "val2");
|
|
map.put("key3", "val3");
|
|
final JSONObject mapJsonObject = (JSONObject) JSONObject.wrap(map);
|
|
|
|
// validate JSON
|
|
doc = Configuration.defaultConfiguration().jsonProvider()
|
|
.parse(mapJsonObject.toString());
|
|
assertTrue("expected 3 top level items",
|
|
((Map<?, ?>) JsonPath.read(doc, "$")).size() == 3);
|
|
assertTrue("expected val1", "val1".equals(JsonPath.read(doc, "$.key1")));
|
|
assertTrue("expected val2", "val2".equals(JsonPath.read(doc, "$.key2")));
|
|
assertTrue("expected val3", "val3".equals(JsonPath.read(doc, "$.key3")));
|
|
}
|
|
|
|
/**
|
|
* Exercise the JSONObject write() method
|
|
*/
|
|
@Test
|
|
public void write() {
|
|
final String str = "{\"key\":\"value\"}";
|
|
final String expectedStr = str;
|
|
final JSONObject jsonObject = new JSONObject(str);
|
|
final StringWriter stringWriter = new StringWriter();
|
|
final Writer writer = jsonObject.write(stringWriter);
|
|
final String actualStr = writer.toString();
|
|
assertTrue(
|
|
"write() expected " + expectedStr + "but found " + actualStr,
|
|
expectedStr.equals(actualStr));
|
|
}
|
|
}
|