, InstanceCreator>> getCollectionMapping() {
- return this.collectionMapping;
- }
-
- /**
- * Adds or updates a type conversion function for a given class.
- *
- * This allows users to customize how objects are converted into specific types
- * during processing (e.g., JSON deserialization).
- *
- * @param clazz the target class for which the conversion function is to be set
- * @param function a function that takes an {@code Object} and returns an instance of {@code clazz}
- */
- public void setClassMapping(Class> clazz, TypeConverter> function) {
- classMapping.put(clazz, function);
- }
-
- /**
- * Adds or updates a supplier function for instantiating a collection type.
- *
- *
This allows customization of which concrete implementation is used for
- * interface types like {@code List}, {@code Set}, or {@code Map}.
- *
- * @param clazz the collection interface class (e.g., {@code List.class})
- * @param function a supplier that creates a new instance of a concrete implementation
- */
- public void setCollectionMapping(Class> clazz, InstanceCreator> function) {
- collectionMapping.put(clazz, function);
- }
-}
diff --git a/src/main/java/org/json/JSONObject.java b/src/main/java/org/json/JSONObject.java
index f6e1d43..52bd2fe 100644
--- a/src/main/java/org/json/JSONObject.java
+++ b/src/main/java/org/json/JSONObject.java
@@ -19,6 +19,7 @@ import java.util.Map.Entry;
import java.util.regex.Pattern;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
+import java.lang.reflect.GenericArrayType;
/**
* A JSONObject is an unordered collection of name/value pairs. Its external
@@ -121,12 +122,6 @@ public class JSONObject {
*/
static final Pattern NUMBER_PATTERN = Pattern.compile("-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?");
-
- /**
- * A Builder class for handling the conversion of JSON to Object.
- */
- private JSONBuilder builder;
-
/**
* The map where the JSONObject's properties are kept.
*/
@@ -162,6 +157,145 @@ public class JSONObject {
this.map = new HashMap();
}
+ /**
+ * A mapping from Java classes to functions that convert a generic {@code Object}
+ * into an instance of the target class.
+ *
+ * Examples of default mappings:
+ *
+ * {@code int.class} or {@code Integer.class} -> Converts a {@code Number} to {@code int}
+ * {@code boolean.class} or {@code Boolean.class} -> Identity function
+ * {@code String.class} -> Identity function
+ *
+ */
+ private static final Map, TypeConverter>> classMapping = new HashMap, TypeConverter>>();
+
+ /**
+ * A mapping from collection interface types to suppliers that produce
+ * instances of concrete collection implementations.
+ *
+ */
+ private static final Map, InstanceCreator>> collectionMapping = new HashMap, InstanceCreator>>();
+
+ // Static initializer block to populate default mappings
+ static {
+ classMapping.put(int.class, new TypeConverter() {
+ public Integer convert(Object input) {
+ return ((Number) input).intValue();
+ }
+ });
+ classMapping.put(Integer.class, new TypeConverter() {
+ public Integer convert(Object input) {
+ return ((Number) input).intValue();
+ }
+ });
+ classMapping.put(double.class, new TypeConverter() {
+ public Double convert(Object input) {
+ return ((Number) input).doubleValue();
+ }
+ });
+ classMapping.put(Double.class, new TypeConverter() {
+ public Double convert(Object input) {
+ return ((Number) input).doubleValue();
+ }
+ });
+ classMapping.put(float.class, new TypeConverter() {
+ public Float convert(Object input) {
+ return ((Number) input).floatValue();
+ }
+ });
+ classMapping.put(Float.class, new TypeConverter() {
+ public Float convert(Object input) {
+ return ((Number) input).floatValue();
+ }
+ });
+ classMapping.put(long.class, new TypeConverter() {
+ public Long convert(Object input) {
+ return ((Number) input).longValue();
+ }
+ });
+ classMapping.put(Long.class, new TypeConverter() {
+ public Long convert(Object input) {
+ return ((Number) input).longValue();
+ }
+ });
+ classMapping.put(boolean.class, new TypeConverter() {
+ public Boolean convert(Object input) {
+ return (Boolean) input;
+ }
+ });
+ classMapping.put(Boolean.class, new TypeConverter() {
+ public Boolean convert(Object input) {
+ return (Boolean) input;
+ }
+ });
+ classMapping.put(String.class, new TypeConverter() {
+ public String convert(Object input) {
+ return (String) input;
+ }
+ });
+
+ collectionMapping.put(List.class, new InstanceCreator() {
+ public List create() {
+ return new ArrayList();
+ }
+ });
+ collectionMapping.put(Set.class, new InstanceCreator() {
+ public Set create() {
+ return new HashSet();
+ }
+ });
+ collectionMapping.put(Map.class, new InstanceCreator() {
+ public Map create() {
+ return new HashMap();
+ }
+ });
+ }
+
+ /**
+ * Returns the current class-to-function mapping used for type conversions.
+ *
+ * @return a map of classes to functions that convert an {@code Object} to that class
+ */
+ public Map, TypeConverter>> getClassMapping() {
+ return this.classMapping;
+ }
+
+ /**
+ * Returns the current collection-to-supplier mapping used for instantiating collections.
+ *
+ * @return a map of collection interface types to suppliers of concrete implementations
+ */
+ public Map, InstanceCreator>> getCollectionMapping() {
+ return collectionMapping;
+ }
+
+ /**
+ * Adds or updates a type conversion function for a given class.
+ *
+ * This allows users to customize how objects are converted into specific types
+ * during processing (e.g., JSON deserialization).
+ *
+ * @param clazz the target class for which the conversion function is to be set
+ * @param function a function that takes an {@code Object} and returns an instance of {@code clazz}
+ */
+ public void setClassMapping(Class> clazz, TypeConverter> function) {
+ classMapping.put(clazz, function);
+ }
+
+ /**
+ * Adds or updates a supplier function for instantiating a collection type.
+ *
+ *
This allows customization of which concrete implementation is used for
+ * interface types like {@code List}, {@code Set}, or {@code Map}.
+ *
+ * @param clazz the collection interface class (e.g., {@code List.class})
+ * @param function a supplier that creates a new instance of a concrete implementation
+ */
+ public void setCollectionMapping(Class> clazz, InstanceCreator> function) {
+ collectionMapping.put(clazz, function);
+ }
+
/**
* Construct a JSONObject from a subset of another JSONObject. An array of
* strings is used to identify the keys that should be copied. Missing keys
@@ -220,25 +354,6 @@ public class JSONObject {
}
}
- /**
- * Construct a JSONObject with JSONBuilder for conversion from JSON to POJO
- *
- * @param builder builder option for json to POJO
- */
- public JSONObject(JSONBuilder builder) {
- this();
- this.builder = builder;
- }
-
- /**
- * Method to set JSONBuilder.
- *
- * @param builder
- */
- public void setJSONBuilder(JSONBuilder builder) {
- this.builder = builder;
- }
-
/**
* Parses entirety of JSON object
*
@@ -3236,114 +3351,59 @@ public class JSONObject {
}
/**
- * Deserializes a JSON string into an instance of the specified class.
- *
- *
This method attempts to map JSON key-value pairs to the corresponding fields
- * of the given class. It supports basic data types including int, double, float,
- * long, and boolean (as well as their boxed counterparts). The class must have a
- * no-argument constructor, and the field names in the class must match the keys
- * in the JSON string.
- *
- * @param clazz the class of the object to be returned
- * @param the type of the object
- * @return an instance of type T with fields populated from the JSON string
+ * Helper method to extract the raw Class from Type.
*/
- public T fromJson(Class clazz) {
- try {
- T obj = clazz.getDeclaredConstructor().newInstance();
- if (this.builder == null) {
- this.builder = new JSONBuilder();
+ private Class> getRawType(Type type) {
+ if (type instanceof Class) {
+ return (Class>) type;
+ } else if (type instanceof ParameterizedType) {
+ return (Class>) ((ParameterizedType) type).getRawType();
+ } else if (type instanceof GenericArrayType) {
+ return Object[].class; // Simplified handling for arrays
}
- Map, TypeConverter>> classMapping = this.builder.getClassMapping();
-
- for (Field field: clazz.getDeclaredFields()) {
- field.setAccessible(true);
- String fieldName = field.getName();
- if (this.has(fieldName)) {
- Object value = this.get(fieldName);
- Class> pojoClass = field.getType();
- if (classMapping.containsKey(pojoClass)) {
- field.set(obj, classMapping.get(pojoClass).convert(value));
- } else {
- if (value.getClass() == JSONObject.class) {
- field.set(obj, fromJson((JSONObject) value, pojoClass));
- } else if (value.getClass() == JSONArray.class) {
- if (Collection.class.isAssignableFrom(pojoClass)) {
-
- Collection> nestedCollection = fromJsonArray((JSONArray) value,
- (Class extends Collection>) pojoClass,
- field.getGenericType());
-
- field.set(obj, nestedCollection);
- }
- }
- }
- }
- }
- return obj;
- } catch (NoSuchMethodException e) {
- throw new JSONException(e);
- } catch (InstantiationException e) {
- throw new JSONException(e);
- } catch (IllegalAccessException e) {
- throw new JSONException(e);
- } catch (InvocationTargetException e) {
- throw new JSONException(e);
- }
+ return Object.class; // Fallback
}
- private Collection fromJsonArray(JSONArray jsonArray, Class> collectionType, Type elementType) throws JSONException {
- try {
- Map, TypeConverter>> classMapping = this.builder.getClassMapping();
- Map, InstanceCreator>> collectionMapping = this.builder.getCollectionMapping();
- Collection collection = (Collection) (collectionMapping.containsKey(collectionType) ?
- collectionMapping.get(collectionType).create()
- : collectionType.getDeclaredConstructor().newInstance());
-
-
- Class> innerElementClass = null;
- Type innerElementType = null;
- if (elementType instanceof ParameterizedType) {
- ParameterizedType pType = (ParameterizedType) elementType;
- innerElementType = pType.getActualTypeArguments()[0];
- innerElementClass = (innerElementType instanceof Class) ?
- (Class>) innerElementType
- : (Class>) ((ParameterizedType) innerElementType).getRawType();
- } else {
- innerElementClass = (Class>) elementType;
+ /**
+ * Extracts the element Type for a Collection Type.
+ */
+ private Type getElementType(Type type) {
+ if (type instanceof ParameterizedType) {
+ Type[] args = ((ParameterizedType) type).getActualTypeArguments();
+ return args.length > 0 ? args[0] : Object.class;
}
+ return Object.class;
+ }
- for (int i = 0; i < jsonArray.length(); i++) {
- Object jsonElement = jsonArray.get(i);
- if (classMapping.containsKey(innerElementClass)) {
- collection.add((T) classMapping.get(innerElementClass).convert(jsonElement));
- } else if (jsonElement.getClass() == JSONObject.class) {
- collection.add((T) ((JSONObject) jsonElement).fromJson(innerElementClass));
- } else if (jsonElement.getClass() == JSONArray.class) {
- if (Collection.class.isAssignableFrom(innerElementClass)) {
-
- Collection> nestedCollection = fromJsonArray((JSONArray) jsonElement,
- innerElementClass,
- innerElementType);
-
- collection.add((T) nestedCollection);
- } else {
- throw new JSONException("Expected collection type for nested JSONArray, but got: " + innerElementClass);
+ /**
+ * Extracts the key and value Types for a Map Type.
+ */
+ private Type[] getMapTypes(Type type) {
+ if (type instanceof ParameterizedType) {
+ Type[] args = ((ParameterizedType) type).getActualTypeArguments();
+ if (args.length == 2) {
+ return args;
}
- } else {
- collection.add((T) jsonElement.toString());
- }
}
- return collection;
- } catch (NoSuchMethodException e) {
- throw new JSONException(e);
- } catch (InstantiationException e) {
- throw new JSONException(e);
- } catch (IllegalAccessException e) {
- throw new JSONException(e);
- } catch (InvocationTargetException e) {
- throw new JSONException(e);
- }
+ return new Type[]{Object.class, Object.class}; // Default: String keys, Object values
+ }
+
+ /**
+ * Deserializes a JSON string into an instance of the specified class.
+ *
+ * This method attempts to map JSON key-value pairs to the corresponding fields
+ * of the given class. It supports basic data types including int, double, float,
+ * long, and boolean (as well as their boxed counterparts). The class must have a
+ * no-argument constructor, and the field names in the class must match the keys
+ * in the JSON string.
+ *
+ * @param jsonString json in string format
+ * @param clazz the class of the object to be returned
+ * @return an instance of Object T with fields populated from the JSON string
+ */
+ public static T fromJson(String jsonString, Class clazz) {
+ JSONObject jsonObject = new JSONObject(jsonString);
+ return jsonObject.fromJson(clazz);
}
/**
@@ -3355,12 +3415,161 @@ public class JSONObject {
* no-argument constructor, and the field names in the class must match the keys
* in the JSON string.
*
- * @param object JSONObject of internal class
* @param clazz the class of the object to be returned
- * @param the type of the object
* @return an instance of type T with fields populated from the JSON string
*/
- private T fromJson(JSONObject object, Class clazz) {
- return object.fromJson(clazz);
+ @SuppressWarnings("unchecked")
+ public T fromJson(Class clazz) {
+ try {
+ T obj = clazz.getDeclaredConstructor().newInstance();
+ for (Field field : clazz.getDeclaredFields()) {
+ field.setAccessible(true);
+ String fieldName = field.getName();
+ if (has(fieldName)) {
+ Object value = get(fieldName);
+ Type fieldType = field.getGenericType();
+ Class> rawType = getRawType(fieldType);
+ if (classMapping.containsKey(rawType)) {
+ field.set(obj, classMapping.get(rawType).convert(value));
+ } else {
+ Object convertedValue = convertValue(value, fieldType);
+ field.set(obj, convertedValue);
+ }
+ }
+ }
+ return obj;
+ } catch (NoSuchMethodException e) {
+ throw new JSONException("No no-arg constructor for class: " + clazz.getName(), e);
+ } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) {
+ throw new JSONException("Failed to instantiate or set field for class: " + clazz.getName(), e);
+ }
}
+
+ /**
+ * Handles non-primitive types (Enum, Map, JSONObject, JSONArray) during deserialization.
+ * Now dispatches to the recursive convertValue for consistency.
+ */
+ private void handleNonDataTypes(Class> pojoClass, Object value, Field field, T obj) throws JSONException {
+ try {
+ Type fieldType = field.getGenericType();
+ Object convertedValue = convertValue(value, fieldType);
+ field.set(obj, convertedValue);
+ } catch (IllegalAccessException e) {
+ throw new JSONException("Failed to set field: " + field.getName(), e);
+ }
+ }
+
+ /**
+ * Recursively converts a value to the target Type, handling nested generics for Collections and Maps.
+ */
+ private Object convertValue(Object value, Type targetType) throws JSONException {
+ if (value == null) {
+ return null;
+ }
+
+ Class> rawType = getRawType(targetType);
+
+ // Direct assignment
+ if (rawType.isAssignableFrom(value.getClass())) {
+ return value;
+ }
+
+ // Use registered type converter
+ if (classMapping.containsKey(rawType)) {
+ return classMapping.get(rawType).convert(value);
+ }
+
+ // Enum conversion
+ if (rawType.isEnum() && value instanceof String) {
+ return stringToEnum(rawType, (String) value);
+ }
+
+ // Collection handling (e.g., List>>)
+ if (Collection.class.isAssignableFrom(rawType)) {
+ if (value instanceof JSONArray) {
+ Type elementType = getElementType(targetType);
+ return fromJsonArray((JSONArray) value, rawType, elementType);
+ }
+ }
+ // Map handling (e.g., Map>)
+ else if (Map.class.isAssignableFrom(rawType)) {
+ if (value instanceof JSONObject) {
+ Type[] mapTypes = getMapTypes(targetType);
+ Type keyType = mapTypes[0];
+ Type valueType = mapTypes[1];
+ return convertToMap((JSONObject) value, keyType, valueType, rawType);
+ }
+ }
+ // POJO handling (including custom classes like Tuple)
+ else if (!rawType.isPrimitive() && !rawType.isEnum()) {
+ if (value instanceof JSONObject) {
+ // Recurse with the raw class for POJO deserialization
+ return ((JSONObject) value).fromJson(rawType);
+ }
+ }
+
+ // Fallback
+ return value.toString();
+ }
+
+ /**
+ * Converts a JSONObject to a Map with the specified generic key and value Types.
+ * Supports nested types via recursive convertValue.
+ */
+ private Map, ?> convertToMap(JSONObject jsonMap, Type keyType, Type valueType, Class> mapType) throws JSONException {
+ try {
+ InstanceCreator> creator = collectionMapping.getOrDefault(mapType, () -> new HashMap<>());
+ @SuppressWarnings("unchecked")
+ Map map = (Map) creator.create();
+
+ for (Object keyObj : jsonMap.keySet()) {
+ String keyStr = (String) keyObj;
+ Object mapValue = jsonMap.get(keyStr);
+ // Convert key (e.g., String to Integer for Map)
+ Object convertedKey = convertValue(keyStr, keyType);
+ // Convert value recursively (handles nesting)
+ Object convertedValue = convertValue(mapValue, valueType);
+ map.put(convertedKey, convertedValue);
+ }
+ return map;
+ } catch (Exception e) {
+ throw new JSONException("Failed to convert JSONObject to Map: " + mapType.getName(), e);
+ }
+ }
+
+ /**
+ * Converts a String to an Enum value.
+ */
+ private > E stringToEnum(Class> enumClass, String value) throws JSONException {
+ try {
+ @SuppressWarnings("unchecked")
+ Method valueOfMethod = enumClass.getMethod("valueOf", String.class);
+ return (E) valueOfMethod.invoke(null, value);
+ } catch (NoSuchMethodException | IllegalAccessException | InvocationTargetException e) {
+ throw new JSONException("Failed to convert string to enum: " + value + " for " + enumClass.getName(), e);
+ }
+ }
+
+ /**
+ * Deserializes a JSONArray into a Collection, supporting nested generics.
+ * Uses recursive convertValue for elements.
+ */
+ @SuppressWarnings("unchecked")
+ private Collection fromJsonArray(JSONArray jsonArray, Class> collectionType, Type elementType) throws JSONException {
+ try {
+ InstanceCreator> creator = collectionMapping.getOrDefault(collectionType, () -> new ArrayList<>());
+ Collection collection = (Collection) creator.create();
+
+ for (int i = 0; i < jsonArray.length(); i++) {
+ Object jsonElement = jsonArray.get(i);
+ // Recursively convert each element using the full element Type (handles nesting)
+ Object convertedValue = convertValue(jsonElement, elementType);
+ collection.add((T) convertedValue);
+ }
+ return collection;
+ } catch (Exception e) {
+ throw new JSONException("Failed to convert JSONArray to Collection: " + collectionType.getName(), e);
+ }
+ }
+
}
diff --git a/src/test/java/org/json/junit/JSONObjectTest.java b/src/test/java/org/json/junit/JSONObjectTest.java
index 5a7aedb..f853d24 100644
--- a/src/test/java/org/json/junit/JSONObjectTest.java
+++ b/src/test/java/org/json/junit/JSONObjectTest.java
@@ -33,7 +33,6 @@ import org.json.JSONObject;
import org.json.JSONPointerException;
import org.json.JSONParserConfiguration;
import org.json.JSONString;
-import org.json.JSONBuilder;
import org.json.JSONTokener;
import org.json.ParserConfiguration;
import org.json.XML;
@@ -58,6 +57,17 @@ import org.json.junit.data.RecursiveBeanEquals;
import org.json.junit.data.Singleton;
import org.json.junit.data.SingletonEnum;
import org.json.junit.data.WeirdList;
+import org.json.junit.data.CustomClass;
+import org.json.junit.data.CustomClassA;
+import org.json.junit.data.CustomClassB;
+import org.json.junit.data.CustomClassC;
+import org.json.junit.data.CustomClassD;
+import org.json.junit.data.CustomClassE;
+import org.json.junit.data.CustomClassF;
+import org.json.junit.data.CustomClassG;
+import org.json.junit.data.CustomClassH;
+import org.json.junit.data.CustomClassI;
+import org.json.JSONObject;
import org.junit.After;
import org.junit.Ignore;
import org.junit.Test;
@@ -4110,36 +4120,14 @@ public class JSONObjectTest {
assertEquals(customClass, compareClass);
}
- public static class CustomClass {
- public int number;
- public String name;
- public Long longNumber;
-
- public CustomClass() {}
- public CustomClass (int number, String name, Long longNumber) {
- this.number = number;
- this.name = name;
- this.longNumber = longNumber;
- }
- @Override
- public boolean equals(Object o) {
- CustomClass customClass = (CustomClass) o;
-
- return (this.number == customClass.number
- && this.name.equals(customClass.name)
- && this.longNumber.equals(customClass.longNumber));
- }
- }
-
@Test
public void jsonObjectParseFromJson_1() {
- JSONBuilder builder = new JSONBuilder();
- builder.setClassMapping(java.time.LocalDateTime.class, new TypeConverter() {
+ JSONObject object = new JSONObject();
+ object.setClassMapping(java.time.LocalDateTime.class, new TypeConverter() {
public java.time.LocalDateTime convert(Object input) {
return java.time.LocalDateTime.parse((String) input);
}
});
- JSONObject object = new JSONObject(builder);
java.time.LocalDateTime localDateTime = java.time.LocalDateTime.now();
object.put("localDate", localDateTime.toString());
CustomClassA customClassA = object.fromJson(CustomClassA.class);
@@ -4147,21 +4135,6 @@ public class JSONObjectTest {
assertEquals(customClassA, compareClassClassA);
}
- public static class CustomClassA {
- public java.time.LocalDateTime localDate;
-
- public CustomClassA() {}
- public CustomClassA(java.time.LocalDateTime localDate) {
- this.localDate = localDate;
- }
-
- @Override
- public boolean equals(Object o) {
- CustomClassA classA = (CustomClassA) o;
- return this.localDate.equals(classA.localDate);
- }
- }
-
@Test
public void jsonObjectParseFromJson_2() {
JSONObject object = new JSONObject();
@@ -4179,54 +4152,6 @@ public class JSONObjectTest {
assertEquals(customClassB, compareClassB);
}
- public static class CustomClassB {
- public int number;
- public CustomClassC classC;
-
- public CustomClassB() {}
- public CustomClassB(int number, CustomClassC classC) {
- this.number = number;
- this.classC = classC;
- }
-
- @Override
- public boolean equals(Object o) {
- CustomClassB classB = (CustomClassB) o;
- return this.number == classB.number
- && this.classC.equals(classB.classC);
- }
- }
-
- public static class CustomClassC {
- public String stringName;
- public Long longNumber;
-
- public CustomClassC() {}
- public CustomClassC(String stringName, Long longNumber) {
- this.stringName = stringName;
- this.longNumber = longNumber;
- }
-
- public JSONObject toJSON() {
- JSONObject object = new JSONObject();
- object.put("stringName", this.stringName);
- object.put("longNumber", this.longNumber);
- return object;
- }
-
- @Override
- public boolean equals(Object o) {
- CustomClassC classC = (CustomClassC) o;
- return this.stringName.equals(classC.stringName)
- && this.longNumber.equals(classC.longNumber);
- }
-
- @Override
- public int hashCode() {
- return java.util.Objects.hash(stringName, longNumber);
- }
- }
-
@Test
public void jsonObjectParseFromJson_3() {
JSONObject object = new JSONObject();
@@ -4241,21 +4166,6 @@ public class JSONObjectTest {
assertEquals(customClassD, compareClassD);
}
- public static class CustomClassD {
- public List stringList;
-
- public CustomClassD() {}
- public CustomClassD(List stringList) {
- this.stringList = stringList;
- }
-
- @Override
- public boolean equals(Object o) {
- CustomClassD classD = (CustomClassD) o;
- return this.stringList.equals(classD.stringList);
- }
- }
-
@Test
public void jsonObjectParseFromJson_4() {
JSONObject object = new JSONObject();
@@ -4271,21 +4181,6 @@ public class JSONObjectTest {
assertEquals(customClassE, compareClassE);
}
- public static class CustomClassE {
- public List listClassC;
-
- public CustomClassE() {}
- public CustomClassE(List listClassC) {
- this.listClassC = listClassC;
- }
-
- @Override
- public boolean equals(Object o) {
- CustomClassE classE = (CustomClassE) o;
- return this.listClassC.equals(classE.listClassC);
- }
- }
-
@Test
public void jsonObjectParseFromJson_5() {
JSONObject object = new JSONObject();
@@ -4302,18 +4197,43 @@ public class JSONObjectTest {
assertEquals(customClassF, compareClassF);
}
- public static class CustomClassF {
- public List> listOfString;
+ @Test
+ public void jsonObjectParseFromJson_6() {
+ JSONObject object = new JSONObject();
+ Map dataList = new HashMap<>();
+ dataList.put("A", "Aa");
+ dataList.put("B", "Bb");
+ dataList.put("C", "Cc");
+ object.put("dataList", dataList);
- public CustomClassF() {}
- public CustomClassF(List> listOfString) {
- this.listOfString = listOfString;
- }
+ CustomClassG customClassG = object.fromJson(CustomClassG.class);
+ CustomClassG compareClassG = new CustomClassG(dataList);
+ assertEquals(customClassG, compareClassG);
+ }
- @Override
- public boolean equals(Object o) {
- CustomClassF classF = (CustomClassF) o;
- return this.listOfString.equals(classF.listOfString);
- }
+ @Test
+ public void jsonObjectParseFromJson_7() {
+ JSONObject object = new JSONObject();
+ Map> dataList = new HashMap<>();
+ dataList.put("1", Arrays.asList(1, 2, 3, 4));
+ dataList.put("2", Arrays.asList(2, 3, 4, 5));
+ object.put("integerMap", dataList);
+
+ CustomClassH customClassH = object.fromJson(CustomClassH.class);
+ CustomClassH compareClassH = new CustomClassH(dataList);
+ assertEquals(customClassH.integerMap.toString(), compareClassH.integerMap.toString());
+ }
+
+ @Test
+ public void jsonObjectParseFromJson_8() {
+ JSONObject object = new JSONObject();
+ Map> dataList = new HashMap<>();
+ dataList.put("1", Collections.singletonMap("1", 1));
+ dataList.put("2", Collections.singletonMap("2", 2));
+ object.put("integerMap", dataList);
+
+ CustomClassI customClassI = object.fromJson(CustomClassI.class);
+ CustomClassI compareClassI = new CustomClassI(dataList);
+ assertEquals(customClassI.integerMap.toString(), compareClassI.integerMap.toString());
}
}
diff --git a/src/test/java/org/json/junit/data/CustomClass.java b/src/test/java/org/json/junit/data/CustomClass.java
new file mode 100644
index 0000000..9ae4055
--- /dev/null
+++ b/src/test/java/org/json/junit/data/CustomClass.java
@@ -0,0 +1,23 @@
+package org.json.junit.data;
+
+public class CustomClass {
+ public int number;
+ public String name;
+ public Long longNumber;
+
+ public CustomClass() {}
+ public CustomClass (int number, String name, Long longNumber) {
+ this.number = number;
+ this.name = name;
+ this.longNumber = longNumber;
+ }
+ @Override
+ public boolean equals(Object o) {
+ CustomClass customClass = (CustomClass) o;
+
+ return (this.number == customClass.number
+ && this.name.equals(customClass.name)
+ && this.longNumber.equals(customClass.longNumber));
+ }
+}
+
diff --git a/src/test/java/org/json/junit/data/CustomClassA.java b/src/test/java/org/json/junit/data/CustomClassA.java
new file mode 100644
index 0000000..275e9a5
--- /dev/null
+++ b/src/test/java/org/json/junit/data/CustomClassA.java
@@ -0,0 +1,17 @@
+package org.json.junit.data;
+
+public class CustomClassA {
+ public java.time.LocalDateTime localDate;
+
+ public CustomClassA() {}
+ public CustomClassA(java.time.LocalDateTime localDate) {
+ this.localDate = localDate;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ CustomClassA classA = (CustomClassA) o;
+ return this.localDate.equals(classA.localDate);
+ }
+}
+
diff --git a/src/test/java/org/json/junit/data/CustomClassB.java b/src/test/java/org/json/junit/data/CustomClassB.java
new file mode 100644
index 0000000..688997e
--- /dev/null
+++ b/src/test/java/org/json/junit/data/CustomClassB.java
@@ -0,0 +1,20 @@
+package org.json.junit.data;
+
+public class CustomClassB {
+ public int number;
+ public CustomClassC classC;
+
+ public CustomClassB() {}
+ public CustomClassB(int number, CustomClassC classC) {
+ this.number = number;
+ this.classC = classC;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ CustomClassB classB = (CustomClassB) o;
+ return this.number == classB.number
+ && this.classC.equals(classB.classC);
+ }
+}
+
diff --git a/src/test/java/org/json/junit/data/CustomClassC.java b/src/test/java/org/json/junit/data/CustomClassC.java
new file mode 100644
index 0000000..9d20aa3
--- /dev/null
+++ b/src/test/java/org/json/junit/data/CustomClassC.java
@@ -0,0 +1,34 @@
+package org.json.junit.data;
+
+import org.json.JSONObject;
+
+public class CustomClassC {
+ public String stringName;
+ public Long longNumber;
+
+ public CustomClassC() {}
+ public CustomClassC(String stringName, Long longNumber) {
+ this.stringName = stringName;
+ this.longNumber = longNumber;
+ }
+
+ public JSONObject toJSON() {
+ JSONObject object = new JSONObject();
+ object.put("stringName", this.stringName);
+ object.put("longNumber", this.longNumber);
+ return object;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ CustomClassC classC = (CustomClassC) o;
+ return this.stringName.equals(classC.stringName)
+ && this.longNumber.equals(classC.longNumber);
+ }
+
+ @Override
+ public int hashCode() {
+ return java.util.Objects.hash(stringName, longNumber);
+ }
+}
+
diff --git a/src/test/java/org/json/junit/data/CustomClassD.java b/src/test/java/org/json/junit/data/CustomClassD.java
new file mode 100644
index 0000000..4a85805
--- /dev/null
+++ b/src/test/java/org/json/junit/data/CustomClassD.java
@@ -0,0 +1,19 @@
+package org.json.junit.data;
+
+import java.util.List;
+
+public class CustomClassD {
+ public List stringList;
+
+ public CustomClassD() {}
+ public CustomClassD(List stringList) {
+ this.stringList = stringList;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ CustomClassD classD = (CustomClassD) o;
+ return this.stringList.equals(classD.stringList);
+ }
+}
+
diff --git a/src/test/java/org/json/junit/data/CustomClassE.java b/src/test/java/org/json/junit/data/CustomClassE.java
new file mode 100644
index 0000000..807dc55
--- /dev/null
+++ b/src/test/java/org/json/junit/data/CustomClassE.java
@@ -0,0 +1,18 @@
+package org.json.junit.data;
+
+import java.util.List;
+
+public class CustomClassE {
+ public List listClassC;
+
+ public CustomClassE() {}
+ public CustomClassE(List listClassC) {
+ this.listClassC = listClassC;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ CustomClassE classE = (CustomClassE) o;
+ return this.listClassC.equals(classE.listClassC);
+ }
+}
diff --git a/src/test/java/org/json/junit/data/CustomClassF.java b/src/test/java/org/json/junit/data/CustomClassF.java
new file mode 100644
index 0000000..d858610
--- /dev/null
+++ b/src/test/java/org/json/junit/data/CustomClassF.java
@@ -0,0 +1,19 @@
+package org.json.junit.data;
+
+import java.util.List;
+
+public class CustomClassF {
+ public List> listOfString;
+
+ public CustomClassF() {}
+ public CustomClassF(List> listOfString) {
+ this.listOfString = listOfString;
+ }
+
+ @Override
+ public boolean equals(Object o) {
+ CustomClassF classF = (CustomClassF) o;
+ return this.listOfString.equals(classF.listOfString);
+ }
+}
+
diff --git a/src/test/java/org/json/junit/data/CustomClassG.java b/src/test/java/org/json/junit/data/CustomClassG.java
new file mode 100644
index 0000000..c8c9f57
--- /dev/null
+++ b/src/test/java/org/json/junit/data/CustomClassG.java
@@ -0,0 +1,18 @@
+package org.json.junit.data;
+
+import java.util.Map;
+
+public class CustomClassG {
+ public Map dataList;
+
+ public CustomClassG () {}
+ public CustomClassG (Map dataList) {
+ this.dataList = dataList;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ CustomClassG classG = (CustomClassG) object;
+ return this.dataList.equals(classG.dataList);
+ }
+}
diff --git a/src/test/java/org/json/junit/data/CustomClassH.java b/src/test/java/org/json/junit/data/CustomClassH.java
new file mode 100644
index 0000000..ce9b1af
--- /dev/null
+++ b/src/test/java/org/json/junit/data/CustomClassH.java
@@ -0,0 +1,22 @@
+package org.json.junit.data;
+
+import java.util.Map;
+import java.util.List;
+import java.util.ArrayList;
+
+public class CustomClassH {
+ public Map> integerMap;
+
+ public CustomClassH() {}
+ public CustomClassH(Map> integerMap) {
+ this.integerMap = integerMap;
+ }
+
+ @Override
+ public boolean equals(Object object) {
+ CustomClassH classH = (CustomClassH) object;
+ return this.integerMap.size() == classH.integerMap.size()
+ && this.integerMap.keySet().equals(classH.integerMap.keySet())
+ && new ArrayList<>(this.integerMap.values()).equals(new ArrayList<>(classH.integerMap.values()));
+ }
+}
diff --git a/src/test/java/org/json/junit/data/CustomClassI.java b/src/test/java/org/json/junit/data/CustomClassI.java
new file mode 100644
index 0000000..bd7c4ed
--- /dev/null
+++ b/src/test/java/org/json/junit/data/CustomClassI.java
@@ -0,0 +1,12 @@
+package org.json.junit.data;
+
+import java.util.Map;
+
+public class CustomClassI {
+ public Map> integerMap;
+
+ public CustomClassI() {}
+ public CustomClassI(Map> integerMap) {
+ this.integerMap = integerMap;
+ }
+}