diff --git a/pom.xml b/pom.xml index e4a3503e4f9840ba6029b7ad6c466858c5f3c7c6..a5cfa3bfdbf71c157e1b03137e1011e1707c8521 100644 --- a/pom.xml +++ b/pom.xml @@ -1,7 +1,7 @@ 4.0.0 - org.json + name.cathyzhou json 20220320 bundle @@ -32,9 +32,9 @@ - https://github.com/douglascrockford/JSON-java.git - scm:git:git://github.com/douglascrockford/JSON-java.git - scm:git:git@github.com:douglascrockford/JSON-java.git + https://github.com/Aegaina/JSON-java.git + scm:git:git://github.com/Aegaina/JSON-java.git + scm:git:git@github.com:Aegaina/JSON-java.git @@ -98,6 +98,35 @@ + + + + + org.apache.maven.plugins + maven-resources-plugin + 3.3.0 + + + + org.apache.maven.plugins + maven-surefire-plugin + 3.0.0-M7 + + + + org.apache.maven.plugins + maven-install-plugin + 3.0.1 + + + + org.apache.maven.plugins + maven-deploy-plugin + 3.0.0 + + + + org.apache.felix @@ -151,7 +180,7 @@ - + org.apache.maven.plugins maven-jar-plugin @@ -190,4 +219,11 @@ - + + + + github + https://maven.pkg.github.com/Aegaina/JSON-java + + + \ No newline at end of file diff --git a/src/main/java/org/json/DefaultMapFactory.java b/src/main/java/org/json/DefaultMapFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..cb0e9e1e4ad7936a3c5eac8428542ebcfc5e903d --- /dev/null +++ b/src/main/java/org/json/DefaultMapFactory.java @@ -0,0 +1,45 @@ +package org.json; + +import java.util.HashMap; +import java.util.Map; + +/** + * The default implementation of MapFactory + * + * @author Cathy Zhou + */ +class DefaultMapFactory implements MapFactory { + private DefaultMapFactory() { + } + + /** + * Create an instance of Map + */ + @Override + public Map createMap() { + return new HashMap(); + } + + /** + * Create an instance of Map + * + * @param initialCapacity the initial capacity. + */ + @Override + public Map createMap(int initialCapacity) { + return new HashMap(initialCapacity); + } + + //region static + + private static final DefaultMapFactory instance = new DefaultMapFactory(); + + /** + * Get the instance + */ + public static DefaultMapFactory getInstance() { + return instance; + } + + //endregion +} \ No newline at end of file diff --git a/src/main/java/org/json/JSONObject.java b/src/main/java/org/json/JSONObject.java index ea549e3f7afd5a1768ad8ed0a47fba7c87700e59..4c7157dc84019ed7bd0972473a1a919944b78c89 100644 --- a/src/main/java/org/json/JSONObject.java +++ b/src/main/java/org/json/JSONObject.java @@ -174,6 +174,8 @@ public class JSONObject { */ public static final Object NULL = new Null(); + //region Constructors + /** * Construct an empty JSONObject. */ @@ -184,7 +186,7 @@ public class JSONObject { // implementations to rearrange their items for a faster element // retrieval based on associative access. // Therefore, an implementation mustn't rely on the order of the item. - this.map = new HashMap(); + this.map = getMapFactory().createMap(); } /** @@ -296,9 +298,9 @@ public class JSONObject { */ public JSONObject(Map m) { if (m == null) { - this.map = new HashMap(); + this.map = getMapFactory().createMap(); } else { - this.map = new HashMap(m.size()); + this.map = getMapFactory().createMap(m.size()); for (final Entry e : m.entrySet()) { if(e.getKey() == null) { throw new NullPointerException("Null key."); @@ -471,8 +473,17 @@ public class JSONObject { * * @param initialCapacity initial capacity of the internal map. */ - protected JSONObject(int initialCapacity){ - this.map = new HashMap(initialCapacity); + protected JSONObject(int initialCapacity) { + this.map = getMapFactory().createMap(initialCapacity); + } + + //endregion + + /** + * Returns the factory used to create the map + */ + protected MapFactory getMapFactory() { + return DefaultMapFactory.getInstance(); } /** diff --git a/src/main/java/org/json/MapFactory.java b/src/main/java/org/json/MapFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..7bcdacd59b69604ca19e0cf619e42b316eacfe94 --- /dev/null +++ b/src/main/java/org/json/MapFactory.java @@ -0,0 +1,22 @@ +package org.json; + +import java.util.Map; + +/** + * Define a set of methods to create an instance of Map + * + * @author Cathy Zhou + */ +public interface MapFactory { + /** + * Create an instance of Map + */ + Map createMap(); + + /** + * Create an instance of Map + * + * @param initialCapacity the initial capacity. + */ + Map createMap(int initialCapacity); +} \ No newline at end of file diff --git a/src/main/java/org/json/OrderedJSONObject.java b/src/main/java/org/json/OrderedJSONObject.java new file mode 100644 index 0000000000000000000000000000000000000000..7a053460816eb2bee54725e6c054d1fbd6835f69 --- /dev/null +++ b/src/main/java/org/json/OrderedJSONObject.java @@ -0,0 +1,174 @@ +package org.json; + +import java.util.Locale; +import java.util.Map; + +/** + * An extended JSONObject which keeps the insertion order + */ +public class OrderedJSONObject extends JSONObject { + //region Constructors + + /** + * Construct an empty JSONObject. + */ + public OrderedJSONObject() { + } + + /** + * 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 + * are ignored. + * + * @param jo A JSONObject. + * @param names An array of strings. + */ + public OrderedJSONObject(JSONObject jo, String... names) { + super(jo, names); + } + + /** + * Construct a JSONObject from a JSONTokener. + * + * @param x A JSONTokener object containing the source string. + * @throws JSONException If there is a syntax error in the source string or a + * duplicated key. + */ + public OrderedJSONObject(JSONTokener x) throws JSONException { + super(x); + } + + /** + * Construct a JSONObject from a Map. + * + * @param m A map object that can be used to initialize the contents of + * the JSONObject. + * @throws JSONException If a value in the map is non-finite number. + * @throws NullPointerException If a key in the map is null + */ + public OrderedJSONObject(Map m) { + super(m); + } + + /** + * Construct a JSONObject from an Object using bean getters. It reflects on + * all of the public methods of the object. For each of the methods with no + * parameters and a name starting with "get" or + * "is" followed by an uppercase letter, the method is invoked, + * and a key and the value returned from the getter method are put into the + * new JSONObject. + *

