diff --git a/Examples.md b/Examples.md index 3f45e78..fb010d5 100644 --- a/Examples.md +++ b/Examples.md @@ -1,7 +1,7 @@

Examples

Imports used in the examples:

-``` +```java import java.util.HashMap; import java.util.Map; import java.util.Properties; @@ -14,353 +14,353 @@ import java.util.Properties;

Using JSONArray

-``` - private static void JSONExampleArray1() { - //We create a JSONObject from a String containing an array using JSONArray - //Firstly, we declare an Array in a String - - String arrayStr = - "["+"true,"+"false,"+ "\"true\","+ "\"false\","+"\"hello\","+"23.45e-4,"+ - "\"23.45\","+"42,"+"\"43\","+"["+"\"world\""+"],"+ - "{"+ - "\"key1\":\"value1\","+ - "\"key2\":\"value2\","+ - "\"key3\":\"value3\","+ - "\"key4\":\"value4\""+ - "},"+ - "0,"+"\"-1\""+ - "]"; - - //Then, we initializate the JSONArray thanks to its constructor - - JSONArray array = new JSONArray(arrayStr); - System.out.println("Values array: "+ array); - - //We convert that array into a JSONObject, but first, we need the labels, so we need another JSONArray with the labels. - //Here we will use an auxiliary function to get one for the example. - - JSONArray list = listNumberArray(array.length()); - System.out.println("Label Array: "+ list.toString()); - //Now, we construct the JSONObject using both the value array and the label array. - JSONObject object = array.toJSONObject(list); - System.out.println("Final JSONOBject: " + object); - } +```java +private static void JSONExampleArray1() { + //We create a JSONObject from a String containing an array using JSONArray + //Firstly, we declare an Array in a String + + String arrayStr = + "["+"true,"+"false,"+ "\"true\","+ "\"false\","+"\"hello\","+"23.45e-4,"+ + "\"23.45\","+"42,"+"\"43\","+"["+"\"world\""+"],"+ + "{"+ + "\"key1\":\"value1\","+ + "\"key2\":\"value2\","+ + "\"key3\":\"value3\","+ + "\"key4\":\"value4\""+ + "},"+ + "0,"+"\"-1\""+ + "]"; + + //Then, we initializate the JSONArray thanks to its constructor + + JSONArray array = new JSONArray(arrayStr); + System.out.println("Values array: "+ array); + + //We convert that array into a JSONObject, but first, we need the labels, so we need another JSONArray with the labels. + //Here we will use an auxiliary function to get one for the example. + + JSONArray list = listNumberArray(array.length()); + System.out.println("Label Array: "+ list.toString()); + //Now, we construct the JSONObject using both the value array and the label array. + JSONObject object = array.toJSONObject(list); + System.out.println("Final JSONOBject: " + object); +} - //This method creates an JSONArray of labels in which those are generated by their positions +//This method creates an JSONArray of labels in which those are generated by their positions - private static JSONArray listNumberArray(int max){ - JSONArray res = new JSONArray(); - for (int i=0; iUsing JSONStringer -``` - private static void JSONExampleStringer() { +```java +private static void JSONExampleStringer() { - //We initializate the JSONStringer + //We initializate the JSONStringer - JSONStringer jsonStringer = new JSONStringer(); + JSONStringer jsonStringer = new JSONStringer(); - //Now we start the process of adding elements with .object() + //Now we start the process of adding elements with .object() - jsonStringer.object(); + jsonStringer.object(); - //We can now add elements as keys and values with .values () and .key() + //We can now add elements as keys and values with .values () and .key() - jsonStringer.key("trueValue").value(true); - jsonStringer.key("falseValue").value(false); - jsonStringer.key("nullValue").value(null); - jsonStringer.key("stringValue").value("hello world!"); - jsonStringer.key("complexStringValue").value("h\be\tllo w\u1234orld!"); - jsonStringer.key("intValue").value(42); - jsonStringer.key("doubleValue").value(-23.45e67); + jsonStringer.key("trueValue").value(true); + jsonStringer.key("falseValue").value(false); + jsonStringer.key("nullValue").value(null); + jsonStringer.key("stringValue").value("hello world!"); + jsonStringer.key("complexStringValue").value("h\be\tllo w\u1234orld!"); + jsonStringer.key("intValue").value(42); + jsonStringer.key("doubleValue").value(-23.45e67); - //We end this prcedure with .ednObject + //We end this prcedure with .ednObject - jsonStringer.endObject(); + jsonStringer.endObject(); - //Once we have a JSONStringer, we convert it to JSONObject generating a String and using JSONObject's contructor. + //Once we have a JSONStringer, we convert it to JSONObject generating a String and using JSONObject's contructor. - String str = jsonStringer.toString(); - JSONObject jsonObject = new JSONObject(str); - - System.out.println("Final JSONOBject: " + jsonObject); - } + String str = jsonStringer.toString(); + JSONObject jsonObject = new JSONObject(str); + + System.out.println("Final JSONOBject: " + jsonObject); +} ```

Using JSONObject

-``` - private static void JSONExampleObject1() { +```java +private static void JSONExampleObject1() { - //We can create a JSONObject from a String with the class builder + //We can create a JSONObject from a String with the class builder - String string = "{\"0\":\"value\",\"1\":5,\"2\":-2.345E68,\"3\":true}"; - JSONObject example = new JSONObject(string); - System.out.println("Final JSONObject: " + example); - - } -``` + String string = "{\"0\":\"value\",\"1\":5,\"2\":-2.345E68,\"3\":true}"; + JSONObject example = new JSONObject(string); + System.out.println("Final JSONObject: " + example); + +} ``` - private static void JSONExampleObject2() { +```java +private static void JSONExampleObject2() { - //We can also create a JSONObject directly without messing around with any of the other functions. + //We can also create a JSONObject directly without messing around with any of the other functions. - JSONObject example = new JSONObject(); + JSONObject example = new JSONObject(); - //Now we add the keys and values in a similar way as the Stringer method - example.put("key", "value"); + //Now we add the keys and values in a similar way as the Stringer method + example.put("key", "value"); - //As you can see, the first entry is the key and the second would be its associeted value. + //As you can see, the first entry is the key and the second would be its associeted value. - example.put("key2", 5); - example.put("key3", -23.45e67); - example.put("trueValue", true); + example.put("key2", 5); + example.put("key3", -23.45e67); + example.put("trueValue", true); - //We can't add null values thougth + //We can't add null values thougth - //example.put("nullValue", null); //This is not possible - - System.out.println("Final JSONOBject: " + example); - } -``` + //example.put("nullValue", null); //This is not possible + + System.out.println("Final JSONOBject: " + example); +} ``` - private static void JSONExampleObject3() { +```java +private static void JSONExampleObject3() { - //We can also create a JSONObject with a Java Map - //YoU will need a Map whose keys are Strings. The values can be whatever you want + //We can also create a JSONObject with a Java Map + //YoU will need a Map whose keys are Strings. The values can be whatever you want - Map map = new HashMap(); - - map.put("key1", 1.0); - map.put("key2", -23.45e67); - - //We create the JSONObject with the map with its class builder + Map map = new HashMap(); - JSONObject example = new JSONObject(map); - System.out.println("Final JSONOBject: " + example); - } + map.put("key1", 1.0); + map.put("key2", -23.45e67); + + //We create the JSONObject with the map with its class builder + + JSONObject example = new JSONObject(map); + System.out.println("Final JSONOBject: " + example); +} ```

Using JSONWriter

-``` - private static void JSONExamplWriter() { - - //This method works in a very similar way to Object and Stringer in the construction of the JSON. - //The difference is that it needs a Java object called "Appendable" like StringBuilder - - StringBuilder write = new StringBuilder(); - JSONWriter jsonWriter = new JSONWriter(write); - - //We behave now the same way as Stringer - - jsonWriter.object(); - - jsonWriter.key("trueValue").value(true); - jsonWriter.key("falseValue").value(false); - jsonWriter.key("nullValue").value(null); - jsonWriter.key("stringValue").value("hello world!"); - jsonWriter.key("complexStringValue").value("h\be\tllo w\u1234orld!"); - jsonWriter.key("intValue").value(42); - jsonWriter.key("doubleValue").value(-23.45e67); - - jsonWriter.endObject(); - - //The resoult should be in the "write" object - - System.out.println("JSON: " + write.toString()); - - //The difference is that we don't get a JSONObject in this one. - - - } +```java +private static void JSONExamplWriter() { + + //This method works in a very similar way to Object and Stringer in the construction of the JSON. + //The difference is that it needs a Java object called "Appendable" like StringBuilder + + StringBuilder write = new StringBuilder(); + JSONWriter jsonWriter = new JSONWriter(write); + + //We behave now the same way as Stringer + + jsonWriter.object(); + + jsonWriter.key("trueValue").value(true); + jsonWriter.key("falseValue").value(false); + jsonWriter.key("nullValue").value(null); + jsonWriter.key("stringValue").value("hello world!"); + jsonWriter.key("complexStringValue").value("h\be\tllo w\u1234orld!"); + jsonWriter.key("intValue").value(42); + jsonWriter.key("doubleValue").value(-23.45e67); + + jsonWriter.endObject(); + + //The resoult should be in the "write" object + + System.out.println("JSON: " + write.toString()); + + //The difference is that we don't get a JSONObject in this one. + + +} ``` -``` - private static void JSONExampleTokener() { +```java +private static void JSONExampleTokener() { - //A partir de una String podemos crear un JSONTokener, que lo podemos usar alternativamente para JSONArray,JSONObject + //A partir de una String podemos crear un JSONTokener, que lo podemos usar alternativamente para JSONArray,JSONObject - String string = "this is not a valid JSON string"; - JSONTokener token = new JSONTokener(string); - - //Now you can use the token in JSONObject and Array the same way as a String + String string = "this is not a valid JSON string"; + JSONTokener token = new JSONTokener(string); - JSONObject object = new JSONObject(token); - JSONArray array = new JSONArray(token); - - } + //Now you can use the token in JSONObject and Array the same way as a String + + JSONObject object = new JSONObject(token); + JSONArray array = new JSONArray(token); + +} ```

Part 2: Conversion methods

-

We don't need to have a JSON docuemnt to work. This project also admits conversions from other type of files.

+

We don't need to have a JSON document to work. This project also admits conversions from other type of files.

Secondly, we can also convert from JSON to those type of files.

Extra: Conversion to JSONArray

-``` - private static void JSONObjectToArray() { - //We start with a JSONObject - - String string = "{\"0\":\"value\",\"1\":5,\"2\":-2.345E68,\"3\":true}"; - - JSONObject example = new JSONObject(string); - - //We need a list of key strings like the reverse operation - - JSONArray keyStrings = listNumberArray(example.length()); - - //Then we convert to the Array using both elelements - - JSONArray array = example.toJSONArray(keyStrings); - - System.out.println("Final JSONArray: " + array); - } +```java +private static void JSONObjectToArray() { + //We start with a JSONObject + + String string = "{\"0\":\"value\",\"1\":5,\"2\":-2.345E68,\"3\":true}"; + + JSONObject example = new JSONObject(string); + + //We need a list of key strings like the reverse operation + + JSONArray keyStrings = listNumberArray(example.length()); + + //Then we convert to the Array using both elelements + + JSONArray array = example.toJSONArray(keyStrings); + + System.out.println("Final JSONArray: " + array); +} ```

XML Conversions

-``` - private static void XMLToExampleConversion() { +```java +private static void XMLToExampleConversion() { + + //We start with a JSONObject - //We start with a JSONObject - - String string = "{\"0\":\"value\",\"1\":5,\"2\":-2.345E68,\"3\":true}"; - JSONObject example = new JSONObject(string); + String string = "{\"0\":\"value\",\"1\":5,\"2\":-2.345E68,\"3\":true}"; + JSONObject example = new JSONObject(string); - //We obtain a String with XML format with toString() + //We obtain a String with XML format with toString() - String output = XML.toString(example); - System.out.println("Final XML: " + output); - } + String output = XML.toString(example); + System.out.println("Final XML: " + output); +} ``` -``` - private static void XMLFromExampleConversion() { +```java +private static void XMLFromExampleConversion() { - //We start with a string with the XML format + //We start with a string with the XML format - String string = "<0>value<1>5<2>-2.345E+68<3>true"; + String string = "<0>value<1>5<2>-2.345E+68<3>true"; - //We obtain a JSONObject with toJSONOBject() + //We obtain a JSONObject with toJSONOBject() - JSONObject output = XML.toJSONObject(string); - - System.out.println("Final JSONObject: " + output); - } + JSONObject output = XML.toJSONObject(string); + + System.out.println("Final JSONObject: " + output); +} ```

Cookie Conversions

-``` - private static void CookieToExampleConversion() { +```java +private static void CookieToExampleConversion() { - //We start with a JSONObject - //The JSONOBject needs to entries that gives the cookie a name and gives the field "name" a name too. - //The Cokkie format doesn't support booleans + //We start with a JSONObject + //The JSONOBject needs to entries that gives the cookie a name and gives the field "name" a name too. + //The Cokkie format doesn't support booleans - String string = "{\"name\":\"Cookie-Name\",\"value\":\"name\",\"1\":5,\"2\":-2.345E68,\"3\":'true'}"; - JSONObject example = new JSONObject(string); - - //We obtain a String with Cookie format with toString() + String string = "{\"name\":\"Cookie-Name\",\"value\":\"name\",\"1\":5,\"2\":-2.345E68,\"3\":'true'}"; + JSONObject example = new JSONObject(string); - String output = Cookie.toString(example); - System.out.println("Final Cookie: " + output); - } -``` + //We obtain a String with Cookie format with toString() + + String output = Cookie.toString(example); + System.out.println("Final Cookie: " + output); +} ``` - private static void CookieFromExampleConversion() { +```java +private static void CookieFromExampleConversion() { - //We start with a string with the Cookie format + //We start with a string with the Cookie format - String string = "Cookie-Name=name;1=5;2=-2.345E%2b68;3=true"; + String string = "Cookie-Name=name;1=5;2=-2.345E%2b68;3=true"; - //We obtain a JSONObject with toJSONOBject() + //We obtain a JSONObject with toJSONOBject() - JSONObject output = Cookie.toJSONObject(string); - System.out.println("Final JSONObject: " + output); - } + JSONObject output = Cookie.toJSONObject(string); + System.out.println("Final JSONObject: " + output); +} ```

HTTP Conversions

-``` - private static void HTTPToExampleConversion() { +```java +private static void HTTPToExampleConversion() { - //We start with a JSONObject - //The JSONObject must have the minimun header for a HTTP request or header + //We start with a JSONObject + //The JSONObject must have the minimun header for a HTTP request or header - String string = "{\"Method\":\"POST\",\"Request-URI\":'/',\"HTTP-Version\":'HTTP/1.1',\"Value1\":true,\"Value2\":2,\"Value3\":-2.345E68}"; + String string = "{\"Method\":\"POST\",\"Request-URI\":'/',\"HTTP-Version\":'HTTP/1.1',\"Value1\":true,\"Value2\":2,\"Value3\":-2.345E68}"; - JSONObject example = new JSONObject(string); + JSONObject example = new JSONObject(string); - //We obtain a String with HTTP format with toString() + //We obtain a String with HTTP format with toString() - String output = HTTP.toString(example); - System.out.println("Final HTTP: " + output); - } + String output = HTTP.toString(example); + System.out.println("Final HTTP: " + output); +} ``` -``` - private static void HTTPFromExampleConversion() { +```java +private static void HTTPFromExampleConversion() { - //We start with a string with the HTTP format + //We start with a string with the HTTP format - String string = "Final HTTP: POST '/' HTTP/1.1 Value3: -2.345E+68 Value1: true Value2: 2"; + String string = "Final HTTP: POST '/' HTTP/1.1 Value3: -2.345E+68 Value1: true Value2: 2"; - //We obtain a JSONObject with toJSONOBject() + //We obtain a JSONObject with toJSONOBject() - JSONObject output = HTTP.toJSONObject(string); - System.out.println("Final JSONObject: " + output); - } + JSONObject output = HTTP.toJSONObject(string); + System.out.println("Final JSONObject: " + output); +} ```

CDL Conversions

-``` +```java private static void CDLToExampleConversion() { - //We start with some JSONObjects with the same values in the keys but different values in the "values" + //We start with some JSONObjects with the same values in the keys but different values in the "values" - String string = "{\"0\":\"value\",\"1\":5,\"2\":-2.345E68,\"3\":true}"; - JSONObject example = new JSONObject(string); - - String string2 = "{\"0\":\"value2\",\"1\":6,\"2\":-8.345E68,\"3\":false}"; - JSONObject example2 = new JSONObject(string2); - - //We need now a JSONArray with those JSONObjects + String string = "{\"0\":\"value\",\"1\":5,\"2\":-2.345E68,\"3\":true}"; + JSONObject example = new JSONObject(string); - JSONArray array = new JSONArray(); - array.put(example); - array.put(example2); + String string2 = "{\"0\":\"value2\",\"1\":6,\"2\":-8.345E68,\"3\":false}"; + JSONObject example2 = new JSONObject(string2); - //We obtain a String with XML format with toString() + //We need now a JSONArray with those JSONObjects - String output = CDL.toString(array); - System.out.println("Final CDL: \r\n" + output); - } -``` + JSONArray array = new JSONArray(); + array.put(example); + array.put(example2); + + //We obtain a String with XML format with toString() + + String output = CDL.toString(array); + System.out.println("Final CDL: \r\n" + output); +} ``` +```java private static void CDLFromExampleConversion() { //We start wtih a String with the CDL format @@ -368,7 +368,7 @@ private static void CDLFromExampleConversion() { String string = "0,1,2,3\n" + "value,5,-2.345E+68,true\n" + "value2,6,-8.345E+68,false"; - + //We obtain a JSONArray with toJSONOBject() JSONArray output = CDL.toJSONArray(string); @@ -377,8 +377,8 @@ private static void CDLFromExampleConversion() { ```

Properties Conversions

-``` - private static Properties PropertyToExampleConversion() { +```java +private static Properties PropertyToExampleConversion() { //We start with a JSONObject @@ -391,43 +391,43 @@ private static void CDLFromExampleConversion() { System.out.println("Final Properties: " + output); return output; - } +} ``` -``` - private static void PropertyFromExampleConversion() { +```java +private static void PropertyFromExampleConversion() { - //We start with a Properties object + //We start with a Properties object - Properties input = PropertyToExampleConversion(); + Properties input = PropertyToExampleConversion(); - //We obtain a JSONObject with toJSONOBject() - - JSONObject output = Property.toJSONObject(input); - System.out.println("Final JSONObject: " + output); - } -``` -

List of all examples methods

+ //We obtain a JSONObject with toJSONOBject() + JSONObject output = Property.toJSONObject(input); + System.out.println("Final JSONObject: " + output); +} ``` - public static void main(String[] args) { - //JSONObjectToArray(); - //JSONExampleArray1(); - //JSONExampleArray2(); - //JSONExampleStringer(); - //JSONExampleObject1(); - //JSONExampleObject2(); - //JSONExampleObject3(); - //JSONExamplWriter(); - //XMLToExampleConversion(); - //XMLFromExampleConversion(); - //CookieToExampleConversion(); - //CookieFromExampleConversion(); - //HTTPToExampleConversion(); - //HTTPFromExampleConversion(); - //CDLToExampleConversion(); - //CDLFromExampleConversion(); - //PropertyToExampleConversion(); - //PropertyFromExampleConversion(); - } +

List of all examples methods

+ +```java +public static void main(String[] args) { + //JSONObjectToArray(); + //JSONExampleArray1(); + //JSONExampleArray2(); + //JSONExampleStringer(); + //JSONExampleObject1(); + //JSONExampleObject2(); + //JSONExampleObject3(); + //JSONExamplWriter(); + //XMLToExampleConversion(); + //XMLFromExampleConversion(); + //CookieToExampleConversion(); + //CookieFromExampleConversion(); + //HTTPToExampleConversion(); + //HTTPFromExampleConversion(); + //CDLToExampleConversion(); + //CDLFromExampleConversion(); + //PropertyToExampleConversion(); + //PropertyFromExampleConversion(); +} ``` diff --git a/LICENSE b/LICENSE index 6cfb9b2..2ef9799 100644 --- a/LICENSE +++ b/LICENSE @@ -1,23 +1,2 @@ - -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. diff --git a/Milestone3_Readme.md b/Milestone3_Readme.md new file mode 100644 index 0000000..daba129 --- /dev/null +++ b/Milestone3_Readme.md @@ -0,0 +1,30 @@ +# Milestone3 + +### Parse() and toJSONObject() methods are added in src/main/java/org.json/XML.java +JSONObject toJSONObject(Reader reader, Function func) [line 741] +* Rewrite toJSONObject() method, inputs are a reader and a lambda function +* Purpose: Add a prefix to all of its keys +* Main method: + * Rewrite Parse() [line 1566]. Compared with original parse(), replace string and tagName variable with keyTransformer.apply(string) and keyTransformer.apply(tagName) + * Call the new Parse() method in toJSONObject(), put reader and func as input + +### Unit Tests are added in src/test/java/org.json.junit/XMLTest.java +We wrote five tests for testing Milestone 3. +
+1. testM3()                        //add "SWE262_" to every keys as prefix
+2. testM3Reverse()                 //reverse the key names
+3. testM3WithEmptyString()         //throws exception: "Invalid: transform key to empty string" 
+4. testM3WithNull()                //throws exception: "Invalid: transform key to null"
+5. testM3WithDuplicateKeyName()    //throws exception: "Invalid: transform key to all the same string"
+
+Run "mvn clean test -Dtest=XMLTest" to test XMLTest.java + +### Performance Comparison + +running time: in-library = 123 ms; +outside = 205 ms +The efficiency increased by 40%. + +![m1](m1_4.png) + +![m3](m3.png) diff --git a/Milestone4_Readme.md b/Milestone4_Readme.md new file mode 100644 index 0000000..36d8916 --- /dev/null +++ b/Milestone4_Readme.md @@ -0,0 +1,34 @@ +# Milestone4 + +### toStream() methods is added in src/main/java/org.json/JSONObject.java at [line 494] + +* toStream() method returns a stream of JSONObjects inside the input JSONObject. It returns the elements in DFS manner. + +For example, the input JSONObject is as follows: +
+{"contact": {
+"nick": "Crista",
+"address": {
+"zipcode": 92614,
+"street": "Ave of Nowhere"
+},
+"name": "Crista Lopes"
+}}
+
+ +The expected output stream should look like this: +
+{"contact":{"nick":"Crista","address":{"zipcode":92614,"street":"Ave of Nowhere"},"name":"Crista Lopes"}}
+{"nick":"Crista"}
+{"address":{"zipcode":92614,"street":"Ave of Nowhere"}}
+{"zipcode":92614}
+{"street":"Ave of Nowhere"}
+{"name":"Crista Lopes"}
+
+ +### Unit Tests are added in src/test/java/org.json.junit/Milestone4Test.java + +`testForEach()` at line 19 ~ 34 +`testFilter()` at line 38 ~ 51 +`testMap()` at line 54 ~ 63 + diff --git a/Milestone5_Readme.md b/Milestone5_Readme.md new file mode 100644 index 0000000..c46f351 --- /dev/null +++ b/Milestone5_Readme.md @@ -0,0 +1,6 @@ +# Milestone5 + +### toJSONObject() method is added in src/main/java/org.json/XML.java +* ```Future toJSONObject(Reader reader, Function keyTransformer, Consumer exceptionHandler)``` method returns a Future which contains the JSONObject info or NUll. + +### Unit Tests are added in src/test/java/org.json.junit/Milestone5Test.java \ No newline at end of file diff --git a/README.md b/README.md index 69869cd..213e16a 100644 --- a/README.md +++ b/README.md @@ -3,12 +3,43 @@ image credit: Ismael Pérez Ortiz +### < Milestone2 > +
+We wrote eight tests for testing Problem1 and Problem2.  
+
+-----Problem 1-----
+1. testM2P1WithNoSlash_1()     //No slash at the end of JSONPointer
+2. testM2P1WithNoSlash_2()     //No slash at the end of JSONPointer
+3. testM2P1WithSlash()         //With slash at the end of JSONPointer (throws exception: "Invalid Path with '/' ending")
+4. testM2P1WrongPath()         //Wrong JSONPointer (throws exception: "Path not found")
+
+-----Problem 2-----
+1. testM2P2WithNoSlash_1()     //No slash at the end of JSONPointer
+2. testM2P2WithNoSlash_2()     //No slash at the end of JSONPointer
+3. testM2P2WithSlash()         //With slash at the end of JSONPointer (throws exception: "Invalid Path with '/' ending")
+4. testM2P2WrongPath()         //Wrong JSONPointer (throws exception: "Path not found")
+
+Run "mvn clean test -Dtest=XMLTest" to test XMLTest.java
+
+ +### < Milestone3 > +
+We wrote four tests for testing Milestone 3.  
+
+1. testM3()                        //add "SWE262_" to every keys as prefix
+2. testM3WithEmptyString()         //throws exception: "Invalid: transform key to empty string" 
+3. testM3WithNull()                //throws exception: "Invalid: transform key to null"
+4. testM3WithDuplicateKeyName()    //throws exception: "Invalid: transform key to all the same string"
+
+Run "mvn clean test -Dtest=XMLTest" to test XMLTest.java
+
+ JSON in Java [package org.json] =============================== [![Maven Central](https://img.shields.io/maven-central/v/org.json/json.svg)](https://mvnrepository.com/artifact/org.json/json) -**[Click here if you just want the latest release jar file.](https://search.maven.org/remotecontent?filepath=org/json/json/20220320/json-20220320.jar)** +**[Click here if you just want the latest release jar file.](https://search.maven.org/remotecontent?filepath=org/json/json/20220924/json-20220924.jar)** # Overview @@ -28,8 +59,6 @@ Project goals include: The files in this package implement JSON encoders and decoders. The package can also convert between JSON and XML, HTTP headers, Cookies, and CDL. -The license includes this restriction: ["The software shall be used for good, not evil."](https://en.wikipedia.org/wiki/Douglas_Crockford#%22Good,_not_Evil%22) If your conscience cannot live with that, then choose a different package. - # If you would like to contribute to this project For more information on contributions, please see [CONTRIBUTING.md](https://github.com/stleary/JSON-java/blob/master/docs/CONTRIBUTING.md) diff --git a/build.gradle b/build.gradle index 63a31a7..a10ee60 100644 --- a/build.gradle +++ b/build.gradle @@ -32,7 +32,7 @@ subprojects { group = 'org.json' version = 'v20211205-SNAPSHOT' description = 'JSON in Java' -sourceCompatibility = '1.7' +sourceCompatibility = "1.8" configurations.all { } @@ -53,3 +53,4 @@ publishing { tasks.withType(JavaCompile) { options.encoding = 'UTF-8' } +targetCompatibility = JavaVersion.VERSION_1_8 diff --git a/docs/RELEASES.md b/docs/RELEASES.md index 149525d..3fbab78 100644 --- a/docs/RELEASES.md +++ b/docs/RELEASES.md @@ -5,6 +5,8 @@ and artifactId "json". For example: [https://search.maven.org/search?q=g:org.json%20AND%20a:json&core=gav](https://search.maven.org/search?q=g:org.json%20AND%20a:json&core=gav) ~~~ +20220924 New License - public domain, and some minor updates + 20220320 Wrap StackOverflow with JSONException 20211205 Recent commits and some bug fixes for similar() @@ -18,6 +20,7 @@ and artifactId "json". For example: 20190722 Recent commits 20180813 POM change to include Automatic-Module-Name (#431) + JSONObject(Map) now throws an exception if any of a map keys are null (#405) 20180130 Recent commits diff --git a/m1_4.png b/m1_4.png new file mode 100644 index 0000000..a1a4f4a Binary files /dev/null and b/m1_4.png differ diff --git a/m3.png b/m3.png new file mode 100644 index 0000000..634a763 Binary files /dev/null and b/m3.png differ diff --git a/pom.xml b/pom.xml index e4a3503..93fed2c 100644 --- a/pom.xml +++ b/pom.xml @@ -3,7 +3,7 @@ org.json json - 20220320 + 20220924 bundle JSON in Java @@ -18,10 +18,6 @@ This is a reference implementation. There is a large number of JSON packages in Java. Perhaps someday the Java community will standardize on one. Until then, choose carefully. - - The license includes this restriction: "The software shall be used for good, - not evil." If your conscience cannot live with that, then choose a different - package. https://github.com/douglascrockford/JSON-java @@ -39,28 +35,9 @@ - The JSON License - http://json.org/license.html + Public Domain + https://github.com/stleary/JSON-java/blob/master/LICENSE repo - Copyright (c) 2002 JSON.org - - Permission is hereby granted, free of charge, to any person obtaining a copy of this software and - associated documentation files (the "Software"), to deal in the Software without restriction, including - without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the - following conditions: - - The above copyright notice and this permission notice shall be included in all copies or substantial - portions of the Software. - - The Software shall be used for Good, not Evil. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT - LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN - NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE - SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - @@ -118,8 +95,8 @@ maven-compiler-plugin 2.3.2 - 1.6 - 1.6 + 1.8 + 1.8 diff --git a/src/main/java/M2Test.java b/src/main/java/M2Test.java new file mode 100644 index 0000000..41dd7b0 --- /dev/null +++ b/src/main/java/M2Test.java @@ -0,0 +1,41 @@ +import java.io.StringReader; + +import org.json.JSONException; +import org.json.JSONPointer; +import org.json.JSONObject; +import org.json.XML; + +public class M2Test { + public static void main(String[] args) { + String xmlString = "\n"+ + "\n"+ + " Crista \n"+ + " Crista Lopes\n" + + "
\n" + + " Ave of Nowhere\n" + + " 92614\n" + + "
\n" + + "
"; + + try { + + JSONObject jobj = XML.toJSONObject(new StringReader(xmlString), new JSONPointer("/contact")); + + System.out.println("res: " + jobj); + + } catch (JSONException e) { + System.out.println(e); + } + + System.out.println("-----------------------"); + + try { + JSONObject replacement = XML.toJSONObject("Ave of the Arts\n"); + System.out.println("Given replacement: " + replacement); + JSONObject jobj = XML.toJSONObject(new StringReader(xmlString), new JSONPointer("/contact/address/street"), replacement); + System.out.println("res: " + jobj); + } catch (JSONException e) { + System.out.println(e); + } + } +} diff --git a/src/main/java/M3.java b/src/main/java/M3.java new file mode 100644 index 0000000..71713f8 --- /dev/null +++ b/src/main/java/M3.java @@ -0,0 +1,60 @@ +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONPointer; +import org.json.XML; + +import java.io.StringReader; +import java.util.function.Function; + +public class M3 { + public static void main(String[] args) { + String xmlString ="\n" + + "\n" + + " \n" + + " Gambardella, Matthew\n" + + " XML Developer's Guide\n" + + " Computer\n" + + " 44.95\n" + + " 2000-10-01\n" + + " An in-depth look at creating applications\n" + + " with XML.\n" + + " \n" + + " \n" + + " Ralls, Kim\n" + + " Midnight Rain\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-12-16\n" + + " A former architect battles corporate zombies,\n" + + " an evil sorceress, and her own childhood to become queen\n" + + " of the world.\n" + + " \n" + + " \n" + + " Corets, Eva\n" + + " Maeve Ascendant\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-11-17\n" + + " After the collapse of a nanotechnology\n" + + " society in England, the young survivors lay the\n" + + " foundation for a new society.\n" + + " \n" + + ""; + + try { + + JSONObject jobj = XML.toJSONObject(new StringReader(xmlString), s -> { + StringBuilder builder = new StringBuilder(s); + builder.reverse(); + return builder.toString(); + }); + + //JSONObject jobj = XML.toJSONObject(new StringReader(xmlString), s -> "swe262p_" + s); + System.out.println("all keys: " + jobj.keySet()); + System.out.println("res: " + jobj); + + } catch (JSONException e) { + System.out.println(e); + } + } +} diff --git a/src/main/java/M4.java b/src/main/java/M4.java new file mode 100644 index 0000000..533850c --- /dev/null +++ b/src/main/java/M4.java @@ -0,0 +1,120 @@ +import org.json.JSONException; +import org.json.JSONObject; +import org.json.JSONPointer; +import org.json.XML; + +import java.io.StringReader; +import java.util.List; +import java.util.Set; +import java.util.function.Function; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public class M4 { + public static void main(String[] args) { + String xmlString ="\n" + + "\n" + + " \n" + + " Gambardella, Matthew\n" + + " XML Developer's Guide\n" + + " Computer\n" + + " 44.95\n" + + " 2000-10-01\n" + + " An in-depth look at creating applications\n" + + " with XML.\n" + + " \n" + + " \n" + + " Ralls, Kim\n" + + " Midnight Rain\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-12-16\n" + + " A former architect battles corporate zombies,\n" + + " an evil sorceress, and her own childhood to become queen\n" + + " of the world.\n" + + " \n" + + " \n" + + " Corets, Eva\n" + + " Maeve Ascendant\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-11-17\n" + + " After the collapse of a nanotechnology\n" + + " society in England, the young survivors lay the\n" + + " foundation for a new society.\n" + + " \n" + + ""; + + String xmlString2 = "\n" + + "\n" + + " Crista \n" + + " Crista Lopes\n" + + "
\n" + + " Ave of Nowhere\n" + + " 92614\n" + + "
\n" + + "
"; + + String xmlString3 = "\n" + + "\n" + + "\n" + + " Crista \n" + + " Crista Lopes\n" + + "
\n" + + " Ave of Nowhere\n" + + " 92614\n" + + "
\n" + + "
" + + "\n" + + " Eric \n" + + " Eric\n" + + "
\n" + + " Verano\n" + + " 92617\n" + + "
\n" + + "
" + + "
"; + + String xmlString4 = "AAAASmithBBBBSmith"; + + String xml1 = "\n" + + "92617\n"; + + + JSONObject[] xmlArray = { + XML.toJSONObject(xml1), + }; + + try { + + JSONObject obj = XML.toJSONObject(xmlString2); + Stream stream = obj.toStream(); + + //System.out.println(obj); + List l = stream.collect(Collectors.toList()); + int i = 0; + for (JSONObject node : l) { + //System.out.println(i); + System.out.println(node.toString()); + i++; + } + + //stream.filter(node -> node.has("zipcode")).forEach(node -> System.out.println(node)); + //System.out.println(xmlArray[0].toString()); + //System.out.println(stream.filter(node -> node.has("zipcode")).count()); + /*List l2 = stream.filter(node -> node.has("zipcode")).collect(Collectors.toList()); + for (JSONObject j : l2) { + System.out.println(j.toString()); + }*/ + + /*System.out.println(obj.keySet()); + List> l3 = stream.map(node -> node.keySet()).collect(Collectors.toList()); + for (Set s : l3) { + System.out.println(s.toString());; + }*/ + + } catch (JSONException e) { + System.out.println(e); + } + } +} diff --git a/src/main/java/org/json/CDL.java b/src/main/java/org/json/CDL.java index f12cfc0..848831d 100644 --- a/src/main/java/org/json/CDL.java +++ b/src/main/java/org/json/CDL.java @@ -1,27 +1,7 @@ package org.json; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ /** diff --git a/src/main/java/org/json/Cookie.java b/src/main/java/org/json/Cookie.java index 1c5fb78..7a7e028 100644 --- a/src/main/java/org/json/Cookie.java +++ b/src/main/java/org/json/Cookie.java @@ -3,27 +3,7 @@ import java.util.Locale; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ /** diff --git a/src/main/java/org/json/CookieList.java b/src/main/java/org/json/CookieList.java index 83b2630..8ad8b58 100644 --- a/src/main/java/org/json/CookieList.java +++ b/src/main/java/org/json/CookieList.java @@ -1,27 +1,7 @@ package org.json; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ /** diff --git a/src/main/java/org/json/HTTP.java b/src/main/java/org/json/HTTP.java index cc01167..6fee6ba 100644 --- a/src/main/java/org/json/HTTP.java +++ b/src/main/java/org/json/HTTP.java @@ -1,27 +1,7 @@ package org.json; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import java.util.Locale; diff --git a/src/main/java/org/json/HTTPTokener.java b/src/main/java/org/json/HTTPTokener.java index 16c7081..48cad31 100644 --- a/src/main/java/org/json/HTTPTokener.java +++ b/src/main/java/org/json/HTTPTokener.java @@ -1,27 +1,7 @@ package org.json; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ /** diff --git a/src/main/java/org/json/JSONArray.java b/src/main/java/org/json/JSONArray.java index 2b33e1d..3be3e14 100644 --- a/src/main/java/org/json/JSONArray.java +++ b/src/main/java/org/json/JSONArray.java @@ -1,27 +1,7 @@ package org.json; /* - Copyright (c) 2002 JSON.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - The Software shall be used for Good, not Evil. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. +Public Domain. */ import java.io.IOException; @@ -1386,6 +1366,10 @@ public boolean similar(Object other) { if (!JSONObject.isNumberSimilar((Number)valueThis, (Number)valueOther)) { return false; } + } else if (valueThis instanceof JSONString && valueOther instanceof JSONString) { + if (!((JSONString) valueThis).toJSONString().equals(((JSONString) valueOther).toJSONString())) { + return false; + } } else if (!valueThis.equals(valueOther)) { return false; } diff --git a/src/main/java/org/json/JSONException.java b/src/main/java/org/json/JSONException.java index ab7ff77..02c29f3 100644 --- a/src/main/java/org/json/JSONException.java +++ b/src/main/java/org/json/JSONException.java @@ -1,27 +1,7 @@ package org.json; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ /** diff --git a/src/main/java/org/json/JSONML.java b/src/main/java/org/json/JSONML.java index aafdf72..2f9b840 100644 --- a/src/main/java/org/json/JSONML.java +++ b/src/main/java/org/json/JSONML.java @@ -1,27 +1,7 @@ package org.json; /* -Copyright (c) 2008 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ /** diff --git a/src/main/java/org/json/JSONObject.java b/src/main/java/org/json/JSONObject.java index 782f8a4..0912117 100644 --- a/src/main/java/org/json/JSONObject.java +++ b/src/main/java/org/json/JSONObject.java @@ -1,31 +1,10 @@ package org.json; -import java.io.Closeable; - /* - Copyright (c) 2002 JSON.org - - Permission is hereby granted, free of charge, to any person obtaining a copy - of this software and associated documentation files (the "Software"), to deal - in the Software without restriction, including without limitation the rights - to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - copies of the Software, and to permit persons to whom the Software is - furnished to do so, subject to the following conditions: - - The above copyright notice and this permission notice shall be included in all - copies or substantial portions of the Software. - - The Software shall be used for Good, not Evil. - - THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - SOFTWARE. - */ +Public Domain. +*/ +import java.io.Closeable; import java.io.IOException; import java.io.StringWriter; import java.io.Writer; @@ -36,18 +15,15 @@ of this software and associated documentation files (the "Software"), to deal import java.lang.reflect.Modifier; import java.math.BigDecimal; import java.math.BigInteger; -import java.util.Collection; -import java.util.Collections; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.IdentityHashMap; -import java.util.Iterator; -import java.util.Locale; +import java.util.*; import java.util.Map; import java.util.Map.Entry; import java.util.ResourceBundle; import java.util.Set; +import java.util.function.Consumer; import java.util.regex.Pattern; +import java.util.stream.Stream; +import java.util.stream.StreamSupport; /** * A JSONObject is an unordered collection of name/value pairs. Its external @@ -514,6 +490,111 @@ public JSONObject accumulate(String key, Object value) throws JSONException { } return this; } + // milestone 4 + public Stream toStream() { + return StreamSupport.stream(this.spliterator(), false); + } + + public Spliterator spliterator() { + return new NodeSpliterator(this); + } + + /** + * NodeSpliterator implements Spliterator and methods are overwritten + */ + class NodeSpliterator implements Spliterator { + + private final JSONObject root; + private JSONObject tree; + + NodeSpliterator(JSONObject t) { + root = tree = t; + } + + /** + * DISTINCT: Characteristic value signifying that, for each pair of encountered elements x, y, !x.equals(y). + * IMMUTABLE: Characteristic value signifying that the element source cannot be structurally modified; + * NONNULL: Characteristic value signifying that the source guarantees that encountered elements will not be null. + * + * @return + */ + @Override + public int characteristics() { + return Spliterator.DISTINCT | Spliterator.IMMUTABLE | Spliterator.NONNULL; + } + + @Override + public long estimateSize() { + return Long.MAX_VALUE; + } + + /** + * tryAdvance() iterate elements individually + * If a remaining element exists, performs the given action on it, returning true; else returns false. + * We only manipulate the JSONObject. So in the stream, all the elements are JSONObject + * + * @param action + * @return + */ + @Override + public boolean tryAdvance(Consumer action) { + // tree is a global variable responsible for recording tree node + // current gets the value of tree + JSONObject current = tree; + + // entrySet() gets a set of entries of the JSONObject. + Set> all_entry = tree.entrySet(); + // iterate the set of entries of tree node + for (Entry entry : all_entry) { + if (entry.getValue() instanceof JSONObject) { + // update tree node + tree = (JSONObject) entry.getValue(); + //Repackage JSONObject so that it contains its key value and puts it into the stream + JSONObject newObj = new JSONObject(); + newObj.put(entry.getKey(), entry.getValue()); + action.accept(newObj); + // DFS: recall the tryAdvance to get all the JSONObjects + tryAdvance(action); + } + else if(entry.getValue() instanceof JSONArray) { + JSONArray ja = (JSONArray) entry.getValue(); + JSONObject newObj = new JSONObject(); + newObj.put(entry.getKey(), entry.getValue()); + action.accept(newObj); + for (Object jo : ja) { + JSONObject newObjInArray = new JSONObject(); + newObjInArray.put(entry.getKey(), jo); + tree = (JSONObject) jo; + action.accept(newObjInArray); + // DFS: recall the tryAdvance to get all the JSONObjects + tryAdvance(action); + } + } + else if (!(entry.getValue() instanceof JSONArray)) { + //Repackage JSONObject so that it contains its key value and puts it into the stream + JSONObject newObj = new JSONObject(); + newObj.put(entry.getKey(), entry.getValue()); + action.accept(newObj); + } + } + tree = current; + if (tree == root) + return false; + else + return true; + } + + /** + * return null: this spliterator cannot be split + * + * @return + */ + @Override + public Spliterator trySplit() { + return null; + } + } + /** * Append values to the array under a key. If the key does not exist in the @@ -2146,6 +2227,10 @@ public boolean similar(Object other) { if (!isNumberSimilar((Number)valueThis, (Number)valueOther)) { return false; } + } else if (valueThis instanceof JSONString && valueOther instanceof JSONString) { + if (!((JSONString) valueThis).toJSONString().equals(((JSONString) valueOther).toJSONString())) { + return false; + } } else if (!valueThis.equals(valueOther)) { return false; } diff --git a/src/main/java/org/json/JSONPointer.java b/src/main/java/org/json/JSONPointer.java index f1f7f33..963fdec 100644 --- a/src/main/java/org/json/JSONPointer.java +++ b/src/main/java/org/json/JSONPointer.java @@ -10,27 +10,7 @@ import java.util.List; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ /** diff --git a/src/main/java/org/json/JSONPointerException.java b/src/main/java/org/json/JSONPointerException.java index 0ce1aeb..a0e128c 100644 --- a/src/main/java/org/json/JSONPointerException.java +++ b/src/main/java/org/json/JSONPointerException.java @@ -1,27 +1,7 @@ package org.json; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ /** diff --git a/src/main/java/org/json/JSONPropertyIgnore.java b/src/main/java/org/json/JSONPropertyIgnore.java index 682de74..d3a5bc5 100644 --- a/src/main/java/org/json/JSONPropertyIgnore.java +++ b/src/main/java/org/json/JSONPropertyIgnore.java @@ -1,27 +1,7 @@ package org.json; /* -Copyright (c) 2018 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static java.lang.annotation.ElementType.METHOD; @@ -31,13 +11,13 @@ of this software and associated documentation files (the "Software"), to deal import java.lang.annotation.Retention; import java.lang.annotation.Target; -@Documented -@Retention(RUNTIME) -@Target({METHOD}) /** * Use this annotation on a getter method to override the Bean name * parser for Bean -> JSONObject mapping. If this annotation is * present at any level in the class hierarchy, then the method will * not be serialized from the bean into the JSONObject. */ +@Documented +@Retention(RUNTIME) +@Target({METHOD}) public @interface JSONPropertyIgnore { } diff --git a/src/main/java/org/json/JSONPropertyName.java b/src/main/java/org/json/JSONPropertyName.java index a1bcd58..4391bb7 100644 --- a/src/main/java/org/json/JSONPropertyName.java +++ b/src/main/java/org/json/JSONPropertyName.java @@ -1,27 +1,7 @@ package org.json; /* -Copyright (c) 2018 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static java.lang.annotation.ElementType.METHOD; @@ -31,14 +11,14 @@ of this software and associated documentation files (the "Software"), to deal import java.lang.annotation.Retention; import java.lang.annotation.Target; -@Documented -@Retention(RUNTIME) -@Target({METHOD}) /** * Use this annotation on a getter method to override the Bean name * parser for Bean -> JSONObject mapping. A value set to empty string "" * will have the Bean parser fall back to the default field name processing. */ +@Documented +@Retention(RUNTIME) +@Target({METHOD}) public @interface JSONPropertyName { /** * @return The name of the property as to be used in the JSON Object. diff --git a/src/main/java/org/json/JSONString.java b/src/main/java/org/json/JSONString.java index bcd9a81..cd8d184 100644 --- a/src/main/java/org/json/JSONString.java +++ b/src/main/java/org/json/JSONString.java @@ -1,27 +1,7 @@ package org.json; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ /** diff --git a/src/main/java/org/json/JSONStringer.java b/src/main/java/org/json/JSONStringer.java index d2a4dfb..2f6cf9e 100644 --- a/src/main/java/org/json/JSONStringer.java +++ b/src/main/java/org/json/JSONStringer.java @@ -1,27 +1,7 @@ package org.json; /* -Copyright (c) 2006 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import java.io.StringWriter; diff --git a/src/main/java/org/json/JSONTokener.java b/src/main/java/org/json/JSONTokener.java index 7f0c86a..8c98c77 100644 --- a/src/main/java/org/json/JSONTokener.java +++ b/src/main/java/org/json/JSONTokener.java @@ -8,27 +8,7 @@ import java.io.StringReader; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ /** diff --git a/src/main/java/org/json/JSONWriter.java b/src/main/java/org/json/JSONWriter.java index dafb1b2..11f4a5c 100644 --- a/src/main/java/org/json/JSONWriter.java +++ b/src/main/java/org/json/JSONWriter.java @@ -5,27 +5,7 @@ import java.util.Map; /* -Copyright (c) 2006 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ /** diff --git a/src/main/java/org/json/Property.java b/src/main/java/org/json/Property.java index 7caeebb..83694c0 100644 --- a/src/main/java/org/json/Property.java +++ b/src/main/java/org/json/Property.java @@ -1,27 +1,7 @@ package org.json; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import java.util.Enumeration; diff --git a/src/main/java/org/json/XML.java b/src/main/java/org/json/XML.java index 33838a1..56318df 100644 --- a/src/main/java/org/json/XML.java +++ b/src/main/java/org/json/XML.java @@ -1,34 +1,20 @@ package org.json; /* -Copyright (c) 2015 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import java.io.Reader; import java.io.StringReader; import java.math.BigDecimal; import java.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Iterator; +import java.util.List; +import java.util.concurrent.*; +import java.util.function.Consumer; +import java.util.function.Function; /** @@ -41,31 +27,61 @@ of this software and associated documentation files (the "Software"), to deal @SuppressWarnings("boxing") public class XML { - /** The Character '&'. */ + public static boolean isReachedParse1 = false; + public static boolean isReachedParse2 = false; + + private static class EarlyTermination extends Exception { + + public JSONObject subObject; + + public EarlyTermination(JSONObject obj) { + subObject = obj; + } + } + + /** + * The Character '&'. + */ public static final Character AMP = '&'; - /** The Character '''. */ + /** + * The Character '''. + */ public static final Character APOS = '\''; - /** The Character '!'. */ + /** + * The Character '!'. + */ public static final Character BANG = '!'; - /** The Character '='. */ + /** + * The Character '='. + */ public static final Character EQ = '='; - /** The Character
{@code '>'. }
*/ + /** + * The Character
{@code '>'. }
+ */ public static final Character GT = '>'; - /** The Character '<'. */ + /** + * The Character '<'. + */ public static final Character LT = '<'; - /** The Character '?'. */ + /** + * The Character '?'. + */ public static final Character QUEST = '?'; - /** The Character '"'. */ + /** + * The Character '"'. + */ public static final Character QUOT = '"'; - /** The Character '/'. */ + /** + * The Character '/'. + */ public static final Character SLASH = '/'; /** @@ -84,7 +100,7 @@ public class XML { * which is available in Java8 and above. * * @see http://stackoverflow.com/a/21791059/6030888 + * "http://stackoverflow.com/a/21791059/6030888">http://stackoverflow.com/a/21791059/6030888 */ private static Iterable codePointIterator(final String string) { return new Iterable() { @@ -118,7 +134,7 @@ public void remove() { /** * Replace special characters with XML escapes: * - *
{@code 
+     * 
{@code
      * & (ampersand) is replaced by &amp;
      * < (less than) is replaced by &lt;
      * > (greater than) is replaced by &gt;
@@ -126,37 +142,36 @@ public void remove() {
      * ' (single quote / apostrophe) is replaced by &apos;
      * }
* - * @param string - * The string to be escaped. + * @param string The string to be escaped. * @return The escaped string. */ public static String escape(String string) { StringBuilder sb = new StringBuilder(string.length()); for (final int cp : codePointIterator(string)) { switch (cp) { - case '&': - sb.append("&"); - break; - case '<': - sb.append("<"); - break; - case '>': - sb.append(">"); - break; - case '"': - sb.append("""); - break; - case '\'': - sb.append("'"); - break; - default: - if (mustEscape(cp)) { - sb.append("&#x"); - sb.append(Integer.toHexString(cp)); - sb.append(';'); - } else { - sb.appendCodePoint(cp); - } + case '&': + sb.append("&"); + break; + case '<': + sb.append("<"); + break; + case '>': + sb.append(">"); + break; + case '"': + sb.append("""); + break; + case '\'': + sb.append("'"); + break; + default: + if (mustEscape(cp)) { + sb.append("&#x"); + sb.append(Integer.toHexString(cp)); + sb.append(';'); + } else { + sb.appendCodePoint(cp); + } } } return sb.toString(); @@ -179,20 +194,19 @@ private static boolean mustEscape(int cp) { && cp != 0x9 && cp != 0xA && cp != 0xD - ) || !( + ) || !( // valid the range of acceptable characters that aren't control (cp >= 0x20 && cp <= 0xD7FF) - || (cp >= 0xE000 && cp <= 0xFFFD) - || (cp >= 0x10000 && cp <= 0x10FFFF) - ) - ; + || (cp >= 0xE000 && cp <= 0xFFFD) + || (cp >= 0x10000 && cp <= 0x10FFFF) + ) + ; } /** * Removes XML escapes from the string. * - * @param string - * string to remove escapes from + * @param string string to remove escapes from * @return string with converted entities */ public static String unescape(String string) { @@ -223,8 +237,7 @@ public static String unescape(String string) { * Throw an exception if the string contains whitespace. Whitespace is not * allowed in tagNames and attributes. * - * @param string - * A string. + * @param string A string. * @throws JSONException Thrown if the string contains whitespace or is empty. */ public static void noSpace(String string) throws JSONException { @@ -243,226 +256,22 @@ public static void noSpace(String string) throws JSONException { /** * Scan the content following the named tag, attaching it to the context. * - * @param x - * The XMLTokener containing the source string. - * @param context - * The JSONObject that will include the new material. - * @param name - * The tag name. + * @param x The XMLTokener containing the source string. + * @param context The JSONObject that will include the new material. + * @param name The tag name. * @return true if the close tag is processed. * @throws JSONException */ - private static boolean parse(XMLTokener x, JSONObject context, String name, XMLParserConfiguration config) - throws JSONException { - char c; - int i; - JSONObject jsonObject = null; - String string; - String tagName; - Object token; - XMLXsiTypeConverter xmlXsiTypeConverter; - - // Test for and skip past these forms: - // - // - // - // - // Report errors for these forms: - // <> - // <= - // << - - token = x.nextToken(); - - // "); - return false; - } - x.back(); - } else if (c == '[') { - token = x.nextToken(); - if ("CDATA".equals(token)) { - if (x.next() == '[') { - string = x.nextCDATA(); - if (string.length() > 0) { - context.accumulate(config.getcDataTagName(), string); - } - return false; - } - } - throw x.syntaxError("Expected 'CDATA['"); - } - i = 1; - do { - token = x.nextMeta(); - if (token == null) { - throw x.syntaxError("Missing '>' after ' 0); - return false; - } else if (token == QUEST) { - - // "); - return false; - } else if (token == SLASH) { - - // Close tag - if (x.nextToken() != GT) { - throw x.syntaxError("Misshaped tag"); - } - if (config.getForceList().contains(tagName)) { - // Force the value to be an array - if (nilAttributeFound) { - context.append(tagName, JSONObject.NULL); - } else if (jsonObject.length() > 0) { - context.append(tagName, jsonObject); - } else { - context.put(tagName, new JSONArray()); - } - } else { - if (nilAttributeFound) { - context.accumulate(tagName, JSONObject.NULL); - } else if (jsonObject.length() > 0) { - context.accumulate(tagName, jsonObject); - } else { - context.accumulate(tagName, ""); - } - } - return false; - - } else if (token == GT) { - // Content, between <...> and - for (;;) { - token = x.nextContent(); - if (token == null) { - if (tagName != null) { - throw x.syntaxError("Unclosed tag " + tagName); - } - return false; - } else if (token instanceof String) { - string = (String) token; - if (string.length() > 0) { - if(xmlXsiTypeConverter != null) { - jsonObject.accumulate(config.getcDataTagName(), - stringToValue(string, xmlXsiTypeConverter)); - } else { - jsonObject.accumulate(config.getcDataTagName(), - config.isKeepStrings() ? string : stringToValue(string)); - } - } - - } else if (token == LT) { - // Nested element - if (parse(x, jsonObject, tagName, config)) { - if (config.getForceList().contains(tagName)) { - // Force the value to be an array - if (jsonObject.length() == 0) { - context.put(tagName, new JSONArray()); - } else if (jsonObject.length() == 1 - && jsonObject.opt(config.getcDataTagName()) != null) { - context.append(tagName, jsonObject.opt(config.getcDataTagName())); - } else { - context.append(tagName, jsonObject); - } - } else { - if (jsonObject.length() == 0) { - context.accumulate(tagName, ""); - } else if (jsonObject.length() == 1 - && jsonObject.opt(config.getcDataTagName()) != null) { - context.accumulate(tagName, jsonObject.opt(config.getcDataTagName())); - } else { - context.accumulate(tagName, jsonObject); - } - } - - return false; - } - } - } - } else { - throw x.syntaxError("Misshaped tag"); - } - } - } - } /** * This method tries to convert the given string value to the target object - * @param string String to convert + * + * @param string String to convert * @param typeConverter value converter to convert string to integer, boolean e.t.c * @return JSON value of this string or the string */ public static Object stringToValue(String string, XMLXsiTypeConverter typeConverter) { - if(typeConverter != null) { + if (typeConverter != null) { return typeConverter.convert(string); } return stringToValue(string); @@ -507,7 +316,7 @@ public static Object stringToValue(String string) { } return string; } - + /** * direct copy of {@link JSONObject#stringToNumber(String)} to maintain Android support. */ @@ -521,7 +330,7 @@ private static Number stringToNumber(final String val) throws NumberFormatExcept // keep that by forcing a decimal. try { BigDecimal bd = new BigDecimal(val); - if(initial == '-' && BigDecimal.ZERO.compareTo(bd)==0) { + if (initial == '-' && BigDecimal.ZERO.compareTo(bd) == 0) { return Double.valueOf(-0.0); } return bd; @@ -529,48 +338,48 @@ private static Number stringToNumber(final String val) throws NumberFormatExcept // this is to support "Hex Floats" like this: 0x1.0P-1074 try { Double d = Double.valueOf(val); - if(d.isNaN() || d.isInfinite()) { - throw new NumberFormatException("val ["+val+"] is not a valid number."); + if (d.isNaN() || d.isInfinite()) { + throw new NumberFormatException("val [" + val + "] is not a valid number."); } return d; } catch (NumberFormatException ignore) { - throw new NumberFormatException("val ["+val+"] is not a valid number."); + throw new NumberFormatException("val [" + val + "] is not a valid number."); } } } // block items like 00 01 etc. Java number parsers treat these as Octal. - if(initial == '0' && val.length() > 1) { + if (initial == '0' && val.length() > 1) { char at1 = val.charAt(1); - if(at1 >= '0' && at1 <= '9') { - throw new NumberFormatException("val ["+val+"] is not a valid number."); + if (at1 >= '0' && at1 <= '9') { + throw new NumberFormatException("val [" + val + "] is not a valid number."); } } else if (initial == '-' && val.length() > 2) { char at1 = val.charAt(1); char at2 = val.charAt(2); - if(at1 == '0' && at2 >= '0' && at2 <= '9') { - throw new NumberFormatException("val ["+val+"] is not a valid number."); + if (at1 == '0' && at2 >= '0' && at2 <= '9') { + throw new NumberFormatException("val [" + val + "] is not a valid number."); } } // integer representation. // This will narrow any values to the smallest reasonable Object representation // (Integer, Long, or BigInteger) - + // BigInteger down conversion: We use a similar bitLength compare as // BigInteger#intValueExact uses. Increases GC, but objects hold // only what they need. i.e. Less runtime overhead if the value is // long lived. BigInteger bi = new BigInteger(val); - if(bi.bitLength() <= 31){ + if (bi.bitLength() <= 31) { return Integer.valueOf(bi.intValue()); } - if(bi.bitLength() <= 63){ + if (bi.bitLength() <= 63) { return Long.valueOf(bi.longValue()); } return bi; } - throw new NumberFormatException("val ["+val+"] is not a valid number."); + throw new NumberFormatException("val [" + val + "] is not a valid number."); } - + /** * direct copy of {@link JSONObject#isDecimalNotation(String)} to maintain Android support. */ @@ -588,12 +397,11 @@ private static boolean isDecimalNotation(final String val) { * name/value pairs and arrays of values. JSON does not does not like to * distinguish between elements and attributes. Sequences of similar * elements are represented as JSONArrays. Content text may be placed in a - * "content" member. Comments, prologs, DTDs, and
{@code 
+     * "content" member. Comments, prologs, DTDs, and 
{@code
      * <[ [ ]]>}
* are ignored. * - * @param string - * The source string. + * @param string The source string. * @return A JSONObject containing the structured data from the XML string. * @throws JSONException Thrown if there is an errors while parsing the string */ @@ -601,6 +409,7 @@ public static JSONObject toJSONObject(String string) throws JSONException { return toJSONObject(string, XMLParserConfiguration.ORIGINAL); } + /** * Convert a well-formed (but not necessarily valid) XML into a * JSONObject. Some information may be lost in this transformation because @@ -609,7 +418,7 @@ public static JSONObject toJSONObject(String string) throws JSONException { * name/value pairs and arrays of values. JSON does not does not like to * distinguish between elements and attributes. Sequences of similar * elements are represented as JSONArrays. Content text may be placed in a - * "content" member. Comments, prologs, DTDs, and
{@code 
+     * "content" member. Comments, prologs, DTDs, and 
{@code
      * <[ [ ]]>}
* are ignored. * @@ -632,18 +441,18 @@ public static JSONObject toJSONObject(Reader reader) throws JSONException { * "content" member. Comments, prologs, DTDs, and
{@code
      * <[ [ ]]>}
* are ignored. - * + *

* All values are converted as strings, for 1, 01, 29.0 will not be coerced to * numbers but will instead be the exact value as seen in the XML document. * - * @param reader The XML source reader. + * @param reader The XML source reader. * @param keepStrings If true, then values will not be coerced into boolean - * or numeric values and will instead be left as strings + * or numeric values and will instead be left as strings * @return A JSONObject containing the structured data from the XML string. * @throws JSONException Thrown if there is an errors while parsing the string */ public static JSONObject toJSONObject(Reader reader, boolean keepStrings) throws JSONException { - if(keepStrings) { + if (keepStrings) { return toJSONObject(reader, XMLParserConfiguration.KEEP_STRINGS); } return toJSONObject(reader, XMLParserConfiguration.ORIGINAL); @@ -660,7 +469,7 @@ public static JSONObject toJSONObject(Reader reader, boolean keepStrings) throws * "content" member. Comments, prologs, DTDs, and

{@code
      * <[ [ ]]>}
* are ignored. - * + *

* All values are converted as strings, for 1, 01, 29.0 will not be coerced to * numbers but will instead be the exact value as seen in the XML document. * @@ -674,56 +483,131 @@ public static JSONObject toJSONObject(Reader reader, XMLParserConfiguration conf XMLTokener x = new XMLTokener(reader); while (x.more()) { x.skipPast("<"); - if(x.more()) { - parse(x, jo, null, config); + if (x.more()) { + parse(x, jo, null, config,s->s); } } return jo; } - /** - * Convert a well-formed (but not necessarily valid) XML string into a - * JSONObject. Some information may be lost in this transformation because - * JSON is a data format and XML is a document format. XML uses elements, - * attributes, and content text, while JSON uses unordered collections of - * name/value pairs and arrays of values. JSON does not does not like to - * distinguish between elements and attributes. Sequences of similar - * elements are represented as JSONArrays. Content text may be placed in a - * "content" member. Comments, prologs, DTDs, and

{@code 
-     * <[ [ ]]>}
- * are ignored. - * - * All values are converted as strings, for 1, 01, 29.0 will not be coerced to - * numbers but will instead be the exact value as seen in the XML document. - * - * @param string - * The source string. - * @param keepStrings If true, then values will not be coerced into boolean - * or numeric values and will instead be left as strings - * @return A JSONObject containing the structured data from the XML string. - * @throws JSONException Thrown if there is an errors while parsing the string - */ - public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException { - return toJSONObject(new StringReader(string), keepStrings); - } - - /** - * Convert a well-formed (but not necessarily valid) XML string into a + // milestone 2 P1 + public static JSONObject toJSONObject(Reader reader, JSONPointer path) throws JSONException { + JSONObject jo = new JSONObject(); + XMLTokener x = new XMLTokener(reader); + String desiredPath = path.toString(); + isReachedParse1 = false; + if (Character.toString(desiredPath.charAt(desiredPath.length() - 1)).equalsIgnoreCase("/")) { + throw new JSONPointerException("Invalid Path with '/' ending"); + } + while (x.more()) { + x.skipPast("<"); + if (x.more()) { + try { + parse1(x, jo, null, XMLParserConfiguration.ORIGINAL, desiredPath, ""); + } catch (EarlyTermination e) { + System.out.println(e); + return e.subObject; + } + + } + } + if (isReachedParse1 == false) { + throw new JSONPointerException("Path not found"); + } + return jo; + } + + // milestone 2 P2 + public static JSONObject toJSONObject(Reader reader, JSONPointer path, JSONObject replacement) throws JSONException { + JSONObject jo = new JSONObject(); + XMLTokener x = new XMLTokener(reader); + String desiredPath = path.toString(); + isReachedParse2 = false; + if (Character.toString(desiredPath.charAt(desiredPath.length() - 1)).equalsIgnoreCase("/")) { + throw new JSONPointerException("Invalid Path with '/' ending"); + } + while (x.more()) { + x.skipPast("<"); + if (x.more()) { + parse2(x, jo, null, XMLParserConfiguration.ORIGINAL, desiredPath, "", replacement); + } + } + if (isReachedParse2 == false) { + throw new JSONPointerException("Path not found"); + } + return jo; + } + + // milestone 3 + public static JSONObject toJSONObject(Reader reader, Function keyTransformer) { + // check string condition + String res1 = keyTransformer.apply("res1"); + String res2 = keyTransformer.apply("res2"); + // Transform key to null + if (res1 == null) { + throw new JSONException("Invalid: transform key to null"); + } + // Transform key to empty string + if (res2.equals("")) { + throw new JSONException("Invalid: transform key to empty string"); + } + // Transform key to all the same string + if (res1.equals(res2)){ + throw new JSONException("Invalid: transform key to all the same string"); + } + JSONObject jo = new JSONObject(); + XMLTokener x = new XMLTokener(reader); + while (x.more()) { + x.skipPast("<"); + if (x.more()) { + parse(x, jo, null, XMLParserConfiguration.ORIGINAL, keyTransformer); + } + } + return jo; + + } + + /** + * Convert a well-formed (but not necessarily valid) XML string into a * JSONObject. Some information may be lost in this transformation because * JSON is a data format and XML is a document format. XML uses elements, * attributes, and content text, while JSON uses unordered collections of * name/value pairs and arrays of values. JSON does not does not like to * distinguish between elements and attributes. Sequences of similar * elements are represented as JSONArrays. Content text may be placed in a - * "content" member. Comments, prologs, DTDs, and
{@code 
+     * "content" member. Comments, prologs, DTDs, and 
{@code
      * <[ [ ]]>}
* are ignored. + *

+ * All values are converted as strings, for 1, 01, 29.0 will not be coerced to + * numbers but will instead be the exact value as seen in the XML document. * + * @param string The source string. + * @param keepStrings If true, then values will not be coerced into boolean + * or numeric values and will instead be left as strings + * @return A JSONObject containing the structured data from the XML string. + * @throws JSONException Thrown if there is an errors while parsing the string + */ + public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException { + return toJSONObject(new StringReader(string), keepStrings); + } + + /** + * Convert a well-formed (but not necessarily valid) XML string into a + * JSONObject. Some information may be lost in this transformation because + * JSON is a data format and XML is a document format. XML uses elements, + * attributes, and content text, while JSON uses unordered collections of + * name/value pairs and arrays of values. JSON does not does not like to + * distinguish between elements and attributes. Sequences of similar + * elements are represented as JSONArrays. Content text may be placed in a + * "content" member. Comments, prologs, DTDs, and

{@code
+     * <[ [ ]]>}
+ * are ignored. + *

* All values are converted as strings, for 1, 01, 29.0 will not be coerced to * numbers but will instead be the exact value as seen in the XML document. * - * @param string - * The source string. + * @param string The source string. * @param config Configuration options for the parser. * @return A JSONObject containing the structured data from the XML string. * @throws JSONException Thrown if there is an errors while parsing the string @@ -735,8 +619,7 @@ public static JSONObject toJSONObject(String string, XMLParserConfiguration conf /** * Convert a JSONObject into a well-formed, element-normal XML string. * - * @param object - * A JSONObject. + * @param object A JSONObject. * @return A string. * @throws JSONException Thrown if there is an error parsing the string */ @@ -747,10 +630,8 @@ public static String toString(Object object) throws JSONException { /** * Convert a JSONObject into a well-formed, element-normal XML string. * - * @param object - * A JSONObject. - * @param tagName - * The optional name of the enclosing tag. + * @param object A JSONObject. + * @param tagName The optional name of the enclosing tag. * @return A string. * @throws JSONException Thrown if there is an error parsing the string */ @@ -761,17 +642,31 @@ public static String toString(final Object object, final String tagName) { /** * Convert a JSONObject into a well-formed, element-normal XML string. * - * @param object - * A JSONObject. - * @param tagName - * The optional name of the enclosing tag. - * @param config - * Configuration that can control output to XML. + * @param object A JSONObject. + * @param tagName The optional name of the enclosing tag. + * @param config Configuration that can control output to XML. * @return A string. * @throws JSONException Thrown if there is an error parsing the string */ public static String toString(final Object object, final String tagName, final XMLParserConfiguration config) throws JSONException { + return toString(object, tagName, config, 0, 0); + } + + /** + * Convert a JSONObject into a well-formed, element-normal XML string, + * either pretty print or single-lined depending on indent factor. + * + * @param object A JSONObject. + * @param tagName The optional name of the enclosing tag. + * @param config Configuration that can control output to XML. + * @param indentFactor The number of spaces to add to each level of indentation. + * @param indent The current ident level in spaces. + * @return + * @throws JSONException + */ + private static String toString(final Object object, final String tagName, final XMLParserConfiguration config, int indentFactor, int indent) + throws JSONException { StringBuilder sb = new StringBuilder(); JSONArray ja; JSONObject jo; @@ -781,9 +676,14 @@ public static String toString(final Object object, final String tagName, final X // Emit if (tagName != null) { + sb.append(indent(indent)); sb.append('<'); sb.append(tagName); sb.append('>'); + if (indentFactor > 0) { + sb.append("\n"); + indent += indentFactor; + } } // Loop thru the keys. @@ -803,7 +703,7 @@ public static String toString(final Object object, final String tagName, final X ja = (JSONArray) value; int jaLength = ja.length(); // don't use the new iterator API to maintain support for Android - for (int i = 0; i < jaLength; i++) { + for (int i = 0; i < jaLength; i++) { if (i > 0) { sb.append('\n'); } @@ -820,64 +720,888 @@ public static String toString(final Object object, final String tagName, final X ja = (JSONArray) value; int jaLength = ja.length(); // don't use the new iterator API to maintain support for Android - for (int i = 0; i < jaLength; i++) { + for (int i = 0; i < jaLength; i++) { Object val = ja.opt(i); if (val instanceof JSONArray) { sb.append('<'); sb.append(key); sb.append('>'); - sb.append(toString(val, null, config)); + sb.append(toString(val, null, config, indentFactor, indent)); sb.append("'); } else { - sb.append(toString(val, key, config)); + sb.append(toString(val, key, config, indentFactor, indent)); } } } else if ("".equals(value)) { + sb.append(indent(indent)); sb.append('<'); sb.append(key); sb.append("/>"); + if (indentFactor > 0) { + sb.append("\n"); + } // Emit a new tag } else { - sb.append(toString(value, key, config)); + sb.append(toString(value, key, config, indentFactor, indent)); } } if (tagName != null) { // Emit the close tag + sb.append(indent(indent - indentFactor)); sb.append("'); + if (indentFactor > 0) { + sb.append("\n"); + } } return sb.toString(); } - if (object != null && (object instanceof JSONArray || object.getClass().isArray())) { - if(object.getClass().isArray()) { + if (object != null && (object instanceof JSONArray || object.getClass().isArray())) { + if (object.getClass().isArray()) { ja = new JSONArray(object); } else { ja = (JSONArray) object; } int jaLength = ja.length(); // don't use the new iterator API to maintain support for Android - for (int i = 0; i < jaLength; i++) { + for (int i = 0; i < jaLength; i++) { Object val = ja.opt(i); // XML does not have good support for arrays. If an array // appears in a place where XML is lacking, synthesize an // element. - sb.append(toString(val, tagName == null ? "array" : tagName, config)); + sb.append(toString(val, tagName == null ? "array" : tagName, config, indentFactor, indent)); } return sb.toString(); } + string = (object == null) ? "null" : escape(object.toString()); - return (tagName == null) ? "\"" + string + "\"" - : (string.length() == 0) ? "<" + tagName + "/>" : "<" + tagName - + ">" + string + ""; + if (tagName == null) { + return indent(indent) + "\"" + string + "\"" + ((indentFactor > 0) ? "\n" : ""); + } else if (string.length() == 0) { + return indent(indent) + "<" + tagName + "/>" + ((indentFactor > 0) ? "\n" : ""); + } else { + return indent(indent) + "<" + tagName + + ">" + string + "" + ((indentFactor > 0) ? "\n" : ""); + } + } + + /** + * Convert a JSONObject into a well-formed, pretty printed element-normal XML string. + * + * @param object A JSONObject. + * @param indentFactor The number of spaces to add to each level of indentation. + * @return A string. + * @throws JSONException Thrown if there is an error parsing the string + */ + public static String toString(Object object, int indentFactor) { + return toString(object, null, XMLParserConfiguration.ORIGINAL, indentFactor); + } + + /** + * Convert a JSONObject into a well-formed, pretty printed element-normal XML string. + * + * @param object A JSONObject. + * @param tagName The optional name of the enclosing tag. + * @param indentFactor The number of spaces to add to each level of indentation. + * @return A string. + * @throws JSONException Thrown if there is an error parsing the string + */ + public static String toString(final Object object, final String tagName, int indentFactor) { + return toString(object, tagName, XMLParserConfiguration.ORIGINAL, indentFactor); + } + + /** + * Convert a JSONObject into a well-formed, pretty printed element-normal XML string. + * + * @param object A JSONObject. + * @param tagName The optional name of the enclosing tag. + * @param config Configuration that can control output to XML. + * @param indentFactor The number of spaces to add to each level of indentation. + * @return A string. + * @throws JSONException Thrown if there is an error parsing the string + */ + public static String toString(final Object object, final String tagName, final XMLParserConfiguration config, int indentFactor) + throws JSONException { + return toString(object, tagName, config, indentFactor, 0); + } + + /** + * Return a String consisting of a number of space characters specified by indent + * + * @param indent The number of spaces to be appended to the String. + * @return + */ + private static final String indent(int indent) { + StringBuilder sb = new StringBuilder(); + for (int i = 0; i < indent; i++) { + sb.append(' '); + } + return sb.toString(); } + + /** + * Scan the content following the named tag, attaching it to the context. + * + * @param x The XMLTokener containing the source string. + * @param context The JSONObject that will include the new material. + * @param name The tag name. + * @return true if the close tag is processed. + * @throws JSONException + */ + private static boolean parse1(XMLTokener x, JSONObject context, String name, XMLParserConfiguration config, String desiredPath, String currPath) + throws JSONException, EarlyTermination { + // keep track of the path + char c; + int i; + JSONObject jsonObject = null; + String string; + String tagName; + Object token; + XMLXsiTypeConverter xmlXsiTypeConverter; + + // Test for and skip past these forms: + // + // + // + // + // Report errors for these forms: + // <> + // <= + // << + + token = x.nextToken(); +// System.out.println(currPath); +// System.out.println("token: " + token); + + + // "); + return false; + } + x.back(); + } else if (c == '[') { + token = x.nextToken(); + if ("CDATA".equals(token)) { + if (x.next() == '[') { + string = x.nextCDATA(); + if (string.length() > 0) { + context.accumulate(config.getcDataTagName(), string); + } + return false; + } + } + throw x.syntaxError("Expected 'CDATA['"); + } + i = 1; + do { + token = x.nextMeta(); + if (token == null) { + throw x.syntaxError("Missing '>' after ' 0); + return false; + } else if (token == QUEST) { + + // "); + return false; + } else if (token == SLASH) { + + // Close tag level = new ArrayList<>(Arrays.asList(desiredPath.split("/"))); +// System.out.println("level: " + level.get(level.size()-1)); + if (currPath.equalsIgnoreCase(desiredPath) && token.toString().equalsIgnoreCase(level.get(level.size() - 1))) { + isReachedParse1 = true; +// System.out.println("isReached:" + isReached); + } + if (name == null) { + throw x.syntaxError("Mismatched close tag " + token); + } + if (!token.equals(name)) { + throw x.syntaxError("Mismatched " + name + " and " + token); + } + if (x.nextToken() != GT) { + throw x.syntaxError("Misshaped close tag"); + } + return true; + + } else if (token instanceof Character) { + + throw x.syntaxError("Misshaped tag"); + + // Open tag < + + } else { + tagName = (String) token; + currPath += "/" + tagName; +// System.out.println("curr: " + currPath); + token = null; + jsonObject = new JSONObject(); + boolean nilAttributeFound = false; + xmlXsiTypeConverter = null; + + for (; ; ) { + if (token == null) { + token = x.nextToken(); +// System.out.println(x.next()); +// System.out.println("token after tagName: " + token); + } + // attribute = value + if (token instanceof String) { + + string = (String) token; +// System.out.println("inString: " + string); + token = x.nextToken(); + if (token == EQ) { + token = x.nextToken(); + if (!(token instanceof String)) { + throw x.syntaxError("Missing value"); + } + + if (config.isConvertNilAttributeToNull() + && NULL_ATTR.equals(string) + && Boolean.parseBoolean((String) token)) { + nilAttributeFound = true; + } else if (config.getXsiTypeMap() != null && !config.getXsiTypeMap().isEmpty() + && TYPE_ATTR.equals(string)) { + xmlXsiTypeConverter = config.getXsiTypeMap().get(token); + } else if (!nilAttributeFound) { + jsonObject.accumulate(string, + config.isKeepStrings() + ? ((String) token) + : stringToValue((String) token)); + } + token = null; + } else { + jsonObject.accumulate(string, ""); + } + + + } else if (token == SLASH) { + // Empty tag <.../> + if (x.nextToken() != GT) { + + throw x.syntaxError("Misshaped tag"); + } + if (currPath.startsWith(desiredPath)) { + if (config.getForceList().contains(tagName)) { + // Force the value to be an array + if (nilAttributeFound) { + context.append(tagName, JSONObject.NULL); + } else if (jsonObject.length() > 0) { + context.append(tagName, jsonObject); + } else { + context.put(tagName, new JSONArray()); + } + } else { + if (nilAttributeFound) { + context.accumulate(tagName, JSONObject.NULL); + } else if (jsonObject.length() > 0) { + context.accumulate(tagName, jsonObject); + } else { + context.accumulate(tagName, ""); + } + } + return false; + } + + + } else if (token == GT) { + // Content, between <...> and + for (; ; ) { + + token = x.nextContent(); +// System.out.println("token next Content: " + token); + if (token == null) { + if (tagName != null) { + throw x.syntaxError("Unclosed tag " + tagName); + } + return false; + } else if (token instanceof String) { + string = (String) token; + if (string.length() > 0) { + if (xmlXsiTypeConverter != null) { + jsonObject.accumulate(config.getcDataTagName(), + stringToValue(string, xmlXsiTypeConverter)); + } else { +// System.out.println("In"); + jsonObject.accumulate(config.getcDataTagName(), + config.isKeepStrings() ? string : stringToValue(string)); + } + } + + + } else if (token == LT) { + // Nested element +// System.out.println("In LT"); +// System.out.println(currPath + " ----" + desiredPath); + if (parse1(x, jsonObject, tagName, config, desiredPath, currPath)) { +// System.out.println(currPath + " " + desiredPath); +// System.out.println("subJo: " +jsonObject); + if (currPath.startsWith(desiredPath)) { +// System.out.println("TEST"); +// System.out.println("subJo: " +jsonObject); +// System.out.println(token ); + if (config.getForceList().contains(tagName)) { + // Force the value to be an array + if (jsonObject.length() == 0) { + context.put(tagName, new JSONArray()); + } else if (jsonObject.length() == 1 + && jsonObject.opt(config.getcDataTagName()) != null) { + context.append(tagName, jsonObject.opt(config.getcDataTagName())); + } else { + context.append(tagName, jsonObject); + } + } else { + if (jsonObject.length() == 0) { + context.accumulate(tagName, ""); + } else if (jsonObject.length() == 1 + && jsonObject.opt(config.getcDataTagName()) != null) { + context.accumulate(tagName, jsonObject.opt(config.getcDataTagName())); + } else { + context.accumulate(tagName, jsonObject); + } + } + if (isReachedParse1 == true) { + System.out.println("context: " + context); + throw new EarlyTermination(context); + } + + } +// System.out.println("isReached1:" + isReachedParse1); + /*if (isReachedParse1 == true){ + System.out.println("context: " + context); + throw new EarlyTermination(context); + }*/ + + return false; + } + } + + } + + } else { + throw x.syntaxError("Misshaped tag"); + } + } + } + } + + private static boolean parse2(XMLTokener x, JSONObject context, String name, XMLParserConfiguration config, String desiredPath, String currPath, JSONObject replacement) + throws JSONException { + // keep track of the path + char c; + int i; + JSONObject jsonObject = null; + String string; + String tagName; + Object token; + XMLXsiTypeConverter xmlXsiTypeConverter; + + // Test for and skip past these forms: + // + // + // + // + // Report errors for these forms: + // <> + // <= + // << + + token = x.nextToken(); + + + + // "); + return false; + } + x.back(); + } else if (c == '[') { + token = x.nextToken(); + if ("CDATA".equals(token)) { + if (x.next() == '[') { + string = x.nextCDATA(); + if (string.length() > 0) { + context.accumulate(config.getcDataTagName(), string); + } + return false; + } + } + throw x.syntaxError("Expected 'CDATA['"); + } + i = 1; + do { + token = x.nextMeta(); + if (token == null) { + throw x.syntaxError("Missing '>' after ' 0); + return false; + } else if (token == QUEST) { + + // "); + return false; + } else if (token == SLASH) { + + // Close tag level = new ArrayList<>(Arrays.asList(desiredPath.split("/"))); +// System.out.println("level: " + level.get(level.size()-1)); + if (currPath.equalsIgnoreCase(desiredPath) && token.toString().equalsIgnoreCase(level.get(level.size() - 1))) { + isReachedParse2 = true; +// System.out.println("isReached:" + isReached); + } + if (name == null) { + throw x.syntaxError("Mismatched close tag " + token); + } + if (!token.equals(name)) { + throw x.syntaxError("Mismatched " + name + " and " + token); + } + if (x.nextToken() != GT) { + throw x.syntaxError("Misshaped close tag"); + } + return true; + + } else if (token instanceof Character) { + + throw x.syntaxError("Misshaped tag"); + + // Open tag < + + } else { + tagName = (String) token; + currPath += "/" + tagName; +// System.out.println("curr: " + currPath); + token = null; + jsonObject = new JSONObject(); + boolean nilAttributeFound = false; + xmlXsiTypeConverter = null; + + for (; ; ) { + if (token == null) { + token = x.nextToken(); +// System.out.println(x.next()); +// System.out.println("token after tagName: " + token); + } + // attribute = value + if (token instanceof String) { + + string = (String) token; +// System.out.println("inString: " + string); + token = x.nextToken(); + if (token == EQ) { + token = x.nextToken(); + if (!(token instanceof String)) { + throw x.syntaxError("Missing value"); + } + + if (config.isConvertNilAttributeToNull() + && NULL_ATTR.equals(string) + && Boolean.parseBoolean((String) token)) { + nilAttributeFound = true; + } else if (config.getXsiTypeMap() != null && !config.getXsiTypeMap().isEmpty() + && TYPE_ATTR.equals(string)) { + xmlXsiTypeConverter = config.getXsiTypeMap().get(token); + } else if (!nilAttributeFound) { + jsonObject.accumulate(string, + config.isKeepStrings() + ? ((String) token) + : stringToValue((String) token)); + } + token = null; + } else { + jsonObject.accumulate(string, ""); + } + + + } else if (token == SLASH) { + // Empty tag <.../> + if (x.nextToken() != GT) { + + throw x.syntaxError("Misshaped tag"); + } + + if (config.getForceList().contains(tagName)) { + // Force the value to be an array + if (nilAttributeFound) { + context.append(tagName, JSONObject.NULL); + } else if (jsonObject.length() > 0) { + context.append(tagName, jsonObject); + } else { + context.put(tagName, new JSONArray()); + } + } else { + if (nilAttributeFound) { + context.accumulate(tagName, JSONObject.NULL); + } else if (jsonObject.length() > 0) { + context.accumulate(tagName, jsonObject); + } else { + context.accumulate(tagName, ""); + } + } + return false; + + + } else if (token == GT) { + // Content, between <...> and + for (; ; ) { + + token = x.nextContent(); +// System.out.println("token next Content: " + token); + if (token == null) { + if (tagName != null) { + throw x.syntaxError("Unclosed tag " + tagName); + } + return false; + } else if (token instanceof String) { + string = (String) token; + if (string.length() > 0) { + if (xmlXsiTypeConverter != null) { + jsonObject.accumulate(config.getcDataTagName(), + stringToValue(string, xmlXsiTypeConverter)); + } else { +// System.out.println("In"); + jsonObject.accumulate(config.getcDataTagName(), + config.isKeepStrings() ? string : stringToValue(string)); + } + } + + + } else if (token == LT) { + // Nested element +// System.out.println("In LT"); +// System.out.println(currPath + " ----" + desiredPath); + if (parse2(x, jsonObject, tagName, config, desiredPath, currPath, replacement)) { + + if (config.getForceList().contains(tagName)) { + // Force the value to be an array + if (jsonObject.length() == 0) { +// System.out.println("a" + tagName); + context.put(tagName, new JSONArray()); + } else if (jsonObject.length() == 1 + && jsonObject.opt(config.getcDataTagName()) != null) { +// System.out.println("b" + tagName); + context.append(tagName, jsonObject.opt(config.getcDataTagName())); + } else { +// System.out.println("c" + tagName); + context.append(tagName, jsonObject); + } + } else { + if (jsonObject.length() == 0) { +// System.out.println("d" + tagName); + context.accumulate(tagName, ""); + } else if (jsonObject.length() == 1 + && jsonObject.opt(config.getcDataTagName()) != null) { + if (currPath.equalsIgnoreCase(desiredPath)) { + +// System.out.println("tagName: " + tagName); + context.accumulate(tagName, replacement.get(tagName)); + } else { + context.accumulate(tagName, jsonObject.opt(config.getcDataTagName())); +// System.out.println("f" + tagName); + } + } else { +// System.out.println("e" + tagName); + if (currPath.equalsIgnoreCase(desiredPath)) { + context.accumulate(tagName, replacement); + } else { + context.accumulate(tagName, jsonObject); + } + + } +// System.out.println(currPath); +// System.out.println("context: " + context); + } + + return false; + } + } + + } + } else { + throw x.syntaxError("Misshaped tag"); + } + } + } + } + + // milestone 3 + private static boolean parse(XMLTokener x, JSONObject context, String name, XMLParserConfiguration config, Function keyTransformer) + throws JSONException { + char c; + int i; + JSONObject jsonObject = null; + String string; + String tagName; + Object token; + XMLXsiTypeConverter xmlXsiTypeConverter; + + // Test for and skip past these forms: + // + // + // + // + // Report errors for these forms: + // <> + // <= + // << + + token = x.nextToken(); +// System.out.println("token: " + token); + + // "); + return false; + } + x.back(); + } else if (c == '[') { + token = x.nextToken(); + if ("CDATA".equals(token)) { + if (x.next() == '[') { + string = x.nextCDATA(); + if (string.length() > 0) { + context.accumulate(config.getcDataTagName(), string); + } + return false; + } + } + throw x.syntaxError("Expected 'CDATA['"); + } + i = 1; + do { + token = x.nextMeta(); + if (token == null) { + throw x.syntaxError("Missing '>' after ' 0); + return false; + } else if (token == QUEST) { + + // "); // + return false; + } else if (token == SLASH) { + + // Close tag return True + if (x.nextToken() != GT) { + throw x.syntaxError("Misshaped tag"); + } + + String newTagName = keyTransformer.apply(tagName); + + if (config.getForceList().contains(tagName)) { + + // Force the value to be an array + if (nilAttributeFound) { + context.append(newTagName, JSONObject.NULL); + } else if (jsonObject.length() > 0) { + context.append(newTagName, jsonObject); + } else { + context.put(newTagName, new JSONArray()); + } + } else { + if (nilAttributeFound) { + context.accumulate(newTagName, JSONObject.NULL); + } else if (jsonObject.length() > 0) { + context.accumulate(newTagName, jsonObject); + } else { + context.accumulate(newTagName, ""); + } + } + return false; + + } else if (token == GT) { + // Content, between <...> and + for (; ; ) { + token = x.nextContent(); + if (token == null) { + if (tagName != null) { + throw x.syntaxError("Unclosed tag " + tagName); + } + return false; + } else if (token instanceof String) { + string = (String) token; + if (string.length() > 0) { + if (xmlXsiTypeConverter != null) { + jsonObject.accumulate(config.getcDataTagName(), + stringToValue(string, xmlXsiTypeConverter)); + } else { + jsonObject.accumulate(config.getcDataTagName(), + config.isKeepStrings() ? string : stringToValue(string)); + } + } + + } else if (token == LT) { + // Nested element + if (parse(x, jsonObject, tagName, config, keyTransformer)) { + String newTagName = keyTransformer.apply(tagName); + + if (config.getForceList().contains(tagName)) { + // Force the value to be an array + + if (jsonObject.length() == 0) { + context.put(newTagName, new JSONArray()); + } else if (jsonObject.length() == 1 + && jsonObject.opt(config.getcDataTagName()) != null) { + context.append(newTagName, jsonObject.opt(config.getcDataTagName())); + } else { + context.append(newTagName, jsonObject); + } + } else { + if (jsonObject.length() == 0) { + context.accumulate(newTagName, ""); + } else if (jsonObject.length() == 1 + && jsonObject.opt(config.getcDataTagName()) != null) { + context.accumulate(newTagName, jsonObject.opt(config.getcDataTagName())); + } else { + context.accumulate(newTagName, jsonObject); + } + } + + return false; + } + } + } + } else { + throw x.syntaxError("Misshaped tag"); + } + } + } + } + + /* + milestone 5 + + When a task is submitted to the ExecutorService, it is added to a queue of tasks to be executed. + The ExecutorService then uses a pool of worker threads to execute the tasks in the queue. + + The ExecutorService also provides a way to obtain a Future object when a task is submitted. + A Future represents the result of an asynchronous computation, and allows the calling thread to continue executing while the task is being processed by the worker thread. + The calling thread can later retrieve the result of the computation by calling the get() method on the Future. + */ + + public static Future toJSONObject(Reader reader, Function keyTransformer, + Consumer exceptionHandler) { + + ExecutorService executor = Executors.newSingleThreadExecutor(); + + Future future; + if (keyTransformer == null) { + exceptionHandler.accept(new Exception()); + return null; + } + //milestone 3 function using in lambda expression body as a task + future = executor.submit(()->XML.toJSONObject(reader, keyTransformer)); + + if (future.isDone()) { + executor.shutdown(); + } + return future; + } + } diff --git a/src/main/java/org/json/XMLParserConfiguration.java b/src/main/java/org/json/XMLParserConfiguration.java index a1fd63e..9f00710 100644 --- a/src/main/java/org/json/XMLParserConfiguration.java +++ b/src/main/java/org/json/XMLParserConfiguration.java @@ -1,26 +1,6 @@ package org.json; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import java.util.Collections; diff --git a/src/main/java/org/json/XMLTokener.java b/src/main/java/org/json/XMLTokener.java index 3bbd382..957498c 100644 --- a/src/main/java/org/json/XMLTokener.java +++ b/src/main/java/org/json/XMLTokener.java @@ -1,27 +1,7 @@ package org.json; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import java.io.Reader; diff --git a/src/main/java/org/json/XMLXsiTypeConverter.java b/src/main/java/org/json/XMLXsiTypeConverter.java index 0f8a8c3..0011eff 100644 --- a/src/main/java/org/json/XMLXsiTypeConverter.java +++ b/src/main/java/org/json/XMLXsiTypeConverter.java @@ -1,26 +1,6 @@ package org.json; /* -Copyright (c) 2002 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ /** diff --git a/src/test/java/org/json/junit/CDLTest.java b/src/test/java/org/json/junit/CDLTest.java index b8bdede..f3364fb 100644 --- a/src/test/java/org/json/junit/CDLTest.java +++ b/src/test/java/org/json/junit/CDLTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.*; diff --git a/src/test/java/org/json/junit/CookieListTest.java b/src/test/java/org/json/junit/CookieListTest.java index c3f647f..0af9640 100644 --- a/src/test/java/org/json/junit/CookieListTest.java +++ b/src/test/java/org/json/junit/CookieListTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.*; diff --git a/src/test/java/org/json/junit/CookieTest.java b/src/test/java/org/json/junit/CookieTest.java index 7e7b62b..edd8a7e 100644 --- a/src/test/java/org/json/junit/CookieTest.java +++ b/src/test/java/org/json/junit/CookieTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.*; diff --git a/src/test/java/org/json/junit/EnumTest.java b/src/test/java/org/json/junit/EnumTest.java index 6867123..1496a63 100644 --- a/src/test/java/org/json/junit/EnumTest.java +++ b/src/test/java/org/json/junit/EnumTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.assertEquals; diff --git a/src/test/java/org/json/junit/HTTPTest.java b/src/test/java/org/json/junit/HTTPTest.java index 8182b60..703d5ad 100644 --- a/src/test/java/org/json/junit/HTTPTest.java +++ b/src/test/java/org/json/junit/HTTPTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.*; diff --git a/src/test/java/org/json/junit/JSONArrayTest.java b/src/test/java/org/json/junit/JSONArrayTest.java index 946f407..1a2df7f 100644 --- a/src/test/java/org/json/junit/JSONArrayTest.java +++ b/src/test/java/org/json/junit/JSONArrayTest.java @@ -1,31 +1,12 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; +import static org.junit.Assert.assertNotEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; @@ -49,7 +30,9 @@ of this software and associated documentation files (the "Software"), to deal import org.json.JSONException; import org.json.JSONObject; import org.json.JSONPointerException; +import org.json.JSONString; import org.json.JSONTokener; +import org.json.junit.data.MyJsonString; import org.junit.Test; import com.jayway.jsonpath.Configuration; @@ -1354,4 +1337,25 @@ public void issue654StackOverflowInputWellFormed() { fail("Excepected Exception."); Util.checkJSONArrayMaps(json_input); } + + @Test + public void testIssue682SimilarityOfJSONString() { + JSONArray ja1 = new JSONArray() + .put(new MyJsonString()) + .put(2); + JSONArray ja2 = new JSONArray() + .put(new MyJsonString()) + .put(2); + assertTrue(ja1.similar(ja2)); + + JSONArray ja3 = new JSONArray() + .put(new JSONString() { + @Override + public String toJSONString() { + return "\"different value\""; + } + }) + .put(2); + assertFalse(ja1.similar(ja3)); + } } diff --git a/src/test/java/org/json/junit/JSONMLTest.java b/src/test/java/org/json/junit/JSONMLTest.java index 390cbd8..34bc9f0 100644 --- a/src/test/java/org/json/junit/JSONMLTest.java +++ b/src/test/java/org/json/junit/JSONMLTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.*; diff --git a/src/test/java/org/json/junit/JSONObjectLocaleTest.java b/src/test/java/org/json/junit/JSONObjectLocaleTest.java index 5112bf5..1cdaf74 100755 --- a/src/test/java/org/json/junit/JSONObjectLocaleTest.java +++ b/src/test/java/org/json/junit/JSONObjectLocaleTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.*; diff --git a/src/test/java/org/json/junit/JSONObjectNumberTest.java b/src/test/java/org/json/junit/JSONObjectNumberTest.java new file mode 100644 index 0000000..f6e13c6 --- /dev/null +++ b/src/test/java/org/json/junit/JSONObjectNumberTest.java @@ -0,0 +1,126 @@ +package org.json.junit; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +import java.math.BigDecimal; +import java.math.BigInteger; +import java.util.Arrays; +import java.util.Collection; + +import org.json.JSONObject; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.junit.runners.Parameterized; +import org.junit.runners.Parameterized.Parameters; + +@RunWith(value = Parameterized.class) +public class JSONObjectNumberTest { + private final String objectString; + private Integer value = 50; + + @Parameters(name = "{index}: {0}") + public static Collection data() { + return Arrays.asList(new Object[][]{ + {"{value:50}", 1}, + {"{value:50.0}", 1}, + {"{value:5e1}", 1}, + {"{value:5E1}", 1}, + {"{value:5e1}", 1}, + {"{value:'50'}", 1}, + {"{value:-50}", -1}, + {"{value:-50.0}", -1}, + {"{value:-5e1}", -1}, + {"{value:-5E1}", -1}, + {"{value:-5e1}", -1}, + {"{value:'-50'}", -1} + // JSON does not support octal or hex numbers; + // see https://stackoverflow.com/a/52671839/6323312 + // "{value:062}", // octal 50 + // "{value:0x32}" // hex 50 + }); + } + + public JSONObjectNumberTest(String objectString, int resultIsNegative) { + this.objectString = objectString; + this.value *= resultIsNegative; + } + + private JSONObject object; + + @Before + public void setJsonObject() { + object = new JSONObject(objectString); + } + + @Test + public void testGetNumber() { + assertEquals(value.intValue(), object.getNumber("value").intValue()); + } + + @Test + public void testGetBigDecimal() { + assertTrue(BigDecimal.valueOf(value).compareTo(object.getBigDecimal("value")) == 0); + } + + @Test + public void testGetBigInteger() { + assertEquals(BigInteger.valueOf(value), object.getBigInteger("value")); + } + + @Test + public void testGetFloat() { + assertEquals(value.floatValue(), object.getFloat("value"), 0.0f); + } + + @Test + public void testGetDouble() { + assertEquals(value.doubleValue(), object.getDouble("value"), 0.0d); + } + + @Test + public void testGetInt() { + assertEquals(value.intValue(), object.getInt("value")); + } + + @Test + public void testGetLong() { + assertEquals(value.longValue(), object.getLong("value")); + } + + @Test + public void testOptNumber() { + assertEquals(value.intValue(), object.optNumber("value").intValue()); + } + + @Test + public void testOptBigDecimal() { + assertTrue(BigDecimal.valueOf(value).compareTo(object.optBigDecimal("value", null)) == 0); + } + + @Test + public void testOptBigInteger() { + assertEquals(BigInteger.valueOf(value), object.optBigInteger("value", null)); + } + + @Test + public void testOptFloat() { + assertEquals(value.floatValue(), object.optFloat("value"), 0.0f); + } + + @Test + public void testOptDouble() { + assertEquals(value.doubleValue(), object.optDouble("value"), 0.0d); + } + + @Test + public void testOptInt() { + assertEquals(value.intValue(), object.optInt("value")); + } + + @Test + public void testOptLong() { + assertEquals(value.longValue(), object.optLong("value")); + } +} diff --git a/src/test/java/org/json/junit/JSONObjectTest.java b/src/test/java/org/json/junit/JSONObjectTest.java index 3681148..ea0cec3 100644 --- a/src/test/java/org/json/junit/JSONObjectTest.java +++ b/src/test/java/org/json/junit/JSONObjectTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.assertEquals; @@ -50,6 +30,7 @@ of this software and associated documentation files (the "Software"), to deal import org.json.JSONException; import org.json.JSONObject; import org.json.JSONPointerException; +import org.json.JSONString; import org.json.JSONTokener; import org.json.XML; import org.json.junit.data.BrokenToString; @@ -3507,4 +3488,25 @@ public void issue654StackOverflowInputWellFormed() { assertNotNull(json_input); fail("Excepected Exception."); } + + @Test + public void testIssue682SimilarityOfJSONString() { + JSONObject jo1 = new JSONObject() + .put("a", new MyJsonString()) + .put("b", 2); + JSONObject jo2 = new JSONObject() + .put("a", new MyJsonString()) + .put("b", 2); + assertTrue(jo1.similar(jo2)); + + JSONObject jo3 = new JSONObject() + .put("a", new JSONString() { + @Override + public String toJSONString() { + return "\"different value\""; + } + }) + .put("b", 2); + assertFalse(jo1.similar(jo3)); + } } diff --git a/src/test/java/org/json/junit/JSONPointerTest.java b/src/test/java/org/json/junit/JSONPointerTest.java index 4ea7434..45c7dbd 100644 --- a/src/test/java/org/json/junit/JSONPointerTest.java +++ b/src/test/java/org/json/junit/JSONPointerTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.assertEquals; @@ -92,8 +72,10 @@ public void queryByEmptyKey() { @Test public void queryByEmptyKeySubObject() { - assertEquals( "{\"\":\"empty key of an object with an empty key\",\"subKey\":\"Some" + - " other value\"}", query("/obj/").toString()); + JSONObject json = new JSONObject("{\"\":\"empty key of an object with an empty key\",\"subKey\":\"Some" + + " other value\"}"); + JSONObject obj = (JSONObject) query("/obj/"); + assertTrue(json.similar(obj)); } @Test diff --git a/src/test/java/org/json/junit/JSONStringTest.java b/src/test/java/org/json/junit/JSONStringTest.java index a199611..b4fee3e 100644 --- a/src/test/java/org/json/junit/JSONStringTest.java +++ b/src/test/java/org/json/junit/JSONStringTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.*; diff --git a/src/test/java/org/json/junit/JSONStringerTest.java b/src/test/java/org/json/junit/JSONStringerTest.java index a99db3b..0ecb9d6 100644 --- a/src/test/java/org/json/junit/JSONStringerTest.java +++ b/src/test/java/org/json/junit/JSONStringerTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.*; diff --git a/src/test/java/org/json/junit/JSONTokenerTest.java b/src/test/java/org/json/junit/JSONTokenerTest.java index e8e0f98..da716b8 100644 --- a/src/test/java/org/json/junit/JSONTokenerTest.java +++ b/src/test/java/org/json/junit/JSONTokenerTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.assertEquals; diff --git a/src/test/java/org/json/junit/Milestone4Test.java b/src/test/java/org/json/junit/Milestone4Test.java new file mode 100644 index 0000000..f48bd5c --- /dev/null +++ b/src/test/java/org/json/junit/Milestone4Test.java @@ -0,0 +1,64 @@ +package org.json.junit; + +import org.json.JSONObject; +import org.json.XML; +import org.junit.Test; + +import java.util.*; +import java.util.stream.Collectors; + + +import static org.junit.Assert.*; + +// Add streaming methods to the library that allow the client code to chain operations on JSON nodes + +public class Milestone4Test { + + + @Test + public void testForEach() { + JSONObject obj = XML.toJSONObject("AAAASmith" + + "BBBBSmith"); + + obj.toStream().forEach(node -> { + + for (String key : node.keySet()) { +// System.out.println(key); + Object value = node.get(key); + node.remove(key); + node.put(key + "_postfix", value); + + } + node.keySet().stream().forEach(modifiedKey -> assertTrue(modifiedKey.contains("_postfix"))); +// System.out.println(node); + }); + } + + @Test + public void testFilter() { + JSONObject obj = XML.toJSONObject("AAAASmith" + + "BBBBSmith"); + List JOwithTitles = obj.toStream().filter(node -> node.has("author")).collect(Collectors.toList()); +// System.out.println(JOwithTitles); + List expected = new ArrayList<>(); + JSONObject jo1 = XML.toJSONObject("ASmith"); + JSONObject jo2 = XML.toJSONObject("BSmith"); + expected.add(jo1); + expected.add(jo2); + for (int i = 0; i < JOwithTitles.size(); i++) { + assertEquals(expected.get(i).get("author"), JOwithTitles.get(i).get("author")); + } + } + + @Test + public void testMap() { + JSONObject obj = XML.toJSONObject("AAAASmith" + + "BBBBSmith"); + List titles = obj.toStream().map(node -> + (node.has("title")) ? node.getString("title") : null).filter(res -> res != null).collect(Collectors.toList()); + List expected = new ArrayList<>(); + expected.add("AAA"); + expected.add("BBB"); + assertEquals(expected, titles); + } +} \ No newline at end of file diff --git a/src/test/java/org/json/junit/Milestone5Test.java b/src/test/java/org/json/junit/Milestone5Test.java new file mode 100644 index 0000000..b5f510e --- /dev/null +++ b/src/test/java/org/json/junit/Milestone5Test.java @@ -0,0 +1,64 @@ +package org.json.junit; + +import org.json.JSONObject; +import org.json.XML; +import org.junit.Test; +import static org.junit.Assert.*; +import java.io.*; +import java.util.concurrent.ExecutionException; +import java.util.concurrent.Future; +import java.util.function.Consumer; +import java.util.function.Function; + +// Add asynchronous methods to the library that allow the client code to proceed, while specifying what to do when the JSONObject becomes available. +public class Milestone5Test { + /** + * Test on "Future toJSONObjectMS5(Reader reader, Function f, Consumer c)" + * Test whether the function can handle with XML successfully and return the correct output + */ + + String xml ="\n"+ + "\n"+ + " Crista \n"+ + " Crista Lopes\n" + + "

\n" + + " Ave of Nowhere\n" + + " 92614\n" + + "
\n" + + ""; + + String expect = "{\"SWE262_contact\":{\"SWE262_name\":\"Crista Lopes\",\"SWE262_nick\":\"Crista\",\"SWE262_address\":{\"SWE262_street\":\"Ave of Nowhere\",\"SWE262_zipcode\":92614}}}"; + + @Test + public void testSuccess(){ + try { + Reader reader = new StringReader(xml); + Function f = (key) -> "SWE262_" + key; + Consumer c = (e) -> e.printStackTrace(); + + // call the method to get future + Future future = XML.toJSONObject(reader, f, c); + JSONObject current = future.get(); + + // check equals + assertEquals(current.toString(), expect); + + } catch (ExecutionException e) { + e.printStackTrace(); + } catch (InterruptedException e) { + e.printStackTrace(); + } + } + + /** + * Test on "Future toJSONObjectMS5(Reader reader, Function k, Consumer c)" + * Test the exception occasion, expect print "No input function!" and future return NULL + */ + @Test + public void shouldThrowExecutionException() { + Reader reader = new StringReader(xml); + Consumer c = (e) -> System.out.println("No input function!"); + Future future = XML.toJSONObject(reader, null, c); + assertNull(future); + } +} \ No newline at end of file diff --git a/src/test/java/org/json/junit/PropertyTest.java b/src/test/java/org/json/junit/PropertyTest.java index e1a9b8d..eee482f 100644 --- a/src/test/java/org/json/junit/PropertyTest.java +++ b/src/test/java/org/json/junit/PropertyTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import java.util.*; diff --git a/src/test/java/org/json/junit/Util.java b/src/test/java/org/json/junit/Util.java index a4d0e22..b676045 100644 --- a/src/test/java/org/json/junit/Util.java +++ b/src/test/java/org/json/junit/Util.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.*; diff --git a/src/test/java/org/json/junit/XMLConfigurationTest.java b/src/test/java/org/json/junit/XMLConfigurationTest.java index 2ab06be..f9d24a6 100755 --- a/src/test/java/org/json/junit/XMLConfigurationTest.java +++ b/src/test/java/org/json/junit/XMLConfigurationTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.assertEquals; diff --git a/src/test/java/org/json/junit/XMLTest.java b/src/test/java/org/json/junit/XMLTest.java index 0155472..16cb8d6 100644 --- a/src/test/java/org/json/junit/XMLTest.java +++ b/src/test/java/org/json/junit/XMLTest.java @@ -1,27 +1,7 @@ package org.json.junit; /* -Copyright (c) 2020 JSON.org - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom the Software is -furnished to do so, subject to the following conditions: - -The above copyright notice and this permission notice shall be included in all -copies or substantial portions of the Software. - -The Software shall be used for Good, not Evil. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -SOFTWARE. +Public Domain. */ import static org.junit.Assert.assertEquals; @@ -41,15 +21,10 @@ of this software and associated documentation files (the "Software"), to deal import java.util.HashMap; import java.util.Map; -import org.json.JSONArray; -import org.json.JSONException; -import org.json.JSONObject; -import org.json.JSONTokener; -import org.json.XML; -import org.json.XMLParserConfiguration; -import org.json.XMLXsiTypeConverter; +import org.json.*; import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; @@ -1069,4 +1044,591 @@ public void testXSITypeMapNotModifiable() { fail("Expected to be unable to modify the config"); } catch (Exception ignored) { } } + + @Test + public void testIndentComplicatedJsonObject(){ + String str = "{\n" + + " \"success\": true,\n" + + " \"error\": null,\n" + + " \"response\": [\n" + + " {\n" + + " \"timestamp\": 1664917200,\n" + + " \"dateTimeISO\": \"2022-10-05T00:00:00+03:00\",\n" + + " \"loc\": {\n" + + " \"lat\": 39.91987,\n" + + " \"long\": 32.85427\n" + + " },\n" + + " \"place\": {\n" + + " \"name\": \"ankara\",\n" + + " \"state\": \"an\",\n" + + " \"country\": \"tr\"\n" + + " },\n" + + " \"profile\": {\n" + + " \"tz\": \"Europe/Istanbul\"\n" + + " },\n" + + " \"sun\": {\n" + + " \"rise\": 1664941721,\n" + + " \"riseISO\": \"2022-10-05T06:48:41+03:00\",\n" + + " \"set\": 1664983521,\n" + + " \"setISO\": \"2022-10-05T18:25:21+03:00\",\n" + + " \"transit\": 1664962621,\n" + + " \"transitISO\": \"2022-10-05T12:37:01+03:00\",\n" + + " \"midnightSun\": false,\n" + + " \"polarNight\": false,\n" + + " \"twilight\": {\n" + + " \"civilBegin\": 1664940106,\n" + + " \"civilBeginISO\": \"2022-10-05T06:21:46+03:00\",\n" + + " \"civilEnd\": 1664985136,\n" + + " \"civilEndISO\": \"2022-10-05T18:52:16+03:00\",\n" + + " \"nauticalBegin\": 1664938227,\n" + + " \"nauticalBeginISO\": \"2022-10-05T05:50:27+03:00\",\n" + + " \"nauticalEnd\": 1664987015,\n" + + " \"nauticalEndISO\": \"2022-10-05T19:23:35+03:00\",\n" + + " \"astronomicalBegin\": 1664936337,\n" + + " \"astronomicalBeginISO\": \"2022-10-05T05:18:57+03:00\",\n" + + " \"astronomicalEnd\": 1664988905,\n" + + " \"astronomicalEndISO\": \"2022-10-05T19:55:05+03:00\"\n" + + " }\n" + + " },\n" + + " \"moon\": {\n" + + " \"rise\": 1664976480,\n" + + " \"riseISO\": \"2022-10-05T16:28:00+03:00\",\n" + + " \"set\": 1664921520,\n" + + " \"setISO\": \"2022-10-05T01:12:00+03:00\",\n" + + " \"transit\": 1664994240,\n" + + " \"transitISO\": \"2022-10-05T21:24:00+03:00\",\n" + + " \"underfoot\": 1664949360,\n" + + " \"underfootISO\": \"2022-10-05T08:56:00+03:00\",\n" + + " \"phase\": {\n" + + " \"phase\": 0.3186,\n" + + " \"name\": \"waxing gibbous\",\n" + + " \"illum\": 71,\n" + + " \"age\": 9.41,\n" + + " \"angle\": 0.55\n" + + " }\n" + + " }\n" + + " }\n" + + " ]\n" + + "}" ; + JSONObject jsonObject = new JSONObject(str); + String actualIndentedXmlString = XML.toString(jsonObject, 1); + String expected = "true\n" + + "\n" + + " 2022-10-05T00:00:00+03:00\n" + + " \n" + + " 39.91987\n" + + " 32.85427\n" + + " \n" + + " \n" + + " \n" + + " 0.3186\n" + + " waxing gibbous\n" + + " 0.55\n" + + " 71\n" + + " 9.41\n" + + " \n" + + " 2022-10-05T01:12:00+03:00\n" + + " 1664949360\n" + + " 1664921520\n" + + " 1664994240\n" + + " 2022-10-05T21:24:00+03:00\n" + + " 2022-10-05T16:28:00+03:00\n" + + " 1664976480\n" + + " 2022-10-05T08:56:00+03:00\n" + + " \n" + + " \n" + + " Europe/Istanbul\n" + + " \n" + + " \n" + + " tr\n" + + " ankara\n" + + " an\n" + + " \n" + + " \n" + + " 2022-10-05T18:25:21+03:00\n" + + " false\n" + + " 1664983521\n" + + " 1664962621\n" + + " false\n" + + " 2022-10-05T12:37:01+03:00\n" + + " 2022-10-05T06:48:41+03:00\n" + + " 1664941721\n" + + " \n" + + " 1664985136\n" + + " 1664936337\n" + + " 1664988905\n" + + " 2022-10-05T05:18:57+03:00\n" + + " 1664940106\n" + + " 2022-10-05T19:23:35+03:00\n" + + " 2022-10-05T19:55:05+03:00\n" + + " 1664938227\n" + + " 1664987015\n" + + " 2022-10-05T05:50:27+03:00\n" + + " 2022-10-05T06:21:46+03:00\n" + + " 2022-10-05T18:52:16+03:00\n" + + " \n" + + " \n" + + " 1664917200\n" + + "\n" + + "null\n"; + assertEquals(actualIndentedXmlString, expected); + + + } + @Test + public void testIndentSimpleJsonObject(){ + String str = "{ \"employee\": { \n" + + " \"name\": \"sonoo\", \n" + + " \"salary\": 56000, \n" + + " \"married\": true \n" + + " }}"; + JSONObject jsonObject = new JSONObject(str); + String actual = XML.toString(jsonObject, "Test", 2); + String expected = "\n" + + " \n" + + " sonoo\n" + + " 56000\n" + + " true\n" + + " \n" + + "\n"; + assertEquals(actual, expected); + } + + @Test + public void testIndentSimpleJsonArray(){ + String str = "[ \n" + + " {\"name\":\"Ram\", \"email\":\"Ram@gmail.com\"}, \n" + + " {\"name\":\"Bob\", \"email\":\"bob32@gmail.com\"} \n" + + "] "; + JSONArray jsonObject = new JSONArray(str); + String actual = XML.toString(jsonObject, 2); + String expected = "\n" + + " Ram\n" + + " Ram@gmail.com\n" + + "\n" + + "\n" + + " Bob\n" + + " bob32@gmail.com\n" + + "\n"; + assertEquals(actual, expected); + + + } + + @Test + public void testIndentComplicatedJsonObjectWithArrayAndWithConfig(){ + try { + InputStream jsonStream = null; + try { + jsonStream = XMLTest.class.getClassLoader().getResourceAsStream("Issue593.json"); + final JSONObject object = new JSONObject(new JSONTokener(jsonStream)); + String actualString = XML.toString(object, null, XMLParserConfiguration.KEEP_STRINGS,2); + InputStream xmlStream = null; + try { + xmlStream = XMLTest.class.getClassLoader().getResourceAsStream("Issue593.xml"); + int bufferSize = 1024; + char[] buffer = new char[bufferSize]; + StringBuilder expected = new StringBuilder(); + Reader in = new InputStreamReader(xmlStream, "UTF-8"); + for (int numRead; (numRead = in.read(buffer, 0, buffer.length)) > 0; ) { + expected.append(buffer, 0, numRead); + } + assertEquals(expected.toString(), actualString.replaceAll("\\n|\\r\\n", System.getProperty("line.separator"))); + } finally { + if (xmlStream != null) { + xmlStream.close(); + } + } + } finally { + if (jsonStream != null) { + jsonStream.close(); + } + } + } catch (IOException e) { + fail("file writer error: " +e.getMessage()); + } + } + + @Test + public void testM2P1WithNoSlash_1(){ + String xmlString = "\n"+ + "\n"+ + " Crista \n"+ + " Crista Lopes\n" + + "
\n" + + " Ave of Nowhere\n" + + " 92614\n" + + "
\n" + + "
"; + JSONObject jobj = XML.toJSONObject(new StringReader(xmlString), new JSONPointer("/contact/address")); + String expectedJsonString = "{\"address\":{\"street\":\"Ave of Nowhere\",\"zipcode\":92614}}"; + JSONObject expectedJson = new JSONObject(expectedJsonString); + Util.compareActualVsExpectedJsonObjects(jobj, expectedJson); + } + + @Test + public void testM2P1WithNoSlash_2(){ + String xmlString = "\n"+ + "\n"+ + " Crista \n"+ + " Crista Lopes\n" + + "
\n" + + " Ave of Nowhere\n" + + " 92614\n" + + "
\n" + + "
"; + JSONObject jobj = XML.toJSONObject(new StringReader(xmlString), new JSONPointer("/contact")); + String expectedJsonString = "{\"contact\":{\"nick\":\"Crista\",\"address\":{\"zipcode\":92614,\"street\":\"Ave of Nowhere\"},\"name\":\"Crista Lopes\"}}"; + JSONObject expectedJson = new JSONObject(expectedJsonString); + Util.compareActualVsExpectedJsonObjects(jobj, expectedJson); + } + + @Test + public void testM2P1WithSlash() { + exceptionRule.expect(JSONPointerException.class); + exceptionRule.expectMessage("Invalid Path with '/' ending"); + String xmlString = "\n"+ + "\n"+ + " Crista \n"+ + " Crista Lopes\n" + + "
\n" + + " Ave of Nowhere\n" + + " 92614\n" + + "
\n" + + "
"; + XML.toJSONObject(new StringReader(xmlString), new JSONPointer("/contact/address/")); + } + + @Rule + public ExpectedException exceptionRule = ExpectedException.none(); + + @Test + public void testM2P1WrongPath() { + exceptionRule.expect(JSONPointerException.class); + exceptionRule.expectMessage("Path not found"); + String xmlString = "\n"+ + "\n"+ + " Crista \n"+ + " Crista Lopes\n" + + "
\n" + + " Ave of Nowhere\n" + + " 92614\n" + + "
\n" + + "
"; + XML.toJSONObject(new StringReader(xmlString), new JSONPointer("/contact/address/nooo")); + } + + @Test + public void testM2P2WithNoSlash_1(){ + String xmlString = "\n"+ + "\n"+ + " Crista \n"+ + " Crista Lopes\n" + + "
\n" + + " Ave of Nowhere\n" + + " 92614\n" + + "
\n" + + "
"; + JSONObject replacement = XML.toJSONObject("Ave of the Arts\n"); + JSONObject jobj = XML.toJSONObject(new StringReader(xmlString), new JSONPointer("/contact/address/street"), replacement); + String expectedJsonString = "{\"contact\":{\"nick\":\"Crista\",\"address\":{\"zipcode\":92614,\"street\":\"Ave of the Arts\"},\"name\":\"Crista Lopes\"}}"; + JSONObject expectedJson = new JSONObject(expectedJsonString); + Util.compareActualVsExpectedJsonObjects(jobj, expectedJson); + } + + @Test + public void testM2P2WithNoSlash_2(){ + String xmlString = "\n"+ + "\n"+ + " Crista \n"+ + " Crista Lopes\n" + + "
\n" + + " Ave of Nowhere\n" + + " 92614\n" + + "
\n" + + "
"; + JSONObject replacement = XML.toJSONObject("Ave of the Arts\n"); + JSONObject jobj = XML.toJSONObject(new StringReader(xmlString), new JSONPointer("/contact"), replacement); + String expectedJsonString = "{\"contact\":{\"street\":\"Ave of the Arts\"}}"; + JSONObject expectedJson = new JSONObject(expectedJsonString); + Util.compareActualVsExpectedJsonObjects(jobj, expectedJson); + } + + @Test + public void testM2P2WithSlash() { + exceptionRule.expect(JSONPointerException.class); + exceptionRule.expectMessage("Invalid Path with '/' ending"); + String xmlString = "\n"+ + "\n"+ + " Crista \n"+ + " Crista Lopes\n" + + "
\n" + + " Ave of Nowhere\n" + + " 92614\n" + + "
\n" + + "
"; + JSONObject replacement = XML.toJSONObject("Ave of the Arts\n"); + XML.toJSONObject(new StringReader(xmlString), new JSONPointer("/contact/address/"), replacement); + } + + @Test + public void testM2P2WrongPath() { + try{ + String xmlString = "\n"+ + "\n"+ + " Crista \n"+ + " Crista Lopes\n" + + "
\n" + + " Ave of Nowhere\n" + + " 92614\n" + + "
\n" + + "
"; + JSONObject replacement = XML.toJSONObject("Ave of the Arts\n"); + XML.toJSONObject(new StringReader(xmlString), new JSONPointer("/contact/address/nooo"), replacement); + fail("Should have thrown wrong path exception, but not!"); + } + catch (JSONPointerException e){ + String errorMessage = "Path not found"; + assertEquals(errorMessage, e.getMessage()); + } + + } + + @Test + public void testM3(){ + String xmlStr ="\n" + + "\n" + + " \n" + + " Gambardella, Matthew\n" + + " XML Developer's Guide\n" + + " Computer\n" + + " 44.95\n" + + " 2000-10-01\n" + + " An in-depth look at creating applications\n" + + " with XML.\n" + + " \n" + + " \n" + + " Ralls, Kim\n" + + " Midnight Rain\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-12-16\n" + + " A former architect battles corporate zombies,\n" + + " an evil sorceress, and her own childhood to become queen\n" + + " of the world.\n" + + " \n" + + " \n" + + " Corets, Eva\n" + + " Maeve Ascendant\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-11-17\n" + + " After the collapse of a nanotechnology\n" + + " society in England, the young survivors lay the\n" + + " foundation for a new society.\n" + + " \n" + + ""; + try { + Reader reader = new StringReader(xmlStr); + JSONObject jo = XML.toJSONObject(reader, s -> "SWE262_" + s); + reader.close(); + assertEquals("Correct result.","{\"SWE262_catalog\":{\"SWE262_book\":[{\"SWE262_author\":\"Gambardella, Matthew\",\"SWE262_title\":\"XML Developer's Guide\",\"SWE262_publish_date\":\"2000-10-01\",\"SWE262_genre\":\"Computer\",\"SWE262_description\":\"An in-depth look at creating applications\\n with XML.\",\"SWE262_id\":\"bk101\",\"SWE262_price\":44.95},{\"SWE262_author\":\"Ralls, Kim\",\"SWE262_title\":\"Midnight Rain\",\"SWE262_publish_date\":\"2000-12-16\",\"SWE262_genre\":\"Fantasy\",\"SWE262_description\":\"A former architect battles corporate zombies,\\n an evil sorceress, and her own childhood to become queen\\n of the world.\",\"SWE262_id\":\"bk102\",\"SWE262_price\":5.95},{\"SWE262_author\":\"Corets, Eva\",\"SWE262_title\":\"Maeve Ascendant\",\"SWE262_publish_date\":\"2000-11-17\",\"SWE262_genre\":\"Fantasy\",\"SWE262_description\":\"After the collapse of a nanotechnology\\n society in England, the young survivors lay the\\n foundation for a new society.\",\"SWE262_id\":\"bk103\",\"SWE262_price\":5.95}]}}", + jo.toString()); + } + catch (IOException e){ + System.out.println("Caught a IO Exception "); + e.printStackTrace(); + } + } + + @Test + public void testM3Reverse(){ + String xmlStr ="\n" + + "\n" + + " \n" + + " Gambardella, Matthew\n" + + " XML Developer's Guide\n" + + " Computer\n" + + " 44.95\n" + + " 2000-10-01\n" + + " An in-depth look at creating applications\n" + + " with XML.\n" + + " \n" + + " \n" + + " Ralls, Kim\n" + + " Midnight Rain\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-12-16\n" + + " A former architect battles corporate zombies,\n" + + " an evil sorceress, and her own childhood to become queen\n" + + " of the world.\n" + + " \n" + + " \n" + + " Corets, Eva\n" + + " Maeve Ascendant\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-11-17\n" + + " After the collapse of a nanotechnology\n" + + " society in England, the young survivors lay the\n" + + " foundation for a new society.\n" + + " \n" + + ""; + try { + Reader reader = new StringReader(xmlStr); + JSONObject jo = XML.toJSONObject(reader, s -> { + StringBuilder builder = new StringBuilder(s); + builder.reverse(); + return builder.toString(); + }); + reader.close(); + assertEquals("Correct result.", "{\"golatac\":{\"koob\":[{\"rohtua\":\"Gambardella, Matthew\",\"ecirp\":44.95,\"di\":\"bk101\",\"erneg\":\"Computer\",\"etad_hsilbup\":\"2000-10-01\",\"eltit\":\"XML Developer's Guide\",\"noitpircsed\":\"An in-depth look at creating applications\\n with XML.\"},{\"rohtua\":\"Ralls, Kim\",\"ecirp\":5.95,\"di\":\"bk102\",\"erneg\":\"Fantasy\",\"etad_hsilbup\":\"2000-12-16\",\"eltit\":\"Midnight Rain\",\"noitpircsed\":\"A former architect battles corporate zombies,\\n an evil sorceress, and her own childhood to become queen\\n of the world.\"},{\"rohtua\":\"Corets, Eva\",\"ecirp\":5.95,\"di\":\"bk103\",\"erneg\":\"Fantasy\",\"etad_hsilbup\":\"2000-11-17\",\"eltit\":\"Maeve Ascendant\",\"noitpircsed\":\"After the collapse of a nanotechnology\\n society in England, the young survivors lay the\\n foundation for a new society.\"}]}}", jo.toString()); + } + catch (IOException e){ + System.out.println("Caught a IO Exception "); + e.printStackTrace(); + } + } + + @Test + public void testM3WithEmptyString(){ + String xmlStr ="\n" + + "\n" + + " \n" + + " Gambardella, Matthew\n" + + " XML Developer's Guide\n" + + " Computer\n" + + " 44.95\n" + + " 2000-10-01\n" + + " An in-depth look at creating applications\n" + + " with XML.\n" + + " \n" + + " \n" + + " Ralls, Kim\n" + + " Midnight Rain\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-12-16\n" + + " A former architect battles corporate zombies,\n" + + " an evil sorceress, and her own childhood to become queen\n" + + " of the world.\n" + + " \n" + + " \n" + + " Corets, Eva\n" + + " Maeve Ascendant\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-11-17\n" + + " After the collapse of a nanotechnology\n" + + " society in England, the young survivors lay the\n" + + " foundation for a new society.\n" + + " \n" + + ""; + try { + Reader reader = new StringReader(xmlStr); + JSONObject jo = XML.toJSONObject(reader, s -> ""); + fail("Should have thrown empty string exception. "); + + } + catch (JSONException e){ + String expected = "Invalid: transform key to empty string"; + assertEquals(e.getMessage(), expected); + } + } + + @Test + public void testM3WithNull(){ + String xmlStr ="\n" + + "\n" + + " \n" + + " Gambardella, Matthew\n" + + " XML Developer's Guide\n" + + " Computer\n" + + " 44.95\n" + + " 2000-10-01\n" + + " An in-depth look at creating applications\n" + + " with XML.\n" + + " \n" + + " \n" + + " Ralls, Kim\n" + + " Midnight Rain\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-12-16\n" + + " A former architect battles corporate zombies,\n" + + " an evil sorceress, and her own childhood to become queen\n" + + " of the world.\n" + + " \n" + + " \n" + + " Corets, Eva\n" + + " Maeve Ascendant\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-11-17\n" + + " After the collapse of a nanotechnology\n" + + " society in England, the young survivors lay the\n" + + " foundation for a new society.\n" + + " \n" + + ""; + try { + Reader reader = new StringReader(xmlStr); + JSONObject jo = XML.toJSONObject(reader, s -> null); + fail("Should have thrown null exception. "); + + } + catch (JSONException e){ + String expected = "Invalid: transform key to null"; + assertEquals(e.getMessage(), expected); + } + } + + @Test + public void testM3WithDuplicateKeyName(){ + String xmlStr ="\n" + + "\n" + + " \n" + + " Gambardella, Matthew\n" + + " XML Developer's Guide\n" + + " Computer\n" + + " 44.95\n" + + " 2000-10-01\n" + + " An in-depth look at creating applications\n" + + " with XML.\n" + + " \n" + + " \n" + + " Ralls, Kim\n" + + " Midnight Rain\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-12-16\n" + + " A former architect battles corporate zombies,\n" + + " an evil sorceress, and her own childhood to become queen\n" + + " of the world.\n" + + " \n" + + " \n" + + " Corets, Eva\n" + + " Maeve Ascendant\n" + + " Fantasy\n" + + " 5.95\n" + + " 2000-11-17\n" + + " After the collapse of a nanotechnology\n" + + " society in England, the young survivors lay the\n" + + " foundation for a new society.\n" + + " \n" + + ""; + try { + Reader reader = new StringReader(xmlStr); + JSONObject jo = XML.toJSONObject(reader, s -> "random string"); + fail("Should have thrown duplicate exception. "); + + } + catch (JSONException e){ + String expected = "Invalid: transform key to all the same string"; + assertEquals(e.getMessage(), expected); + } + } } + + + diff --git a/src/test/resources/Issue593.json b/src/test/resources/Issue593.json new file mode 100644 index 0000000..213625a --- /dev/null +++ b/src/test/resources/Issue593.json @@ -0,0 +1,704 @@ +{ + "success": true, + "error": null, + "response": [ + { + "loc": { + "long": 31.25, + "lat": 30.063 + }, + "interval": "day", + "place": { + "name": "cairo", + "state": "qh", + "country": "eg" + }, + "periods": [ + { + "timestamp": 1665032400, + "validTime": "2022-10-06T07:00:00+02:00", + "dateTimeISO": "2022-10-06T07:00:00+02:00", + "maxTempC": 32, + "maxTempF": 90, + "minTempC": 19, + "minTempF": 66, + "avgTempC": 25, + "avgTempF": 78, + "tempC": null, + "tempF": null, + "maxFeelslikeC": 32, + "maxFeelslikeF": 89, + "minFeelslikeC": 21, + "minFeelslikeF": 70, + "avgFeelslikeC": 26, + "avgFeelslikeF": 80, + "feelslikeC": 21, + "feelslikeF": 70, + "maxDewpointC": 17, + "maxDewpointF": 63, + "minDewpointC": 11, + "minDewpointF": 52, + "avgDewpointC": 14, + "avgDewpointF": 58, + "dewpointC": 17, + "dewpointF": 63, + "maxHumidity": 77, + "minHumidity": 29, + "humidity": 77, + "pop": 0, + "precipMM": 0, + "precipIN": 0, + "iceaccum": null, + "iceaccumMM": null, + "iceaccumIN": null, + "snowCM": 0, + "snowIN": 0, + "pressureMB": 1015, + "pressureIN": 29.97, + "windDir": "N", + "windDirDEG": 353, + "windSpeedKTS": 5, + "windSpeedKPH": 9, + "windSpeedMPH": 6, + "windGustKTS": 21, + "windGustKPH": 40, + "windGustMPH": 25, + "windDirMax": "NNW", + "windDirMaxDEG": 342, + "windSpeedMaxKTS": 9, + "windSpeedMaxKPH": 16, + "windSpeedMaxMPH": 10, + "windDirMin": "N", + "windDirMinDEG": 353, + "windSpeedMinKTS": 1, + "windSpeedMinKPH": 2, + "windSpeedMinMPH": 1, + "windDir80m": "N", + "windDir80mDEG": 11, + "windSpeed80mKTS": 12, + "windSpeed80mKPH": 22, + "windSpeed80mMPH": 13, + "windGust80mKTS": 22, + "windGust80mKPH": 41, + "windGust80mMPH": 25, + "windDirMax80m": "NNW", + "windDirMax80mDEG": 343, + "windSpeedMax80mKTS": 22, + "windSpeedMax80mKPH": 41, + "windSpeedMax80mMPH": 25, + "windDirMin80m": "E", + "windDirMin80mDEG": 95, + "windSpeedMin80mKTS": 8, + "windSpeedMin80mKPH": 15, + "windSpeedMin80mMPH": 10, + "sky": 22, + "cloudsCoded": "FW", + "weather": "Mostly Sunny", + "weatherCoded": [], + "weatherPrimary": "Mostly Sunny", + "weatherPrimaryCoded": "::FW", + "icon": "fair.png", + "visibilityKM": 24.135, + "visibilityMI": 15, + "uvi": 6, + "solradWM2": 5608, + "solradMinWM2": 0, + "solradMaxWM2": 778, + "isDay": true, + "maxCoverage": "", + "sunrise": 1665028274, + "sunset": 1665070502, + "sunriseISO": "2022-10-06T05:51:14+02:00", + "sunsetISO": "2022-10-06T17:35:02+02:00" + }, + { + "timestamp": 1665118800, + "validTime": "2022-10-07T07:00:00+02:00", + "dateTimeISO": "2022-10-07T07:00:00+02:00", + "maxTempC": 30, + "maxTempF": 86, + "minTempC": 19, + "minTempF": 66, + "avgTempC": 24, + "avgTempF": 76, + "tempC": null, + "tempF": null, + "maxFeelslikeC": 29, + "maxFeelslikeF": 85, + "minFeelslikeC": 19, + "minFeelslikeF": 67, + "avgFeelslikeC": 24, + "avgFeelslikeF": 76, + "feelslikeC": 19, + "feelslikeF": 67, + "maxDewpointC": 15, + "maxDewpointF": 60, + "minDewpointC": 10, + "minDewpointF": 50, + "avgDewpointC": 12, + "avgDewpointF": 54, + "dewpointC": 15, + "dewpointF": 60, + "maxHumidity": 77, + "minHumidity": 30, + "humidity": 77, + "pop": 0, + "precipMM": 0, + "precipIN": 0, + "iceaccum": null, + "iceaccumMM": null, + "iceaccumIN": null, + "snowCM": 0, + "snowIN": 0, + "pressureMB": 1014, + "pressureIN": 29.95, + "windDir": "NW", + "windDirDEG": 325, + "windSpeedKTS": 1, + "windSpeedKPH": 2, + "windSpeedMPH": 1, + "windGustKTS": 16, + "windGustKPH": 29, + "windGustMPH": 18, + "windDirMax": "WNW", + "windDirMaxDEG": 298, + "windSpeedMaxKTS": 7, + "windSpeedMaxKPH": 13, + "windSpeedMaxMPH": 8, + "windDirMin": "NW", + "windDirMinDEG": 325, + "windSpeedMinKTS": 1, + "windSpeedMinKPH": 2, + "windSpeedMinMPH": 1, + "windDir80m": "NNW", + "windDir80mDEG": 347, + "windSpeed80mKTS": 6, + "windSpeed80mKPH": 10, + "windSpeed80mMPH": 6, + "windGust80mKTS": 20, + "windGust80mKPH": 37, + "windGust80mMPH": 23, + "windDirMax80m": "NW", + "windDirMax80mDEG": 316, + "windSpeedMax80mKTS": 20, + "windSpeedMax80mKPH": 37, + "windSpeedMax80mMPH": 23, + "windDirMin80m": "NNW", + "windDirMin80mDEG": 347, + "windSpeedMin80mKTS": 6, + "windSpeedMin80mKPH": 10, + "windSpeedMin80mMPH": 6, + "sky": 30, + "cloudsCoded": "FW", + "weather": "Mostly Sunny", + "weatherCoded": [], + "weatherPrimary": "Mostly Sunny", + "weatherPrimaryCoded": "::FW", + "icon": "fair.png", + "visibilityKM": 24.135, + "visibilityMI": 15, + "uvi": 6, + "solradWM2": 5486, + "solradMinWM2": 0, + "solradMaxWM2": 742, + "isDay": true, + "maxCoverage": "", + "sunrise": 1665114710, + "sunset": 1665156831, + "sunriseISO": "2022-10-07T05:51:50+02:00", + "sunsetISO": "2022-10-07T17:33:51+02:00" + }, + { + "timestamp": 1665205200, + "validTime": "2022-10-08T07:00:00+02:00", + "dateTimeISO": "2022-10-08T07:00:00+02:00", + "maxTempC": 30, + "maxTempF": 87, + "minTempC": 19, + "minTempF": 66, + "avgTempC": 25, + "avgTempF": 76, + "tempC": null, + "tempF": null, + "maxFeelslikeC": 30, + "maxFeelslikeF": 86, + "minFeelslikeC": 19, + "minFeelslikeF": 67, + "avgFeelslikeC": 25, + "avgFeelslikeF": 76, + "feelslikeC": 19, + "feelslikeF": 67, + "maxDewpointC": 15, + "maxDewpointF": 59, + "minDewpointC": 11, + "minDewpointF": 52, + "avgDewpointC": 13, + "avgDewpointF": 56, + "dewpointC": 15, + "dewpointF": 59, + "maxHumidity": 76, + "minHumidity": 32, + "humidity": 76, + "pop": 0, + "precipMM": 0, + "precipIN": 0, + "iceaccum": null, + "iceaccumMM": null, + "iceaccumIN": null, + "snowCM": 0, + "snowIN": 0, + "pressureMB": 1014, + "pressureIN": 29.94, + "windDir": "NNE", + "windDirDEG": 21, + "windSpeedKTS": 1, + "windSpeedKPH": 2, + "windSpeedMPH": 1, + "windGustKTS": 17, + "windGustKPH": 32, + "windGustMPH": 20, + "windDirMax": "WNW", + "windDirMaxDEG": 301, + "windSpeedMaxKTS": 7, + "windSpeedMaxKPH": 13, + "windSpeedMaxMPH": 8, + "windDirMin": "NNE", + "windDirMinDEG": 21, + "windSpeedMinKTS": 1, + "windSpeedMinKPH": 2, + "windSpeedMinMPH": 1, + "windDir80m": "NW", + "windDir80mDEG": 309, + "windSpeed80mKTS": 5, + "windSpeed80mKPH": 9, + "windSpeed80mMPH": 5, + "windGust80mKTS": 17, + "windGust80mKPH": 31, + "windGust80mMPH": 19, + "windDirMax80m": "NW", + "windDirMax80mDEG": 322, + "windSpeedMax80mKTS": 17, + "windSpeedMax80mKPH": 31, + "windSpeedMax80mMPH": 19, + "windDirMin80m": "NW", + "windDirMin80mDEG": 309, + "windSpeedMin80mKTS": 5, + "windSpeedMin80mKPH": 9, + "windSpeedMin80mMPH": 5, + "sky": 47, + "cloudsCoded": "SC", + "weather": "Partly Cloudy", + "weatherCoded": [], + "weatherPrimary": "Partly Cloudy", + "weatherPrimaryCoded": "::SC", + "icon": "pcloudy.png", + "visibilityKM": 24.135, + "visibilityMI": 15, + "uvi": 7, + "solradWM2": 4785, + "solradMinWM2": 0, + "solradMaxWM2": 682, + "isDay": true, + "maxCoverage": "", + "sunrise": 1665201146, + "sunset": 1665243161, + "sunriseISO": "2022-10-08T05:52:26+02:00", + "sunsetISO": "2022-10-08T17:32:41+02:00" + }, + { + "timestamp": 1665291600, + "validTime": "2022-10-09T07:00:00+02:00", + "dateTimeISO": "2022-10-09T07:00:00+02:00", + "maxTempC": 31, + "maxTempF": 87, + "minTempC": 19, + "minTempF": 67, + "avgTempC": 25, + "avgTempF": 77, + "tempC": null, + "tempF": null, + "maxFeelslikeC": 30, + "maxFeelslikeF": 86, + "minFeelslikeC": 20, + "minFeelslikeF": 67, + "avgFeelslikeC": 25, + "avgFeelslikeF": 77, + "feelslikeC": 20, + "feelslikeF": 67, + "maxDewpointC": 17, + "maxDewpointF": 63, + "minDewpointC": 11, + "minDewpointF": 52, + "avgDewpointC": 14, + "avgDewpointF": 57, + "dewpointC": 17, + "dewpointF": 63, + "maxHumidity": 86, + "minHumidity": 31, + "humidity": 86, + "pop": 0, + "precipMM": 0, + "precipIN": 0, + "iceaccum": null, + "iceaccumMM": null, + "iceaccumIN": null, + "snowCM": 0, + "snowIN": 0, + "pressureMB": 1016, + "pressureIN": 29.99, + "windDir": "N", + "windDirDEG": 356, + "windSpeedKTS": 2, + "windSpeedKPH": 4, + "windSpeedMPH": 2, + "windGustKTS": 19, + "windGustKPH": 36, + "windGustMPH": 22, + "windDirMax": "NNW", + "windDirMaxDEG": 343, + "windSpeedMaxKTS": 8, + "windSpeedMaxKPH": 14, + "windSpeedMaxMPH": 9, + "windDirMin": "N", + "windDirMinDEG": 356, + "windSpeedMinKTS": 2, + "windSpeedMinKPH": 4, + "windSpeedMinMPH": 2, + "windDir80m": "NW", + "windDir80mDEG": 316, + "windSpeed80mKTS": 5, + "windSpeed80mKPH": 9, + "windSpeed80mMPH": 6, + "windGust80mKTS": 20, + "windGust80mKPH": 36, + "windGust80mMPH": 23, + "windDirMax80m": "N", + "windDirMax80mDEG": 354, + "windSpeedMax80mKTS": 20, + "windSpeedMax80mKPH": 36, + "windSpeedMax80mMPH": 23, + "windDirMin80m": "NW", + "windDirMin80mDEG": 316, + "windSpeedMin80mKTS": 5, + "windSpeedMin80mKPH": 9, + "windSpeedMin80mMPH": 6, + "sky": 47, + "cloudsCoded": "SC", + "weather": "Partly Cloudy", + "weatherCoded": [], + "weatherPrimary": "Partly Cloudy", + "weatherPrimaryCoded": "::SC", + "icon": "pcloudy.png", + "visibilityKM": 24.135, + "visibilityMI": 15, + "uvi": 7, + "solradWM2": 4768, + "solradMinWM2": 0, + "solradMaxWM2": 726, + "isDay": true, + "maxCoverage": "", + "sunrise": 1665287583, + "sunset": 1665329491, + "sunriseISO": "2022-10-09T05:53:03+02:00", + "sunsetISO": "2022-10-09T17:31:31+02:00" + }, + { + "timestamp": 1665378000, + "validTime": "2022-10-10T07:00:00+02:00", + "dateTimeISO": "2022-10-10T07:00:00+02:00", + "maxTempC": 31, + "maxTempF": 87, + "minTempC": 21, + "minTempF": 70, + "avgTempC": 26, + "avgTempF": 78, + "tempC": null, + "tempF": null, + "maxFeelslikeC": 30, + "maxFeelslikeF": 86, + "minFeelslikeC": 21, + "minFeelslikeF": 69, + "avgFeelslikeC": 25, + "avgFeelslikeF": 78, + "feelslikeC": 21, + "feelslikeF": 69, + "maxDewpointC": 16, + "maxDewpointF": 61, + "minDewpointC": 13, + "minDewpointF": 55, + "avgDewpointC": 14, + "avgDewpointF": 58, + "dewpointC": 16, + "dewpointF": 61, + "maxHumidity": 75, + "minHumidity": 35, + "humidity": 75, + "pop": 0, + "precipMM": 0, + "precipIN": 0, + "iceaccum": null, + "iceaccumMM": null, + "iceaccumIN": null, + "snowCM": 0, + "snowIN": 0, + "pressureMB": 1017, + "pressureIN": 30.03, + "windDir": "N", + "windDirDEG": 358, + "windSpeedKTS": 2, + "windSpeedKPH": 4, + "windSpeedMPH": 2, + "windGustKTS": 16, + "windGustKPH": 30, + "windGustMPH": 19, + "windDirMax": "N", + "windDirMaxDEG": 10, + "windSpeedMaxKTS": 8, + "windSpeedMaxKPH": 15, + "windSpeedMaxMPH": 9, + "windDirMin": "N", + "windDirMinDEG": 358, + "windSpeedMinKTS": 2, + "windSpeedMinKPH": 4, + "windSpeedMinMPH": 2, + "windDir80m": "N", + "windDir80mDEG": 8, + "windSpeed80mKTS": 7, + "windSpeed80mKPH": 13, + "windSpeed80mMPH": 8, + "windGust80mKTS": 19, + "windGust80mKPH": 36, + "windGust80mMPH": 22, + "windDirMax80m": "N", + "windDirMax80mDEG": 10, + "windSpeedMax80mKTS": 19, + "windSpeedMax80mKPH": 36, + "windSpeedMax80mMPH": 22, + "windDirMin80m": "E", + "windDirMin80mDEG": 91, + "windSpeedMin80mKTS": 7, + "windSpeedMin80mKPH": 13, + "windSpeedMin80mMPH": 8, + "sky": 64, + "cloudsCoded": "SC", + "weather": "Partly Cloudy", + "weatherCoded": [], + "weatherPrimary": "Partly Cloudy", + "weatherPrimaryCoded": "::SC", + "icon": "pcloudy.png", + "visibilityKM": 24.135, + "visibilityMI": 15, + "uvi": 6, + "solradWM2": 4494, + "solradMinWM2": 0, + "solradMaxWM2": 597, + "isDay": true, + "maxCoverage": "", + "sunrise": 1665374020, + "sunset": 1665415821, + "sunriseISO": "2022-10-10T05:53:40+02:00", + "sunsetISO": "2022-10-10T17:30:21+02:00" + }, + { + "timestamp": 1665464400, + "validTime": "2022-10-11T07:00:00+02:00", + "dateTimeISO": "2022-10-11T07:00:00+02:00", + "maxTempC": 31, + "maxTempF": 87, + "minTempC": 21, + "minTempF": 70, + "avgTempC": 26, + "avgTempF": 78, + "tempC": null, + "tempF": null, + "maxFeelslikeC": 31, + "maxFeelslikeF": 87, + "minFeelslikeC": 22, + "minFeelslikeF": 72, + "avgFeelslikeC": 26, + "avgFeelslikeF": 79, + "feelslikeC": 22, + "feelslikeF": 72, + "maxDewpointC": 17, + "maxDewpointF": 62, + "minDewpointC": 11, + "minDewpointF": 51, + "avgDewpointC": 13, + "avgDewpointF": 55, + "dewpointC": 17, + "dewpointF": 62, + "maxHumidity": 71, + "minHumidity": 30, + "humidity": 71, + "pop": 0, + "precipMM": 0, + "precipIN": 0, + "iceaccum": null, + "iceaccumMM": null, + "iceaccumIN": null, + "snowCM": 0, + "snowIN": 0, + "pressureMB": 1015, + "pressureIN": 29.98, + "windDir": "NNE", + "windDirDEG": 13, + "windSpeedKTS": 8, + "windSpeedKPH": 15, + "windSpeedMPH": 9, + "windGustKTS": 15, + "windGustKPH": 28, + "windGustMPH": 17, + "windDirMax": "NNE", + "windDirMaxDEG": 28, + "windSpeedMaxKTS": 15, + "windSpeedMaxKPH": 28, + "windSpeedMaxMPH": 18, + "windDirMin": "NNE", + "windDirMinDEG": 14, + "windSpeedMinKTS": 7, + "windSpeedMinKPH": 14, + "windSpeedMinMPH": 8, + "windDir80m": "NNE", + "windDir80mDEG": 16, + "windSpeed80mKTS": 10, + "windSpeed80mKPH": 19, + "windSpeed80mMPH": 12, + "windGust80mKTS": 17, + "windGust80mKPH": 31, + "windGust80mMPH": 19, + "windDirMax80m": "NNE", + "windDirMax80mDEG": 28, + "windSpeedMax80mKTS": 17, + "windSpeedMax80mKPH": 31, + "windSpeedMax80mMPH": 19, + "windDirMin80m": "NNE", + "windDirMin80mDEG": 13, + "windSpeedMin80mKTS": 9, + "windSpeedMin80mKPH": 18, + "windSpeedMin80mMPH": 11, + "sky": 0, + "cloudsCoded": "CL", + "weather": "Sunny", + "weatherCoded": [], + "weatherPrimary": "Sunny", + "weatherPrimaryCoded": "::CL", + "icon": "sunny.png", + "visibilityKM": 24.135, + "visibilityMI": 15, + "uvi": null, + "solradWM2": 5450, + "solradMinWM2": 0, + "solradMaxWM2": 758, + "isDay": true, + "maxCoverage": "", + "sunrise": 1665460458, + "sunset": 1665502153, + "sunriseISO": "2022-10-11T05:54:18+02:00", + "sunsetISO": "2022-10-11T17:29:13+02:00" + }, + { + "timestamp": 1665550800, + "validTime": "2022-10-12T07:00:00+02:00", + "dateTimeISO": "2022-10-12T07:00:00+02:00", + "maxTempC": 31, + "maxTempF": 88, + "minTempC": 21, + "minTempF": 69, + "avgTempC": 26, + "avgTempF": 79, + "tempC": null, + "tempF": null, + "maxFeelslikeC": 31, + "maxFeelslikeF": 88, + "minFeelslikeC": 22, + "minFeelslikeF": 72, + "avgFeelslikeC": 26, + "avgFeelslikeF": 80, + "feelslikeC": 22, + "feelslikeF": 72, + "maxDewpointC": 16, + "maxDewpointF": 60, + "minDewpointC": 11, + "minDewpointF": 51, + "avgDewpointC": 13, + "avgDewpointF": 55, + "dewpointC": 16, + "dewpointF": 60, + "maxHumidity": 68, + "minHumidity": 29, + "humidity": 68, + "pop": 0, + "precipMM": 0, + "precipIN": 0, + "iceaccum": null, + "iceaccumMM": null, + "iceaccumIN": null, + "snowCM": 0, + "snowIN": 0, + "pressureMB": 1014, + "pressureIN": 29.95, + "windDir": "NNE", + "windDirDEG": 12, + "windSpeedKTS": 8, + "windSpeedKPH": 15, + "windSpeedMPH": 9, + "windGustKTS": 15, + "windGustKPH": 28, + "windGustMPH": 17, + "windDirMax": "E", + "windDirMaxDEG": 96, + "windSpeedMaxKTS": 14, + "windSpeedMaxKPH": 26, + "windSpeedMaxMPH": 16, + "windDirMin": "NNE", + "windDirMinDEG": 12, + "windSpeedMinKTS": 7, + "windSpeedMinKPH": 13, + "windSpeedMinMPH": 8, + "windDir80m": "NNE", + "windDir80mDEG": 15, + "windSpeed80mKTS": 10, + "windSpeed80mKPH": 19, + "windSpeed80mMPH": 12, + "windGust80mKTS": 18, + "windGust80mKPH": 33, + "windGust80mMPH": 21, + "windDirMax80m": "E", + "windDirMax80mDEG": 96, + "windSpeedMax80mKTS": 18, + "windSpeedMax80mKPH": 33, + "windSpeedMax80mMPH": 21, + "windDirMin80m": "NNE", + "windDirMin80mDEG": 15, + "windSpeedMin80mKTS": 10, + "windSpeedMin80mKPH": 18, + "windSpeedMin80mMPH": 11, + "sky": 27, + "cloudsCoded": "FW", + "weather": "Mostly Sunny", + "weatherCoded": [], + "weatherPrimary": "Mostly Sunny", + "weatherPrimaryCoded": "::FW", + "icon": "fair.png", + "visibilityKM": 24.135, + "visibilityMI": 15, + "uvi": null, + "solradWM2": 4740, + "solradMinWM2": 0, + "solradMaxWM2": 743, + "isDay": true, + "maxCoverage": "", + "sunrise": 1665546895, + "sunset": 1665588484, + "sunriseISO": "2022-10-12T05:54:55+02:00", + "sunsetISO": "2022-10-12T17:28:04+02:00" + } + ], + "profile": { + "tz": "Africa/Cairo", + "elevM": 23, + "elevFT": 75 + } + } + ] +} \ No newline at end of file diff --git a/src/test/resources/Issue593.xml b/src/test/resources/Issue593.xml new file mode 100644 index 0000000..0c6c038 --- /dev/null +++ b/src/test/resources/Issue593.xml @@ -0,0 +1,691 @@ +true + + + 31.25 + 30.063 + + + 23 + Africa/Cairo + 75 + + + 2022-10-06T07:00:00+02:00 + E + 95 + 21 + 15 + 10 + 353 + N + 2022-10-06T05:51:14+02:00 + null + 9 + null + 66 + 0 + Mostly Sunny + 2022-10-06T17:35:02+02:00 + 32 + 77 + N + 89 + 0 + 22 + 25 + 25 + Mostly Sunny + 41 + 58 + 41 + 22 + 14 + 0 + 22 + 353 + 16 + 8 + 70 + 2022-10-06T07:00:00+02:00 + 10 + 778 + 25 + 15 + ::FW + 1665028274 + 78 + N + + fair.png + 21 + 17 + FW + 70 + 29 + 63 + 12 + 0 + 0 + NNW + 13 + 22 + 11 + 32 + 1015 + 24.135 + 1665032400 + 90 + null + 11 + 0 + 1 + 343 + 21 + 2 + 63 + 1 + 26 + 6 + NNW + 17 + 29.97 + 80 + null + true + 19 + 52 + 5 + 1665070502 + 5608 + 9 + 25 + 77 + 6 + 40 + 342 + null + + + 2022-10-07T07:00:00+02:00 + NNW + 347 + 19 + 15 + 8 + 325 + NW + 2022-10-07T05:51:50+02:00 + null + 7 + null + 66 + 0 + Mostly Sunny + 2022-10-07T17:33:51+02:00 + 29 + 77 + NNW + 85 + 0 + 30 + 23 + 23 + Mostly Sunny + 37 + 54 + 37 + 20 + 12 + 0 + 20 + 325 + 13 + 6 + 67 + 2022-10-07T07:00:00+02:00 + 6 + 742 + 24 + 10 + ::FW + 1665114710 + 76 + NW + + fair.png + 19 + 15 + FW + 67 + 30 + 60 + 6 + 0 + 0 + WNW + 6 + 10 + 347 + 30 + 1014 + 24.135 + 1665118800 + 86 + null + 10 + 0 + 1 + 316 + 16 + 2 + 60 + 1 + 24 + 6 + NW + 15 + 29.95 + 76 + null + true + 19 + 50 + 1 + 1665156831 + 5486 + 2 + 18 + 77 + 1 + 29 + 298 + null + + + 2022-10-08T07:00:00+02:00 + NW + 309 + 19 + 15 + 8 + 21 + NNE + 2022-10-08T05:52:26+02:00 + null + 7 + null + 66 + 0 + Partly Cloudy + 2022-10-08T17:32:41+02:00 + 30 + 76 + NW + 86 + 0 + 47 + 19 + 19 + Partly Cloudy + 31 + 56 + 31 + 17 + 13 + 0 + 17 + 21 + 13 + 5 + 67 + 2022-10-08T07:00:00+02:00 + 5 + 682 + 25 + 9 + ::SC + 1665201146 + 76 + NNE + + pcloudy.png + 19 + 15 + SC + 67 + 32 + 59 + 5 + 0 + 0 + WNW + 5 + 9 + 309 + 30 + 1014 + 24.135 + 1665205200 + 87 + null + 11 + 0 + 1 + 322 + 17 + 2 + 59 + 1 + 25 + 7 + NW + 15 + 29.94 + 76 + null + true + 19 + 52 + 1 + 1665243161 + 4785 + 2 + 20 + 76 + 1 + 32 + 301 + null + + + 2022-10-09T07:00:00+02:00 + NW + 316 + 20 + 15 + 9 + 356 + N + 2022-10-09T05:53:03+02:00 + null + 8 + null + 67 + 0 + Partly Cloudy + 2022-10-09T17:31:31+02:00 + 30 + 86 + NW + 86 + 0 + 47 + 23 + 23 + Partly Cloudy + 36 + 57 + 36 + 20 + 14 + 0 + 20 + 356 + 14 + 5 + 67 + 2022-10-09T07:00:00+02:00 + 6 + 726 + 25 + 9 + ::SC + 1665287583 + 77 + N + + pcloudy.png + 20 + 17 + SC + 67 + 31 + 63 + 5 + 0 + 0 + NNW + 6 + 9 + 316 + 31 + 1016 + 24.135 + 1665291600 + 87 + null + 11 + 0 + 2 + 354 + 19 + 4 + 63 + 2 + 25 + 7 + N + 17 + 29.99 + 77 + null + true + 19 + 52 + 2 + 1665329491 + 4768 + 4 + 22 + 86 + 2 + 36 + 343 + null + + + 2022-10-10T07:00:00+02:00 + E + 91 + 21 + 15 + 9 + 358 + N + 2022-10-10T05:53:40+02:00 + null + 8 + null + 70 + 0 + Partly Cloudy + 2022-10-10T17:30:21+02:00 + 30 + 75 + N + 86 + 0 + 64 + 22 + 22 + Partly Cloudy + 36 + 58 + 36 + 19 + 14 + 0 + 19 + 358 + 15 + 7 + 69 + 2022-10-10T07:00:00+02:00 + 8 + 597 + 26 + 13 + ::SC + 1665374020 + 78 + N + + pcloudy.png + 21 + 16 + SC + 69 + 35 + 61 + 7 + 0 + 0 + N + 8 + 13 + 8 + 31 + 1017 + 24.135 + 1665378000 + 87 + null + 13 + 0 + 2 + 10 + 16 + 4 + 61 + 2 + 25 + 6 + N + 16 + 30.03 + 78 + null + true + 21 + 55 + 2 + 1665415821 + 4494 + 4 + 19 + 75 + 2 + 30 + 10 + null + + + 2022-10-11T07:00:00+02:00 + NNE + 13 + 22 + 15 + 18 + 13 + NNE + 2022-10-11T05:54:18+02:00 + null + 15 + null + 70 + 0 + Sunny + 2022-10-11T17:29:13+02:00 + 31 + 71 + NNE + 87 + 0 + 0 + 19 + 19 + Sunny + 31 + 55 + 31 + 17 + 13 + 0 + 17 + 14 + 28 + 9 + 72 + 2022-10-11T07:00:00+02:00 + 11 + 758 + 26 + 18 + ::CL + 1665460458 + 78 + NNE + + sunny.png + 22 + 17 + CL + 72 + 30 + 62 + 10 + 0 + 0 + NNE + 12 + 19 + 16 + 31 + 1015 + 24.135 + 1665464400 + 87 + null + 11 + 0 + 7 + 28 + 15 + 14 + 62 + 8 + 26 + null + NNE + 17 + 29.98 + 79 + null + true + 21 + 51 + 8 + 1665502153 + 5450 + 15 + 17 + 71 + 9 + 28 + 28 + null + + + 2022-10-12T07:00:00+02:00 + NNE + 15 + 22 + 15 + 16 + 12 + NNE + 2022-10-12T05:54:55+02:00 + null + 14 + null + 69 + 0 + Mostly Sunny + 2022-10-12T17:28:04+02:00 + 31 + 68 + NNE + 88 + 0 + 27 + 21 + 21 + Mostly Sunny + 33 + 55 + 33 + 18 + 13 + 0 + 18 + 12 + 26 + 10 + 72 + 2022-10-12T07:00:00+02:00 + 11 + 743 + 26 + 18 + ::FW + 1665546895 + 79 + NNE + + fair.png + 22 + 16 + FW + 72 + 29 + 60 + 10 + 0 + 0 + E + 12 + 19 + 15 + 31 + 1014 + 24.135 + 1665550800 + 88 + null + 11 + 0 + 7 + 96 + 15 + 13 + 60 + 8 + 26 + null + E + 16 + 29.95 + 80 + null + true + 21 + 51 + 8 + 1665588484 + 4740 + 15 + 17 + 68 + 9 + 28 + 96 + null + + day + + eg + cairo + qh + + +null