+ * The key is formed by removing the "get" or "is" + * prefix. If the second remaining character is not upper case, then the + * first character is converted to lower case. + *

+ * Methods that are static, return void, + * have parameters, or are "bridge" methods, are ignored. + *

+ * For example, if an object has a method named "getName", and + * if the result of calling object.getName() is + * "Larry Fine", then the JSONObject will contain + * "name": "Larry Fine". + *

+ * The {@link JSONPropertyName} annotation can be used on a bean getter to + * override key name used in the JSONObject. For example, using the object + * above with the getName method, if we annotated it with: + *

+     * @JSONPropertyName("FullName")
+     * public String getName() { return this.name; }
+     * 
+ * The resulting JSON object would contain "FullName": "Larry Fine" + *

+ * Similarly, the {@link JSONPropertyName} annotation can be used on non- + * get and is methods. We can also override key + * name used in the JSONObject as seen below even though the field would normally + * be ignored: + *

+     * @JSONPropertyName("FullName")
+     * public String fullName() { return this.name; }
+     * 
+ * The resulting JSON object would contain "FullName": "Larry Fine" + *

+ * The {@link JSONPropertyIgnore} annotation can be used to force the bean property + * to not be serialized into JSON. If both {@link JSONPropertyIgnore} and + * {@link JSONPropertyName} are defined on the same method, a depth comparison is + * performed and the one closest to the concrete class being serialized is used. + * If both annotations are at the same level, then the {@link JSONPropertyIgnore} + * annotation takes precedent and the field is not serialized. + * For example, the following declaration would prevent the getName + * method from being serialized: + *

+     * @JSONPropertyName("FullName")
+     * @JSONPropertyIgnore
+     * public String getName() { return this.name; }
+     * 
+ *

+ * + * @param bean An object that has getter methods that should be used to make + * a JSONObject. + */ + public OrderedJSONObject(Object bean) { + super(bean); + } + + /** + * Construct a JSONObject from an Object, using reflection to find the + * public members. The resulting JSONObject's keys will be the strings from + * the names array, and the values will be the field values associated with + * those keys in the object. If a key is not found or not visible, then it + * will not be copied into the new JSONObject. + * + * @param object An object that has fields that should be used to make a + * JSONObject. + * @param names An array of strings, the names of the fields to be obtained + */ + public OrderedJSONObject(Object object, String... names) { + super(object, names); + } + + /** + * Construct a JSONObject from a source JSON text string. This is the most + * commonly used JSONObject constructor. + * + * @param source A string beginning with { (left + * brace) and ending with } + *  (right brace). + * @throws JSONException If there is a syntax error in the source string or a + * duplicated key. + */ + public OrderedJSONObject(String source) throws JSONException { + super(source); + } + + /** + * Construct a JSONObject from a ResourceBundle. + * + * @param baseName The ResourceBundle base name. + * @param locale The Locale to load the ResourceBundle for. + * @throws JSONException If any JSONExceptions are detected. + */ + public OrderedJSONObject(String baseName, Locale locale) throws JSONException { + super(baseName, locale); + } + + /** + * Constructor to specify an initial capacity of the internal map. Useful for library + * internal calls where we know, or at least can best guess, how big this JSONObject + * will be. + * + * @param initialCapacity initial capacity of the internal map. + */ + protected OrderedJSONObject(int initialCapacity) { + super(initialCapacity); + } + + //endregion + + /** + * Returns the factory used to create the map + */ + @Override + protected MapFactory getMapFactory() { + return OrderedMapFactory.getInstance(); + } +} \ No newline at end of file diff --git a/src/main/java/org/json/OrderedMapFactory.java b/src/main/java/org/json/OrderedMapFactory.java new file mode 100644 index 0000000000000000000000000000000000000000..d7fabf7e79855a960ec513760e4b6d9053973735 --- /dev/null +++ b/src/main/java/org/json/OrderedMapFactory.java @@ -0,0 +1,45 @@ +package org.json; + +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * A MapFactory produces ordered maps + * + * @author Cathy Zhou + */ +public class OrderedMapFactory implements MapFactory { + private OrderedMapFactory() { + } + + /** + * Create an instance of Map + */ + @Override + public Map createMap() { + return new LinkedHashMap(); + } + + /** + * Create an instance of Map + * + * @param initialCapacity the initial capacity. + */ + @Override + public Map createMap(int initialCapacity) { + return new LinkedHashMap(initialCapacity); + } + + //region static + + private static final OrderedMapFactory instance = new OrderedMapFactory(); + + /** + * Get the instance + */ + public static OrderedMapFactory getInstance() { + return instance; + } + + //endregion +}