From 693bd970fce0ad040c3d97dae8b7554fe0e7b203 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Wed, 31 Aug 2016 17:52:04 -0500 Subject: [PATCH 01/48] See the change log section of README.txt for details. --- .classpath | 7 +- .gitignore | 9 + .project | 27 +- AUTHORS.txt | 3 - ChangeLog.txt | 28 - LICENSE.txt | 202 --- README.txt | 313 +++- VERSION.txt | 1 - build.xml | 41 - pom.xml | 158 +- .../json/simple/DeserializationException.java | 71 + src/main/java/org/json/simple/ItemList.java | 112 +- src/main/java/org/json/simple/JSONArray.java | 128 +- src/main/java/org/json/simple/JSONAware.java | 4 +- src/main/java/org/json/simple/JSONObject.java | 27 +- .../java/org/json/simple/JSONStreamAware.java | 6 +- src/main/java/org/json/simple/JSONValue.java | 38 +- src/main/java/org/json/simple/JsonArray.java | 261 ++++ src/main/java/org/json/simple/JsonObject.java | 264 ++++ src/main/java/org/json/simple/Jsonable.java | 18 + src/main/java/org/json/simple/Jsoner.java | 846 ++++++++++ src/main/java/org/json/simple/Yylex.java | 695 +++++++++ src/main/java/org/json/simple/Yytoken.java | 84 + .../json/simple/parser/ContainerFactory.java | 4 +- .../json/simple/parser/ContentHandler.java | 29 +- .../org/json/simple/parser/JSONParser.java | 90 +- .../json/simple/parser/ParseException.java | 47 +- .../java/org/json/simple/parser/Yylex.java | 1361 +++++++++-------- .../java/org/json/simple/parser/Yytoken.java | 38 +- {doc => src/main/lex}/json.lex | 0 src/main/lex/jsonstrict.lex | 59 + .../java/org/json/simple/JSONArrayTest.java | 545 +++---- .../java/org/json/simple/JSONValueTest.java | 561 ++++--- .../java/org/json/simple/JsonArrayTest.java | 196 +++ .../java/org/json/simple/JsonObjectTest.java | 167 ++ src/test/java/org/json/simple/JsonerTest.java | 479 ++++++ src/test/java/org/json/simple/Test.java | 383 ----- src/test/java/org/json/simple/YylexTest.java | 207 +++ .../json/simple/parser/JSONParserTest.java | 291 ++++ .../org/json/simple/parser/YylexTest.java | 146 +- test.xml | 48 - 41 files changed, 5892 insertions(+), 2102 deletions(-) create mode 100644 .gitignore delete mode 100644 AUTHORS.txt delete mode 100644 ChangeLog.txt delete mode 100644 LICENSE.txt delete mode 100644 VERSION.txt delete mode 100644 build.xml create mode 100644 src/main/java/org/json/simple/DeserializationException.java create mode 100644 src/main/java/org/json/simple/JsonArray.java create mode 100644 src/main/java/org/json/simple/JsonObject.java create mode 100644 src/main/java/org/json/simple/Jsonable.java create mode 100644 src/main/java/org/json/simple/Jsoner.java create mode 100644 src/main/java/org/json/simple/Yylex.java create mode 100644 src/main/java/org/json/simple/Yytoken.java rename {doc => src/main/lex}/json.lex (100%) create mode 100644 src/main/lex/jsonstrict.lex create mode 100644 src/test/java/org/json/simple/JsonArrayTest.java create mode 100644 src/test/java/org/json/simple/JsonObjectTest.java create mode 100644 src/test/java/org/json/simple/JsonerTest.java delete mode 100644 src/test/java/org/json/simple/Test.java create mode 100644 src/test/java/org/json/simple/YylexTest.java create mode 100644 src/test/java/org/json/simple/parser/JSONParserTest.java delete mode 100644 test.xml diff --git a/.classpath b/.classpath index 41c3da14..159850db 100644 --- a/.classpath +++ b/.classpath @@ -1,8 +1,9 @@ - - + + - + + diff --git a/.gitignore b/.gitignore new file mode 100644 index 00000000..5968b343 --- /dev/null +++ b/.gitignore @@ -0,0 +1,9 @@ +bin +target +.project +.classpath +.metadata +.settings +*.log +*.java~ +json-simple* diff --git a/.project b/.project index b1980df9..63ad8efc 100644 --- a/.project +++ b/.project @@ -1,17 +1,14 @@ - json-simple - - - - - - org.eclipse.jdt.core.javabuilder - - - - - - org.eclipse.jdt.core.javanature - - + json-simple + A simple Java toolkit for JSON. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. + + + + org.eclipse.jdt.core.javabuilder + + + + org.eclipse.jdt.core.javanature + + \ No newline at end of file diff --git a/AUTHORS.txt b/AUTHORS.txt deleted file mode 100644 index 8f2b7cb0..00000000 --- a/AUTHORS.txt +++ /dev/null @@ -1,3 +0,0 @@ -Yidong Fang -Chris Nokleberg -Dave Hughes diff --git a/ChangeLog.txt b/ChangeLog.txt deleted file mode 100644 index 481db746..00000000 --- a/ChangeLog.txt +++ /dev/null @@ -1,28 +0,0 @@ -ChangeLog - -Version 1.1.1 (2012/01/29) -* Supports OSGi -* Accepts a java.util.Map parameter in constructor of JSONObject - -Version 1.1 (2009/01/23) -* Supports stoppable SAX-like content handler for streaming of JSON text -* Added JSONStreamAware to support streaming JSON text -* Added ContainerFactory to support creating arbitrary Map and List as JSON object and JSON array container during decoding -* Supports any Map and List as JSON object and JSON array container during encoding -* Added interface JSONAware -* Added ParseException to get detail error report while parsing -* Added escaping for Unicode characters that cause problems for browser JS eval - -Version 1.02 (2009/01/10) -* Updated json.lex to improve performance of the lexer -* Removed Rope.java and related junit test - -Version 1.01 (2008/08/26) -* License changed to a more commerce friendly and clear one, Apache License 2.0 -* Use JFlex to generate a faster Yylex.java -* Added Rope.java to get faster string operations -* Separate test codes from source codes -* Added ant build file build.xml - -Version 1.0 (2006/04/15) -* Initial version diff --git a/LICENSE.txt b/LICENSE.txt deleted file mode 100644 index d6456956..00000000 --- a/LICENSE.txt +++ /dev/null @@ -1,202 +0,0 @@ - - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. diff --git a/README.txt b/README.txt index e31e82cf..cfe77531 100644 --- a/README.txt +++ b/README.txt @@ -1,2 +1,311 @@ -Please visit: -http://code.google.com/p/json-simple/ \ No newline at end of file +[EXAMPLES] +/* Quickly serialize stuff in json-simple: */ +Object stuff = null; +String serialized = Jsoner.serialize(stuff); +/* Deserialize stuff in json-simple by handling a DeserializationException: */ +try{ + Object deserialized = Jsoner.deserialize(serialized); +}catch(DeserializationException caught){ + /* Oops bad JSON. */ +} +/* When you know you only want a JsonObject or an empty one if it fails: */ +JsonObject deserializedObject = Jsoner.deserializeJsonObject(serialized, new JsonObject()); +/* When you know you only want a JsonArray or an empty one if it fails: */ +JsonArray deserializedArray = Jsoner.deserializeJsonArray(serialized, new JsonArray()); +/* When you want it to look pretty: */ +String prettyPrinted = Jsoner.prettyPrint(serialized); + +[AUTHORS] +Davin Loegering +Yidong Fang +Chris Nokleberg +Dave Hughes + +[DEVELOPERS] +Generate json-simple project files for eclipse: +mvn eclipse:eclipse + +Run unit tests: +mvn test + +Full build including javadocs: +mvn clean compile install package + +[CHANGE LOG] +Version 2.0.0 (2016/08/31) +* Davin Loegering was added to the list of Authors. +* Consolidated the author list, change log, and license files from the base directory into the README.txt file. +* Removed ant build file. +* SCM section of the POM is updated with the github information since the svn repo urls were 404s. +* POM now defines the source at 1.7 instead of 1.2, and is the only cause for the major version increment. The 2.0.0 release of this library is otherwise 100% backwards compatible with the older versions. +* Minor code quality changes have been made to the old files of the project. +* JFlex plugin now included in POM. +* JFlex will produce a lexing class from all lex files in src/main/lex. +* Javadocs are now produced when the jar goal is executed. +* Moved lex files from doc/ to src/main/lex. +* Deprecated the old json.lex in favor of jsonstrict.lex. +* Deprecated ContentHandler and doesn't have a 2.0 equivalent. +* Deprecated ContainerFactory and doesn't have a 2.0 equivalent. +* Deprecated ItemList and doesn't have a 2.0 equivalent. +* Deprecated JSONParse and JSONValue in favor of Jsoner. +* Deprecated JSONStreamAware and JSONAware in favor of Jsonable. +* Deprecated JSONObject in favor of JsonObject. +* Deprecated JSONArray in favor of JsonArray. +* Deprecated org.json.simple.parser.ParseException for org.json.simple.ParseException. +* Deprecated org.json.simple.parser.Yytoken for org.json.simple.Yytoken. +* Deprecated org.json.simple.parser.Yylex for org.json.simple.Yylex. +* Tests for deprecated classes have been reorganized and updated to ensure backwards compatibility is maintained throughout the 2.x release lifetime. +* Classes that have been deprecated still have shoddy javadocs but were updated to not produce errors and warnings during the build process. +* Classes introduced in the 2.0 release have substantial javadocs to help projects heathily update ASAP. +* The Jsonable interface allows others to define how their objects should be serialized in JSON. +* The new ParseException has a new problem type for disallowed tokens. +* The new ParseException now recommends recovery actions based on the problem that caused the ParseException in its message. All recovery scenarios are basically the same so ParseException is still the only json-simple exception class. +* The new Yytoken types are renamed. +* The new Yytoken is robustly constructed only allowing a null value when it is a null value in the DATUM tokens. +* Jsoner can escape strings provided to it to help with implementing the Jsonable interface. +* Jsoner can pretty print JSON strings provided to it for logging and basic display purposes. +* Jsoner can serialize data defined in the RFC 4627 specification and objects that implement the Jsonable interface. If data could be serialized multiple ways the deepest Jsonable implementation in the heiarchy is preferred. Any defined Jsonable implementation will be preferred before falling back to a default serialization. +* Jsoner can serialize an Enum that doesn't implement Jsonable. +* Jsoner will deserialize any numerical value as a BigDecimal. +* Jsoner can deserialize JsonArrays, JsonObjects, Strings, Numbers, Booleans, and null from strings provided to it. +* Jsoner can deserialize a JsonArray and exception out if any other value would be returned. +* Jsoner can deserialize a JsonObject and exception out if any other value would be returned. +* Jsoner can deserialize multiple JsonArrays, JsonObjects, Strings, Numbers, Booleans, and nulls from a single string provided to it. +* Jsoner deserialization (parsing) is thread safe. +* JsonArray is based on ArrayList. So it won't produce code warnings and can be used to construct a more convenient Collection. +* JsonArrays that are homogeneous can be cast and copied into a provided collection of the homogenous type. +* JsonArray contains gets for each allowed data type in JSON and convenience methods for Collections, Enums, and Maps. Note that they will throw ClassCastExceptions in such cases since it is still indictitive of a programmer's error. +* JsonObject is based on HashMap. +* JsonObject contains getOrDefaults for each allowed data type in JSON and convenience methods for Collections, Enums, and Maps. Note that they will throw ClassCastExceptions in such cases since it is still indictitive of a programmer's error. + +Version 1.1.1 (2012/01/29) +* Supports OSGi +* Accepts a java.util.Map parameter in constructor of JSONObject + +Version 1.1 (2009/01/23) +* Supports stoppable SAX-like content handler for streaming of JSON text +* Added JSONStreamAware to support streaming JSON text +* Added ContainerFactory to support creating arbitrary Map and List as JSON object and JSON array container during decoding +* Supports any Map and List as JSON object and JSON array container during encoding +* Added interface JSONAware +* Added ParseException to get detail error report while parsing +* Added escaping for Unicode characters that cause problems for browser JS eval + +Version 1.02 (2009/01/10) +* Updated json.lex to improve performance of the lexer +* Removed Rope.java and related junit test + +Version 1.01 (2008/08/26) +* License changed to a more commerce friendly and clear one, Apache License 2.0 +* Use JFlex to generate a faster Yylex.java +* Added Rope.java to get faster string operations +* Separate test codes from source codes +* Added ant build file build.xml + +Version 1.0 (2006/04/15) +* Initial version + +[LICENSE] + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright 2016 Clifton Labs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. + +Please visit: http://code.google.com/p/json-simple/ for the old version of the library. diff --git a/VERSION.txt b/VERSION.txt deleted file mode 100644 index 524cb552..00000000 --- a/VERSION.txt +++ /dev/null @@ -1 +0,0 @@ -1.1.1 diff --git a/build.xml b/build.xml deleted file mode 100644 index ff49be51..00000000 --- a/build.xml +++ /dev/null @@ -1,41 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/pom.xml b/pom.xml index bfa0b627..907b6955 100644 --- a/pom.xml +++ b/pom.xml @@ -2,47 +2,52 @@ 4.0.0 com.googlecode.json-simple json-simple - bundle + jar + JSON.simple - 1.1.1 A simple Java toolkit for JSON http://code.google.com/p/json-simple/ + + 2.0.0 + + + UTF-8 + + The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt + + + scm:git:https://github.com/cliftonlabs/json-simple.git + scm:git:https://github.com/cliftonlabs/json-simple.git + https://github.com/cliftonlabs/json-simple.git + + Yidong Yidong Fang - - architect - developer - - +8 + + + Davin Loegering + davin.loegering@cliftonlabs.com + Clifton Labs + https://cliftonlabs.com - - scm:svn:http://json-simple.googlecode.com/svn/trunk/ - scm:svn:http://json-simple.googlecode.com/svn/trunk/ - http://json-simple.googlecode.com/svn/trunk/ - - - - UTF-8 - junit junit - 4.10 - test + 4.12 + test - @@ -56,8 +61,8 @@ maven-compiler-plugin 2.3.2 - 1.2 - 1.2 + 1.7 + 1.7 @@ -65,47 +70,90 @@ maven-source-plugin 2.1.2 - - attach-sources - verify - - jar-no-fork - - + + attach-sources + verify + + jar-no-fork + + - - - - - - release-sign-artifacts - - - performRelease - true - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.4 + maven-javadoc-plugin + 2.8.1 - - sign-artifacts - verify - - sign - - + + attach-javadocs + + jar + + - - - + + de.jflex + maven-jflex-plugin + 1.4.3 + + + jlex + + generate + + + src/main/java + + src/main/lex + + true + + + + + + org.apache.maven.plugins + maven-jar-plugin + + + + true + true + + + + + + + + + release-sign-artifacts + + + performRelease + true + + + + + + org.apache.maven.plugins + maven-gpg-plugin + 1.4 + + + sign-artifacts + verify + + sign + + + + + + + - diff --git a/src/main/java/org/json/simple/DeserializationException.java b/src/main/java/org/json/simple/DeserializationException.java new file mode 100644 index 00000000..35ed3e33 --- /dev/null +++ b/src/main/java/org/json/simple/DeserializationException.java @@ -0,0 +1,71 @@ +/* See: README for this file's copyright, terms, and conditions. */ +package org.json.simple; + +/** DeserializationException explains why and where the exception occurs in source JSON text. + * + * @since 2.0.0 */ +public class DeserializationException extends Exception{ + /** The kinds of exceptions that can trigger a DeserializationException. */ + enum Problems{ + @SuppressWarnings("javadoc") + DISALLOWED_TOKEN, + @SuppressWarnings("javadoc") + UNEXPECTED_CHARACTER, + @SuppressWarnings("javadoc") + UNEXPECTED_EXCEPTION, + @SuppressWarnings("javadoc") + UNEXPECTED_TOKEN; + } + + private static final long serialVersionUID = -7880698968187728547L; + private final Problems problemType; + private final int position; + private final Object unexpectedObject; + + /** @param position where the exception occurred. + * @param problemType how the exception occurred. + * @param unexpectedObject what caused the exception. */ + public DeserializationException(final int position, final Problems problemType, final Object unexpectedObject){ + this.position = position; + this.problemType = problemType; + this.unexpectedObject = unexpectedObject; + } + + /** @return the enumeration for how the exception occurred. */ + public Problems getProblemType(){ + return this.problemType; + } + + @Override + public String getMessage(){ + final StringBuilder sb = new StringBuilder(); + switch(this.problemType){ + case DISALLOWED_TOKEN: + sb.append("The disallowed token (").append(this.unexpectedObject).append(") was found at position ").append(this.position).append(". If this is in error, try again with a parse that allows the token instead. Otherwise, fix the parsable string and try again."); + break; + case UNEXPECTED_CHARACTER: + sb.append("The unexpected character (").append(this.unexpectedObject).append(") was found at position ").append(this.position).append(". Fix the parsable string and try again."); + break; + case UNEXPECTED_TOKEN: + sb.append("The unexpected token ").append(this.unexpectedObject).append(" was found at position ").append(this.position).append(". Fix the parsable string and try again."); + break; + case UNEXPECTED_EXCEPTION: + sb.append("Please report this to the library's maintainer. The unexpected exception that should be addressed before trying again occurred at position ").append(this.position).append(": ").append(this.unexpectedObject); + break; + default: + sb.append("Please report this to the library's maintainer. An error at position ").append(this.position).append(" occurred. There are no recovery recommendations available."); + break; + } + return sb.toString(); + } + + /** @return an index of the string character the error type occurred at. */ + public int getPosition(){ + return this.position; + } + + /** @return a representation of what caused the exception. */ + public Object getUnexpectedObject(){ + return this.unexpectedObject; + } +} diff --git a/src/main/java/org/json/simple/ItemList.java b/src/main/java/org/json/simple/ItemList.java index 07231e67..ff748690 100644 --- a/src/main/java/org/json/simple/ItemList.java +++ b/src/main/java/org/json/simple/ItemList.java @@ -9,40 +9,75 @@ import java.util.StringTokenizer; /** - * |a:b:c| => |a|,|b|,|c| - * |:| => ||,|| - * |a:| => |a|,|| - * @author FangYidong + * |a:b:c| => |a|,|b|,|c| + * |:| => ||,|| + * |a:| => |a|,|| + * @author FangYidong<fangyidong@yahoo.com.cn> + * @deprecated since 2.0.0 all of the functionality provided by the class seems to be already provided in the JDK. */ +@Deprecated public class ItemList { private String sp=","; List items=new ArrayList(); + /** + * description omitted. + */ public ItemList(){} + /** + * @param s description omitted. + */ public ItemList(String s){ this.split(s,sp,items); } + /** + * @param s description omitted. + * @param sp description omitted. + */ public ItemList(String s,String sp){ this.sp=s; this.split(s,sp,items); } + /** + * @param s description omitted. + * @param sp description omitted. + * @param isMultiToken description omitted. + */ public ItemList(String s,String sp,boolean isMultiToken){ split(s,sp,items,isMultiToken); } + /** + * description omitted. + * + * @return description omitted. + */ public List getItems(){ return this.items; } + /** + * description omitted. + * + * @return description omitted. + */ public String[] getArray(){ return (String[])this.items.toArray(); } + /** + * description omitted. + * + * @param s description omitted. + * @param sp description omitted. + * @param append description omitted. + * @param isMultiToken description omitted. + */ public void split(String s,String sp,List append,boolean isMultiToken){ if(s==null || sp==null) return; @@ -57,6 +92,13 @@ public void split(String s,String sp,List append,boolean isMultiToken){ } } + /** + * description omitted. + * + * @param s description omitted. + * @param sp description omitted. + * @param append description omitted. + */ public void split(String s,String sp,List append){ if(s==null || sp==null) return; @@ -73,54 +115,104 @@ public void split(String s,String sp,List append){ append.add(s.substring(prevPos).trim()); } + /** + * description omitted. + * + * @param sp description omitted. + */ public void setSP(String sp){ this.sp=sp; } + /** + * description omitted. + * + * @param i description omitted. + * @param item description omitted. + */ public void add(int i,String item){ if(item==null) return; items.add(i,item.trim()); } + /** + * description omitted. + * + * @param item description omitted. + */ public void add(String item){ if(item==null) return; items.add(item.trim()); } + /** + * description omitted. + * + * @param list description omitted. + */ public void addAll(ItemList list){ items.addAll(list.items); } + /** + * description omitted. + * + * @param s description omitted. + */ public void addAll(String s){ this.split(s,sp,items); } + /** + * description omitted. + * + * @param s description omitted. + * @param sp description omitted. + */ public void addAll(String s,String sp){ this.split(s,sp,items); } + /** + * description omitted. + * + * @param s description omitted. + * @param sp description omitted. + * @param isMultiToken description omitted. + */ public void addAll(String s,String sp,boolean isMultiToken){ this.split(s,sp,items,isMultiToken); } /** * @param i 0-based - * @return + * @return description omitted. */ public String get(int i){ return (String)items.get(i); } + /** + * description omitted. + * + * @return description omitted. + */ public int size(){ return items.size(); } - + @Override public String toString(){ return toString(sp); } + /** + * description omitted. + * + * @param sp description omitted. + * @return description omitted. + */ public String toString(String sp){ StringBuffer sb=new StringBuffer(); @@ -136,10 +228,18 @@ public String toString(String sp){ } + /** + * description omitted. + * + */ public void clear(){ items.clear(); } + /** + * description omitted. + * + */ public void reset(){ sp=","; items.clear(); diff --git a/src/main/java/org/json/simple/JSONArray.java b/src/main/java/org/json/simple/JSONArray.java index 3a499d2e..14bbdb16 100644 --- a/src/main/java/org/json/simple/JSONArray.java +++ b/src/main/java/org/json/simple/JSONArray.java @@ -14,8 +14,10 @@ /** * A JSON array. JSONObject supports java.util.List interface. * - * @author FangYidong + * @author FangYidong<fangyidong@yahoo.com.cn> + * @deprecated since 2.0.0, replaced by {@link org.json.simple.JsonArray} */ +@Deprecated public class JSONArray extends ArrayList implements JSONAware, JSONStreamAware { private static final long serialVersionUID = 3957988303675231981L; @@ -42,8 +44,9 @@ public JSONArray(Collection c){ * * @see org.json.simple.JSONValue#writeJSONString(Object, Writer) * - * @param collection - * @param out + * @param collection description omitted. + * @param out description omitted. + * @throws IOException description omitted. */ public static void writeJSONString(Collection collection, Writer out) throws IOException{ if(collection == null){ @@ -82,7 +85,7 @@ public void writeJSONString(Writer out) throws IOException{ * * @see org.json.simple.JSONValue#toJSONString(Object) * - * @param collection + * @param collection description omitted. * @return JSON text, or "null" if list is null. */ public static String toJSONString(Collection collection){ @@ -97,6 +100,13 @@ public static String toJSONString(Collection collection){ } } + /** + * description omitted. + * + * @param array description omitted. + * @param out description omitted. + * @throws IOException description omitted. + */ public static void writeJSONString(byte[] array, Writer out) throws IOException{ if(array == null){ out.write("null"); @@ -115,6 +125,12 @@ public static void writeJSONString(byte[] array, Writer out) throws IOException{ } } + /** + * description omitted. + * + * @param array description omitted. + * @return description omitted. + */ public static String toJSONString(byte[] array){ final StringWriter writer = new StringWriter(); @@ -127,6 +143,13 @@ public static String toJSONString(byte[] array){ } } + /** + * description omitted. + * + * @param array description omitted. + * @param out description omitted. + * @throws IOException description omitted. + */ public static void writeJSONString(short[] array, Writer out) throws IOException{ if(array == null){ out.write("null"); @@ -145,6 +168,12 @@ public static void writeJSONString(short[] array, Writer out) throws IOException } } + /** + * description omitted. + * + * @param array description omitted. + * @return description omitted. + */ public static String toJSONString(short[] array){ final StringWriter writer = new StringWriter(); @@ -157,6 +186,13 @@ public static String toJSONString(short[] array){ } } + /** + * description omitted. + * + * @param array description omitted. + * @param out description omitted. + * @throws IOException description omitted. + */ public static void writeJSONString(int[] array, Writer out) throws IOException{ if(array == null){ out.write("null"); @@ -175,6 +211,12 @@ public static void writeJSONString(int[] array, Writer out) throws IOException{ } } + /** + * description omitted. + * + * @param array description omitted. + * @return description omitted. + */ public static String toJSONString(int[] array){ final StringWriter writer = new StringWriter(); @@ -187,6 +229,13 @@ public static String toJSONString(int[] array){ } } + /** + * description omitted. + * + * @param array description omitted. + * @param out description omitted. + * @throws IOException description omitted. + */ public static void writeJSONString(long[] array, Writer out) throws IOException{ if(array == null){ out.write("null"); @@ -205,6 +254,12 @@ public static void writeJSONString(long[] array, Writer out) throws IOException{ } } + /** + * description omitted. + * + * @param array description omitted. + * @return description omitted. + */ public static String toJSONString(long[] array){ final StringWriter writer = new StringWriter(); @@ -217,6 +272,13 @@ public static String toJSONString(long[] array){ } } + /** + * description omitted. + * + * @param array description omitted. + * @param out description omitted. + * @throws IOException description omitted. + */ public static void writeJSONString(float[] array, Writer out) throws IOException{ if(array == null){ out.write("null"); @@ -235,6 +297,12 @@ public static void writeJSONString(float[] array, Writer out) throws IOException } } + /** + * description omitted. + * + * @param array description omitted. + * @return description omitted. + */ public static String toJSONString(float[] array){ final StringWriter writer = new StringWriter(); @@ -247,6 +315,13 @@ public static String toJSONString(float[] array){ } } + /** + * description omitted. + * + * @param array description omitted. + * @param out description omitted. + * @throws IOException description omitted. + */ public static void writeJSONString(double[] array, Writer out) throws IOException{ if(array == null){ out.write("null"); @@ -265,6 +340,12 @@ public static void writeJSONString(double[] array, Writer out) throws IOExceptio } } + /** + * description omitted. + * + * @param array description omitted. + * @return description omitted. + */ public static String toJSONString(double[] array){ final StringWriter writer = new StringWriter(); @@ -277,6 +358,13 @@ public static String toJSONString(double[] array){ } } + /** + * description omitted. + * + * @param array description omitted. + * @param out description omitted. + * @throws IOException description omitted. + */ public static void writeJSONString(boolean[] array, Writer out) throws IOException{ if(array == null){ out.write("null"); @@ -295,6 +383,12 @@ public static void writeJSONString(boolean[] array, Writer out) throws IOExcepti } } + /** + * description omitted. + * + * @param array description omitted. + * @return description omitted. + */ public static String toJSONString(boolean[] array){ final StringWriter writer = new StringWriter(); @@ -307,6 +401,13 @@ public static String toJSONString(boolean[] array){ } } + /** + * description omitted. + * + * @param array description omitted. + * @param out description omitted. + * @throws IOException description omitted. + */ public static void writeJSONString(char[] array, Writer out) throws IOException{ if(array == null){ out.write("null"); @@ -325,6 +426,12 @@ public static void writeJSONString(char[] array, Writer out) throws IOException{ } } + /** + * description omitted. + * + * @param array description omitted. + * @return description omitted. + */ public static String toJSONString(char[] array){ final StringWriter writer = new StringWriter(); @@ -337,6 +444,13 @@ public static String toJSONString(char[] array){ } } + /** + * description omitted. + * + * @param array description omitted. + * @param out description omitted. + * @throws IOException description omitted. + */ public static void writeJSONString(Object[] array, Writer out) throws IOException{ if(array == null){ out.write("null"); @@ -355,6 +469,12 @@ public static void writeJSONString(Object[] array, Writer out) throws IOExceptio } } + /** + * description omitted. + * + * @param array description omitted. + * @return description omitted. + */ public static String toJSONString(Object[] array){ final StringWriter writer = new StringWriter(); diff --git a/src/main/java/org/json/simple/JSONAware.java b/src/main/java/org/json/simple/JSONAware.java index 89f15251..187f3c92 100644 --- a/src/main/java/org/json/simple/JSONAware.java +++ b/src/main/java/org/json/simple/JSONAware.java @@ -2,8 +2,10 @@ /** * Beans that support customized output of JSON text shall implement this interface. - * @author FangYidong + * @author FangYidong<fangyidong@yahoo.com.cn> + * @deprecated since 2.0.0, replaced by {@link org.json.simple.Jsonable} */ +@Deprecated public interface JSONAware { /** * @return JSON text diff --git a/src/main/java/org/json/simple/JSONObject.java b/src/main/java/org/json/simple/JSONObject.java index f565b3e3..bd69770b 100644 --- a/src/main/java/org/json/simple/JSONObject.java +++ b/src/main/java/org/json/simple/JSONObject.java @@ -14,13 +14,18 @@ /** * A JSON object. Key value pairs are unordered. JSONObject supports java.util.Map interface. * - * @author FangYidong + * @author FangYidong<fangyidong@yahoo.com.cn> + * @deprecated since 2.0.0, replaced by {@link org.json.simple.JsonObject} */ +@Deprecated public class JSONObject extends HashMap implements Map, JSONAware, JSONStreamAware{ private static final long serialVersionUID = -503443796854799292L; + /** + * + */ public JSONObject() { super(); } @@ -29,7 +34,7 @@ public JSONObject() { * Allows creation of a JSONObject from a Map. After that, both the * generated JSONObject and the Map can be modified independently. * - * @param map + * @param map description omitted. */ public JSONObject(Map map) { super(map); @@ -42,8 +47,9 @@ public JSONObject(Map map) { * * @see org.json.simple.JSONValue#writeJSONString(Object, Writer) * - * @param map - * @param out + * @param map description omitted. + * @param out description omitted. + * @throws IOException description omitted. */ public static void writeJSONString(Map map, Writer out) throws IOException { if(map == null){ @@ -80,7 +86,7 @@ public void writeJSONString(Writer out) throws IOException{ * * @see org.json.simple.JSONValue#toJSONString(Object) * - * @param map + * @param map description omitted. * @return JSON text, or "null" if map is null. */ public static String toJSONString(Map map){ @@ -103,6 +109,13 @@ public String toString(){ return toJSONString(); } + /** + * description omitted. + * + * @param key description omitted. + * @param value description omitted. + * @return description omitted. + */ public static String toString(String key,Object value){ StringBuffer sb = new StringBuffer(); sb.append('\"'); @@ -123,8 +136,8 @@ public static String toString(String key,Object value){ * * @see org.json.simple.JSONValue#escape(String) * - * @param s - * @return + * @param s description omitted. + * @return description omitted. */ public static String escape(String s){ return JSONValue.escape(s); diff --git a/src/main/java/org/json/simple/JSONStreamAware.java b/src/main/java/org/json/simple/JSONStreamAware.java index c2287c45..c9ed7b78 100644 --- a/src/main/java/org/json/simple/JSONStreamAware.java +++ b/src/main/java/org/json/simple/JSONStreamAware.java @@ -5,11 +5,15 @@ /** * Beans that support customized output of JSON text to a writer shall implement this interface. - * @author FangYidong + * @author FangYidong<fangyidong@yahoo.com.cn> + * @deprecated since 2.0.0, replaced by {@link org.json.simple.Jsonable} */ +@Deprecated public interface JSONStreamAware { /** * write JSON string to out. + * @param out description omitted. + * @throws IOException description omitted. */ void writeJSONString(Writer out) throws IOException; } diff --git a/src/main/java/org/json/simple/JSONValue.java b/src/main/java/org/json/simple/JSONValue.java index 2fddb217..16091c4b 100644 --- a/src/main/java/org/json/simple/JSONValue.java +++ b/src/main/java/org/json/simple/JSONValue.java @@ -18,8 +18,10 @@ /** - * @author FangYidong + * @author FangYidong<fangyidong@yahoo.com.cn> + * @deprecated since 2.0.0, replaced by {@link org.json.simple.Jsoner} */ +@Deprecated public class JSONValue { /** * Parse JSON text into java object from the input source. @@ -28,7 +30,7 @@ public class JSONValue { * @see org.json.simple.parser.JSONParser#parse(Reader) * @see #parseWithException(Reader) * - * @param in + * @param in description omitted. * @return Instance of the following: * org.json.simple.JSONObject, * org.json.simple.JSONArray, @@ -58,7 +60,7 @@ public static Object parse(Reader in){ * @see org.json.simple.parser.JSONParser#parse(Reader) * @see #parseWithException(Reader) * - * @param s + * @param s description omitted. * @return Instance of the following: * org.json.simple.JSONObject, * org.json.simple.JSONArray, @@ -81,7 +83,7 @@ public static Object parse(String s){ * * @see org.json.simple.parser.JSONParser * - * @param in + * @param in description omitted. * @return Instance of the following: * org.json.simple.JSONObject, * org.json.simple.JSONArray, @@ -90,14 +92,21 @@ public static Object parse(String s){ * java.lang.Boolean, * null * - * @throws IOException - * @throws ParseException + * @throws IOException description omitted. + * @throws ParseException description omitted. */ public static Object parseWithException(Reader in) throws IOException, ParseException{ JSONParser parser=new JSONParser(); return parser.parse(in); } + /** + * description omitted. + * + * @param s description omitted. + * @return description omitted. + * @throws ParseException description omitted. + */ public static Object parseWithException(String s) throws ParseException{ JSONParser parser=new JSONParser(); return parser.parse(s); @@ -112,10 +121,11 @@ public static Object parseWithException(String s) throws ParseException{ * "this" as the first parameter, use JSONObject.writeJSONString(Map, Writer) or JSONArray.writeJSONString(List, Writer) instead. * * @see org.json.simple.JSONObject#writeJSONString(Map, Writer) - * @see org.json.simple.JSONArray#writeJSONString(List, Writer) + * @see org.json.simple.JSONArray#writeJSONString(Collection, Writer) * - * @param value - * @param writer + * @param value description omitted. + * @param out description omitted. + * @throws IOException description omitted. */ public static void writeJSONString(Object value, Writer out) throws IOException { if(value == null){ @@ -233,9 +243,9 @@ public static void writeJSONString(Object value, Writer out) throws IOException * "this" as the parameter, use JSONObject.toJSONString(Map) or JSONArray.toJSONString(List) instead. * * @see org.json.simple.JSONObject#toJSONString(Map) - * @see org.json.simple.JSONArray#toJSONString(List) + * @see org.json.simple.JSONArray#toJSONString(Collection) * - * @param value + * @param value description omitted. * @return JSON text, or "null" if value is null or it's an NaN or an INF number. */ public static String toJSONString(Object value){ @@ -252,8 +262,8 @@ public static String toJSONString(Object value){ /** * Escape quotes, \, /, \r, \n, \b, \f, \t and other control characters (U+0000 through U+001F). - * @param s - * @return + * @param s description omitted. + * @return description omitted. */ public static String escape(String s){ if(s==null) @@ -265,7 +275,7 @@ public static String escape(String s){ /** * @param s - Must not be null. - * @param sb + * @param sb description omitted. */ static void escape(String s, StringBuffer sb) { final int len = s.length(); diff --git a/src/main/java/org/json/simple/JsonArray.java b/src/main/java/org/json/simple/JsonArray.java new file mode 100644 index 00000000..822e2f9a --- /dev/null +++ b/src/main/java/org/json/simple/JsonArray.java @@ -0,0 +1,261 @@ +/* See: README for this file's copyright, terms, and conditions. */ +package org.json.simple; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Iterator; +import java.util.Map; + +/** JsonArray is a common non-thread safe data format for listing data. The contents of a JsonArray are only validated as + * JSON values on serialization. + * @see Jsoner + * @since 2.0.0 */ +public class JsonArray extends ArrayList implements Jsonable{ + /** The serialization version this class is compatible + * with. This value doesn't need to be incremented if and only if the only changes to occur were updating comments, + * updating javadocs, adding new + * fields to the class, changing the fields from static to non-static, or changing the fields from transient to non + * transient. All other changes require this number be incremented. */ + private static final long serialVersionUID = 1L; + + /** Instantiates an empty JsonArray. */ + public JsonArray(){ + super(); + } + + /** Instantiate a new JsonArray using ArrayList's constructor of the same type. + * @param collection represents the elements to produce the JsonArray with. */ + public JsonArray(final Collection collection){ + super(collection); + } + + /** A convenience method that assumes every element of the JsonArray is castable to T before adding it to a + * collection of Ts. + * @param represents the type that all of the elements of the JsonArray should be cast to and the type the + * collection will contain. + * @param destination represents where all of the elements of the JsonArray are added to after being cast to the + * generic type + * provided. + * @throws ClassCastException if the unchecked cast of an element to T fails. */ + @SuppressWarnings("unchecked") + public void asCollection(final Collection destination){ + for(final Object o : this){ + destination.add((T)o); + } + } + + /** A convenience method that assumes there is a BigDecimal, Number, or String at the given index. If a Number or + * String is there it is used to construct a new BigDecimal. + * @param index representing where the value is expected to be at. + * @return the value stored at the key or the default provided if the key doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return types. + * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal. + * @see BigDecimal + * @see Number#doubleValue() */ + public BigDecimal getBigDecimal(final int index){ + Object returnable = this.get(index); + if(returnable instanceof BigDecimal){ + /* Success there was a BigDecimal. */ + }else if(returnable instanceof Number){ + /* A number can be used to construct a BigDecimal */ + returnable = new BigDecimal(returnable.toString()); + }else if(returnable instanceof String){ + /* A number can be used to construct a BigDecimal */ + returnable = new BigDecimal((String)returnable); + } + return (BigDecimal)returnable; + } + + /** A convenience method that assumes there is a boolean value at the given index. + * @param index represents where the value is expected to be at. + * @return the value at the index provided cast to a boolean. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. */ + public boolean getBoolean(final int index){ + return (boolean)this.get(index); + } + + /** A convenience method that assumes there is a Number value at the given index. + * @param index represents where the value is expected to be at. + * @return the value at the index provided cast to a byte. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. + * @see Number */ + public byte getByte(final int index){ + return ((Number)this.get(index)).byteValue(); + } + + /** A convenience method that assumes there is a Number value at the given index. + * @param index represents where the value is expected to be at. + * @return the value at the index provided cast to a double. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. + * @see Number */ + public double getDouble(final int index){ + return ((Number)this.get(index)).doubleValue(); + } + + /** A convenience method that assumes there is a String value at the given index representing a fully qualified name + * in dot notation of an enum. + * @param index representing where the value is expected to be at. + * @param the Enum type the value at the index is expected to belong to. + * @return the enum based on the string found at the index. + * @throws ClassNotFoundException if the element was a String but the declaring enum type couldn't be determined + * with it. + * @throws ClassCastException if the element at the index was not a String or if the fully qualified enum name is of + * the wrong type. + * @throws IllegalArgumentException if an enum type was dynamically determined but it doesn't define an enum with + * the dynamically determined name. + * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. + * @see Enum static method valueOf(Class, String). */ + @SuppressWarnings("unchecked") + public > T getEnum(final int index) throws ClassNotFoundException{ + /* Supressing the unchecked warning because the returnType is dynamically identified and could lead to a + * ClassCastException when returnType is cast to Class, which is expected by the method's contract. */ + T returnable; + final String element; + final String[] splitValues; + final int numberOfValues; + final StringBuilder returnTypeName; + final StringBuilder enumName; + final Class returnType; + /* Make sure the element at the index is a String. */ + element = this.getString(index); + /* Get the package, class, and enum names. */ + splitValues = element.split("\\."); + numberOfValues = splitValues.length; + returnTypeName = new StringBuilder(); + enumName = new StringBuilder(); + for(int i = 0; i < numberOfValues; i++){ + if(i == (numberOfValues - 1)){ + /* If it is the last split value then it should be the name of the Enum since dots are not allowed in + * enum names. */ + enumName.append(splitValues[i]); + }else if(i == (numberOfValues - 2)){ + /* If it is the penultimate split value then it should be the end of the package/enum type and not need + * a dot appended to it. */ + returnTypeName.append(splitValues[i]); + }else{ + /* Must be part of the package/enum type and will need a dot appended to it since they got removed in + * the split. */ + returnTypeName.append(splitValues[i]); + returnTypeName.append("."); + } + } + /* Use the package/class and enum names to get the Enum. */ + returnType = (Class)Class.forName(returnTypeName.toString()); + returnable = Enum.valueOf(returnType, enumName.toString()); + return returnable; + } + + /** A convenience method that assumes there is a Number value at the given index. + * @param index represents where the value is expected to be at. + * @return the value at the index provided cast to a float. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. + * @see Number */ + public float getFloat(final int index){ + return ((Number)this.get(index)).floatValue(); + } + + /** A convenience method that assumes there is a Number value at the given index. + * @param index represents where the value is expected to be at. + * @return the value at the index provided cast to a int. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. + * @see Number */ + public int getInteger(final int index){ + return ((Number)this.get(index)).intValue(); + } + + /** A convenience method that assumes there is a Collection value at the given index. + * @param the kind of collection to expect at the index. + * @param index represents where the value is expected to be at. + * @return the value at the index provided cast to a Collection. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. + * @see Collection */ + @SuppressWarnings("unchecked") + public > T getCollection(final int index){ + /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will work. */ + return (T)this.get(index); + } + + /** A convenience method that assumes there is a Map value at the given index. + * @param the kind of map to expect at the index. + * @param index represents where the value is expected to be at. + * @return the value at the index provided cast to a Map. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. + * @see Map */ + @SuppressWarnings("unchecked") + public > T getMap(final int index){ + /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will work. */ + return (T)this.get(index); + } + + /** A convenience method that assumes there is a Number value at the given index. + * @param index represents where the value is expected to be at. + * @return the value at the index provided cast to a long. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. + * @see Number */ + public long getLong(final int index){ + return ((Number)this.get(index)).longValue(); + } + + /** A convenience method that assumes there is a Number value at the given index. + * @param index represents where the value is expected to be at. + * @return the value at the index provided cast to a short. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. + * @see Number */ + public short getShort(final int index){ + return ((Number)this.get(index)).shortValue(); + } + + /** A convenience method that assumes there is a String value at the given index. + * @param index represents where the value is expected to be at. + * @return the value at the index provided cast to a String. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. */ + public String getString(final int index){ + return (String)this.get(index); + } + + /* (non-Javadoc) + * @see org.json.simple.Jsonable#asJsonString() */ + @Override + public String toJson(){ + final StringWriter writable = new StringWriter(); + try{ + this.toJson(writable); + }catch(final IOException caught){ + /* See java.io.StringWriter. */ + } + return writable.toString(); + } + + /* (non-Javadoc) + * @see org.json.simple.Jsonable#toJsonString(java.io.Writer) */ + @Override + public void toJson(final Writer writable) throws IOException{ + boolean isFirstElement = true; + final Iterator elements = this.iterator(); + writable.write('['); + while(elements.hasNext()){ + if(isFirstElement){ + isFirstElement = false; + }else{ + writable.write(','); + } + writable.write(Jsoner.serialize(elements.next())); + } + writable.write(']'); + } +} diff --git a/src/main/java/org/json/simple/JsonObject.java b/src/main/java/org/json/simple/JsonObject.java new file mode 100644 index 00000000..fe202cca --- /dev/null +++ b/src/main/java/org/json/simple/JsonObject.java @@ -0,0 +1,264 @@ +/* See: README for this file's copyright, terms, and conditions. */ +package org.json.simple; + +import java.io.IOException; +import java.io.StringWriter; +import java.io.Writer; +import java.math.BigDecimal; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.Map; + +/** JsonObject is a common non-thread safe data format for string to data mappings. The contents of a JsonObject are only + * validated as JSON values on serialization. + * @see Jsoner + * @since 2.0.0 */ +public class JsonObject extends HashMap implements Jsonable{ + /** The serialization version this class is compatible + * with. This value doesn't need to be incremented if and only if the only changes to occur were updating comments, + * updating javadocs, adding new + * fields to the class, changing the fields from static to non-static, or changing the fields from transient to non + * transient. All other changes require this number be incremented. */ + private static final long serialVersionUID = 1L; + + /** Instantiates an empty JsonObject. */ + public JsonObject(){ + super(); + } + + /** Instantiate a new JsonObject by accepting a map's entries, which could lead to de/serialization issues of the + * resulting JsonObject since the entry values aren't validated as JSON values. + * @param map represents the mappings to produce the JsonObject with. */ + public JsonObject(final Map map){ + super(map); + } + + /** A convenience method that assumes there is a BigDecimal, Number, or String at the given key. If a Number is there + * its Number#doubleValue() is used to construct a new BigDecimal(double). If a String is there it is used to + * construct a new BigDecimal(String). + * @param key representing where the value ought to be stored at. + * @param defaultValue representing what is returned when the key isn't in the JsonObject. + * @return the value stored at the key or the default provided if the key doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return types. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal. + * @see BigDecimal + * @see Number#doubleValue() */ + public BigDecimal getBigDecimalOrDefault(final String key, final BigDecimal defaultValue){ + Object returnable = this.getOrDefault(key, defaultValue); + if(returnable instanceof BigDecimal){ + /* Success there was a BigDecimal or it defaulted. */ + }else if(returnable instanceof Number){ + /* A number can be used to construct a BigDecimal */ + returnable = new BigDecimal(returnable.toString()); + }else if(returnable instanceof String){ + /* A number can be used to construct a BigDecimal */ + returnable = new BigDecimal((String)returnable); + } + return (BigDecimal)returnable; + } + + /** A convenience method that assumes there is a boolean value at the given key. + * @param key representing where the value ought to be stored at. + * @param defaultValue representing what is returned when the key isn't in the JsonObject. + * @return the value stored at the key or the default provided if the key doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return type. */ + public boolean getBooleanOrDefault(final String key, final boolean defaultValue){ + return (boolean)this.getOrDefault(key, defaultValue); + } + + /** A convenience method that assumes there is a Number value at the given key. + * @param key representing where the value ought to be stored at. + * @param defaultValue representing what is returned when the key isn't in the JsonObject. + * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key + * doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @see Number#byteValue() */ + public float getByteOrDefault(final String key, final byte defaultValue){ + return ((Number)this.getOrDefault(key, defaultValue)).byteValue(); + } + + /** A convenience method that assumes there is a Number value at the given key. + * @param key representing where the value ought to be stored at. + * @param defaultValue representing what is returned when the key isn't in the JsonObject. + * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key + * doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @see Number#doubleValue() */ + public double getDoubleOrDefault(final String key, final double defaultValue){ + return ((Number)this.getOrDefault(key, defaultValue)).doubleValue(); + } + + /** A convenience method that assumes there is a String value at the given key representing a fully qualified name in + * dot notation of an enum. + * @param key representing where the value ought to be stored at. + * @param defaultValue representing what is returned when the key isn't in the JsonObject. + * @param the Enum type the value at the key is expected to belong to. + * @return the enum based on the string found at the key, or the defaultValue provided if the key doesn't exist or + * an IllegalArgumentException or NullPointerException occurs due to the value lookup. + * @throws ClassNotFoundException if the value was a String but the declaring enum type couldn't be determined with + * it. + * @throws ClassCastException if the element at the index was not a String or if the fully qualified enum name is of + * the wrong type. + * @throws IllegalArgumentException if an enum type was determined but it doesn't define an enum with the determined + * name. + * @see Enum static method valueOf(Class, String) */ + @SuppressWarnings("unchecked") + public > T getEnumOrDefault(final String key, final T defaultValue) throws ClassNotFoundException{ + /* Supressing the unchecked warning because the returnType is dynamically identified and could lead to a + * ClassCastException when returnType is cast to Class, which is expected by the method's contract. */ + T returnable; + final String value; + final String[] splitValues; + final int numberOfSplitValues; + final StringBuilder returnTypeName; + final StringBuilder enumName; + final Class returnType; + /* Check to make sure the key wasn't actually there and wasn't coincidentally the defaulted String as its value. */ + if(this.containsKey(key)){ + /* Make sure the value at the key is a String. */ + value = this.getStringOrDefault(key, ""); + /* Get the package, class, and enum names. */ + splitValues = value.split("\\."); + numberOfSplitValues = splitValues.length; + returnTypeName = new StringBuilder(); + enumName = new StringBuilder(); + for(int i = 0; i < numberOfSplitValues; i++){ + if(i == (numberOfSplitValues - 1)){ + /* If it is the last split value then it should be the name of the Enum since dots are not allowed + * in enum names. */ + enumName.append(splitValues[i]); + }else if(i == (numberOfSplitValues - 2)){ + /* If it is the penultimate split value then it should be the end of the package/enum type and not + * need a dot appended to it. */ + returnTypeName.append(splitValues[i]); + }else{ + /* Must be part of the package/enum type and will need a dot appended to it since they got removed + * in the split. */ + returnTypeName.append(splitValues[i]); + returnTypeName.append("."); + } + } + /* Use the package/class and enum names to get the Enum. */ + returnType = (Class)Class.forName(returnTypeName.toString()); + returnable = Enum.valueOf(returnType, enumName.toString()); + return returnable; + }else{ + /* It wasn't there and according to the method's contract we return the default value. */ + returnable = defaultValue; + } + return returnable; + } + + /** A convenience method that assumes there is a Number value at the given key. + * @param key representing where the value ought to be stored at. + * @param defaultValue representing what is returned when the key isn't in the JsonObject. + * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key + * doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @see Number#floatValue() */ + public float getFloatOrDefault(final String key, final float defaultValue){ + return ((Number)this.getOrDefault(key, defaultValue)).floatValue(); + } + + /** A convenience method that assumes there is a Number value at the given key. + * @param key representing where the value ought to be stored at. + * @param defaultValue representing what is returned when the key isn't in the JsonObject. + * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key + * doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @see Number#intValue() */ + public int getIntegerOrDefault(final String key, final int defaultValue){ + return ((Number)this.getOrDefault(key, defaultValue)).intValue(); + } + + /** A convenience method that assumes there is a Collection at the given key. + * @param the kind of collection to expect at the key. + * @param key representing where the value ought to be stored at. + * @param defaultValue representing what is returned when the key isn't in the JsonObject. + * @return the value stored at the key or the default provided if the key doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return type. */ + @SuppressWarnings("unchecked") + public > T getCollectionOrDefault(final String key, final T defaultValue){ + /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will work. */ + return (T)this.getOrDefault(key, defaultValue); + } + + /** A convenience method that assumes there is a Map at the given key. + * @param the kind of map to expect at the key. + * @param key representing where the value ought to be stored at. + * @param defaultValue representing what is returned when the key isn't in the JsonObject. + * @return the value stored at the key or the default provided if the key doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return type. */ + @SuppressWarnings("unchecked") + public > T getMapOrDefault(final String key, final T defaultValue){ + /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will work. */ + return (T)this.getOrDefault(key, defaultValue); + } + + /** A convenience method that assumes there is a Number value at the given key. + * @param key representing where the value ought to be stored at. + * @param defaultValue representing what is returned when the key isn't in the JsonObject. + * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key + * doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @see Number#longValue() */ + public long getLongOrDefault(final String key, final long defaultValue){ + return ((Number)this.getOrDefault(key, defaultValue)).longValue(); + } + + /** A convenience method that assumes there is a Number value at the given key. + * @param key representing where the value ought to be stored at. + * @param defaultValue representing what is returned when the key isn't in the JsonObject. + * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key + * doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @see Number#shortValue() */ + public short getShortOrDefault(final String key, final short defaultValue){ + return ((Number)this.getOrDefault(key, defaultValue)).shortValue(); + } + + /** A convenience method that assumes there is a String value at the given key. + * @param key representing where the value ought to be stored at. + * @param defaultValue representing what is returned when the key isn't in the JsonObject. + * @return the value stored at the key or the default provided if the key doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return type. */ + public String getStringOrDefault(final String key, final String defaultValue){ + return (String)this.getOrDefault(key, defaultValue); + } + + /* (non-Javadoc) + * @see org.json.simple.Jsonable#asJsonString() */ + @Override + public String toJson(){ + final StringWriter writable = new StringWriter(); + try{ + this.toJson(writable); + }catch(final IOException caught){ + /* See java.io.StringWriter. */ + } + return writable.toString(); + } + + /* (non-Javadoc) + * @see org.json.simple.Jsonable#toJsonString(java.io.Writer) */ + @Override + public void toJson(final Writer writable) throws IOException{ + /* Writes the map in JSON object format. */ + boolean isFirstEntry = true; + final Iterator> entries = this.entrySet().iterator(); + writable.write('{'); + while(entries.hasNext()){ + if(isFirstEntry){ + isFirstEntry = false; + }else{ + writable.write(','); + } + final Map.Entry entry = entries.next(); + writable.write(Jsoner.serialize(entry.getKey())); + writable.write(':'); + writable.write(Jsoner.serialize(entry.getValue())); + } + writable.write('}'); + } +} diff --git a/src/main/java/org/json/simple/Jsonable.java b/src/main/java/org/json/simple/Jsonable.java new file mode 100644 index 00000000..e8d8f127 --- /dev/null +++ b/src/main/java/org/json/simple/Jsonable.java @@ -0,0 +1,18 @@ +/* See: README for this file's copyright, terms, and conditions. */ +package org.json.simple; + +import java.io.IOException; +import java.io.Writer; + +/** Jsonables can be serialized in java script object notation (JSON). + * @since 2.0.0 */ +public interface Jsonable{ + /** Serialize to a JSON formatted string. + * @return a string, formatted in JSON, that represents the Jsonable. */ + public String toJson(); + + /** Serialize to a JSON formatted stream. + * @param writable where the resulting JSON text should be sent. + * @throws IOException when the writable encounters an I/O error. */ + public void toJson(Writer writable) throws IOException; +} diff --git a/src/main/java/org/json/simple/Jsoner.java b/src/main/java/org/json/simple/Jsoner.java new file mode 100644 index 00000000..0ffa7dbd --- /dev/null +++ b/src/main/java/org/json/simple/Jsoner.java @@ -0,0 +1,846 @@ +/* See: README for this file's copyright, terms, and conditions. */ +package org.json.simple; + +import java.io.IOException; +import java.io.Reader; +import java.io.StringReader; +import java.io.StringWriter; +import java.io.Writer; +import java.util.Collection; +import java.util.EnumSet; +import java.util.Iterator; +import java.util.LinkedList; +import java.util.Map; +import java.util.Set; + +/** Jsoner provides JSON utilities for escaping strings to be JSON compatible, thread safe parsing (RFC 4627) JSON + * strings, and serializing data to strings in JSON format. + * @since 2.0.0 */ +public class Jsoner{ + /** Flags to tweak the behavior of the primary deserialization method. */ + private static enum DeserializationOptions{ + /** Whether a multiple JSON values can be deserialized as a root element. */ + ALLOW_CONCATENATED_JSON_VALUES, + /** Whether a JsonArray can be deserialized as a root element. */ + ALLOW_JSON_ARRAYS, + /** Whether a boolean, null, Number, or String can be deserialized as a root element. */ + ALLOW_JSON_DATA, + /** Whether a JsonObject can be deserialized as a root element. */ + ALLOW_JSON_OBJECTS; + } + + /** Flags to tweak the behavior of the primary serialization method. */ + private static enum SerializationOptions{ + /** Instead of aborting serialization on non-JSON values that are Enums it will continue serialization with the + * Enums' "${PACKAGE}.${DECLARING_CLASS}.${NAME}". + * @see Enum */ + ALLOW_FULLY_QUALIFIED_ENUMERATIONS, + /** Instead of aborting serialization on non-JSON values it will continue serialization by serializing the + * non-JSON value directly into the now invalid JSON. Be mindful that invalid JSON will not successfully + * deserialize. */ + ALLOW_INVALIDS, + /** Instead of aborting serialization on non-JSON values that implement Jsonable it will continue serialization + * by deferring serialization to the Jsonable. + * @see Jsonable */ + ALLOW_JSONABLES, + /** Instead of aborting serialization on non-JSON values it will continue serialization by using reflection to + * best describe the value as a JsonObject. */ + ALLOW_UNDEFINEDS; + } + + /** The possible States of a JSON deserializer. */ + private static enum States{ + /** Post-parsing state. */ + DONE, + /** Pre-parsing state. */ + INITIAL, + /** Parsing error, ParsingException should be thrown. */ + PARSED_ERROR, + PARSING_ARRAY, + /** Parsing a key-value pair inside of an object. */ + PARSING_ENTRY, + PARSING_OBJECT; + } + + private Jsoner(){ + /* Keeping it classy. */ + } + + /** Deserializes a readable stream according to the RFC 4627 JSON specification. + * @param readableDeserializable representing content to be deserialized as JSON. + * @return either a boolean, null, Number, String, JsonObject, or JsonArray that best represents the deserializable. + * @throws DeserializationException if an unexpected token is encountered in the deserializable. To recover from a + * DeserializationException: fix the deserializable + * to no longer have an unexpected token and try again. + * @throws IOException if the underlying reader encounters an I/O error. Ensure the reader is properly instantiated, + * isn't closed, or that it is ready before trying again. */ + public static Object deserialize(final Reader readableDeserializable) throws DeserializationException, IOException{ + return Jsoner.deserialize(readableDeserializable, EnumSet.of(DeserializationOptions.ALLOW_JSON_ARRAYS, DeserializationOptions.ALLOW_JSON_OBJECTS, DeserializationOptions.ALLOW_JSON_DATA)).get(0); + } + + /** Deserialize a stream with all deserialized JSON values are wrapped in a JsonArray. + * @param deserializable representing content to be deserialized as JSON. + * @param flags representing the allowances and restrictions on deserialization. + * @return the allowable object best represented by the deserializable. + * @throws DeserializationException if a disallowed or unexpected token is encountered in the deserializable. To + * recover from a DeserializationException: fix the + * deserializable to no longer have a disallowed or unexpected token and try again. + * @throws IOException if the underlying reader encounters an I/O error. Ensure the reader is properly instantiated, + * isn't closed, or that it is ready before trying again. */ + private static JsonArray deserialize(final Reader deserializable, final Set flags) throws DeserializationException, IOException{ + final Yylex lexer = new Yylex(deserializable); + Yytoken token; + States currentState; + int returnCount = 1; + final LinkedList stateStack = new LinkedList(); + final LinkedList valueStack = new LinkedList(); + stateStack.addLast(States.INITIAL); + //System.out.println("//////////DESERIALIZING//////////"); + do{ + /* Parse through the parsable string's tokens. */ + currentState = Jsoner.popNextState(stateStack); + token = Jsoner.lexNextToken(lexer); + switch(currentState){ + case DONE: + /* The parse has finished a JSON value. */ + if(flags.contains(DeserializationOptions.ALLOW_CONCATENATED_JSON_VALUES) && !Yytoken.Types.END.equals(token.getType())){ + /* Since there could be multiple JSON values treat the parse as if it is in the initial state. */ + returnCount += 1; + switch(token.getType()){ + case DATUM: + /* A boolean, null, Number, or String could be detected. */ + if(flags.contains(DeserializationOptions.ALLOW_JSON_DATA)){ + valueStack.addLast(token.getValue()); + stateStack.addLast(States.DONE); + }else{ + throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token); + } + break; + case LEFT_BRACE: + /* An object is detected. */ + if(flags.contains(DeserializationOptions.ALLOW_JSON_OBJECTS)){ + valueStack.addLast(new JsonObject()); + stateStack.addLast(States.PARSING_OBJECT); + }else{ + throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token); + } + break; + case LEFT_SQUARE: + /* An array is detected. */ + if(flags.contains(DeserializationOptions.ALLOW_JSON_ARRAYS)){ + valueStack.addLast(new JsonArray()); + stateStack.addLast(States.PARSING_ARRAY); + }else{ + throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token); + } + break; + default: + /* Neither a JSON array or object was detected. */ + throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token); + } + } + break; + case INITIAL: + /* The parse has just started. */ + switch(token.getType()){ + case DATUM: + /* A boolean, null, Number, or String could be detected. */ + if(flags.contains(DeserializationOptions.ALLOW_JSON_DATA)){ + valueStack.addLast(token.getValue()); + stateStack.addLast(States.DONE); + }else{ + throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token); + } + break; + case LEFT_BRACE: + /* An object is detected. */ + if(flags.contains(DeserializationOptions.ALLOW_JSON_OBJECTS)){ + valueStack.addLast(new JsonObject()); + stateStack.addLast(States.PARSING_OBJECT); + }else{ + throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token); + } + break; + case LEFT_SQUARE: + /* An array is detected. */ + if(flags.contains(DeserializationOptions.ALLOW_JSON_ARRAYS)){ + valueStack.addLast(new JsonArray()); + stateStack.addLast(States.PARSING_ARRAY); + }else{ + throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.DISALLOWED_TOKEN, token); + } + break; + default: + /* Neither a JSON array or object was detected. */ + throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token); + } + break; + case PARSED_ERROR: + /* The parse could be in this state due to the state stack not having a state to pop off. */ + throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token); + case PARSING_ARRAY: + switch(token.getType()){ + case COMMA: + /* The parse could detect a comma while parsing an array since it separates each element. */ + stateStack.addLast(currentState); + break; + case DATUM: + /* The parse found an element of the array. */ + JsonArray val = (JsonArray)valueStack.getLast(); + val.add(token.getValue()); + stateStack.addLast(currentState); + break; + case LEFT_BRACE: + /* The parse found an object in the array. */ + val = (JsonArray)valueStack.getLast(); + final JsonObject object = new JsonObject(); + val.add(object); + valueStack.addLast(object); + stateStack.addLast(currentState); + stateStack.addLast(States.PARSING_OBJECT); + break; + case LEFT_SQUARE: + /* The parse found another array in the array. */ + val = (JsonArray)valueStack.getLast(); + final JsonArray array = new JsonArray(); + val.add(array); + valueStack.addLast(array); + stateStack.addLast(currentState); + stateStack.addLast(States.PARSING_ARRAY); + break; + case RIGHT_SQUARE: + /* The parse found the end of the array. */ + if(valueStack.size() > returnCount){ + valueStack.removeLast(); + }else{ + /* The parse has been fully resolved. */ + stateStack.addLast(States.DONE); + } + break; + default: + /* Any other token is invalid in an array. */ + throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token); + } + break; + case PARSING_OBJECT: + /* The parse has detected the start of an object. */ + switch(token.getType()){ + case COMMA: + /* The parse could detect a comma while parsing an object since it separates each key value + * pair. Continue parsing the object. */ + stateStack.addLast(currentState); + break; + case DATUM: + /* The token ought to be a key. */ + if(token.getValue() instanceof String){ + /* JSON keys are always strings, strings are not always JSON keys but it is going to be + * treated as one. Continue parsing the object. */ + final String key = (String)token.getValue(); + valueStack.addLast(key); + stateStack.addLast(currentState); + stateStack.addLast(States.PARSING_ENTRY); + }else{ + /* Abort! JSON keys are always strings and it wasn't a string. */ + throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token); + } + break; + case RIGHT_BRACE: + /* The parse has found the end of the object. */ + if(valueStack.size() > returnCount){ + /* There are unresolved values remaining. */ + valueStack.removeLast(); + }else{ + /* The parse has been fully resolved. */ + stateStack.addLast(States.DONE); + } + break; + default: + /* The parse didn't detect the end of an object or a key. */ + throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token); + } + break; + case PARSING_ENTRY: + switch(token.getType()){ + /* Parsed pair keys can only happen while parsing objects. */ + case COLON: + /* The parse could detect a colon while parsing a key value pair since it separates the key + * and value from each other. Continue parsing the entry. */ + stateStack.addLast(currentState); + break; + case DATUM: + /* The parse has found a value for the parsed pair key. */ + String key = (String)valueStack.removeLast(); + JsonObject parent = (JsonObject)valueStack.getLast(); + parent.put(key, token.getValue()); + break; + case LEFT_BRACE: + /* The parse has found an object for the parsed pair key. */ + key = (String)valueStack.removeLast(); + parent = (JsonObject)valueStack.getLast(); + final JsonObject object = new JsonObject(); + parent.put(key, object); + valueStack.addLast(object); + stateStack.addLast(States.PARSING_OBJECT); + break; + case LEFT_SQUARE: + /* The parse has found an array for the parsed pair key. */ + key = (String)valueStack.removeLast(); + parent = (JsonObject)valueStack.getLast(); + final JsonArray array = new JsonArray(); + parent.put(key, array); + valueStack.addLast(array); + stateStack.addLast(States.PARSING_ARRAY); + break; + default: + /* The parse didn't find anything for the parsed pair key. */ + throw new DeserializationException(lexer.getPosition(), DeserializationException.Problems.UNEXPECTED_TOKEN, token); + } + break; + default: + break; + } + //System.out.println("~~~~~~~~~~~~~~~~~~~~~~~~~~~"); + //System.out.println(currentState); + //System.out.println(token); + //System.out.println(valueStack); + //System.out.println(stateStack); + /* If we're not at the END and DONE then do the above again. */ + }while(!(States.DONE.equals(currentState) && Yytoken.Types.END.equals(token.getType()))); + //System.out.println("!!!!!!!!!!DESERIALIZED!!!!!!!!!!"); + return new JsonArray(valueStack); + } + + /** A convenience method that assumes a StringReader to deserialize a string. + * @param deserializable representing content to be deserialized as JSON. + * @return either a boolean, null, Number, String, JsonObject, or JsonArray that best represents the deserializable. + * @throws DeserializationException if an unexpected token is encountered in the deserializable. To recover from a + * DeserializationException: fix the deserializable + * to no longer have an unexpected token and try again. + * @see Jsoner#deserialize(Reader) + * @see StringReader */ + public static Object deserialize(final String deserializable) throws DeserializationException{ + Object returnable; + StringReader readableDeserializable = null; + try{ + readableDeserializable = new StringReader(deserializable); + returnable = Jsoner.deserialize(readableDeserializable); + }catch(IOException | NullPointerException caught){ + /* They both have the same recovery scenario. + * See StringReader. + * If deserializable is null, it should be reasonable to expect null back. */ + returnable = null; + }finally{ + if(readableDeserializable != null){ + readableDeserializable.close(); + } + } + return returnable; + } + + /** A convenience method that assumes a JsonArray must be deserialized. + * @param deserializable representing content to be deserializable as a JsonArray. + * @param defaultValue representing what would be returned if deserializable isn't a JsonArray or an IOException, + * NullPointerException, or DeserializationException occurs during deserialization. + * @return a JsonArray that represents the deserializable, or the defaultValue if there isn't a JsonArray that + * represents deserializable. + * @see Jsoner#deserialize(Reader) */ + public static JsonArray deserializeJsonArray(final String deserializable, final JsonArray defaultValue){ + StringReader readable = null; + JsonArray returnable; + try{ + readable = new StringReader(deserializable); + returnable = Jsoner.deserialize(readable, EnumSet.of(DeserializationOptions.ALLOW_JSON_ARRAYS)).getCollection(0); + }catch(NullPointerException | IOException | DeserializationException caught){ + /* Don't care, just return the default value. */ + returnable = defaultValue; + }finally{ + if(readable != null){ + readable.close(); + } + } + return returnable; + } + + /** A convenience method that assumes a JsonObject must be deserialized. + * @param deserializable representing content to be deserializable as a JsonObject. + * @param defaultValue representing what would be returned if deserializable isn't a JsonObject or an IOException, + * NullPointerException, or DeserializationException occurs during deserialization. + * @return a JsonObject that represents the deserializable, or the defaultValue if there isn't a JsonObject that + * represents deserializable. + * @see Jsoner#deserialize(Reader) */ + public static JsonObject deserializeJsonObject(final String deserializable, final JsonObject defaultValue){ + StringReader readable = null; + JsonObject returnable; + try{ + readable = new StringReader(deserializable); + returnable = Jsoner.deserialize(readable, EnumSet.of(DeserializationOptions.ALLOW_JSON_OBJECTS)).getMap(0); + }catch(NullPointerException | IOException | DeserializationException caught){ + /* Don't care, just return the default value. */ + returnable = defaultValue; + }finally{ + if(readable != null){ + readable.close(); + } + } + return returnable; + } + + /** A convenience method that assumes multiple RFC 4627 JSON values (except numbers) have been concatenated together + * for + * deserilization which will be collectively returned in a JsonArray wrapper. + * There may be numbers included, they just must not be concatenated together as it is prone to + * NumberFormatExceptions (thus causing a DeserializationException) or the numbers no longer represent their + * respective values. + * Examples: + * "123null321" returns [123, null, 321] + * "nullnullnulltruefalse\"\"{}[]" returns [null, null, null, true, false, "", {}, []] + * "123" appended to "321" returns [123321] + * "12.3" appended to "3.21" throws DeserializationException(NumberFormatException) + * "123" appended to "-321" throws DeserializationException(NumberFormatException) + * "123e321" appended to "-1" throws DeserializationException(NumberFormatException) + * "null12.33.21null" throws DeserializationException(NumberFormatException) + * @param deserializable representing concatenated content to be deserialized as JSON in one reader. Its contents + * may + * not contain two numbers concatenated together. + * @return a JsonArray that contains each of the concatenated objects as its elements. Each concatenated element is + * either a boolean, null, Number, String, JsonArray, or JsonObject that best represents the concatenated + * content inside deserializable. + * @throws DeserializationException if an unexpected token is encountered in the deserializable. To recover from a + * DeserializationException: fix the deserializable to no longer have an unexpected token and try again. + * @throws IOException when the underlying reader encounters an I/O error. Ensure the reader is properly + * instantiated, isn't closed, or that it is ready before trying again. */ + public static JsonArray deserializeMultipleJsonValues(final Reader deserializable) throws DeserializationException, IOException{ + return Jsoner.deserialize(deserializable, EnumSet.of(DeserializationOptions.ALLOW_JSON_ARRAYS, DeserializationOptions.ALLOW_JSON_OBJECTS, DeserializationOptions.ALLOW_JSON_DATA, DeserializationOptions.ALLOW_CONCATENATED_JSON_VALUES)); + } + + /** Escapes potentially confusing or important characters in the String provided. + * @param escapable an unescaped string. + * @return an escaped string for usage in JSON; An escaped string is one that has escaped all of the quotes ("), + * backslashes (\), return character (\r), new line character (\n), tab character (\t), + * backspace character (\b), form feed character (\f) and other control characters [u0000..u001F] or + * characters [u007F..u009F], [u2000..u20FF] with a + * backslash (\) which itself must be escaped by the backslash in a java string. */ + public static String escape(final String escapable){ + final StringBuilder builder = new StringBuilder(); + final int characters = escapable.length(); + for(int i = 0; i < characters; i++){ + final char character = escapable.charAt(i); + switch(character){ + case '"': + builder.append("\\\""); + break; + case '\\': + builder.append("\\\\"); + break; + case '\b': + builder.append("\\b"); + break; + case '\f': + builder.append("\\f"); + break; + case '\n': + builder.append("\\n"); + break; + case '\r': + builder.append("\\r"); + break; + case '\t': + builder.append("\\t"); + break; + case '/': + builder.append("\\/"); + break; + default: + /* The many characters that get replaced are benign to software but could be mistaken by people + * reading it for a JSON relevant character. */ + if(((character >= '\u0000') && (character <= '\u001F')) || ((character >= '\u007F') && (character <= '\u009F')) || ((character >= '\u2000') && (character <= '\u20FF'))){ + final String characterHexCode = Integer.toHexString(character); + builder.append("\\u"); + for(int k = 0; k < (4 - characterHexCode.length()); k++){ + builder.append("0"); + } + builder.append(characterHexCode.toUpperCase()); + }else{ + /* Character didn't need escaping. */ + builder.append(character); + } + } + } + return builder.toString(); + } + + /** Processes the lexer's reader for the next token. + * @param lexer represents a text processor being used in the deserialization process. + * @return a token representing a meaningful element encountered by the lexer. + * @throws DeserializationException if an unexpected character is encountered while processing the text. + * @throws IOException if the underlying reader inside the lexer encounters an I/O problem, like being prematurely + * closed. */ + private static Yytoken lexNextToken(final Yylex lexer) throws DeserializationException, IOException{ + Yytoken returnable; + /* Parse through the next token. */ + returnable = lexer.yylex(); + if(returnable == null){ + /* If there isn't another token, it must be the end. */ + returnable = new Yytoken(Yytoken.Types.END, null); + } + return returnable; + } + + /** Used for state transitions while deserializing. + * @param stateStack represents the deserialization states saved for future processing. + * @return a state for deserialization context so it knows how to consume the next token. */ + private static States popNextState(final LinkedList stateStack){ + if(stateStack.size() > 0){ + return stateStack.removeLast(); + }else{ + return States.PARSED_ERROR; + } + } + + /** Makes the JSON string more easily human readable. + * @param printable representing a JSON formatted string with out extraneous characters, like one returned from + * Jsoner#serialize(Object). + * @return printable except it will have '\n' then '\t' characters inserted after '[', '{', ',' and before ']' '}' + * tokens in the JSON. It will return null if printable isn't a JSON string. */ + public static String prettyPrint(final String printable){ + final Yylex lexer = new Yylex(new StringReader(printable)); + Yytoken lexed; + final StringBuilder returnable = new StringBuilder(); + final String indentation = "\t"; + int level = 0; + try{ + do{ + lexed = Jsoner.lexNextToken(lexer); + switch(lexed.getType()){ + case COMMA: + returnable.append(lexed.getValue()); + returnable.append("\n"); + for(int i = 0; i < level; i++){ + returnable.append(indentation); + } + break; + case END: + break; + case LEFT_BRACE: + case LEFT_SQUARE: + returnable.append(lexed.getValue()); + returnable.append("\n"); + level++; + for(int i = 0; i < level; i++){ + returnable.append(indentation); + } + break; + case RIGHT_BRACE: + case RIGHT_SQUARE: + returnable.append("\n"); + level--; + for(int i = 0; i < level; i++){ + returnable.append(indentation); + } + returnable.append(lexed.getValue()); + break; + default: + if(lexed.getValue() instanceof String){ + returnable.append("\""); + returnable.append(Jsoner.escape((String)lexed.getValue())); + returnable.append("\""); + }else{ + returnable.append(lexed.getValue()); + } + break; + } + //System.out.println(lexed); + }while(!lexed.getType().equals(Yytoken.Types.END)); + }catch(final DeserializationException caught){ + /* This is according to the method's contract. */ + return null; + }catch(final IOException caught){ + /* See StringReader. */ + return null; + } + //System.out.println(printable); + //System.out.println(returnable); + //System.out.println(Jsoner.escape(returnable.toString())); + return returnable.toString(); + } + + /** A convenience method that assumes a StringWriter. + * @param jsonSerializable represents the object that should be serialized as a string in JSON format. + * @return a string, in JSON format, that represents the object provided. + * @see Jsoner#serialize(Object, Writer) + * @see StringWriter */ + public static String serialize(final Object jsonSerializable){ + final StringWriter writableDestination = new StringWriter(); + try{ + Jsoner.serialize(jsonSerializable, writableDestination); + }catch(final IOException caught){ + /* See StringWriter. */ + } + return writableDestination.toString(); + } + + /** Serializes values according to the RFC 4627 JSON specification. It will also trust the serialization provided by + * any Jsonables it serializes and serializes Enums that don't implement Jsonable as a string of their fully + * qualified name. + * @param jsonSerializable represents the object that should be serialized in JSON format. + * @param writableDestination represents where the resulting JSON text is written to. + * @throws IOException if the writableDestination encounters an I/O problem, like being closed while in use. */ + public static void serialize(final Object jsonSerializable, final Writer writableDestination) throws IOException{ + Jsoner.serialize(jsonSerializable, writableDestination, EnumSet.of(SerializationOptions.ALLOW_JSONABLES, SerializationOptions.ALLOW_FULLY_QUALIFIED_ENUMERATIONS)); + } + + /** Serialize values to JSON and write them to the provided writer based on behavior flags. + * @param jsonSerializable represents the object that should be serialized to a string in JSON format. + * @param writableDestination represents where the resulting JSON text is written to. + * @param replacement represents what is serialized instead of a non-JSON value when replacements are allowed. + * @param flags represents the allowances and restrictions on serialization. + * @throws IOException if the writableDestination encounters an I/O problem. + * @throws IllegalArgumentException if the jsonSerializable isn't serializable in JSON. + * @see SerializationOptions */ + private static void serialize(final Object jsonSerializable, final Writer writableDestination, final Set flags) throws IOException{ + if(jsonSerializable == null){ + /* When a null is passed in the word null is supported in JSON. */ + writableDestination.write("null"); + }else if(((jsonSerializable instanceof Jsonable) && flags.contains(SerializationOptions.ALLOW_JSONABLES))){ + /* Writes the writable as defined by the writable. */ + writableDestination.write(((Jsonable)jsonSerializable).toJson()); + }else if((jsonSerializable instanceof Enum) && flags.contains(SerializationOptions.ALLOW_FULLY_QUALIFIED_ENUMERATIONS)){ + /* Writes the enum as a special case of string. All enums (unless they implement Jsonable) will be the + * string literal "${DECLARING_CLASS_NAME}.${ENUM_NAME}" as their value. */ + @SuppressWarnings("rawtypes") + final Enum e = (Enum)jsonSerializable; + writableDestination.write('"'); + writableDestination.write(e.getDeclaringClass().getName()); + writableDestination.write('.'); + writableDestination.write(e.name()); + writableDestination.write('"'); + }else if(jsonSerializable instanceof String){ + /* Make sure the string is properly escaped. */ + writableDestination.write('"'); + writableDestination.write(Jsoner.escape((String)jsonSerializable)); + writableDestination.write('"'); + }else if(jsonSerializable instanceof Double){ + if(((Double)jsonSerializable).isInfinite() || ((Double)jsonSerializable).isNaN()){ + /* Infinite and not a number are not supported by the JSON specification, so null is used instead. */ + writableDestination.write("null"); + }else{ + writableDestination.write(jsonSerializable.toString()); + } + }else if(jsonSerializable instanceof Float){ + if(((Float)jsonSerializable).isInfinite() || ((Float)jsonSerializable).isNaN()){ + /* Infinite and not a number are not supported by the JSON specification, so null is used instead. */ + writableDestination.write("null"); + }else{ + writableDestination.write(jsonSerializable.toString()); + } + }else if(jsonSerializable instanceof Number){ + writableDestination.write(jsonSerializable.toString()); + }else if(jsonSerializable instanceof Boolean){ + writableDestination.write(jsonSerializable.toString()); + }else if(jsonSerializable instanceof Map){ + /* Writes the map in JSON object format. */ + boolean isFirstEntry = true; + @SuppressWarnings("rawtypes") + final Iterator entries = ((Map)jsonSerializable).entrySet().iterator(); + writableDestination.write('{'); + while(entries.hasNext()){ + if(isFirstEntry){ + isFirstEntry = false; + }else{ + writableDestination.write(','); + } + @SuppressWarnings("rawtypes") + final Map.Entry entry = (Map.Entry)entries.next(); + writableDestination.write(Jsoner.serialize(entry.getKey())); + writableDestination.write(':'); + writableDestination.write(Jsoner.serialize(entry.getValue())); + } + writableDestination.write('}'); + }else if(jsonSerializable instanceof Collection){ + /* Writes the collection in JSON array format. */ + boolean isFirstElement = true; + @SuppressWarnings("rawtypes") + final Iterator elements = ((Collection)jsonSerializable).iterator(); + writableDestination.write('['); + while(elements.hasNext()){ + if(isFirstElement){ + isFirstElement = false; + }else{ + writableDestination.write(','); + } + writableDestination.write(Jsoner.serialize(elements.next())); + } + writableDestination.write(']'); + }else if(jsonSerializable instanceof byte[]){ + /* Writes the array in JSON array format. */ + final byte[] writableArray = (byte[])jsonSerializable; + final int numberOfElements = writableArray.length; + writableDestination.write('['); + for(int i = 1; i <= numberOfElements; i++){ + if(i == numberOfElements){ + writableDestination.write(String.valueOf(writableArray[i])); + }else{ + writableDestination.write(String.valueOf(writableArray[i])); + writableDestination.write(','); + } + } + writableDestination.write(']'); + }else if(jsonSerializable instanceof short[]){ + /* Writes the array in JSON array format. */ + final short[] writableArray = (short[])jsonSerializable; + final int numberOfElements = writableArray.length; + writableDestination.write('['); + for(int i = 1; i <= numberOfElements; i++){ + if(i == numberOfElements){ + writableDestination.write(String.valueOf(writableArray[i])); + }else{ + writableDestination.write(String.valueOf(writableArray[i])); + writableDestination.write(','); + } + } + writableDestination.write(']'); + }else if(jsonSerializable instanceof int[]){ + /* Writes the array in JSON array format. */ + final int[] writableArray = (int[])jsonSerializable; + final int numberOfElements = writableArray.length; + writableDestination.write('['); + for(int i = 1; i <= numberOfElements; i++){ + if(i == numberOfElements){ + writableDestination.write(String.valueOf(writableArray[i])); + }else{ + writableDestination.write(String.valueOf(writableArray[i])); + writableDestination.write(','); + } + } + writableDestination.write(']'); + }else if(jsonSerializable instanceof long[]){ + /* Writes the array in JSON array format. */ + final long[] writableArray = (long[])jsonSerializable; + final int numberOfElements = writableArray.length; + writableDestination.write('['); + for(int i = 1; i <= numberOfElements; i++){ + if(i == numberOfElements){ + writableDestination.write(String.valueOf(writableArray[i])); + }else{ + writableDestination.write(String.valueOf(writableArray[i])); + writableDestination.write(','); + } + } + writableDestination.write(']'); + }else if(jsonSerializable instanceof float[]){ + /* Writes the array in JSON array format. */ + final float[] writableArray = (float[])jsonSerializable; + final int numberOfElements = writableArray.length; + writableDestination.write('['); + for(int i = 1; i <= numberOfElements; i++){ + if(i == numberOfElements){ + writableDestination.write(String.valueOf(writableArray[i])); + }else{ + writableDestination.write(String.valueOf(writableArray[i])); + writableDestination.write(','); + } + } + writableDestination.write(']'); + }else if(jsonSerializable instanceof double[]){ + /* Writes the array in JSON array format. */ + final double[] writableArray = (double[])jsonSerializable; + final int numberOfElements = writableArray.length; + writableDestination.write('['); + for(int i = 1; i <= numberOfElements; i++){ + if(i == numberOfElements){ + writableDestination.write(String.valueOf(writableArray[i])); + }else{ + writableDestination.write(String.valueOf(writableArray[i])); + writableDestination.write(','); + } + } + writableDestination.write(']'); + }else if(jsonSerializable instanceof boolean[]){ + /* Writes the array in JSON array format. */ + final boolean[] writableArray = (boolean[])jsonSerializable; + final int numberOfElements = writableArray.length; + writableDestination.write('['); + for(int i = 1; i <= numberOfElements; i++){ + if(i == numberOfElements){ + writableDestination.write(String.valueOf(writableArray[i])); + }else{ + writableDestination.write(String.valueOf(writableArray[i])); + writableDestination.write(','); + } + } + writableDestination.write(']'); + }else if(jsonSerializable instanceof char[]){ + /* Writes the array in JSON array format. */ + final char[] writableArray = (char[])jsonSerializable; + final int numberOfElements = writableArray.length; + writableDestination.write("[\""); + for(int i = 1; i <= numberOfElements; i++){ + if(i == numberOfElements){ + writableDestination.write(Jsoner.escape(String.valueOf(writableArray[i]))); + }else{ + writableDestination.write(Jsoner.escape(String.valueOf(writableArray[i]))); + writableDestination.write("\",\""); + } + } + writableDestination.write("\"]"); + }else if(jsonSerializable instanceof Object[]){ + /* Writes the array in JSON array format. */ + final Object[] writableArray = (Object[])jsonSerializable; + final int numberOfElements = writableArray.length; + writableDestination.write('['); + for(int i = 1; i <= numberOfElements; i++){ + if(i == numberOfElements){ + writableDestination.write(Jsoner.serialize(writableArray[i])); + }else{ + writableDestination.write(Jsoner.serialize(writableArray[i])); + writableDestination.write(","); + } + } + writableDestination.write(']'); + }else{ + /* TODO a potential feature for future release since POJOs are often represented as JsonObjects. It would be + * nice to have a flag that tries to reflectively figure out what a non-Jsonable POJO's fields are and use + * their names as keys and their respective values for the keys' values in the JsonObject? + * Naturally implementing Jsonable is safer and in many ways makes this feature a convenience for not + * needing + * to implement Jsonable for very simple POJOs. + * If it fails to produce a JsonObject to serialize it should defer to replacements if allowed. + * If replacement fails it should defer to invalids if allowed. + * This feature would require another serialize method exposed to allow this serialization. + * This feature (although perhaps useful on its own) would also include a method in the JsonObject where you + * pass it a class and it would do its best to instantiate a POJO of the class using the keys in the + * JsonObject. / + * /* It cannot by any measure be safely serialized according to specification. */ + if(flags.contains(SerializationOptions.ALLOW_INVALIDS)){ + /* Can be helpful for debugging how it isn't valid. */ + writableDestination.write(jsonSerializable.toString()); + }else{ + /* Notify the caller the cause of failure for the serialization. */ + throw new IllegalArgumentException("Encountered a: " + jsonSerializable.getClass().getName() + " as: " + jsonSerializable.toString() + " that isn't JSON serializable.\n Try:\n 1) Implementing the Jsonable interface for the object to return valid JSON. If it already does it probably has a bug.\n 2) If you cannot edit the source of the object or couple it with this library consider wrapping it in a class that does implement the Jsonable interface.\n 3) Otherwise convert it to a boolean, null, number, JsonArray, JsonObject, or String value before serializing it.\n 4) If you feel it should have serialized you could use a more tolerant serialization for debugging purposes."); + } + } + //System.out.println(writableDestination.toString()); + } + + /** Serializes like the first version of this library. + * It has been adapted to use Jsonable for serializing custom objects, but otherwise works like the old JSON string + * serializer. It + * will allow non-JSON values in its output like the old one. It can be helpful for last resort log statements and + * debugging errors in self generated JSON. Anything serialized using this method isn't guaranteed to be + * deserializable. + * @param jsonSerializable represents the object that should be serialized in JSON format. + * @param writableDestination represents where the resulting JSON text is written to. + * @throws IOException if the writableDestination encounters an I/O problem, like being closed while in use. */ + public static void serializeCarelessly(final Object jsonSerializable, final Writer writableDestination) throws IOException{ + Jsoner.serialize(jsonSerializable, writableDestination, EnumSet.of(SerializationOptions.ALLOW_JSONABLES, SerializationOptions.ALLOW_INVALIDS)); + } + + /** Serializes JSON values and only JSON values according to the RFC 4627 JSON specification. + * @param jsonSerializable represents the object that should be serialized in JSON format. + * @param writableDestination represents where the resulting JSON text is written to. + * @throws IOException if the writableDestination encounters an I/O problem, like being closed while in use. + * @throws IllegalArgumentException if the jsonSerializable isn't serializable in JSON. */ + public static void serializeStrictly(final Object jsonSerializable, final Writer writableDestination) throws IOException{ + Jsoner.serialize(jsonSerializable, writableDestination, EnumSet.noneOf(SerializationOptions.class)); + } +} diff --git a/src/main/java/org/json/simple/Yylex.java b/src/main/java/org/json/simple/Yylex.java new file mode 100644 index 00000000..db438aa5 --- /dev/null +++ b/src/main/java/org/json/simple/Yylex.java @@ -0,0 +1,695 @@ +/* The following code was generated by JFlex 1.4.3 on 8/30/16 5:50 PM */ + +package org.json.simple; + + +/** + * This class is a scanner generated by + * JFlex 1.4.3 + * on 8/30/16 5:50 PM from the specification file + * /home/davinloegering/cliftonlabs/workspace/json-simple/src/main/lex/jsonstrict.lex + */ +class Yylex { + + /** This character denotes the end of file */ + public static final int YYEOF = -1; + + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int YYINITIAL = 0; + public static final int STRING_BEGIN = 2; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\0\1\7\1\7\2\0\1\7\22\0\1\7\1\0\1\11\10\0"+ + "\1\6\1\31\1\2\1\4\1\12\12\3\1\32\6\0\4\1\1\5"+ + "\1\1\24\0\1\27\1\10\1\30\3\0\1\22\1\13\2\1\1\21"+ + "\1\14\5\0\1\23\1\0\1\15\3\0\1\16\1\24\1\17\1\20"+ + "\5\0\1\25\1\0\1\26\uff82\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\2\0\2\1\1\2\1\3\1\4\3\1\1\5\1\6"+ + "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\5\0"+ + "\1\14\1\16\1\17\1\20\1\21\1\22\1\23\1\24"+ + "\1\0\1\2\1\0\1\2\4\0\1\25\1\26\2\0"+ + "\1\27"; + + private static int [] zzUnpackAction() { + int [] result = new int[45]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /** + * Translates a state to a row index in the transition table + */ + private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); + + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\33\0\66\0\121\0\154\0\207\0\66\0\242"+ + "\0\275\0\330\0\66\0\66\0\66\0\66\0\66\0\66"+ + "\0\363\0\u010e\0\66\0\u0129\0\u0144\0\u015f\0\u017a\0\u0195"+ + "\0\66\0\66\0\66\0\66\0\66\0\66\0\66\0\66"+ + "\0\u01b0\0\u01cb\0\u01e6\0\u01e6\0\u0201\0\u021c\0\u0237\0\u0252"+ + "\0\66\0\66\0\u026d\0\u0288\0\66"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[45]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackRowMap(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); + } + return j; + } + + /** + * The transition table of the DFA + */ + private static final int ZZ_TRANS [] = { + 2, 2, 3, 4, 2, 2, 2, 5, 2, 6, + 2, 2, 7, 8, 2, 9, 2, 2, 2, 2, + 2, 10, 11, 12, 13, 14, 15, 16, 16, 16, + 16, 16, 16, 16, 16, 17, 18, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 4, 19, 20, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 16, 16, 16, 16, 16, 16, 16, + 16, -1, -1, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + -1, -1, -1, -1, -1, -1, -1, -1, 24, 25, + 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 34, 35, -1, -1, + 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 39, -1, 39, -1, 39, -1, -1, + -1, -1, -1, 39, 39, -1, -1, -1, -1, 39, + 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 33, -1, 20, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 42, -1, 42, -1, 42, + -1, -1, -1, -1, -1, 42, 42, -1, -1, -1, + -1, 42, 42, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 43, -1, 43, -1, 43, -1, -1, -1, + -1, -1, 43, 43, -1, -1, -1, -1, 43, 43, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, + -1, 44, -1, 44, -1, -1, -1, -1, -1, 44, + 44, -1, -1, -1, -1, 44, 44, -1, -1, -1, + -1, -1, -1, -1, -1, + }; + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state aState + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\2\0\1\11\3\1\1\11\3\1\6\11\2\1\1\11"+ + "\5\0\10\11\1\0\1\1\1\0\1\1\4\0\2\11"+ + "\2\0\1\11"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[45]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAttribute(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + /** the input device */ + private java.io.Reader zzReader; + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** number of newlines encountered up to the start of the matched text */ + private int yyline; + + /** the number of characters up to the start of the matched text */ + private int yychar; + + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + /* user code: */ +private StringBuilder sb=new StringBuilder(); + +int getPosition(){ + return yychar; +} + + + + /** + * Creates a new scanner + * There is also a java.io.InputStream version of this constructor. + * + * @param in the java.io.Reader to read input from. + */ + Yylex(java.io.Reader in) { + this.zzReader = in; + } + + /** + * Creates a new scanner. + * There is also java.io.Reader version of this constructor. + * + * @param in the java.io.Inputstream to read input from. + */ + Yylex(java.io.InputStream in) { + this(new java.io.InputStreamReader(in)); + } + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 90) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + + /** + * Refills the input buffer. + * + * @return false, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead-zzStartRead); + + /* translate stored positions */ + zzEndRead-= zzStartRead; + zzCurrentPos-= zzStartRead; + zzMarkedPos-= zzStartRead; + zzStartRead = 0; + } + + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length) { + /* if not: blow it up */ + char newBuffer[] = new char[zzCurrentPos*2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + } + + /* finally: fill the buffer with new input */ + int numRead = zzReader.read(zzBuffer, zzEndRead, + zzBuffer.length-zzEndRead); + + if (numRead > 0) { + zzEndRead+= numRead; + return false; + } + // unlikely but not impossible: read 0 characters, but not at end of stream + if (numRead == 0) { + int c = zzReader.read(); + if (c == -1) { + return true; + } else { + zzBuffer[zzEndRead++] = (char) c; + return false; + } + } + + // numRead < 0 + return true; + } + + + /** + * Closes the input stream. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ + + if (zzReader != null) + zzReader.close(); + } + + + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * cannot be reused (internal buffer is discarded and lost). + * Lexical state is set to ZZ_INITIAL. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + zzEOFDone = false; + zzEndRead = zzStartRead = 0; + zzCurrentPos = zzMarkedPos = 0; + yyline = yychar = yycolumn = 0; + zzLexicalState = YYINITIAL; + } + + + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); + } + + + /** + * Returns the character at position pos from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead+pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); + + zzMarkedPos -= number; + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public Yytoken yylex() throws java.io.IOException, DeserializationException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; + + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + yychar+= zzMarkedPosL-zzStartRead; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) + zzInput = zzBufferL[zzCurrentPosL++]; + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = zzBufferL[zzCurrentPosL++]; + } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; + if (zzNext == -1) break zzForAction; + zzState = zzNext; + + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) break zzForAction; + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 4: + { sb = null; sb = new StringBuilder(); yybegin(STRING_BEGIN); + } + case 24: break; + case 11: + { sb.append(yytext()); + } + case 25: break; + case 5: + { return new Yytoken(Yytoken.Types.LEFT_BRACE, null); + } + case 26: break; + case 16: + { sb.append('\b'); + } + case 27: break; + case 23: + { try{ + int ch=Integer.parseInt(yytext().substring(2),16); + sb.append((char)ch); + }catch(Exception e){ + /* The lexer is broken if it can build a 4 byte character code and fail to append the character. */ + throw new DeserializationException(yychar, DeserializationException.Problems.UNEXPECTED_EXCEPTION, e); + } + } + case 28: break; + case 22: + { Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.Types.DATUM, val); + } + case 29: break; + case 12: + { sb.append('\\'); + } + case 30: break; + case 10: + { return new Yytoken(Yytoken.Types.COLON, null); + } + case 31: break; + case 9: + { return new Yytoken(Yytoken.Types.COMMA, null); + } + case 32: break; + case 21: + { return new Yytoken(Yytoken.Types.DATUM, null); + } + case 33: break; + case 19: + { sb.append('\r'); + } + case 34: break; + case 15: + { sb.append('/'); + } + case 35: break; + case 2: + { java.math.BigDecimal val= new java.math.BigDecimal(yytext()); return new Yytoken(Yytoken.Types.DATUM, val); + } + case 36: break; + case 14: + { sb.append('"'); + } + case 37: break; + case 8: + { return new Yytoken(Yytoken.Types.RIGHT_SQUARE, null); + } + case 38: break; + case 17: + { sb.append('\f'); + } + case 39: break; + case 1: + { throw new DeserializationException(yychar, DeserializationException.Problems.UNEXPECTED_CHARACTER, new Character(yycharat(0))); + } + case 40: break; + case 6: + { return new Yytoken(Yytoken.Types.RIGHT_BRACE, null); + } + case 41: break; + case 20: + { sb.append('\t'); + } + case 42: break; + case 7: + { return new Yytoken(Yytoken.Types.LEFT_SQUARE, null); + } + case 43: break; + case 18: + { sb.append('\n'); + } + case 44: break; + case 13: + { yybegin(YYINITIAL);return new Yytoken(Yytoken.Types.DATUM, sb.toString()); + } + case 45: break; + case 3: + { + } + case 46: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + return null; + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/src/main/java/org/json/simple/Yytoken.java b/src/main/java/org/json/simple/Yytoken.java new file mode 100644 index 00000000..9bc613f8 --- /dev/null +++ b/src/main/java/org/json/simple/Yytoken.java @@ -0,0 +1,84 @@ +/* See: README for this file's copyright, terms, and conditions. */ +package org.json.simple; + +/** Represents structural entities in JSON. + * + * @since 2.0.0 */ +class Yytoken{ + /** Represents the different kinds of tokens. */ + enum Types{ + /** Tokens of this type will always have a value of ":" */ + COLON, + /** Tokens of this type will always have a value of "," */ + COMMA, + /** Tokens of this type will always have a value that is a boolean, null, number, or string. */ + DATUM, + /** Tokens of this type will always have a value of "" */ + END, + /** Tokens of this type will always have a value of "{" */ + LEFT_BRACE, + /** Tokens of this type will always have a value of "[" */ + LEFT_SQUARE, + /** Tokens of this type will always have a value of "}" */ + RIGHT_BRACE, + /** Tokens of this type will always have a value of "]" */ + RIGHT_SQUARE; + } + + private final Types type; + private final Object value; + + /** @param type represents the kind of token the instantiated token will be. + * @param value represents the value the token is associated with, will be ignored unless type is equal to + * Types.DATUM. + * @see Types */ + Yytoken(final Types type, final Object value){ + /* Sanity check. Make sure the value is ignored for the proper value unless it is a datum token. */ + switch(type){ + case COLON: + this.value = ":"; + break; + case COMMA: + this.value = ","; + break; + case END: + this.value = ""; + break; + case LEFT_BRACE: + this.value = "{"; + break; + case LEFT_SQUARE: + this.value = "["; + break; + case RIGHT_BRACE: + this.value = "}"; + break; + case RIGHT_SQUARE: + this.value = "]"; + break; + default: + this.value = value; + break; + } + this.type = type; + } + + /** @return which of the Types the token is. + * @see Types */ + Types getType(){ + return this.type; + } + + /** @return what the token is. + * @see Types */ + Object getValue(){ + return this.value; + } + + @Override + public String toString(){ + final StringBuffer sb = new StringBuffer(); + sb.append(this.type.toString()).append("(").append(this.value).append(")"); + return sb.toString(); + } +} diff --git a/src/main/java/org/json/simple/parser/ContainerFactory.java b/src/main/java/org/json/simple/parser/ContainerFactory.java index 366ac4de..b763cd45 100644 --- a/src/main/java/org/json/simple/parser/ContainerFactory.java +++ b/src/main/java/org/json/simple/parser/ContainerFactory.java @@ -8,8 +8,10 @@ * * @see org.json.simple.parser.JSONParser#parse(java.io.Reader, ContainerFactory) * - * @author FangYidong + * @author FangYidong<fangyidong@yahoo.com.cn> + * @deprecated since 2.0.0 the same results can be achieved with the Map and Collection constructors in java post parsing. */ +@Deprecated public interface ContainerFactory { /** * @return A Map instance to store JSON object, or null if you want to use org.json.simple.JSONObject. diff --git a/src/main/java/org/json/simple/parser/ContentHandler.java b/src/main/java/org/json/simple/parser/ContentHandler.java index ae8d0655..a8f34bea 100644 --- a/src/main/java/org/json/simple/parser/ContentHandler.java +++ b/src/main/java/org/json/simple/parser/ContentHandler.java @@ -5,11 +5,13 @@ /** * A simplified and stoppable SAX-like content handler for stream processing of JSON text. * - * @see org.xml.sax.ContentHandler + * * @see org.json.simple.parser.JSONParser#parse(java.io.Reader, ContentHandler, boolean) * - * @author FangYidong + * @author FangYidong<fangyidong@yahoo.com.cn> + * @deprecated since 2.0.0 it doesn't extend the SAX ContentHandler promoting bad practices and incompatible code. */ +@Deprecated public interface ContentHandler { /** * Receive notification of the beginning of JSON processing. @@ -17,13 +19,15 @@ public interface ContentHandler { * * @throws ParseException * - JSONParser will stop and throw the same exception to the caller when receiving this exception. + * @throws IOException description omitted. */ void startJSON() throws ParseException, IOException; /** * Receive notification of the end of JSON processing. * - * @throws ParseException + * @throws ParseException description omitted. + * @throws IOException description omitted. */ void endJSON() throws ParseException, IOException; @@ -33,6 +37,7 @@ public interface ContentHandler { * @return false if the handler wants to stop parsing after return. * @throws ParseException * - JSONParser will stop and throw the same exception to the caller when receiving this exception. + * @throws IOException description omitted. * @see #endJSON */ boolean startObject() throws ParseException, IOException; @@ -41,7 +46,8 @@ public interface ContentHandler { * Receive notification of the end of a JSON object. * * @return false if the handler wants to stop parsing after return. - * @throws ParseException + * @throws ParseException description omitted. + * @throws IOException description omitted. * * @see #startObject */ @@ -53,7 +59,8 @@ public interface ContentHandler { * @param key - Key of a JSON object entry. * * @return false if the handler wants to stop parsing after return. - * @throws ParseException + * @throws ParseException description omitted. + * @throws IOException description omitted. * * @see #endObjectEntry */ @@ -63,7 +70,8 @@ public interface ContentHandler { * Receive notification of the end of the value of previous object entry. * * @return false if the handler wants to stop parsing after return. - * @throws ParseException + * @throws ParseException description omitted. + * @throws IOException description omitted. * * @see #startObjectEntry */ @@ -73,7 +81,8 @@ public interface ContentHandler { * Receive notification of the beginning of a JSON array. * * @return false if the handler wants to stop parsing after return. - * @throws ParseException + * @throws ParseException description omitted. + * @throws IOException description omitted. * * @see #endArray */ @@ -83,7 +92,8 @@ public interface ContentHandler { * Receive notification of the end of a JSON array. * * @return false if the handler wants to stop parsing after return. - * @throws ParseException + * @throws ParseException description omitted. + * @throws IOException description omitted. * * @see #startArray */ @@ -103,7 +113,8 @@ public interface ContentHandler { * null * * @return false if the handler wants to stop parsing after return. - * @throws ParseException + * @throws ParseException description omitted. + * @throws IOException description omitted. */ boolean primitive(Object value) throws ParseException, IOException; diff --git a/src/main/java/org/json/simple/parser/JSONParser.java b/src/main/java/org/json/simple/parser/JSONParser.java index 9acaa377..7d638585 100644 --- a/src/main/java/org/json/simple/parser/JSONParser.java +++ b/src/main/java/org/json/simple/parser/JSONParser.java @@ -18,16 +18,42 @@ /** * Parser for JSON text. Please note that JSONParser is NOT thread-safe. * - * @author FangYidong + * @author FangYidong<fangyidong@yahoo.com.cn> + * @deprecated since 2.0.0, copied to a new package {@link org.json.simple.Jsoner}. */ +@Deprecated public class JSONParser { + /** + * description omitted. + */ public static final int S_INIT=0; + /** + * description omitted. + */ public static final int S_IN_FINISHED_VALUE=1;//string,number,boolean,null,object,array + /** + * description omitted. + */ public static final int S_IN_OBJECT=2; + /** + * description omitted. + */ public static final int S_IN_ARRAY=3; + /** + * description omitted. + */ public static final int S_PASSED_PAIR_KEY=4; + /** + * description omitted. + */ public static final int S_IN_PAIR_VALUE=5; + /** + * description omitted. + */ public static final int S_END=6; + /** + * description omitted. + */ public static final int S_IN_ERROR=-1; private LinkedList handlerStatusStack; @@ -56,8 +82,6 @@ public void reset(){ * Reset the parser to the initial state with a new character reader. * * @param in - The new character reader. - * @throws IOException - * @throws ParseException */ public void reset(Reader in){ lexer.yyreset(in); @@ -71,10 +95,25 @@ public int getPosition(){ return lexer.getPosition(); } + /** + * description omitted. + * + * @param s description omitted. + * @return description omitted. + * @throws ParseException description omitted. + */ public Object parse(String s) throws ParseException{ return parse(s, (ContainerFactory)null); } + /** + * description omitted. + * + * @param s description omitted. + * @param containerFactory description omitted. + * @return description omitted. + * @throws ParseException description omitted. + */ public Object parse(String s, ContainerFactory containerFactory) throws ParseException{ StringReader in=new StringReader(s); try{ @@ -88,6 +127,14 @@ public Object parse(String s, ContainerFactory containerFactory) throws ParseExc } } + /** + * description omitted. + * + * @param in description omitted. + * @return description omitted. + * @throws IOException description omitted. + * @throws ParseException description omitted. + */ public Object parse(Reader in) throws IOException, ParseException{ return parse(in, (ContainerFactory)null); } @@ -95,7 +142,7 @@ public Object parse(Reader in) throws IOException, ParseException{ /** * Parse JSON text into java object from the input source. * - * @param in + * @param in description omitted. * @param containerFactory - Use this factory to createyour own JSON object and JSON array containers. * @return Instance of the following: * org.json.simple.JSONObject, @@ -105,8 +152,8 @@ public Object parse(Reader in) throws IOException, ParseException{ * java.lang.Boolean, * null * - * @throws IOException - * @throws ParseException + * @throws IOException description omitted. + * @throws ParseException description omitted. */ public Object parse(Reader in, ContainerFactory containerFactory) throws IOException, ParseException{ reset(in); @@ -291,10 +338,25 @@ private List createArrayContainer(ContainerFactory containerFactory){ return l; } + /** + * description omitted. + * + * @param s description omitted. + * @param contentHandler description omitted. + * @throws ParseException description omitted. + */ public void parse(String s, ContentHandler contentHandler) throws ParseException{ parse(s, contentHandler, false); } + /** + * description omitted. + * + * @param s description omitted. + * @param contentHandler description omitted. + * @param isResume description omitted. + * @throws ParseException description omitted. + */ public void parse(String s, ContentHandler contentHandler, boolean isResume) throws ParseException{ StringReader in=new StringReader(s); try{ @@ -308,6 +370,14 @@ public void parse(String s, ContentHandler contentHandler, boolean isResume) thr } } + /** + * description omitted. + * + * @param in description omitted. + * @param contentHandler description omitted. + * @throws IOException description omitted. + * @throws ParseException description omitted. + */ public void parse(Reader in, ContentHandler contentHandler) throws IOException, ParseException{ parse(in, contentHandler, false); } @@ -317,14 +387,14 @@ public void parse(Reader in, ContentHandler contentHandler) throws IOException, * * @see ContentHandler * - * @param in - * @param contentHandler + * @param in description omitted. + * @param contentHandler description omitted. * @param isResume - Indicates if it continues previous parsing operation. * If set to true, resume parsing the old stream, and parameter 'in' will be ignored. * If this method is called for the first time in this instance, isResume will be ignored. * - * @throws IOException - * @throws ParseException + * @throws IOException description omitted. + * @throws ParseException description omitted. */ public void parse(Reader in, ContentHandler contentHandler, boolean isResume) throws IOException, ParseException{ if(!isResume){ diff --git a/src/main/java/org/json/simple/parser/ParseException.java b/src/main/java/org/json/simple/parser/ParseException.java index dbfefc0e..c562009a 100644 --- a/src/main/java/org/json/simple/parser/ParseException.java +++ b/src/main/java/org/json/simple/parser/ParseException.java @@ -3,38 +3,71 @@ /** * ParseException explains why and where the error occurs in source JSON text. * - * @author FangYidong - * + * @author FangYidong<fangyidong@yahoo.com.cn> + * + * @deprecated since 2.0.0, copied to a new package. */ +@Deprecated public class ParseException extends Exception { private static final long serialVersionUID = -7880698968187728547L; + /** + * description omitted. + */ public static final int ERROR_UNEXPECTED_CHAR = 0; + /** + * description omitted. + */ public static final int ERROR_UNEXPECTED_TOKEN = 1; + /** + * description omitted. + */ public static final int ERROR_UNEXPECTED_EXCEPTION = 2; private int errorType; private Object unexpectedObject; private int position; + /** + * @param errorType description omitted. + */ public ParseException(int errorType){ this(-1, errorType, null); } + /** + * @param errorType description omitted. + * @param unexpectedObject description omitted. + */ public ParseException(int errorType, Object unexpectedObject){ this(-1, errorType, unexpectedObject); } + /** + * @param position description omitted. + * @param errorType description omitted. + * @param unexpectedObject description omitted. + */ public ParseException(int position, int errorType, Object unexpectedObject){ this.position = position; this.errorType = errorType; this.unexpectedObject = unexpectedObject; } + /** + * Action on data for a result. + * + * @return description omitted. + */ public int getErrorType() { return errorType; } + /** + * Action on data for a result. + * + * @param errorType description omitted. + */ public void setErrorType(int errorType) { this.errorType = errorType; } @@ -48,6 +81,11 @@ public int getPosition() { return position; } + /** + * Action on data for a result. + * + * @param position description omitted. + */ public void setPosition(int position) { this.position = position; } @@ -64,6 +102,11 @@ public Object getUnexpectedObject() { return unexpectedObject; } + /** + * Action on data for a result. + * + * @param unexpectedObject description omitted. + */ public void setUnexpectedObject(Object unexpectedObject) { this.unexpectedObject = unexpectedObject; } diff --git a/src/main/java/org/json/simple/parser/Yylex.java b/src/main/java/org/json/simple/parser/Yylex.java index e58e27e6..940a275e 100644 --- a/src/main/java/org/json/simple/parser/Yylex.java +++ b/src/main/java/org/json/simple/parser/Yylex.java @@ -1,688 +1,701 @@ -/* The following code was generated by JFlex 1.4.2 */ - +/* The following code was generated by JFlex 1.4.3 on 8/22/16 3:26 PM */ + package org.json.simple.parser; -class Yylex { - - /** This character denotes the end of file */ - public static final int YYEOF = -1; - - /** initial size of the lookahead buffer */ - private static final int ZZ_BUFFERSIZE = 16384; - - /** lexical states */ - public static final int YYINITIAL = 0; - public static final int STRING_BEGIN = 2; - - /** - * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l - * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l - * at the beginning of a line - * l is of the form l = 2*k, k a non negative integer - */ - private static final int ZZ_LEXSTATE[] = { - 0, 0, 1, 1 - }; - - /** - * Translates characters to character classes - */ - private static final String ZZ_CMAP_PACKED = - "\11\0\1\7\1\7\2\0\1\7\22\0\1\7\1\0\1\11\10\0"+ - "\1\6\1\31\1\2\1\4\1\12\12\3\1\32\6\0\4\1\1\5"+ - "\1\1\24\0\1\27\1\10\1\30\3\0\1\22\1\13\2\1\1\21"+ - "\1\14\5\0\1\23\1\0\1\15\3\0\1\16\1\24\1\17\1\20"+ - "\5\0\1\25\1\0\1\26\uff82\0"; - - /** - * Translates characters to character classes - */ - private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); - - /** - * Translates DFA states to action switch labels. - */ - private static final int [] ZZ_ACTION = zzUnpackAction(); - - private static final String ZZ_ACTION_PACKED_0 = - "\2\0\2\1\1\2\1\3\1\4\3\1\1\5\1\6"+ - "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\5\0"+ - "\1\14\1\16\1\17\1\20\1\21\1\22\1\23\1\24"+ - "\1\0\1\25\1\0\1\25\4\0\1\26\1\27\2\0"+ - "\1\30"; - - private static int [] zzUnpackAction() { - int [] result = new int[45]; - int offset = 0; - offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAction(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do result[j++] = value; while (--count > 0); - } - return j; - } - - - /** - * Translates a state to a row index in the transition table - */ - private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); - - private static final String ZZ_ROWMAP_PACKED_0 = - "\0\0\0\33\0\66\0\121\0\154\0\207\0\66\0\242"+ - "\0\275\0\330\0\66\0\66\0\66\0\66\0\66\0\66"+ - "\0\363\0\u010e\0\66\0\u0129\0\u0144\0\u015f\0\u017a\0\u0195"+ - "\0\66\0\66\0\66\0\66\0\66\0\66\0\66\0\66"+ - "\0\u01b0\0\u01cb\0\u01e6\0\u01e6\0\u0201\0\u021c\0\u0237\0\u0252"+ - "\0\66\0\66\0\u026d\0\u0288\0\66"; - - private static int [] zzUnpackRowMap() { - int [] result = new int[45]; - int offset = 0; - offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackRowMap(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int high = packed.charAt(i++) << 16; - result[j++] = high | packed.charAt(i++); - } - return j; - } - - /** - * The transition table of the DFA - */ - private static final int ZZ_TRANS [] = { - 2, 2, 3, 4, 2, 2, 2, 5, 2, 6, - 2, 2, 7, 8, 2, 9, 2, 2, 2, 2, - 2, 10, 11, 12, 13, 14, 15, 16, 16, 16, - 16, 16, 16, 16, 16, 17, 18, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 4, 19, 20, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 16, 16, 16, 16, 16, 16, 16, - 16, -1, -1, 16, 16, 16, 16, 16, 16, 16, - 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, - -1, -1, -1, -1, -1, -1, -1, -1, 24, 25, - 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 34, 35, -1, -1, - 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 39, -1, 39, -1, 39, -1, -1, - -1, -1, -1, 39, 39, -1, -1, -1, -1, 39, - 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 33, -1, 20, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, 42, -1, 42, -1, 42, - -1, -1, -1, -1, -1, 42, 42, -1, -1, -1, - -1, 42, 42, -1, -1, -1, -1, -1, -1, -1, - -1, -1, 43, -1, 43, -1, 43, -1, -1, -1, - -1, -1, 43, 43, -1, -1, -1, -1, 43, 43, - -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, - -1, 44, -1, 44, -1, -1, -1, -1, -1, 44, - 44, -1, -1, -1, -1, 44, 44, -1, -1, -1, - -1, -1, -1, -1, -1, - }; - - /* error codes */ - private static final int ZZ_UNKNOWN_ERROR = 0; - private static final int ZZ_NO_MATCH = 1; - private static final int ZZ_PUSHBACK_2BIG = 2; - - /* error messages for the codes above */ - private static final String ZZ_ERROR_MSG[] = { - "Unkown internal scanner error", - "Error: could not match input", - "Error: pushback value was too large" - }; - - /** - * ZZ_ATTRIBUTE[aState] contains the attributes of state aState - */ - private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); - - private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\2\0\1\11\3\1\1\11\3\1\6\11\2\1\1\11"+ - "\5\0\10\11\1\0\1\1\1\0\1\1\4\0\2\11"+ - "\2\0\1\11"; - - private static int [] zzUnpackAttribute() { - int [] result = new int[45]; - int offset = 0; - offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); - return result; - } - - private static int zzUnpackAttribute(String packed, int offset, int [] result) { - int i = 0; /* index in packed string */ - int j = offset; /* index in unpacked array */ - int l = packed.length(); - while (i < l) { - int count = packed.charAt(i++); - int value = packed.charAt(i++); - do result[j++] = value; while (--count > 0); - } - return j; - } - - /** the input device */ - private java.io.Reader zzReader; - - /** the current state of the DFA */ - private int zzState; - - /** the current lexical state */ - private int zzLexicalState = YYINITIAL; - - /** this buffer contains the current text to be matched and is - the source of the yytext() string */ - private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; - - /** the textposition at the last accepting state */ - private int zzMarkedPos; - - /** the current text position in the buffer */ - private int zzCurrentPos; - - /** startRead marks the beginning of the yytext() string in the buffer */ - private int zzStartRead; - - /** endRead marks the last character in the buffer, that has been read - from input */ - private int zzEndRead; - - /** number of newlines encountered up to the start of the matched text */ - private int yyline; - - /** the number of characters up to the start of the matched text */ - private int yychar; - - /** - * the number of characters from the last newline up to the start of the - * matched text - */ - private int yycolumn; - - /** - * zzAtBOL == true <=> the scanner is currently at the beginning of a line - */ - private boolean zzAtBOL = true; - - /** zzAtEOF == true <=> the scanner is at the EOF */ - private boolean zzAtEOF; - - /* user code: */ + +/** + * This class is a scanner generated by + * JFlex 1.4.3 + * on 8/22/16 3:26 PM from the specification file + * /home/davinloegering/cliftonlabs/workspace/json-simple/src/main/lex/json.lex + * + */ +@Deprecated +class Yylex { + + /** This character denotes the end of file */ + public static final int YYEOF = -1; + + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int YYINITIAL = 0; + public static final int STRING_BEGIN = 2; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0, 1, 1 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\0\1\7\1\7\2\0\1\7\22\0\1\7\1\0\1\11\10\0"+ + "\1\6\1\31\1\2\1\4\1\12\12\3\1\32\6\0\4\1\1\5"+ + "\1\1\24\0\1\27\1\10\1\30\3\0\1\22\1\13\2\1\1\21"+ + "\1\14\5\0\1\23\1\0\1\15\3\0\1\16\1\24\1\17\1\20"+ + "\5\0\1\25\1\0\1\26\uff82\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\2\0\2\1\1\2\1\3\1\4\3\1\1\5\1\6"+ + "\1\7\1\10\1\11\1\12\1\13\1\14\1\15\5\0"+ + "\1\14\1\16\1\17\1\20\1\21\1\22\1\23\1\24"+ + "\1\0\1\25\1\0\1\25\4\0\1\26\1\27\2\0"+ + "\1\30"; + + private static int [] zzUnpackAction() { + int [] result = new int[45]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /** + * Translates a state to a row index in the transition table + */ + private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); + + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\33\0\66\0\121\0\154\0\207\0\66\0\242"+ + "\0\275\0\330\0\66\0\66\0\66\0\66\0\66\0\66"+ + "\0\363\0\u010e\0\66\0\u0129\0\u0144\0\u015f\0\u017a\0\u0195"+ + "\0\66\0\66\0\66\0\66\0\66\0\66\0\66\0\66"+ + "\0\u01b0\0\u01cb\0\u01e6\0\u01e6\0\u0201\0\u021c\0\u0237\0\u0252"+ + "\0\66\0\66\0\u026d\0\u0288\0\66"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[45]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackRowMap(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); + } + return j; + } + + /** + * The transition table of the DFA + */ + private static final int ZZ_TRANS [] = { + 2, 2, 3, 4, 2, 2, 2, 5, 2, 6, + 2, 2, 7, 8, 2, 9, 2, 2, 2, 2, + 2, 10, 11, 12, 13, 14, 15, 16, 16, 16, + 16, 16, 16, 16, 16, 17, 18, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 4, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 4, 19, 20, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 20, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 5, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 21, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 22, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 23, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 16, 16, 16, 16, 16, 16, 16, + 16, -1, -1, 16, 16, 16, 16, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 16, 16, 16, + -1, -1, -1, -1, -1, -1, -1, -1, 24, 25, + 26, 27, 28, 29, 30, 31, 32, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 33, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 34, 35, -1, -1, + 34, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 36, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, 37, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, 38, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 39, -1, 39, -1, 39, -1, -1, + -1, -1, -1, 39, 39, -1, -1, -1, -1, 39, + 39, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 33, -1, 20, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, 20, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 35, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, 38, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 40, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, 41, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, 42, -1, 42, -1, 42, + -1, -1, -1, -1, -1, 42, 42, -1, -1, -1, + -1, 42, 42, -1, -1, -1, -1, -1, -1, -1, + -1, -1, 43, -1, 43, -1, 43, -1, -1, -1, + -1, -1, 43, 43, -1, -1, -1, -1, 43, 43, + -1, -1, -1, -1, -1, -1, -1, -1, -1, 44, + -1, 44, -1, 44, -1, -1, -1, -1, -1, 44, + 44, -1, -1, -1, -1, 44, 44, -1, -1, -1, + -1, -1, -1, -1, -1, + }; + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state aState + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\2\0\1\11\3\1\1\11\3\1\6\11\2\1\1\11"+ + "\5\0\10\11\1\0\1\1\1\0\1\1\4\0\2\11"+ + "\2\0\1\11"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[45]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAttribute(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + /** the input device */ + private java.io.Reader zzReader; + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private char zzBuffer[] = new char[ZZ_BUFFERSIZE]; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** number of newlines encountered up to the start of the matched text */ + private int yyline; + + /** the number of characters up to the start of the matched text */ + private int yychar; + + /** + * the number of characters from the last newline up to the start of the + * matched text + */ + private int yycolumn; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + /* user code: */ private StringBuffer sb=new StringBuffer(); int getPosition(){ return yychar; } - - - /** - * Creates a new scanner - * There is also a java.io.InputStream version of this constructor. - * - * @param in the java.io.Reader to read input from. - */ - Yylex(java.io.Reader in) { - this.zzReader = in; - } - - /** - * Creates a new scanner. - * There is also java.io.Reader version of this constructor. - * - * @param in the java.io.Inputstream to read input from. - */ - Yylex(java.io.InputStream in) { - this(new java.io.InputStreamReader(in)); - } - - /** - * Unpacks the compressed character translation table. - * - * @param packed the packed character translation table - * @return the unpacked character translation table - */ - private static char [] zzUnpackCMap(String packed) { - char [] map = new char[0x10000]; - int i = 0; /* index in packed string */ - int j = 0; /* index in unpacked array */ - while (i < 90) { - int count = packed.charAt(i++); - char value = packed.charAt(i++); - do map[j++] = value; while (--count > 0); - } - return map; - } - - - /** - * Refills the input buffer. - * - * @return false, iff there was new input. - * - * @exception java.io.IOException if any I/O-Error occurs - */ - private boolean zzRefill() throws java.io.IOException { - - /* first: make room (if you can) */ - if (zzStartRead > 0) { - System.arraycopy(zzBuffer, zzStartRead, - zzBuffer, 0, - zzEndRead-zzStartRead); - - /* translate stored positions */ - zzEndRead-= zzStartRead; - zzCurrentPos-= zzStartRead; - zzMarkedPos-= zzStartRead; - zzStartRead = 0; - } - - /* is the buffer big enough? */ - if (zzCurrentPos >= zzBuffer.length) { - /* if not: blow it up */ - char newBuffer[] = new char[zzCurrentPos*2]; - System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); - zzBuffer = newBuffer; - } - - /* finally: fill the buffer with new input */ - int numRead = zzReader.read(zzBuffer, zzEndRead, - zzBuffer.length-zzEndRead); - - if (numRead > 0) { - zzEndRead+= numRead; - return false; - } - // unlikely but not impossible: read 0 characters, but not at end of stream - if (numRead == 0) { - int c = zzReader.read(); - if (c == -1) { - return true; - } else { - zzBuffer[zzEndRead++] = (char) c; - return false; - } - } - - // numRead < 0 - return true; - } - - - /** - * Closes the input stream. - */ - public final void yyclose() throws java.io.IOException { - zzAtEOF = true; /* indicate end of file */ - zzEndRead = zzStartRead; /* invalidate buffer */ - - if (zzReader != null) - zzReader.close(); - } - - - /** - * Resets the scanner to read from a new input stream. - * Does not close the old reader. - * - * All internal variables are reset, the old input stream - * cannot be reused (internal buffer is discarded and lost). - * Lexical state is set to ZZ_INITIAL. - * - * @param reader the new input stream - */ - public final void yyreset(java.io.Reader reader) { - zzReader = reader; - zzAtBOL = true; - zzAtEOF = false; - zzEndRead = zzStartRead = 0; - zzCurrentPos = zzMarkedPos = 0; - yyline = yychar = yycolumn = 0; - zzLexicalState = YYINITIAL; - } - - - /** - * Returns the current lexical state. - */ - public final int yystate() { - return zzLexicalState; - } - - - /** - * Enters a new lexical state - * - * @param newState the new lexical state - */ - public final void yybegin(int newState) { - zzLexicalState = newState; - } - - - /** - * Returns the text matched by the current regular expression. - */ - public final String yytext() { - return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); - } - - - /** - * Returns the character at position pos from the - * matched text. - * - * It is equivalent to yytext().charAt(pos), but faster - * - * @param pos the position of the character to fetch. - * A value from 0 to yylength()-1. - * - * @return the character at position pos - */ - public final char yycharat(int pos) { - return zzBuffer[zzStartRead+pos]; - } - - - /** - * Returns the length of the matched text region. - */ - public final int yylength() { - return zzMarkedPos-zzStartRead; - } - - - /** - * Reports an error that occured while scanning. - * - * In a wellformed scanner (no or only correct usage of - * yypushback(int) and a match-all fallback rule) this method - * will only be called with things that "Can't Possibly Happen". - * If this method is called, something is seriously wrong - * (e.g. a JFlex bug producing a faulty scanner etc.). - * - * Usual syntax/scanner level error handling should be done - * in error fallback rules. - * - * @param errorCode the code of the errormessage to display - */ - private void zzScanError(int errorCode) { - String message; - try { - message = ZZ_ERROR_MSG[errorCode]; - } - catch (ArrayIndexOutOfBoundsException e) { - message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; - } - - throw new Error(message); - } - - - /** - * Pushes the specified amount of characters back into the input stream. - * - * They will be read again by then next call of the scanning method - * - * @param number the number of characters to be read again. - * This number must not be greater than yylength()! - */ - public void yypushback(int number) { - if ( number > yylength() ) - zzScanError(ZZ_PUSHBACK_2BIG); - - zzMarkedPos -= number; - } - - - /** - * Resumes scanning until the next regular expression is matched, - * the end of input is encountered or an I/O-Error occurs. - * - * @return the next token - * @exception java.io.IOException if any I/O-Error occurs - */ - public Yytoken yylex() throws java.io.IOException, ParseException { - int zzInput; - int zzAction; - - // cached fields: - int zzCurrentPosL; - int zzMarkedPosL; - int zzEndReadL = zzEndRead; - char [] zzBufferL = zzBuffer; - char [] zzCMapL = ZZ_CMAP; - - int [] zzTransL = ZZ_TRANS; - int [] zzRowMapL = ZZ_ROWMAP; - int [] zzAttrL = ZZ_ATTRIBUTE; - - while (true) { - zzMarkedPosL = zzMarkedPos; - - yychar+= zzMarkedPosL-zzStartRead; - - zzAction = -1; - - zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; - - zzState = ZZ_LEXSTATE[zzLexicalState]; - - - zzForAction: { - while (true) { - - if (zzCurrentPosL < zzEndReadL) - zzInput = zzBufferL[zzCurrentPosL++]; - else if (zzAtEOF) { - zzInput = YYEOF; - break zzForAction; - } - else { - // store back cached positions - zzCurrentPos = zzCurrentPosL; - zzMarkedPos = zzMarkedPosL; - boolean eof = zzRefill(); - // get translated positions and possibly new buffer - zzCurrentPosL = zzCurrentPos; - zzMarkedPosL = zzMarkedPos; - zzBufferL = zzBuffer; - zzEndReadL = zzEndRead; - if (eof) { - zzInput = YYEOF; - break zzForAction; - } - else { - zzInput = zzBufferL[zzCurrentPosL++]; - } - } - int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; - if (zzNext == -1) break zzForAction; - zzState = zzNext; - - int zzAttributes = zzAttrL[zzState]; - if ( (zzAttributes & 1) == 1 ) { - zzAction = zzState; - zzMarkedPosL = zzCurrentPosL; - if ( (zzAttributes & 8) == 8 ) break zzForAction; - } - - } - } - - // store back cached position - zzMarkedPos = zzMarkedPosL; - - switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 11: - { sb.append(yytext()); - } - case 25: break; - case 4: - { sb = null; sb = new StringBuffer(); yybegin(STRING_BEGIN); - } - case 26: break; - case 16: - { sb.append('\b'); - } - case 27: break; - case 6: - { return new Yytoken(Yytoken.TYPE_RIGHT_BRACE,null); - } - case 28: break; - case 23: - { Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); - } - case 29: break; - case 22: - { return new Yytoken(Yytoken.TYPE_VALUE, null); - } - case 30: break; - case 13: - { yybegin(YYINITIAL);return new Yytoken(Yytoken.TYPE_VALUE, sb.toString()); - } - case 31: break; - case 12: - { sb.append('\\'); - } - case 32: break; - case 21: - { Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); - } - case 33: break; - case 1: - { throw new ParseException(yychar, ParseException.ERROR_UNEXPECTED_CHAR, new Character(yycharat(0))); - } - case 34: break; - case 8: - { return new Yytoken(Yytoken.TYPE_RIGHT_SQUARE,null); - } - case 35: break; - case 19: - { sb.append('\r'); - } - case 36: break; - case 15: - { sb.append('/'); - } - case 37: break; - case 10: - { return new Yytoken(Yytoken.TYPE_COLON,null); - } - case 38: break; - case 14: - { sb.append('"'); - } - case 39: break; - case 5: - { return new Yytoken(Yytoken.TYPE_LEFT_BRACE,null); - } - case 40: break; - case 17: - { sb.append('\f'); - } - case 41: break; - case 24: + + + /** + * Creates a new scanner + * There is also a java.io.InputStream version of this constructor. + * + * @param in the java.io.Reader to read input from. + */ + Yylex(java.io.Reader in) { + this.zzReader = in; + } + + /** + * Creates a new scanner. + * There is also java.io.Reader version of this constructor. + * + * @param in the java.io.Inputstream to read input from. + */ + Yylex(java.io.InputStream in) { + this(new java.io.InputStreamReader(in)); + } + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 90) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + + /** + * Refills the input buffer. + * + * @return false, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + + /* first: make room (if you can) */ + if (zzStartRead > 0) { + System.arraycopy(zzBuffer, zzStartRead, + zzBuffer, 0, + zzEndRead-zzStartRead); + + /* translate stored positions */ + zzEndRead-= zzStartRead; + zzCurrentPos-= zzStartRead; + zzMarkedPos-= zzStartRead; + zzStartRead = 0; + } + + /* is the buffer big enough? */ + if (zzCurrentPos >= zzBuffer.length) { + /* if not: blow it up */ + char newBuffer[] = new char[zzCurrentPos*2]; + System.arraycopy(zzBuffer, 0, newBuffer, 0, zzBuffer.length); + zzBuffer = newBuffer; + } + + /* finally: fill the buffer with new input */ + int numRead = zzReader.read(zzBuffer, zzEndRead, + zzBuffer.length-zzEndRead); + + if (numRead > 0) { + zzEndRead+= numRead; + return false; + } + // unlikely but not impossible: read 0 characters, but not at end of stream + if (numRead == 0) { + int c = zzReader.read(); + if (c == -1) { + return true; + } else { + zzBuffer[zzEndRead++] = (char) c; + return false; + } + } + + // numRead < 0 + return true; + } + + + /** + * Closes the input stream. + */ + public final void yyclose() throws java.io.IOException { + zzAtEOF = true; /* indicate end of file */ + zzEndRead = zzStartRead; /* invalidate buffer */ + + if (zzReader != null) + zzReader.close(); + } + + + /** + * Resets the scanner to read from a new input stream. + * Does not close the old reader. + * + * All internal variables are reset, the old input stream + * cannot be reused (internal buffer is discarded and lost). + * Lexical state is set to ZZ_INITIAL. + * + * @param reader the new input stream + */ + public final void yyreset(java.io.Reader reader) { + zzReader = reader; + zzAtBOL = true; + zzAtEOF = false; + zzEOFDone = false; + zzEndRead = zzStartRead = 0; + zzCurrentPos = zzMarkedPos = 0; + yyline = yychar = yycolumn = 0; + zzLexicalState = YYINITIAL; + } + + + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final String yytext() { + return new String( zzBuffer, zzStartRead, zzMarkedPos-zzStartRead ); + } + + + /** + * Returns the character at position pos from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBuffer[zzStartRead+pos]; + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); + + zzMarkedPos -= number; + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public Yytoken yylex() throws java.io.IOException, ParseException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + char [] zzBufferL = zzBuffer; + char [] zzCMapL = ZZ_CMAP; + + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + yychar+= zzMarkedPosL-zzStartRead; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) + zzInput = zzBufferL[zzCurrentPosL++]; + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = zzBufferL[zzCurrentPosL++]; + } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; + if (zzNext == -1) break zzForAction; + zzState = zzNext; + + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) break zzForAction; + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 11: + { sb.append(yytext()); + } + case 25: break; + case 16: + { sb.append('\b'); + } + case 26: break; + case 6: + { return new Yytoken(Yytoken.TYPE_RIGHT_BRACE,null); + } + case 27: break; + case 23: + { Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); + } + case 28: break; + case 22: + { return new Yytoken(Yytoken.TYPE_VALUE, null); + } + case 29: break; + case 13: + { yybegin(YYINITIAL);return new Yytoken(Yytoken.TYPE_VALUE, sb.toString()); + } + case 30: break; + case 12: + { sb.append('\\'); + } + case 31: break; + case 21: + { Double val=Double.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); + } + case 32: break; + case 1: + { throw new ParseException(yychar, ParseException.ERROR_UNEXPECTED_CHAR, new Character(yycharat(0))); + } + case 33: break; + case 8: + { return new Yytoken(Yytoken.TYPE_RIGHT_SQUARE,null); + } + case 34: break; + case 19: + { sb.append('\r'); + } + case 35: break; + case 15: + { sb.append('/'); + } + case 36: break; + case 10: + { return new Yytoken(Yytoken.TYPE_COLON,null); + } + case 37: break; + case 4: + { sb = null; sb = new StringBuffer(); yybegin(STRING_BEGIN); + } + case 38: break; + case 14: + { sb.append('"'); + } + case 39: break; + case 5: + { return new Yytoken(Yytoken.TYPE_LEFT_BRACE,null); + } + case 40: break; + case 17: + { sb.append('\f'); + } + case 41: break; + case 24: { try{ int ch=Integer.parseInt(yytext().substring(2),16); sb.append((char)ch); } catch(Exception e){ throw new ParseException(yychar, ParseException.ERROR_UNEXPECTED_EXCEPTION, e); - } - } - case 42: break; - case 20: - { sb.append('\t'); - } - case 43: break; - case 7: - { return new Yytoken(Yytoken.TYPE_LEFT_SQUARE,null); - } - case 44: break; - case 2: - { Long val=Long.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); - } - case 45: break; - case 18: - { sb.append('\n'); - } - case 46: break; - case 9: - { return new Yytoken(Yytoken.TYPE_COMMA,null); - } - case 47: break; - case 3: - { - } - case 48: break; - default: - if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { - zzAtEOF = true; - return null; - } - else { - zzScanError(ZZ_NO_MATCH); - } - } - } - } - - -} + } + } + case 42: break; + case 20: + { sb.append('\t'); + } + case 43: break; + case 7: + { return new Yytoken(Yytoken.TYPE_LEFT_SQUARE,null); + } + case 44: break; + case 2: + { Long val=Long.valueOf(yytext()); return new Yytoken(Yytoken.TYPE_VALUE, val); + } + case 45: break; + case 18: + { sb.append('\n'); + } + case 46: break; + case 9: + { return new Yytoken(Yytoken.TYPE_COMMA,null); + } + case 47: break; + case 3: + { + } + case 48: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + return null; + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/src/main/java/org/json/simple/parser/Yytoken.java b/src/main/java/org/json/simple/parser/Yytoken.java index ff14e27c..bb8dd302 100644 --- a/src/main/java/org/json/simple/parser/Yytoken.java +++ b/src/main/java/org/json/simple/parser/Yytoken.java @@ -5,21 +5,57 @@ package org.json.simple.parser; /** - * @author FangYidong + * @author FangYidong<fangyidong@yahoo.com.cn> + * @deprecated since 2.0.0, copied to a new package. */ +@Deprecated public class Yytoken { + /** + * description omitted. + */ public static final int TYPE_VALUE=0;//JSON primitive value: string,number,boolean,null + /** + * description omitted. + */ public static final int TYPE_LEFT_BRACE=1; + /** + * description omitted. + */ public static final int TYPE_RIGHT_BRACE=2; + /** + * description omitted. + */ public static final int TYPE_LEFT_SQUARE=3; + /** + * description omitted. + */ public static final int TYPE_RIGHT_SQUARE=4; + /** + * description omitted. + */ public static final int TYPE_COMMA=5; + /** + * description omitted. + */ public static final int TYPE_COLON=6; + /** + * description omitted. + */ public static final int TYPE_EOF=-1;//end of file + /** + * description omitted. + */ public int type=0; + /** + * description omitted. + */ public Object value=null; + /** + * @param type description omitted. + * @param value description omitted. + */ public Yytoken(int type,Object value){ this.type=type; this.value=value; diff --git a/doc/json.lex b/src/main/lex/json.lex similarity index 100% rename from doc/json.lex rename to src/main/lex/json.lex diff --git a/src/main/lex/jsonstrict.lex b/src/main/lex/jsonstrict.lex new file mode 100644 index 00000000..a554f700 --- /dev/null +++ b/src/main/lex/jsonstrict.lex @@ -0,0 +1,59 @@ +package org.json.simple; + +%% + +%{ +private StringBuilder sb=new StringBuilder(); + +int getPosition(){ + return yychar; +} + +%} + +%table +%unicode +%state STRING_BEGIN + +%yylexthrow DeserializationException +%char + +HEX_D = [a-fA-F0-9] +DOUBLE = [-]?[0-9]+((\.[0-9]+)?([eE][-+]?[0-9]+)?) +WS = [ \t\r\n] +UNESCAPED_CH = [^\"\\] +FALLBACK_CH = . +%% + + \" { yybegin(YYINITIAL);return new Yytoken(Yytoken.Types.DATUM, sb.toString());} + {UNESCAPED_CH}+ { sb.append(yytext());} + \\\" {sb.append('"');} + \\\\ {sb.append('\\');} + \\\/ {sb.append('/');} + \\b {sb.append('\b');} + \\f {sb.append('\f');} + \\n {sb.append('\n');} + \\r {sb.append('\r');} + \\t {sb.append('\t');} + \\u{HEX_D}{HEX_D}{HEX_D}{HEX_D} { try{ + int ch=Integer.parseInt(yytext().substring(2),16); + sb.append((char)ch); + }catch(Exception e){ + /* The lexer is broken if it can build a 4 byte character code and fail to append the character. */ + throw new DeserializationException(yychar, DeserializationException.Problems.UNEXPECTED_EXCEPTION, e); + } + } + \\ {sb.append('\\');} + + \" { sb = null; sb = new StringBuilder(); yybegin(STRING_BEGIN);} + {DOUBLE} { java.math.BigDecimal val= new java.math.BigDecimal(yytext()); return new Yytoken(Yytoken.Types.DATUM, val);} + "true"|"false" { Boolean val=Boolean.valueOf(yytext()); return new Yytoken(Yytoken.Types.DATUM, val);} + "null" { return new Yytoken(Yytoken.Types.DATUM, null);} + "{" { return new Yytoken(Yytoken.Types.LEFT_BRACE, null);} + "}" { return new Yytoken(Yytoken.Types.RIGHT_BRACE, null);} + "[" { return new Yytoken(Yytoken.Types.LEFT_SQUARE, null);} + "]" { return new Yytoken(Yytoken.Types.RIGHT_SQUARE, null);} + "," { return new Yytoken(Yytoken.Types.COMMA, null);} + ":" { return new Yytoken(Yytoken.Types.COLON, null);} + {WS}+ {} + {FALLBACK_CH} { throw new DeserializationException(yychar, DeserializationException.Problems.UNEXPECTED_CHARACTER, new Character(yycharat(0)));} diff --git a/src/test/java/org/json/simple/JSONArrayTest.java b/src/test/java/org/json/simple/JSONArrayTest.java index 6e1591dc..96e0aba6 100644 --- a/src/test/java/org/json/simple/JSONArrayTest.java +++ b/src/test/java/org/json/simple/JSONArrayTest.java @@ -6,283 +6,284 @@ import java.util.HashSet; import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; -import junit.framework.TestCase; +/** Ensures that JSONArray hasn't regressed in functionality or breaks its API contract. Deprecated warnings are + * suppressed since it is intentionally testing deprecated code for backwards compatibility. */ +@SuppressWarnings("deprecation") +public class JSONArrayTest{ + /** Called before each Test Method. */ + @Before + public void setUp(){ + /* All of the implemented tests use local variables in their own respective method. */ + } -public class JSONArrayTest extends TestCase { + /** Called after each Test method. */ + @After + public void tearDown(){ + /* All of the implemented tests use local variables in their own respective method. */ + } - public void testJSONArray() { - final JSONArray jsonArray = new JSONArray(); - - assertEquals("[]", jsonArray.toJSONString()); - } + /** Ensures a boolean array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testBooleanArrayToString() throws IOException{ + Assert.assertEquals("null", JSONArray.toJSONString((boolean[])null)); + Assert.assertEquals("[]", JSONArray.toJSONString(new boolean[0])); + Assert.assertEquals("[true]", JSONArray.toJSONString(new boolean[]{true})); + Assert.assertEquals("[true,false,true]", JSONArray.toJSONString(new boolean[]{true, false, true})); + StringWriter writer; + writer = new StringWriter(); + JSONArray.writeJSONString((boolean[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new boolean[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new boolean[]{true}, writer); + Assert.assertEquals("[true]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new boolean[]{true, false, true}, writer); + Assert.assertEquals("[true,false,true]", writer.toString()); + } - public void testJSONArrayCollection() { - final ArrayList testList = new ArrayList(); - testList.add("First item"); - testList.add("Second item"); - - final JSONArray jsonArray = new JSONArray(testList); - - assertEquals("[\"First item\",\"Second item\"]", jsonArray.toJSONString()); - } + /** Ensures a byte array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testByteArrayToString() throws IOException{ + Assert.assertEquals("null", JSONArray.toJSONString((byte[])null)); + Assert.assertEquals("[]", JSONArray.toJSONString(new byte[0])); + Assert.assertEquals("[12]", JSONArray.toJSONString(new byte[]{12})); + Assert.assertEquals("[-7,22,86,-99]", JSONArray.toJSONString(new byte[]{-7, 22, 86, -99})); + StringWriter writer; + writer = new StringWriter(); + JSONArray.writeJSONString((byte[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new byte[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new byte[]{12}, writer); + Assert.assertEquals("[12]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new byte[]{-7, 22, 86, -99}, writer); + Assert.assertEquals("[-7,22,86,-99]", writer.toString()); + } - public void testWriteJSONStringCollectionWriter() throws IOException, ParseException { - final HashSet testSet = new HashSet(); - testSet.add("First item"); - testSet.add("Second item"); - - final JSONArray jsonArray = new JSONArray(testSet); - final StringWriter writer = new StringWriter(); - - jsonArray.writeJSONString(writer); - - final JSONParser parser = new JSONParser(); - final JSONArray parsedArray = (JSONArray)parser.parse(writer.toString()); - - assertTrue(parsedArray.containsAll(jsonArray)); - assertTrue(jsonArray.containsAll(parsedArray)); - assertEquals(2, jsonArray.size()); - } + /** Ensures a char array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testCharArrayToString() throws IOException{ + Assert.assertEquals("null", JSONArray.toJSONString((char[])null)); + Assert.assertEquals("[]", JSONArray.toJSONString(new char[0])); + Assert.assertEquals("[\"a\"]", JSONArray.toJSONString(new char[]{'a'})); + Assert.assertEquals("[\"a\",\"b\",\"c\"]", JSONArray.toJSONString(new char[]{'a', 'b', 'c'})); + StringWriter writer; + writer = new StringWriter(); + JSONArray.writeJSONString((char[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new char[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new char[]{'a'}, writer); + Assert.assertEquals("[\"a\"]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new char[]{'a', 'b', 'c'}, writer); + Assert.assertEquals("[\"a\",\"b\",\"c\"]", writer.toString()); + } - public void testToJSONStringCollection() throws ParseException { - final HashSet testSet = new HashSet(); - testSet.add("First item"); - testSet.add("Second item"); - - final JSONArray jsonArray = new JSONArray(testSet); - - final JSONParser parser = new JSONParser(); - final JSONArray parsedArray = (JSONArray)parser.parse(jsonArray.toJSONString()); - - assertTrue(parsedArray.containsAll(jsonArray)); - assertTrue(jsonArray.containsAll(parsedArray)); - assertEquals(2, jsonArray.size()); - } + /** Ensures a double array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testDoubleArrayToString() throws IOException{ + Assert.assertEquals("null", JSONArray.toJSONString((double[])null)); + Assert.assertEquals("[]", JSONArray.toJSONString(new double[0])); + Assert.assertEquals("[12.8]", JSONArray.toJSONString(new double[]{12.8})); + Assert.assertEquals("[-7.1,22.234,86.7,-99.02]", JSONArray.toJSONString(new double[]{-7.1, 22.234, 86.7, -99.02})); + StringWriter writer; + writer = new StringWriter(); + JSONArray.writeJSONString((double[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new double[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new double[]{12.8}, writer); + Assert.assertEquals("[12.8]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new double[]{-7.1, 22.234, 86.7, -99.02}, writer); + Assert.assertEquals("[-7.1,22.234,86.7,-99.02]", writer.toString()); + } - public void testByteArrayToString() throws IOException { - assertEquals("null", JSONArray.toJSONString((byte[])null)); - assertEquals("[]", JSONArray.toJSONString(new byte[0])); - assertEquals("[12]", JSONArray.toJSONString(new byte[] { 12 })); - assertEquals("[-7,22,86,-99]", JSONArray.toJSONString(new byte[] { -7, 22, 86, -99 })); - - StringWriter writer; - - writer = new StringWriter(); - JSONArray.writeJSONString((byte[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new byte[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new byte[] { 12 }, writer); - assertEquals("[12]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new byte[] { -7, 22, 86, -99 }, writer); - assertEquals("[-7,22,86,-99]", writer.toString()); - } - - public void testShortArrayToString() throws IOException { - assertEquals("null", JSONArray.toJSONString((short[])null)); - assertEquals("[]", JSONArray.toJSONString(new short[0])); - assertEquals("[12]", JSONArray.toJSONString(new short[] { 12 })); - assertEquals("[-7,22,86,-99]", JSONArray.toJSONString(new short[] { -7, 22, 86, -99 })); - - StringWriter writer; - - writer = new StringWriter(); - JSONArray.writeJSONString((short[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new short[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new short[] { 12 }, writer); - assertEquals("[12]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new short[] { -7, 22, 86, -99 }, writer); - assertEquals("[-7,22,86,-99]", writer.toString()); - } - - public void testIntArrayToString() throws IOException { - assertEquals("null", JSONArray.toJSONString((int[])null)); - assertEquals("[]", JSONArray.toJSONString(new int[0])); - assertEquals("[12]", JSONArray.toJSONString(new int[] { 12 })); - assertEquals("[-7,22,86,-99]", JSONArray.toJSONString(new int[] { -7, 22, 86, -99 })); - - StringWriter writer; - - writer = new StringWriter(); - JSONArray.writeJSONString((int[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new int[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new int[] { 12 }, writer); - assertEquals("[12]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new int[] { -7, 22, 86, -99 }, writer); - assertEquals("[-7,22,86,-99]", writer.toString()); - } - - public void testLongArrayToString() throws IOException { - assertEquals("null", JSONArray.toJSONString((long[])null)); - assertEquals("[]", JSONArray.toJSONString(new long[0])); - assertEquals("[12]", JSONArray.toJSONString(new long[] { 12 })); - assertEquals("[-7,22,9223372036854775807,-99]", JSONArray.toJSONString(new long[] { -7, 22, 9223372036854775807L, -99 })); - - StringWriter writer; - - writer = new StringWriter(); - JSONArray.writeJSONString((long[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new long[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new long[] { 12 }, writer); - assertEquals("[12]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new long[] { -7, 22, 86, -99 }, writer); - assertEquals("[-7,22,86,-99]", writer.toString()); - } - - public void testFloatArrayToString() throws IOException { - assertEquals("null", JSONArray.toJSONString((float[])null)); - assertEquals("[]", JSONArray.toJSONString(new float[0])); - assertEquals("[12.8]", JSONArray.toJSONString(new float[] { 12.8f })); - assertEquals("[-7.1,22.234,86.7,-99.02]", JSONArray.toJSONString(new float[] { -7.1f, 22.234f, 86.7f, -99.02f })); - - StringWriter writer; - - writer = new StringWriter(); - JSONArray.writeJSONString((float[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new float[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new float[] { 12.8f }, writer); - assertEquals("[12.8]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new float[] { -7.1f, 22.234f, 86.7f, -99.02f }, writer); - assertEquals("[-7.1,22.234,86.7,-99.02]", writer.toString()); - } - - public void testDoubleArrayToString() throws IOException { - assertEquals("null", JSONArray.toJSONString((double[])null)); - assertEquals("[]", JSONArray.toJSONString(new double[0])); - assertEquals("[12.8]", JSONArray.toJSONString(new double[] { 12.8 })); - assertEquals("[-7.1,22.234,86.7,-99.02]", JSONArray.toJSONString(new double[] { -7.1, 22.234, 86.7, -99.02 })); - - StringWriter writer; - - writer = new StringWriter(); - JSONArray.writeJSONString((double[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new double[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new double[] { 12.8 }, writer); - assertEquals("[12.8]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new double[] { -7.1, 22.234, 86.7, -99.02 }, writer); - assertEquals("[-7.1,22.234,86.7,-99.02]", writer.toString()); - } - - public void testBooleanArrayToString() throws IOException { - assertEquals("null", JSONArray.toJSONString((boolean[])null)); - assertEquals("[]", JSONArray.toJSONString(new boolean[0])); - assertEquals("[true]", JSONArray.toJSONString(new boolean[] { true })); - assertEquals("[true,false,true]", JSONArray.toJSONString(new boolean[] { true, false, true })); - - StringWriter writer; - - writer = new StringWriter(); - JSONArray.writeJSONString((boolean[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new boolean[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new boolean[] { true }, writer); - assertEquals("[true]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new boolean[] { true, false, true }, writer); - assertEquals("[true,false,true]", writer.toString()); - } - - public void testCharArrayToString() throws IOException { - assertEquals("null", JSONArray.toJSONString((char[])null)); - assertEquals("[]", JSONArray.toJSONString(new char[0])); - assertEquals("[\"a\"]", JSONArray.toJSONString(new char[] { 'a' })); - assertEquals("[\"a\",\"b\",\"c\"]", JSONArray.toJSONString(new char[] { 'a', 'b', 'c' })); - - StringWriter writer; - - writer = new StringWriter(); - JSONArray.writeJSONString((char[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new char[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new char[] { 'a' }, writer); - assertEquals("[\"a\"]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new char[] { 'a', 'b', 'c' }, writer); - assertEquals("[\"a\",\"b\",\"c\"]", writer.toString()); - } - - public void testObjectArrayToString() throws IOException { - assertEquals("null", JSONArray.toJSONString((Object[])null)); - assertEquals("[]", JSONArray.toJSONString(new Object[0])); - assertEquals("[\"Hello\"]", JSONArray.toJSONString(new Object[] { "Hello" })); - assertEquals("[\"Hello\",12,[1,2,3]]", JSONArray.toJSONString(new Object[] { "Hello", new Integer(12), new int[] { 1, 2, 3 } })); - - StringWriter writer; - - writer = new StringWriter(); - JSONArray.writeJSONString((Object[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new Object[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new Object[] { "Hello" }, writer); - assertEquals("[\"Hello\"]", writer.toString()); - - writer = new StringWriter(); - JSONArray.writeJSONString(new Object[] { "Hello", new Integer(12), new int[] { 1, 2, 3} }, writer); - assertEquals("[\"Hello\",12,[1,2,3]]", writer.toString()); - } + /** Ensures a float array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testFloatArrayToString() throws IOException{ + Assert.assertEquals("null", JSONArray.toJSONString((float[])null)); + Assert.assertEquals("[]", JSONArray.toJSONString(new float[0])); + Assert.assertEquals("[12.8]", JSONArray.toJSONString(new float[]{12.8f})); + Assert.assertEquals("[-7.1,22.234,86.7,-99.02]", JSONArray.toJSONString(new float[]{-7.1f, 22.234f, 86.7f, -99.02f})); + StringWriter writer; + writer = new StringWriter(); + JSONArray.writeJSONString((float[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new float[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new float[]{12.8f}, writer); + Assert.assertEquals("[12.8]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new float[]{-7.1f, 22.234f, 86.7f, -99.02f}, writer); + Assert.assertEquals("[-7.1,22.234,86.7,-99.02]", writer.toString()); + } + + /** Ensures a int array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testIntArrayToString() throws IOException{ + Assert.assertEquals("null", JSONArray.toJSONString((int[])null)); + Assert.assertEquals("[]", JSONArray.toJSONString(new int[0])); + Assert.assertEquals("[12]", JSONArray.toJSONString(new int[]{12})); + Assert.assertEquals("[-7,22,86,-99]", JSONArray.toJSONString(new int[]{-7, 22, 86, -99})); + StringWriter writer; + writer = new StringWriter(); + JSONArray.writeJSONString((int[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new int[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new int[]{12}, writer); + Assert.assertEquals("[12]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new int[]{-7, 22, 86, -99}, writer); + Assert.assertEquals("[-7,22,86,-99]", writer.toString()); + } + + /** Ensures JSONArray is encode as a JSON string. */ + @Test + public void testJSONArray(){ + final JSONArray jsonArray = new JSONArray(); + Assert.assertEquals("[]", jsonArray.toJSONString()); + } + + /** Ensures JSONArray is encode as a JSON string. */ + @Test + public void testJSONArrayCollection(){ + final ArrayList testList = new ArrayList(); + testList.add("First item"); + testList.add("Second item"); + final JSONArray jsonArray = new JSONArray(testList); + Assert.assertEquals("[\"First item\",\"Second item\"]", jsonArray.toJSONString()); + } + + /** Ensures a long array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testLongArrayToString() throws IOException{ + Assert.assertEquals("null", JSONArray.toJSONString((long[])null)); + Assert.assertEquals("[]", JSONArray.toJSONString(new long[0])); + Assert.assertEquals("[12]", JSONArray.toJSONString(new long[]{12})); + Assert.assertEquals("[-7,22,9223372036854775807,-99]", JSONArray.toJSONString(new long[]{-7, 22, 9223372036854775807L, -99})); + StringWriter writer; + writer = new StringWriter(); + JSONArray.writeJSONString((long[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new long[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new long[]{12}, writer); + Assert.assertEquals("[12]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new long[]{-7, 22, 86, -99}, writer); + Assert.assertEquals("[-7,22,86,-99]", writer.toString()); + } + + /** Ensures a object array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testObjectArrayToString() throws IOException{ + Assert.assertEquals("null", JSONArray.toJSONString((Object[])null)); + Assert.assertEquals("[]", JSONArray.toJSONString(new Object[0])); + Assert.assertEquals("[\"Hello\"]", JSONArray.toJSONString(new Object[]{"Hello"})); + Assert.assertEquals("[\"Hello\",12,[1,2,3]]", JSONArray.toJSONString(new Object[]{"Hello", new Integer(12), new int[]{1, 2, 3}})); + StringWriter writer; + writer = new StringWriter(); + JSONArray.writeJSONString((Object[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new Object[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new Object[]{"Hello"}, writer); + Assert.assertEquals("[\"Hello\"]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new Object[]{"Hello", new Integer(12), new int[]{1, 2, 3}}, writer); + Assert.assertEquals("[\"Hello\",12,[1,2,3]]", writer.toString()); + } + + /** Ensures a short array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testShortArrayToString() throws IOException{ + Assert.assertEquals("null", JSONArray.toJSONString((short[])null)); + Assert.assertEquals("[]", JSONArray.toJSONString(new short[0])); + Assert.assertEquals("[12]", JSONArray.toJSONString(new short[]{12})); + Assert.assertEquals("[-7,22,86,-99]", JSONArray.toJSONString(new short[]{-7, 22, 86, -99})); + StringWriter writer; + writer = new StringWriter(); + JSONArray.writeJSONString((short[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new short[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new short[]{12}, writer); + Assert.assertEquals("[12]", writer.toString()); + writer = new StringWriter(); + JSONArray.writeJSONString(new short[]{-7, 22, 86, -99}, writer); + Assert.assertEquals("[-7,22,86,-99]", writer.toString()); + } + + /** Ensures encoded collections are decoded. + * @throws Exception if the test failed. */ + @SuppressWarnings("unchecked") + @Test + public void testToJSONStringCollection() throws Exception{ + /* The method is unchecked because JSONArray is an unparameterized type. */ + final HashSet testSet = new HashSet(); + testSet.add("First item"); + testSet.add("Second item"); + final JSONArray jsonArray = new JSONArray(testSet); + final JSONParser parser = new JSONParser(); + final JSONArray parsedArray = (JSONArray)parser.parse(jsonArray.toJSONString()); + Assert.assertTrue(parsedArray.containsAll(jsonArray)); + Assert.assertTrue(jsonArray.containsAll(parsedArray)); + Assert.assertEquals(2, jsonArray.size()); + } + + /** Ensures collections are encode as a JSON string. + * @throws Exception if the test failed. */ + @SuppressWarnings("unchecked") + @Test + public void testWriteJSONStringCollectionWriter() throws Exception{ + /* The method is unchecked because JSONArray is an unparameterized type. */ + final HashSet testSet = new HashSet(); + testSet.add("First item"); + testSet.add("Second item"); + final JSONArray jsonArray = new JSONArray(testSet); + final StringWriter writer = new StringWriter(); + jsonArray.writeJSONString(writer); + final JSONParser parser = new JSONParser(); + final JSONArray parsedArray = (JSONArray)parser.parse(writer.toString()); + Assert.assertTrue(parsedArray.containsAll(jsonArray)); + Assert.assertTrue(jsonArray.containsAll(parsedArray)); + Assert.assertEquals(2, jsonArray.size()); + } } diff --git a/src/test/java/org/json/simple/JSONValueTest.java b/src/test/java/org/json/simple/JSONValueTest.java index 97f2b50f..4627c287 100644 --- a/src/test/java/org/json/simple/JSONValueTest.java +++ b/src/test/java/org/json/simple/JSONValueTest.java @@ -2,255 +2,320 @@ import java.io.IOException; import java.io.StringWriter; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; -import junit.framework.TestCase; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; -public class JSONValueTest extends TestCase { - public void testByteArrayToString() throws IOException { - assertEquals("null", JSONValue.toJSONString((byte[])null)); - assertEquals("[]", JSONValue.toJSONString(new byte[0])); - assertEquals("[12]", JSONValue.toJSONString(new byte[] { 12 })); - assertEquals("[-7,22,86,-99]", JSONValue.toJSONString(new byte[] { -7, 22, 86, -99 })); - - StringWriter writer; - - writer = new StringWriter(); - JSONValue.writeJSONString((byte[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new byte[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new byte[] { 12 }, writer); - assertEquals("[12]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new byte[] { -7, 22, 86, -99 }, writer); - assertEquals("[-7,22,86,-99]", writer.toString()); - } - - public void testShortArrayToString() throws IOException { - assertEquals("null", JSONValue.toJSONString((short[])null)); - assertEquals("[]", JSONValue.toJSONString(new short[0])); - assertEquals("[12]", JSONValue.toJSONString(new short[] { 12 })); - assertEquals("[-7,22,86,-99]", JSONValue.toJSONString(new short[] { -7, 22, 86, -99 })); - - StringWriter writer; - - writer = new StringWriter(); - JSONValue.writeJSONString((short[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new short[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new short[] { 12 }, writer); - assertEquals("[12]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new short[] { -7, 22, 86, -99 }, writer); - assertEquals("[-7,22,86,-99]", writer.toString()); - } - - public void testIntArrayToString() throws IOException { - assertEquals("null", JSONValue.toJSONString((int[])null)); - assertEquals("[]", JSONValue.toJSONString(new int[0])); - assertEquals("[12]", JSONValue.toJSONString(new int[] { 12 })); - assertEquals("[-7,22,86,-99]", JSONValue.toJSONString(new int[] { -7, 22, 86, -99 })); - - StringWriter writer; - - writer = new StringWriter(); - JSONValue.writeJSONString((int[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new int[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new int[] { 12 }, writer); - assertEquals("[12]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new int[] { -7, 22, 86, -99 }, writer); - assertEquals("[-7,22,86,-99]", writer.toString()); - } - - public void testLongArrayToString() throws IOException { - assertEquals("null", JSONValue.toJSONString((long[])null)); - assertEquals("[]", JSONValue.toJSONString(new long[0])); - assertEquals("[12]", JSONValue.toJSONString(new long[] { 12 })); - assertEquals("[-7,22,9223372036854775807,-99]", JSONValue.toJSONString(new long[] { -7, 22, 9223372036854775807L, -99 })); - - StringWriter writer; - - writer = new StringWriter(); - JSONValue.writeJSONString((long[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new long[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new long[] { 12 }, writer); - assertEquals("[12]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new long[] { -7, 22, 86, -99 }, writer); - assertEquals("[-7,22,86,-99]", writer.toString()); - } - - public void testFloatArrayToString() throws IOException { - assertEquals("null", JSONValue.toJSONString((float[])null)); - assertEquals("[]", JSONValue.toJSONString(new float[0])); - assertEquals("[12.8]", JSONValue.toJSONString(new float[] { 12.8f })); - assertEquals("[-7.1,22.234,86.7,-99.02]", JSONValue.toJSONString(new float[] { -7.1f, 22.234f, 86.7f, -99.02f })); - - StringWriter writer; - - writer = new StringWriter(); - JSONValue.writeJSONString((float[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new float[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new float[] { 12.8f }, writer); - assertEquals("[12.8]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new float[] { -7.1f, 22.234f, 86.7f, -99.02f }, writer); - assertEquals("[-7.1,22.234,86.7,-99.02]", writer.toString()); - } - - public void testDoubleArrayToString() throws IOException { - assertEquals("null", JSONValue.toJSONString((double[])null)); - assertEquals("[]", JSONValue.toJSONString(new double[0])); - assertEquals("[12.8]", JSONValue.toJSONString(new double[] { 12.8 })); - assertEquals("[-7.1,22.234,86.7,-99.02]", JSONValue.toJSONString(new double[] { -7.1, 22.234, 86.7, -99.02 })); - - StringWriter writer; - - writer = new StringWriter(); - JSONValue.writeJSONString((double[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new double[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new double[] { 12.8 }, writer); - assertEquals("[12.8]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new double[] { -7.1, 22.234, 86.7, -99.02 }, writer); - assertEquals("[-7.1,22.234,86.7,-99.02]", writer.toString()); - } - - public void testBooleanArrayToString() throws IOException { - assertEquals("null", JSONValue.toJSONString((boolean[])null)); - assertEquals("[]", JSONValue.toJSONString(new boolean[0])); - assertEquals("[true]", JSONValue.toJSONString(new boolean[] { true })); - assertEquals("[true,false,true]", JSONValue.toJSONString(new boolean[] { true, false, true })); - - StringWriter writer; - - writer = new StringWriter(); - JSONValue.writeJSONString((boolean[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new boolean[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new boolean[] { true }, writer); - assertEquals("[true]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new boolean[] { true, false, true }, writer); - assertEquals("[true,false,true]", writer.toString()); - } - - public void testCharArrayToString() throws IOException { - assertEquals("null", JSONValue.toJSONString((char[])null)); - assertEquals("[]", JSONValue.toJSONString(new char[0])); - assertEquals("[\"a\"]", JSONValue.toJSONString(new char[] { 'a' })); - assertEquals("[\"a\",\"b\",\"c\"]", JSONValue.toJSONString(new char[] { 'a', 'b', 'c' })); - - StringWriter writer; - - writer = new StringWriter(); - JSONValue.writeJSONString((char[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new char[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new char[] { 'a' }, writer); - assertEquals("[\"a\"]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new char[] { 'a', 'b', 'c' }, writer); - assertEquals("[\"a\",\"b\",\"c\"]", writer.toString()); - } - - public void testObjectArrayToString() throws IOException { - assertEquals("null", JSONValue.toJSONString((Object[])null)); - assertEquals("[]", JSONValue.toJSONString(new Object[0])); - assertEquals("[\"Hello\"]", JSONValue.toJSONString(new Object[] { "Hello" })); - assertEquals("[\"Hello\",12,[1,2,3]]", JSONValue.toJSONString(new Object[] { "Hello", new Integer(12), new int[] { 1, 2, 3 } })); - - StringWriter writer; - - writer = new StringWriter(); - JSONValue.writeJSONString((Object[])null, writer); - assertEquals("null", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new Object[0], writer); - assertEquals("[]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new Object[] { "Hello" }, writer); - assertEquals("[\"Hello\"]", writer.toString()); - - writer = new StringWriter(); - JSONValue.writeJSONString(new Object[] { "Hello", new Integer(12), new int[] { 1, 2, 3} }, writer); - assertEquals("[\"Hello\",12,[1,2,3]]", writer.toString()); - } - - public void testArraysOfArrays() throws IOException { - - StringWriter writer; - - final int[][][] nestedIntArray = new int[][][]{{{1}, {5}}, {{2}, {6}}}; - final String expectedNestedIntString = "[[[1],[5]],[[2],[6]]]"; - - assertEquals(expectedNestedIntString, JSONValue.toJSONString(nestedIntArray)); - - writer = new StringWriter(); - JSONValue.writeJSONString(nestedIntArray, writer); - assertEquals(expectedNestedIntString, writer.toString()); +/** Ensures that JSONValue hasn't regressed in functionality or breaks its API contract. Deprecated warnings are + * suppressed since it is intentionally testing deprecated code for backwards compatibility. */ +@SuppressWarnings("deprecation") +public class JSONValueTest{ + /** Called before each Test Method. */ + @Before + public void setUp(){ + /* All of the implemented tests use local variables in their own respective method. */ + } - final String[][] nestedStringArray = new String[][]{{"a", "b"}, {"c", "d"}}; - final String expectedNestedStringString = "[[\"a\",\"b\"],[\"c\",\"d\"]]"; - - assertEquals(expectedNestedStringString, JSONValue.toJSONString(nestedStringArray)); - - writer = new StringWriter(); - JSONValue.writeJSONString(nestedStringArray, writer); - assertEquals(expectedNestedStringString, writer.toString()); - } + /** Called after each Test method. */ + @After + public void tearDown(){ + /* All of the implemented tests use local variables in their own respective method. */ + } + + /** Ensures an array of array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testArraysOfArraysToJsonString() throws IOException{ + StringWriter writer; + final int[][][] nestedIntArray = new int[][][]{{{1}, {5}}, {{2}, {6}}}; + final String expectedNestedIntString = "[[[1],[5]],[[2],[6]]]"; + Assert.assertEquals(expectedNestedIntString, JSONValue.toJSONString(nestedIntArray)); + writer = new StringWriter(); + JSONValue.writeJSONString(nestedIntArray, writer); + Assert.assertEquals(expectedNestedIntString, writer.toString()); + final String[][] nestedStringArray = new String[][]{{"a", "b"}, {"c", "d"}}; + final String expectedNestedStringString = "[[\"a\",\"b\"],[\"c\",\"d\"]]"; + Assert.assertEquals(expectedNestedStringString, JSONValue.toJSONString(nestedStringArray)); + writer = new StringWriter(); + JSONValue.writeJSONString(nestedStringArray, writer); + Assert.assertEquals(expectedNestedStringString, writer.toString()); + } + + /** Ensures a boolean array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testBooleanArrayToJsonString() throws IOException{ + Assert.assertEquals("null", JSONValue.toJSONString((boolean[])null)); + Assert.assertEquals("[]", JSONValue.toJSONString(new boolean[0])); + Assert.assertEquals("[true]", JSONValue.toJSONString(new boolean[]{true})); + Assert.assertEquals("[true,false,true]", JSONValue.toJSONString(new boolean[]{true, false, true})); + StringWriter writer; + writer = new StringWriter(); + JSONValue.writeJSONString((boolean[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new boolean[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new boolean[]{true}, writer); + Assert.assertEquals("[true]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new boolean[]{true, false, true}, writer); + Assert.assertEquals("[true,false,true]", writer.toString()); + } + + /** Ensures a byte array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testByteArrayToJsonString() throws IOException{ + Assert.assertEquals("null", JSONValue.toJSONString((byte[])null)); + Assert.assertEquals("[]", JSONValue.toJSONString(new byte[0])); + Assert.assertEquals("[12]", JSONValue.toJSONString(new byte[]{12})); + Assert.assertEquals("[-7,22,86,-99]", JSONValue.toJSONString(new byte[]{-7, 22, 86, -99})); + StringWriter writer; + writer = new StringWriter(); + JSONValue.writeJSONString((byte[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new byte[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new byte[]{12}, writer); + Assert.assertEquals("[12]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new byte[]{-7, 22, 86, -99}, writer); + Assert.assertEquals("[-7,22,86,-99]", writer.toString()); + } + + /** Ensures a char array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testCharArrayToJsonString() throws IOException{ + Assert.assertEquals("null", JSONValue.toJSONString((char[])null)); + Assert.assertEquals("[]", JSONValue.toJSONString(new char[0])); + Assert.assertEquals("[\"a\"]", JSONValue.toJSONString(new char[]{'a'})); + Assert.assertEquals("[\"a\",\"b\",\"c\"]", JSONValue.toJSONString(new char[]{'a', 'b', 'c'})); + StringWriter writer; + writer = new StringWriter(); + JSONValue.writeJSONString((char[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new char[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new char[]{'a'}, writer); + Assert.assertEquals("[\"a\"]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new char[]{'a', 'b', 'c'}, writer); + Assert.assertEquals("[\"a\",\"b\",\"c\"]", writer.toString()); + } + + /** Ensures a double array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testDoubleArrayToJsonString() throws IOException{ + Assert.assertEquals("null", JSONValue.toJSONString((double[])null)); + Assert.assertEquals("[]", JSONValue.toJSONString(new double[0])); + Assert.assertEquals("[12.8]", JSONValue.toJSONString(new double[]{12.8})); + Assert.assertEquals("[-7.1,22.234,86.7,-99.02]", JSONValue.toJSONString(new double[]{-7.1, 22.234, 86.7, -99.02})); + StringWriter writer; + writer = new StringWriter(); + JSONValue.writeJSONString((double[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new double[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new double[]{12.8}, writer); + Assert.assertEquals("[12.8]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new double[]{-7.1, 22.234, 86.7, -99.02}, writer); + Assert.assertEquals("[-7.1,22.234,86.7,-99.02]", writer.toString()); + } + + /** Ensures JSON values can be encoded. + * @throws IOException if the test failed. */ + @SuppressWarnings("unchecked") + @Test + public void testEncodeJsonValues() throws IOException{ + final JSONArray array1 = new JSONArray(); + final JSONObject obj1 = new JSONObject(); + array1.add("abc\u0010a/"); + array1.add(new Integer(123)); + array1.add(new Double(222.123)); + array1.add(new Boolean(true)); + Assert.assertEquals("[\"abc\\u0010a\\/\",123,222.123,true]", array1.toString()); + obj1.put("array1", array1); + Assert.assertEquals("{\"array1\":[\"abc\\u0010a\\/\",123,222.123,true]}", obj1.toString()); + obj1.remove("array1"); + array1.add(obj1); + array1.add(null); + Assert.assertEquals("[\"abc\\u0010a\\/\",123,222.123,true,{},null]", array1.toString()); + final List list = new ArrayList(); + list.add("abc\u0010a/"); + list.add(new Integer(123)); + list.add(new Double(222.123)); + list.add(new Boolean(true)); + list.add(null); + Assert.assertEquals("[\"abc\\u0010a\\/\",123,222.123,true,null]", JSONArray.toJSONString(list)); + final Map map = new HashMap(); + map.put("array1", list); + Assert.assertEquals("{\"array1\":[\"abc\\u0010a\\/\",123,222.123,true,null]}", JSONObject.toJSONString(map)); + final Map m1 = new LinkedHashMap(); + final Map m2 = new LinkedHashMap(); + final List l1 = new LinkedList(); + m1.put("k11", "v11"); + m1.put("k12", "v12"); + m1.put("k13", "v13"); + m2.put("k21", "v21"); + m2.put("k22", "v22"); + m2.put("k23", "v23"); + l1.add(m1); + l1.add(m2); + String jsonString = JSONValue.toJSONString(l1); + Assert.assertEquals("[{\"k11\":\"v11\",\"k12\":\"v12\",\"k13\":\"v13\"},{\"k21\":\"v21\",\"k22\":\"v22\",\"k23\":\"v23\"}]", jsonString); + StringWriter out = new StringWriter(); + JSONValue.writeJSONString(l1, out); + jsonString = out.toString(); + Assert.assertEquals("[{\"k11\":\"v11\",\"k12\":\"v12\",\"k13\":\"v13\"},{\"k21\":\"v21\",\"k22\":\"v22\",\"k23\":\"v23\"}]", jsonString); + final List l2 = new LinkedList(); + final Map m3 = new LinkedHashMap(); + m3.put("k31", "v3"); + m3.put("k32", new Double(123.45)); + m3.put("k33", new Boolean(false)); + m3.put("k34", null); + l2.add("vvv"); + l2.add("1.23456789123456789"); + l2.add(new Boolean(true)); + l2.add(null); + m3.put("k35", l2); + m1.put("k14", m3); + out = new StringWriter(); + JSONValue.writeJSONString(l1, out); + jsonString = out.toString(); + Assert.assertEquals("[{\"k11\":\"v11\",\"k12\":\"v12\",\"k13\":\"v13\",\"k14\":{\"k31\":\"v3\",\"k32\":123.45,\"k33\":false,\"k34\":null,\"k35\":[\"vvv\",\"1.23456789123456789\",true,null]}},{\"k21\":\"v21\",\"k22\":\"v22\",\"k23\":\"v23\"}]", jsonString); + } + + /** Ensures a float array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testFloatArrayToString() throws IOException{ + Assert.assertEquals("null", JSONValue.toJSONString((float[])null)); + Assert.assertEquals("[]", JSONValue.toJSONString(new float[0])); + Assert.assertEquals("[12.8]", JSONValue.toJSONString(new float[]{12.8f})); + Assert.assertEquals("[-7.1,22.234,86.7,-99.02]", JSONValue.toJSONString(new float[]{-7.1f, 22.234f, 86.7f, -99.02f})); + StringWriter writer; + writer = new StringWriter(); + JSONValue.writeJSONString((float[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new float[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new float[]{12.8f}, writer); + Assert.assertEquals("[12.8]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new float[]{-7.1f, 22.234f, 86.7f, -99.02f}, writer); + Assert.assertEquals("[-7.1,22.234,86.7,-99.02]", writer.toString()); + } + + /** Ensures an int array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testIntArrayToJsonString() throws IOException{ + Assert.assertEquals("null", JSONValue.toJSONString((int[])null)); + Assert.assertEquals("[]", JSONValue.toJSONString(new int[0])); + Assert.assertEquals("[12]", JSONValue.toJSONString(new int[]{12})); + Assert.assertEquals("[-7,22,86,-99]", JSONValue.toJSONString(new int[]{-7, 22, 86, -99})); + StringWriter writer; + writer = new StringWriter(); + JSONValue.writeJSONString((int[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new int[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new int[]{12}, writer); + Assert.assertEquals("[12]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new int[]{-7, 22, 86, -99}, writer); + Assert.assertEquals("[-7,22,86,-99]", writer.toString()); + } + + /** Ensures a long array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testLongArrayToJsonString() throws IOException{ + Assert.assertEquals("null", JSONValue.toJSONString((long[])null)); + Assert.assertEquals("[]", JSONValue.toJSONString(new long[0])); + Assert.assertEquals("[12]", JSONValue.toJSONString(new long[]{12})); + Assert.assertEquals("[-7,22,9223372036854775807,-99]", JSONValue.toJSONString(new long[]{-7, 22, 9223372036854775807L, -99})); + StringWriter writer; + writer = new StringWriter(); + JSONValue.writeJSONString((long[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new long[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new long[]{12}, writer); + Assert.assertEquals("[12]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new long[]{-7, 22, 86, -99}, writer); + Assert.assertEquals("[-7,22,86,-99]", writer.toString()); + } + + /** Ensures an Object array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testObjectArrayToJsonString() throws IOException{ + Assert.assertEquals("null", JSONValue.toJSONString((Object[])null)); + Assert.assertEquals("[]", JSONValue.toJSONString(new Object[0])); + Assert.assertEquals("[\"Hello\"]", JSONValue.toJSONString(new Object[]{"Hello"})); + Assert.assertEquals("[\"Hello\",12,[1,2,3]]", JSONValue.toJSONString(new Object[]{"Hello", new Integer(12), new int[]{1, 2, 3}})); + StringWriter writer; + writer = new StringWriter(); + JSONValue.writeJSONString((Object[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new Object[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new Object[]{"Hello"}, writer); + Assert.assertEquals("[\"Hello\"]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new Object[]{"Hello", new Integer(12), new int[]{1, 2, 3}}, writer); + Assert.assertEquals("[\"Hello\",12,[1,2,3]]", writer.toString()); + } + + /** Ensures a short array can be encoded as a JSON string. + * @throws IOException if the test failed. */ + @Test + public void testShortArrayToJsonString() throws IOException{ + Assert.assertEquals("null", JSONValue.toJSONString((short[])null)); + Assert.assertEquals("[]", JSONValue.toJSONString(new short[0])); + Assert.assertEquals("[12]", JSONValue.toJSONString(new short[]{12})); + Assert.assertEquals("[-7,22,86,-99]", JSONValue.toJSONString(new short[]{-7, 22, 86, -99})); + StringWriter writer; + writer = new StringWriter(); + JSONValue.writeJSONString((short[])null, writer); + Assert.assertEquals("null", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new short[0], writer); + Assert.assertEquals("[]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new short[]{12}, writer); + Assert.assertEquals("[12]", writer.toString()); + writer = new StringWriter(); + JSONValue.writeJSONString(new short[]{-7, 22, 86, -99}, writer); + Assert.assertEquals("[-7,22,86,-99]", writer.toString()); + } } diff --git a/src/test/java/org/json/simple/JsonArrayTest.java b/src/test/java/org/json/simple/JsonArrayTest.java new file mode 100644 index 00000000..75790606 --- /dev/null +++ b/src/test/java/org/json/simple/JsonArrayTest.java @@ -0,0 +1,196 @@ +/* See: README for this file's copyright, terms, and conditions. */ +package org.json.simple; + +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** Ensures that JsonArray hasn't regressed in functionality or breaks its API contract. */ +public class JsonArrayTest{ + private enum TestEnums{ + A, + B; + } + + private static enum TestStaticEnums{ + ONE, + TWO; + } + + /** Called before each Test Method. */ + @Before + public void setUp(){ + /* All of the implemented tests use local variables in their own respective method. */ + } + + /** Called after each Test method. */ + @After + public void tearDown(){ + /* All of the implemented tests use local variables in their own respective method. */ + } + + /** Ensures a homogeneous JsonArray can be viewed as another collection of a specific type. */ + @Test + public void testAsCollection(){ + JsonArray json; + LinkedList parameterList; + HashSet parameterSet; + json = new JsonArray(); + json.add(1); + json.add(2); + json.add(3); + json.add(4); + json.add(5); + parameterList = new LinkedList(); + parameterSet = new HashSet(); + json.asCollection(parameterList); + json.asCollection(parameterSet); + Assert.assertTrue(parameterList.contains(1)); + Assert.assertTrue(parameterList.contains(2)); + Assert.assertTrue(parameterList.contains(3)); + Assert.assertTrue(parameterList.contains(4)); + Assert.assertTrue(parameterList.contains(5)); + Assert.assertTrue(parameterSet.contains(1)); + Assert.assertTrue(parameterSet.contains(2)); + Assert.assertTrue(parameterSet.contains(3)); + Assert.assertTrue(parameterSet.contains(4)); + Assert.assertTrue(parameterSet.contains(5)); + } + + /** Ensures another collection can be used to instantiate a JsonArray. */ + @Test + public void testConstructor(){ + JsonArray json; + LinkedList parameterList; + HashSet parameterSet; + parameterList = new LinkedList(); + parameterList.add(5); + parameterList.add(10); + parameterList.add(15); + json = new JsonArray(parameterList); + Assert.assertTrue(json.contains(5)); + Assert.assertTrue(json.contains(10)); + Assert.assertTrue(json.contains(15)); + parameterSet = new HashSet(); + parameterSet.add(20); + parameterSet.add(25); + parameterSet.add(30); + json = new JsonArray(parameterSet); + Assert.assertTrue(json.contains(20)); + Assert.assertTrue(json.contains(25)); + Assert.assertTrue(json.contains(30)); + } + + /** Ensures a BigDecimal can be gotten if there is a BigDecimal, Number, or String at the index. */ + @Test + public void testGetBigDecimal(){ + final JsonArray json = new JsonArray(); + json.add(new BigDecimal("0")); + json.add(new Double(0)); + json.add(new Float(0)); + json.add(new Long(0)); + json.add(new Integer(0)); + json.add(new Short((short)0)); + json.add(new Byte((byte)0)); + json.add(new String("0")); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimal(0)); + Assert.assertEquals(new BigDecimal("0.0"), json.getBigDecimal(1)); + Assert.assertEquals(new BigDecimal("0.0"), json.getBigDecimal(2)); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimal(3)); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimal(4)); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimal(5)); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimal(6)); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimal(7)); + } + + /** Ensures a Collection can be returned from an index. */ + @Test + public void testGetCollection(){ + final JsonArray json = new JsonArray(); + LinkedList list; + HashSet set; + JsonArray array; + List output0; + Set output1; + JsonArray output2; + list = new LinkedList(); + list.add(5); + list.add(10); + list.add(15); + set = new HashSet(); + set.add(20); + set.add(25); + set.add(30); + array = new JsonArray(); + array.add(35); + array.add(40); + array.add(45); + json.add(list); + json.add(set); + json.add(array); + output0 = json.getCollection(0); + Assert.assertTrue(output0.contains(5)); + Assert.assertTrue(output0.contains(10)); + Assert.assertTrue(output0.contains(15)); + output1 = json.getCollection(1); + Assert.assertTrue(output1.contains(20)); + Assert.assertTrue(output1.contains(25)); + Assert.assertTrue(output1.contains(30)); + output2 = json.getCollection(2); + Assert.assertTrue(output2.contains(35)); + Assert.assertTrue(output2.contains(40)); + Assert.assertTrue(output2.contains(45)); + } + + /** Ensures enums can be returned from a String value at an index. + * @throws ClassNotFoundException if the test failed. */ + @Test + public void testGetEnum() throws ClassNotFoundException{ + final JsonArray json = new JsonArray(); + json.add("org.json.simple.JsonArrayTest$TestStaticEnums.ONE"); + json.add("org.json.simple.JsonArrayTest$TestEnums.A"); + Assert.assertEquals(JsonArrayTest.TestStaticEnums.ONE, json.getEnum(0)); + Assert.assertEquals(JsonArrayTest.TestEnums.A, json.getEnum(1)); + } + + /** Ensure a map can be returned from an index. */ + @Test + public void testGetMap(){ + final JsonArray json = new JsonArray(); + final LinkedHashMap map = new LinkedHashMap(); + final JsonObject object = new JsonObject(); + Map output0; + JsonObject output1; + map.put("key0", 0); + map.put("key1", 1); + map.put("key2", 2); + object.put("key3", 3); + object.put("key4", 4); + object.put("key5", 5); + json.add(map); + json.add(object); + output0 = json.> getMap(0); + Assert.assertTrue(output0.containsKey("key0")); + Assert.assertTrue(output0.containsKey("key1")); + Assert.assertTrue(output0.containsKey("key2")); + Assert.assertTrue(output0.containsValue(0)); + Assert.assertTrue(output0.containsValue(1)); + Assert.assertTrue(output0.containsValue(2)); + output1 = json. getMap(1); + Assert.assertTrue(output1.containsKey("key3")); + Assert.assertTrue(output1.containsKey("key4")); + Assert.assertTrue(output1.containsKey("key5")); + Assert.assertTrue(output1.containsValue(3)); + Assert.assertTrue(output1.containsValue(4)); + Assert.assertTrue(output1.containsValue(5)); + } +} diff --git a/src/test/java/org/json/simple/JsonObjectTest.java b/src/test/java/org/json/simple/JsonObjectTest.java new file mode 100644 index 00000000..47d1a597 --- /dev/null +++ b/src/test/java/org/json/simple/JsonObjectTest.java @@ -0,0 +1,167 @@ +/* See: README for this file's copyright, terms, and conditions. */ +package org.json.simple; + +import java.math.BigDecimal; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** Ensures that JsonObject hasn't regressed in functionality or breaks its API contract. */ +public class JsonObjectTest{ + private enum TestEnums{ + A, + B; + } + + private static enum TestStaticEnums{ + ONE, + TWO; + } + + /** Called before each Test Method. */ + @Before + public void setUp(){ + /* All of the implemented tests use local variables in their own respective method. */ + } + + /** Called after each Test method. */ + @After + public void tearDown(){ + /* All of the implemented tests use local variables in their own respective method. */ + } + + /** Ensures another collection can be used to instantiate a JsonObject. */ + @Test + public void testConstructor(){ + JsonObject json; + LinkedHashMap parameter; + parameter = new LinkedHashMap(); + parameter.put("key0", 5); + parameter.put("key1", 10); + parameter.put("key2", 15); + json = new JsonObject(parameter); + Assert.assertTrue(json.containsKey("key0")); + Assert.assertTrue(json.containsKey("key1")); + Assert.assertTrue(json.containsKey("key2")); + Assert.assertTrue(json.containsValue(5)); + Assert.assertTrue(json.containsValue(10)); + Assert.assertTrue(json.containsValue(15)); + } + + /** Ensures a BigDecimal can be gotten if there is a BigDecimal, Number, or String at the key. */ + @Test + public void testGetBigDecimalOrDefault(){ + final JsonObject json = new JsonObject(); + final BigDecimal defaultValue = new BigDecimal("101"); + json.put("big", new BigDecimal("0")); + json.put("double", new Double(0)); + json.put("float", new Float(0)); + json.put("long", new Long(0)); + json.put("int", new Integer(0)); + json.put("short", new Short((short)0)); + json.put("byte", new Byte((byte)0)); + json.put("string", new String("0")); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimalOrDefault("big", defaultValue)); + Assert.assertEquals(new BigDecimal("0.0"), json.getBigDecimalOrDefault("double", defaultValue)); + Assert.assertEquals(new BigDecimal("0.0"), json.getBigDecimalOrDefault("float", defaultValue)); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimalOrDefault("long", defaultValue)); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimalOrDefault("int", defaultValue)); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimalOrDefault("short", defaultValue)); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimalOrDefault("byte", defaultValue)); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimalOrDefault("string", defaultValue)); + Assert.assertEquals(new BigDecimal("101"), json.getBigDecimalOrDefault("doesnotexist", defaultValue)); + } + + /** Ensures a Collection can be returned from a key. */ + @Test + public void testGetCollectionOrDefault(){ + final JsonObject json = new JsonObject(); + LinkedList list; + HashSet set; + JsonArray array; + List output0; + Set output1; + JsonArray output2; + list = new LinkedList(); + list.add(5); + list.add(10); + list.add(15); + set = new HashSet(); + set.add(20); + set.add(25); + set.add(30); + array = new JsonArray(); + array.add(35); + array.add(40); + array.add(45); + json.put("list", list); + json.put("set", set); + json.put("array", array); + output0 = json.getCollectionOrDefault("list", new LinkedList()); + Assert.assertTrue(output0.contains(5)); + Assert.assertTrue(output0.contains(10)); + Assert.assertTrue(output0.contains(15)); + output1 = json.getCollectionOrDefault("set", new HashSet()); + Assert.assertTrue(output1.contains(20)); + Assert.assertTrue(output1.contains(25)); + Assert.assertTrue(output1.contains(30)); + output2 = json.getCollectionOrDefault("array", new JsonArray()); + Assert.assertTrue(output2.contains(35)); + Assert.assertTrue(output2.contains(40)); + Assert.assertTrue(output2.contains(45)); + Assert.assertEquals(new JsonArray(), json.getCollectionOrDefault("doesnotexist", new JsonArray())); + } + + /** Ensures enums can be returned from a String value at an index. + * @throws ClassNotFoundException if the test failed. */ + @Test + public void testGetEnumOrDefault() throws ClassNotFoundException{ + final JsonObject json = new JsonObject(); + json.put("key0", "org.json.simple.JsonObjectTest$TestStaticEnums.ONE"); + json.put("key1", "org.json.simple.JsonObjectTest$TestEnums.A"); + Assert.assertEquals(JsonObjectTest.TestStaticEnums.ONE, json.getEnumOrDefault("key0", JsonObjectTest.TestStaticEnums.TWO)); + Assert.assertEquals(JsonObjectTest.TestEnums.A, json.getEnumOrDefault("key1", JsonObjectTest.TestEnums.B)); + Assert.assertEquals(JsonObjectTest.TestEnums.A, json.getEnumOrDefault("doesnotexist", JsonObjectTest.TestEnums.A)); + } + + /** Ensure a map can be returned from a key. */ + @Test + public void testGetMap(){ + final JsonObject json = new JsonObject(); + final LinkedHashMap map = new LinkedHashMap(); + final JsonObject object = new JsonObject(); + Map output0; + JsonObject output1; + map.put("key0", 0); + map.put("key1", 1); + map.put("key2", 2); + object.put("key3", 3); + object.put("key4", 4); + object.put("key5", 5); + json.put("map", map); + json.put("object", object); + output0 = json.> getMapOrDefault("map", new LinkedHashMap()); + Assert.assertTrue(output0.containsKey("key0")); + Assert.assertTrue(output0.containsKey("key1")); + Assert.assertTrue(output0.containsKey("key2")); + Assert.assertTrue(output0.containsValue(0)); + Assert.assertTrue(output0.containsValue(1)); + Assert.assertTrue(output0.containsValue(2)); + output1 = json. getMapOrDefault("object", new JsonObject()); + Assert.assertTrue(output1.containsKey("key3")); + Assert.assertTrue(output1.containsKey("key4")); + Assert.assertTrue(output1.containsKey("key5")); + Assert.assertTrue(output1.containsValue(3)); + Assert.assertTrue(output1.containsValue(4)); + Assert.assertTrue(output1.containsValue(5)); + Assert.assertEquals(new JsonObject(), json.getMapOrDefault("doesnotexist", new JsonObject())); + } +} diff --git a/src/test/java/org/json/simple/JsonerTest.java b/src/test/java/org/json/simple/JsonerTest.java new file mode 100644 index 00000000..b118c7bd --- /dev/null +++ b/src/test/java/org/json/simple/JsonerTest.java @@ -0,0 +1,479 @@ +/* See: README for this file's copyright, terms, and conditions. */ +package org.json.simple; + +import java.io.IOException; +import java.io.StringReader; +import java.io.StringWriter; +import java.math.BigDecimal; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** Ensures that deserialization and serialization hasn't regressed in functionality or breaks its API contract. */ +public class JsonerTest{ + /** @see JsonerTest#testEnumSerialization() */ + private enum TestEnums{ + A, + B; + } + + /** @see JsonerTest#testEnumSerialization() */ + private static enum TestStaticEnums{ + ONE, + TWO; + } + + /** Called before each Test Method. */ + @Before + public void setUp(){ + /* All of the implemented tests use local variables in their own respective method. */ + } + + /** Called after each Test method. */ + @After + public void tearDown(){ + /* All of the implemented tests use local variables in their own respective method. */ + } + + /** Ensures arrays are directly deserializable. + * @throws DeserializationException if the test fails. */ + @Test + public void testArrayDeserialization() throws DeserializationException{ + JsonArray defaultValue; + Object deserialized; + /* Trailing commas are common causes of wasting time debugging JSON. Allowing it in deserialization will + * inevitably make it feel more simple and save the user time debugging pointless things. */ + deserialized = Jsoner.deserialize("[,]"); + Assert.assertEquals(new JsonArray(), deserialized); + /* Serializing JsonArrays directly requires a defaultValue in case it doesn't deserialize a JsonArray. */ + defaultValue = new JsonArray(); + defaultValue.add("default"); + deserialized = Jsoner.deserializeJsonArray("[,]", defaultValue); + Assert.assertEquals(new JsonArray(), deserialized); + /* The call should return the defaultValue instead. */ + deserialized = Jsoner.deserializeJsonArray("[asdf,]", defaultValue); + Assert.assertEquals(defaultValue, deserialized); + } + + /** Ensures arrays are serializable. + * @throws IOException if the test fails. */ + @Test + public void testArraySerialization() throws IOException{ + StringWriter serialized; + /* Extraneous commas are not allowed when serializing an array. */ + serialized = new StringWriter(); + Jsoner.serialize(new JsonArray(), serialized); + Assert.assertEquals("[]", serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeStrictly(new JsonArray(), serialized); + Assert.assertEquals("[]", serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeCarelessly(new JsonArray(), serialized); + Assert.assertEquals("[]", serialized.toString()); + } + + /** Ensures booleans are directly deserializable. + * @throws DeserializationException if the test fails. */ + @Test + public void testBooleanDeserialization() throws DeserializationException{ + Object deserialized; + deserialized = Jsoner.deserialize("true"); + Assert.assertEquals(true, deserialized); + deserialized = Jsoner.deserialize("false"); + Assert.assertEquals(false, deserialized); + } + + /** Ensures booleans are serializable. + * @throws IOException if the test fails. */ + @Test + public void testBooleanSerialization() throws IOException{ + StringWriter serialized; + serialized = new StringWriter(); + Jsoner.serialize(true, serialized); + Assert.assertEquals("true", serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeStrictly(true, serialized); + Assert.assertEquals("true", serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeCarelessly(true, serialized); + Assert.assertEquals("true", serialized.toString()); + serialized = new StringWriter(); + Jsoner.serialize(false, serialized); + Assert.assertEquals("false", serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeStrictly(false, serialized); + Assert.assertEquals("false", serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeCarelessly(false, serialized); + Assert.assertEquals("false", serialized.toString()); + } + + /** Makes sure enums are serialized when appropriate. + * @throws IOException if the test fails. */ + @Test + public void testEnumSerialization() throws IOException{ + StringWriter serialized; + serialized = new StringWriter(); + Jsoner.serialize(TestStaticEnums.ONE, serialized); + Assert.assertEquals("\"org.json.simple.JsonerTest$TestStaticEnums.ONE\"", serialized.toString()); + serialized = new StringWriter(); + try{ + Jsoner.serializeStrictly(TestStaticEnums.ONE, serialized); + }catch(final IllegalArgumentException caught){ + /* Strictly doesn't allow enums. */ + } + serialized = new StringWriter(); + Jsoner.serializeCarelessly(TestStaticEnums.ONE, serialized); + Assert.assertEquals(TestStaticEnums.ONE.toString(), serialized.toString()); + serialized = new StringWriter(); + Jsoner.serialize(TestEnums.A, serialized); + Assert.assertEquals("\"org.json.simple.JsonerTest$TestEnums.A\"", serialized.toString()); + serialized = new StringWriter(); + try{ + Jsoner.serializeStrictly(TestEnums.A, serialized); + }catch(final IllegalArgumentException caught){ + /* Strictly doesn't allow enums. */ + } + serialized = new StringWriter(); + Jsoner.serializeCarelessly(TestEnums.A, serialized); + Assert.assertEquals(TestEnums.A.toString(), serialized.toString()); + } + + /** Ensures multiple concatenated JSON values are directly deserializable. + * @throws DeserializationException if the test fails. + * @throws IOException if the test fails. */ + @Test + public void testMultipleDeserialization() throws DeserializationException, IOException{ + final StringBuilder deserializable = new StringBuilder(); + JsonArray expected; + Object deserialized; + /* Build the input string and the expected output one by one. */ + expected = new JsonArray(); + deserializable.append(false); + expected.add(false); + deserializable.append("{}"); + expected.add(new JsonObject()); + deserializable.append("{}"); + expected.add(new JsonObject()); + deserializable.append("{}"); + expected.add(new JsonObject()); + deserializable.append((String)null); + expected.add(null); + deserializable.append((String)null); + expected.add(null); + deserializable.append((String)null); + expected.add(null); + deserializable.append(true); + expected.add(true); + deserializable.append(true); + expected.add(true); + deserializable.append("[]"); + expected.add(new JsonArray()); + deserializable.append("123"); + expected.add(new BigDecimal("123")); + deserializable.append("{}"); + expected.add(new JsonObject()); + deserializable.append("[]"); + expected.add(new JsonArray()); + deserializable.append("12.3"); + expected.add(new BigDecimal("12.3")); + deserializable.append("\"\""); + expected.add(""); + deserializable.append("\"\\\"\\\"\""); + expected.add("\"\""); + deserializable.append("\"String\""); + expected.add("String"); + deserializable.append("12.3e-10"); + expected.add(new BigDecimal("12.3e-10")); + deserializable.append("[]"); + expected.add(new JsonArray()); + deserializable.append("[]"); + expected.add(new JsonArray()); + deserializable.append("[]"); + expected.add(new JsonArray()); + deserialized = Jsoner.deserializeMultipleJsonValues(new StringReader(deserializable.toString())); + Assert.assertEquals(expected, deserialized); + } + + /** Ensures booleans, JsonArray, JsonObject, null, numbers, and Strings are deserializable while inside a JsonObject + * or JsonArray. + * @throws DeserializationException if the test fails. */ + @Test + public void testNestedDeserialization() throws DeserializationException{ + JsonArray expectedArray; + JsonObject expectedObject; + Object deserialized; + /* Set up the expected array. */ + expectedArray = new JsonArray(); + expectedArray.add(true); + expectedArray.add(false); + expectedArray.add(new JsonArray()); + expectedArray.add(new JsonObject()); + expectedArray.add(null); + expectedArray.add(new BigDecimal("-0.0e-100")); + expectedArray.add("String"); + /* Set up the expected object. */ + expectedObject = new JsonObject(); + expectedObject.put("key0", true); + expectedObject.put("key1", false); + expectedObject.put("key2", new JsonArray()); + expectedObject.put("key3", new JsonObject()); + expectedObject.put("key4", null); + expectedObject.put("key5", new BigDecimal("-0.0e-100")); + expectedObject.put("key6", "String"); + /* Check that the nested serializations worked, with extra commas for good measure. */ + deserialized = Jsoner.deserialize("[true,false,[],,{},null,-0.0e-100,,\"String\",]"); + Assert.assertEquals(expectedArray, deserialized); + deserialized = Jsoner.deserialize("{\"key0\":true,\"key1\":false,\"key2\":[],,\"key3\":{},,\"key4\":null,\"key5\":-0.0e-100,\"key6\":\"String\",}"); + Assert.assertEquals(expectedObject, deserialized); + } + + /** Ensures booleans, JsonArray, JsonObject, null, numbers, and Strings are serializable while inside a JsonObject or + * JsonArray. + * @throws IOException if the test failed. */ + @Test + public void testNestedSerialization() throws IOException{ + JsonArray inputArray; + JsonObject inputObject; + StringWriter output; + String serialized; + /* Set up the input array. */ + inputArray = new JsonArray(); + inputArray.add(true); + inputArray.add(false); + inputArray.add(new JsonArray()); + inputArray.add(new JsonObject()); + inputArray.add(null); + inputArray.add(new BigDecimal("-0.0e-100")); + inputArray.add("String"); + /* Set up the input object. */ + inputObject = new JsonObject(); + inputObject.put("key0", true); + inputObject.put("key1", false); + inputObject.put("key2", new JsonArray()); + inputObject.put("key3", new JsonObject()); + inputObject.put("key4", null); + inputObject.put("key5", new BigDecimal("-0.0e-100")); + inputObject.put("key6", "String"); + /* Check that the nested serializations worked and should never have extraneous commas. + * First check the array's serialization [normal, strictly, carelessly] output. */ + output = new StringWriter(); + Jsoner.serialize(inputArray, output); + serialized = output.toString(); + Assert.assertEquals("[true,false,[],{},null,0E-101,\"String\"]", output.toString()); + output = new StringWriter(); + Jsoner.serializeStrictly(inputArray, output); + serialized = output.toString(); + Assert.assertEquals("[true,false,[],{},null,0E-101,\"String\"]", output.toString()); + output = new StringWriter(); + Jsoner.serializeCarelessly(inputArray, output); + serialized = output.toString(); + Assert.assertEquals("[true,false,[],{},null,0E-101,\"String\"]", output.toString()); + /* Next check the object's serialization [normal, strictly, carelessly] output. */ + output = new StringWriter(); + Jsoner.serialize(inputObject, output); + serialized = output.toString(); + /* Ensure it started with a '{' and ended with a '}'. */ + Assert.assertTrue(serialized.charAt(0) == '{'); + Assert.assertTrue(serialized.charAt(serialized.length() - 1) == '}'); + /* Ensure each key and value were present in the correct format. */ + Assert.assertTrue(serialized.contains("\"key0\":true")); + Assert.assertTrue(serialized.contains("\"key1\":false")); + Assert.assertTrue(serialized.contains("\"key2\":[]")); + Assert.assertTrue(serialized.contains("\"key3\":{}")); + Assert.assertTrue(serialized.contains("\"key4\":null")); + Assert.assertTrue(serialized.contains("\"key5\":0E-101")); + Assert.assertTrue(serialized.contains("\"key6\":\"String\"")); + /* Ensure there were the correct amount of entries separated by a comma. */ + Assert.assertTrue(serialized.split(",").length == 7); + output = new StringWriter(); + Jsoner.serializeStrictly(inputObject, output); + serialized = output.toString(); + /* Ensure it started with a '{' and ended with a '}'. */ + Assert.assertTrue(serialized.charAt(0) == '{'); + Assert.assertTrue(serialized.charAt(serialized.length() - 1) == '}'); + /* Ensure each key and value were present in the correct format. */ + Assert.assertTrue(serialized.contains("\"key0\":true")); + Assert.assertTrue(serialized.contains("\"key1\":false")); + Assert.assertTrue(serialized.contains("\"key2\":[]")); + Assert.assertTrue(serialized.contains("\"key3\":{}")); + Assert.assertTrue(serialized.contains("\"key4\":null")); + Assert.assertTrue(serialized.contains("\"key5\":0E-101")); + Assert.assertTrue(serialized.contains("\"key6\":\"String\"")); + /* Ensure there were the correct amount of entries separated by a comma. */ + Assert.assertTrue(serialized.split(",").length == 7); + output = new StringWriter(); + Jsoner.serializeCarelessly(inputObject, output); + serialized = output.toString(); + /* Ensure it started with a '{' and ended with a '}'. */ + Assert.assertTrue(serialized.charAt(0) == '{'); + Assert.assertTrue(serialized.charAt(serialized.length() - 1) == '}'); + /* Ensure each key and value were present in the correct format. */ + Assert.assertTrue(serialized.contains("\"key0\":true")); + Assert.assertTrue(serialized.contains("\"key1\":false")); + Assert.assertTrue(serialized.contains("\"key2\":[]")); + Assert.assertTrue(serialized.contains("\"key3\":{}")); + Assert.assertTrue(serialized.contains("\"key4\":null")); + Assert.assertTrue(serialized.contains("\"key5\":0E-101")); + Assert.assertTrue(serialized.contains("\"key6\":\"String\"")); + /* Ensure there were the correct amount of entries separated by a comma. */ + Assert.assertTrue(serialized.split(",").length == 7); + } + + /** Ensures null is directly deserializable. + * @throws DeserializationException if the test fails. */ + @Test + public void testNullDeserialization() throws DeserializationException{ + Object deserialized; + deserialized = Jsoner.deserialize("null"); + Assert.assertEquals(null, deserialized); + } + + /** Ensures null is serializable. + * @throws IOException if the test fails. */ + @Test + public void testNullSerialization() throws IOException{ + StringWriter serialized; + serialized = new StringWriter(); + Jsoner.serialize(null, serialized); + Assert.assertEquals("null", serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeStrictly(null, serialized); + Assert.assertEquals("null", serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeCarelessly(null, serialized); + Assert.assertEquals("null", serialized.toString()); + } + + /** Ensures Numbers are directly deserializable. + * @throws DeserializationException if the test fails. */ + @Test + public void testNumberDeserialization() throws DeserializationException{ + Object deserialized; + deserialized = Jsoner.deserialize("-1234567890987654321.01234567890987654321E-50"); + Assert.assertEquals(new BigDecimal("-1234567890987654321.01234567890987654321E-50"), deserialized); + deserialized = Jsoner.deserialize("-1234567890987654321.01234567890987654321"); + Assert.assertEquals(new BigDecimal("-1234567890987654321.01234567890987654321"), deserialized); + deserialized = Jsoner.deserialize("1234567890987654321.01234567890987654321"); + Assert.assertEquals(new BigDecimal("1234567890987654321.01234567890987654321"), deserialized); + deserialized = Jsoner.deserialize("123456789098765432101234567890987654321"); + Assert.assertEquals(new BigDecimal("123456789098765432101234567890987654321"), deserialized); + } + + /** Ensures Numbers are serializable. + * @throws IOException if the test fails. */ + @Test + public void testNumberSerialization() throws IOException{ + StringWriter serialized; + serialized = new StringWriter(); + Jsoner.serialize(new BigDecimal("-1234567890987654321.01234567890987654321E-50"), serialized); + Assert.assertEquals(new BigDecimal("-1234567890987654321.01234567890987654321E-50").toString(), serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeStrictly(new BigDecimal("-1234567890987654321.01234567890987654321E-50"), serialized); + Assert.assertEquals(new BigDecimal("-1234567890987654321.01234567890987654321E-50").toString(), serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeCarelessly(new BigDecimal("-1234567890987654321.01234567890987654321E-50"), serialized); + Assert.assertEquals(new BigDecimal("-1234567890987654321.01234567890987654321E-50").toString(), serialized.toString()); + serialized = new StringWriter(); + Jsoner.serialize(new BigDecimal("-1234567890987654321.01234567890987654321"), serialized); + Assert.assertEquals(new BigDecimal("-1234567890987654321.01234567890987654321").toString(), serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeStrictly(new BigDecimal("-1234567890987654321.01234567890987654321"), serialized); + Assert.assertEquals(new BigDecimal("-1234567890987654321.01234567890987654321").toString(), serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeCarelessly(new BigDecimal("-1234567890987654321.01234567890987654321"), serialized); + Assert.assertEquals(new BigDecimal("-1234567890987654321.01234567890987654321").toString(), serialized.toString()); + serialized = new StringWriter(); + Jsoner.serialize(new BigDecimal("1234567890987654321.01234567890987654321"), serialized); + Assert.assertEquals(new BigDecimal("1234567890987654321.01234567890987654321").toString(), serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeStrictly(new BigDecimal("1234567890987654321.01234567890987654321"), serialized); + Assert.assertEquals(new BigDecimal("1234567890987654321.01234567890987654321").toString(), serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeCarelessly(new BigDecimal("1234567890987654321.01234567890987654321"), serialized); + Assert.assertEquals(new BigDecimal("1234567890987654321.01234567890987654321").toString(), serialized.toString()); + serialized = new StringWriter(); + Jsoner.serialize(new BigDecimal("123456789098765432101234567890987654321"), serialized); + Assert.assertEquals(new BigDecimal("123456789098765432101234567890987654321").toString(), serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeStrictly(new BigDecimal("123456789098765432101234567890987654321"), serialized); + Assert.assertEquals(new BigDecimal("123456789098765432101234567890987654321").toString(), serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeCarelessly(new BigDecimal("123456789098765432101234567890987654321"), serialized); + Assert.assertEquals(new BigDecimal("123456789098765432101234567890987654321").toString(), serialized.toString()); + } + + /** Ensures objects are directly deserializable. + * @throws DeserializationException if the test fails. */ + @Test + public void testObjectDeserialization() throws DeserializationException{ + JsonObject defaultValue; + Object deserialized; + /* Trailing commas are common causes of wasting time debugging JSON. Allowing it in deserialization will + * inevitably make it feel more simple and save the user time debugging pointless things. */ + deserialized = Jsoner.deserialize("{,}"); + Assert.assertEquals(new JsonObject(), deserialized); + /* Serializing JsonObjects directly requires a defaultValue in case it doesn't deserialize a JsonObject. */ + defaultValue = new JsonObject(); + defaultValue.put("default", -1); + deserialized = Jsoner.deserializeJsonObject("{,}", defaultValue); + Assert.assertEquals(new JsonObject(), deserialized); + /* The call should return the defaultValue instead. */ + deserialized = Jsoner.deserializeJsonObject("{asdf,}", defaultValue); + Assert.assertEquals(defaultValue, deserialized); + } + + /** Ensures objects are serializable. + * @throws IOException if the test fails. */ + @Test + public void testObjectSerialization() throws IOException{ + StringWriter serialized; + /* Extraneous commas are not allowed when serializing an object. */ + serialized = new StringWriter(); + Jsoner.serialize(new JsonObject(), serialized); + Assert.assertEquals("{}", serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeStrictly(new JsonObject(), serialized); + Assert.assertEquals("{}", serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeCarelessly(new JsonObject(), serialized); + Assert.assertEquals("{}", serialized.toString()); + } + + /** Ensures arrays and objects can be printed in an easier to read format. */ + @Test + public void testPrettyPrint(){ + Assert.assertEquals("[\n\t0,\n\t1,\n\t2,\n\t{\n\t\t\"k0\"\":\"\"v0\",\n\t\t\"k1\"\":\"\"v1\"\n\t},\n\t[\n\t\t[\n\t\t\t\"\",\n\t\t\t\"\"\n\t\t]\n\t],\n\tnull,\n\ttrue,\n\tfalse\n]", Jsoner.prettyPrint("[0,1,2,{\"k0\":\"v0\",\"k1\":\"v1\"},[[\"\",\"\"]],null,true,false]")); + } + + /** Ensures Strings are directly deserializable. + * @throws DeserializationException if the test fails. */ + @Test + public void testStringDeserialization() throws DeserializationException{ + Object deserialized; + /* Uses typical US English and picks out characters in unicode that have a decimal representation that ends with + * 050, like 1050, 3050, 4050, 5050, etc. */ + deserialized = Jsoner.deserialize("\"ABCDEFGHIJKLMNOPQRSTUVWXYZ<>:{}abcdefghijklmnopqrstuvwxyz,.;'[]\\/`123456789-=~!@#$%^&*_+()\\r\\b\\n\\t\\f\\\\К௪ၐᎺអὲ⍚❂⼒ぐ㋺ꁐꁚꑂ\\u4e2d\""); + Assert.assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ<>:{}abcdefghijklmnopqrstuvwxyz,.;'[]/`123456789-=~!@#$%^&*_+()\r\b\n\t\f\\К௪ၐᎺអὲ⍚❂⼒ぐ㋺ꁐꁚꑂ\u4e2d", deserialized); + } + + /** Ensures Strings are serializable. + * @throws IOException if the test fails. */ + @Test + public void testStringSerialization() throws IOException{ + StringWriter serialized; + /* Uses typical US English and picks out characters in unicode that have a decimal representation that ends with + * 050, like 1050, 3050, 4050, 5050, etc. */ + serialized = new StringWriter(); + Jsoner.serialize("ABCDEFGHIJKLMNOPQRSTUVWXYZ<>:{}abcdefghijklmnopqrstuvwxyz,.;'[]/`123456789-=~!@#$%^&*_+()\r\b\n\t\f\\К௪ၐᎺអὲ⍚❂⼒ぐ㋺ꁐꁚꑂ\u4e2d", serialized); + Assert.assertEquals("\"ABCDEFGHIJKLMNOPQRSTUVWXYZ<>:{}abcdefghijklmnopqrstuvwxyz,.;'[]\\/`123456789-=~!@#$%^&*_+()\\r\\b\\n\\t\\f\\\\К௪ၐᎺអὲ⍚❂⼒ぐ㋺ꁐꁚꑂ中\"", serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeStrictly("ABCDEFGHIJKLMNOPQRSTUVWXYZ<>:{}abcdefghijklmnopqrstuvwxyz,.;'[]/`123456789-=~!@#$%^&*_+()\r\b\n\t\f\\К௪ၐᎺអὲ⍚❂⼒ぐ㋺ꁐꁚꑂ\u4e2d", serialized); + Assert.assertEquals("\"ABCDEFGHIJKLMNOPQRSTUVWXYZ<>:{}abcdefghijklmnopqrstuvwxyz,.;'[]\\/`123456789-=~!@#$%^&*_+()\\r\\b\\n\\t\\f\\\\К௪ၐᎺអὲ⍚❂⼒ぐ㋺ꁐꁚꑂ中\"", serialized.toString()); + serialized = new StringWriter(); + Jsoner.serializeCarelessly("ABCDEFGHIJKLMNOPQRSTUVWXYZ<>:{}abcdefghijklmnopqrstuvwxyz,.;'[]/`123456789-=~!@#$%^&*_+()\r\b\n\t\f\\К௪ၐᎺអὲ⍚❂⼒ぐ㋺ꁐꁚꑂ\u4e2d", serialized); + Assert.assertEquals("\"ABCDEFGHIJKLMNOPQRSTUVWXYZ<>:{}abcdefghijklmnopqrstuvwxyz,.;'[]\\/`123456789-=~!@#$%^&*_+()\\r\\b\\n\\t\\f\\\\К௪ၐᎺអὲ⍚❂⼒ぐ㋺ꁐꁚꑂ中\"", serialized.toString()); + } +} diff --git a/src/test/java/org/json/simple/Test.java b/src/test/java/org/json/simple/Test.java deleted file mode 100644 index dc5ce033..00000000 --- a/src/test/java/org/json/simple/Test.java +++ /dev/null @@ -1,383 +0,0 @@ -/* - * $Id: Test.java,v 1.1 2006/04/15 14:40:06 platform Exp $ - * Created on 2006-4-15 - */ -package org.json.simple; - -import java.io.IOException; -import java.io.StringWriter; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; - -import junit.framework.TestCase; - -import org.json.simple.parser.ContainerFactory; -import org.json.simple.parser.ContentHandler; -import org.json.simple.parser.JSONParser; -import org.json.simple.parser.ParseException; - -/** - * @author FangYidong - */ -public class Test extends TestCase{ - - public void testDecode() throws Exception{ - System.out.println("=======decode======="); - - String s="[0,{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}]"; - Object obj=JSONValue.parse(s); - JSONArray array=(JSONArray)obj; - System.out.println("======the 2nd element of array======"); - System.out.println(array.get(1)); - System.out.println(); - assertEquals("{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}",array.get(1).toString()); - - JSONObject obj2=(JSONObject)array.get(1); - System.out.println("======field \"1\"=========="); - System.out.println(obj2.get("1")); - assertEquals("{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}",obj2.get("1").toString()); - - s="{}"; - obj=JSONValue.parse(s); - assertEquals("{}",obj.toString()); - - s="[5,]"; - obj=JSONValue.parse(s); - assertEquals("[5]",obj.toString()); - - s="[5,,2]"; - obj=JSONValue.parse(s); - assertEquals("[5,2]",obj.toString()); - - s="[\"hello\\bworld\\\"abc\\tdef\\\\ghi\\rjkl\\n123\\u4e2d\"]"; - obj=JSONValue.parse(s); - assertEquals("hello\bworld\"abc\tdef\\ghi\rjkl\n123中",((List)obj).get(0).toString()); - - JSONParser parser = new JSONParser(); - s="{\"name\":"; - try{ - obj = parser.parse(s); - } - catch(ParseException pe){ - assertEquals(ParseException.ERROR_UNEXPECTED_TOKEN, pe.getErrorType()); - assertEquals(8, pe.getPosition()); - } - - s="{\"name\":}"; - try{ - obj = parser.parse(s); - } - catch(ParseException pe){ - assertEquals(ParseException.ERROR_UNEXPECTED_TOKEN, pe.getErrorType()); - assertEquals(8, pe.getPosition()); - } - - - s="{\"name"; - try{ - obj = parser.parse(s); - } - catch(ParseException pe){ - assertEquals(ParseException.ERROR_UNEXPECTED_TOKEN, pe.getErrorType()); - assertEquals(6, pe.getPosition()); - } - - - s = "[[null, 123.45, \"a\\\tb c\"}, true]"; - try{ - parser.parse(s); - } - catch(ParseException pe){ - assertEquals(24, pe.getPosition()); - System.out.println("Error at character position: " + pe.getPosition()); - switch(pe.getErrorType()){ - case ParseException.ERROR_UNEXPECTED_TOKEN: - System.out.println("Unexpected token: " + pe.getUnexpectedObject()); - break; - case ParseException.ERROR_UNEXPECTED_CHAR: - System.out.println("Unexpected character: " + pe.getUnexpectedObject()); - break; - case ParseException.ERROR_UNEXPECTED_EXCEPTION: - ((Exception)pe.getUnexpectedObject()).printStackTrace(); - break; - } - } - - s = "{\"first\": 123, \"second\": [4, 5, 6], \"third\": 789}"; - ContainerFactory containerFactory = new ContainerFactory(){ - public List creatArrayContainer() { - return new LinkedList(); - } - - public Map createObjectContainer() { - return new LinkedHashMap(); - } - - }; - - try{ - Map json = (Map)parser.parse(s, containerFactory); - Iterator iter = json.entrySet().iterator(); - System.out.println("==iterate result=="); - while(iter.hasNext()){ - Map.Entry entry = (Map.Entry)iter.next(); - System.out.println(entry.getKey() + "=>" + entry.getValue()); - } - - System.out.println("==toJSONString()=="); - System.out.println(JSONValue.toJSONString(json)); - assertEquals("{\"first\":123,\"second\":[4,5,6],\"third\":789}", JSONValue.toJSONString(json)); - } - catch(ParseException pe){ - pe.printStackTrace(); - } - - s = "{\"first\": 123, \"second\": [{\"s1\":{\"s11\":\"v11\"}}, 4, 5, 6], \"third\": 789}"; - ContentHandler myHandler = new ContentHandler() { - - public boolean endArray() throws ParseException { - System.out.println("endArray()"); - return true; - } - - public void endJSON() throws ParseException { - System.out.println("endJSON()"); - } - - public boolean endObject() throws ParseException { - System.out.println("endObject()"); - return true; - } - - public boolean endObjectEntry() throws ParseException { - System.out.println("endObjectEntry()"); - return true; - } - - public boolean primitive(Object value) throws ParseException { - System.out.println("primitive(): " + value); - return true; - } - - public boolean startArray() throws ParseException { - System.out.println("startArray()"); - return true; - } - - public void startJSON() throws ParseException { - System.out.println("startJSON()"); - } - - public boolean startObject() throws ParseException { - System.out.println("startObject()"); - return true; - } - - public boolean startObjectEntry(String key) throws ParseException { - System.out.println("startObjectEntry(), key:" + key); - return true; - } - - }; - try{ - parser.parse(s, myHandler); - } - catch(ParseException pe){ - pe.printStackTrace(); - } - - class KeyFinder implements ContentHandler{ - private Object value; - private boolean found = false; - private boolean end = false; - private String key; - private String matchKey; - - public void setMatchKey(String matchKey){ - this.matchKey = matchKey; - } - - public Object getValue(){ - return value; - } - - public boolean isEnd(){ - return end; - } - - public void setFound(boolean found){ - this.found = found; - } - - public boolean isFound(){ - return found; - } - - public void startJSON() throws ParseException, IOException { - found = false; - end = false; - } - - public void endJSON() throws ParseException, IOException { - end = true; - } - - public boolean primitive(Object value) throws ParseException, IOException { - if(key != null){ - if(key.equals(matchKey)){ - found = true; - this.value = value; - key = null; - return false; - } - } - return true; - } - - public boolean startArray() throws ParseException, IOException { - return true; - } - - - public boolean startObject() throws ParseException, IOException { - return true; - } - - public boolean startObjectEntry(String key) throws ParseException, IOException { - this.key = key; - return true; - } - - public boolean endArray() throws ParseException, IOException { - return false; - } - - public boolean endObject() throws ParseException, IOException { - return true; - } - - public boolean endObjectEntry() throws ParseException, IOException { - return true; - } - }; - - s = "{\"first\": 123, \"second\": [{\"k1\":{\"id\":\"id1\"}}, 4, 5, 6, {\"id\": 123}], \"third\": 789, \"id\": null}"; - parser.reset(); - KeyFinder keyFinder = new KeyFinder(); - keyFinder.setMatchKey("id"); - int i = 0; - try{ - while(!keyFinder.isEnd()){ - parser.parse(s, keyFinder, true); - if(keyFinder.isFound()){ - i++; - keyFinder.setFound(false); - System.out.println("found id:"); - System.out.println(keyFinder.getValue()); - if(i == 1) - assertEquals("id1", keyFinder.getValue()); - if(i == 2){ - assertTrue(keyFinder.getValue() instanceof Number); - assertEquals("123", String.valueOf(keyFinder.getValue())); - } - if(i == 3) - assertTrue(null == keyFinder.getValue()); - } - } - } - catch(ParseException pe){ - pe.printStackTrace(); - } - } - - public void testEncode() throws Exception{ - System.out.println("=======encode======="); - - JSONArray array1=new JSONArray(); - array1.add("abc\u0010a/"); - array1.add(new Integer(123)); - array1.add(new Double(222.123)); - array1.add(new Boolean(true)); - System.out.println("======array1=========="); - System.out.println(array1); - System.out.println(); - assertEquals("[\"abc\\u0010a\\/\",123,222.123,true]",array1.toString()); - - JSONObject obj1=new JSONObject(); - obj1.put("array1",array1); - System.out.println("======obj1 with array1==========="); - System.out.println(obj1); - System.out.println(); - assertEquals("{\"array1\":[\"abc\\u0010a\\/\",123,222.123,true]}",obj1.toString()); - - obj1.remove("array1"); - array1.add(obj1); - System.out.println("======array1 with obj1========"); - System.out.println(array1); - System.out.println(); - assertEquals("[\"abc\\u0010a\\/\",123,222.123,true,{}]",array1.toString()); - - List list = new ArrayList(); - list.add("abc\u0010a/"); - list.add(new Integer(123)); - list.add(new Double(222.123)); - list.add(new Boolean(true)); - list.add(null); - System.out.println("======list=========="); - System.out.println(JSONArray.toJSONString(list)); - System.out.println(); - assertEquals("[\"abc\\u0010a\\/\",123,222.123,true,null]",JSONArray.toJSONString(list)); - - Map map = new HashMap(); - map.put("array1",list); - System.out.println("======map with list==========="); - System.out.println(map); - System.out.println(); - assertEquals("{\"array1\":[\"abc\\u0010a\\/\",123,222.123,true,null]}",JSONObject.toJSONString(map)); - - Map m1 = new LinkedHashMap(); - Map m2 = new LinkedHashMap(); - List l1 = new LinkedList(); - - m1.put("k11","v11"); - m1.put("k12","v12"); - m1.put("k13", "v13"); - m2.put("k21","v21"); - m2.put("k22","v22"); - m2.put("k23","v23"); - l1.add(m1); - l1.add(m2); - String jsonString = JSONValue.toJSONString(l1); - System.out.println(jsonString); - assertEquals("[{\"k11\":\"v11\",\"k12\":\"v12\",\"k13\":\"v13\"},{\"k21\":\"v21\",\"k22\":\"v22\",\"k23\":\"v23\"}]", jsonString); - - StringWriter out = new StringWriter(); - JSONValue.writeJSONString(l1, out); - jsonString = out.toString(); - System.out.println(jsonString); - assertEquals("[{\"k11\":\"v11\",\"k12\":\"v12\",\"k13\":\"v13\"},{\"k21\":\"v21\",\"k22\":\"v22\",\"k23\":\"v23\"}]", jsonString); - - List l2 = new LinkedList(); - Map m3 = new LinkedHashMap(); - m3.put("k31", "v3"); - m3.put("k32", new Double(123.45)); - m3.put("k33", new Boolean(false)); - m3.put("k34", null); - l2.add("vvv"); - l2.add("1.23456789123456789"); - l2.add(new Boolean(true)); - l2.add(null); - m3.put("k35", l2); - m1.put("k14", m3); - out = new StringWriter(); - JSONValue.writeJSONString(l1, out); - jsonString = out.toString(); - System.out.println(jsonString); - assertEquals("[{\"k11\":\"v11\",\"k12\":\"v12\",\"k13\":\"v13\",\"k14\":{\"k31\":\"v3\",\"k32\":123.45,\"k33\":false,\"k34\":null,\"k35\":[\"vvv\",\"1.23456789123456789\",true,null]}},{\"k21\":\"v21\",\"k22\":\"v22\",\"k23\":\"v23\"}]",jsonString); - } -} diff --git a/src/test/java/org/json/simple/YylexTest.java b/src/test/java/org/json/simple/YylexTest.java new file mode 100644 index 00000000..3534559a --- /dev/null +++ b/src/test/java/org/json/simple/YylexTest.java @@ -0,0 +1,207 @@ +/* See: README for this file's copyright, terms, and conditions. */ +package org.json.simple; + +import java.io.IOException; +import java.io.StringReader; +import java.math.BigDecimal; + +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** Ensures the lexer hasn't regressed in functionality or breaks its API contract. */ +public class YylexTest{ + /** Called before each Test Method. */ + @Before + public void setUp(){ + /* All of the implemented tests use local variables in their own respective method. */ + } + + /** Called after each Test method. */ + @After + public void tearDown(){ + /* All of the implemented tests use local variables in their own respective method. */ + } + + /** Ensures a negative number is lexable. + * @throws IOException if the test fails. + * @throws DeserializationException if the test fails. */ + @Test + public void testLexingNegativeNumber() throws IOException, DeserializationException{ + StringReader lexable; + Yylex lexer; + Yytoken lexed; + lexable = new StringReader("-123456789098765432101234567890987654321"); + lexer = new Yylex(lexable); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals(new BigDecimal("-123456789098765432101234567890987654321"), lexed.getValue()); + } + + /** Ensures a number with a decimal place in it is lexable. + * @throws IOException if the test fails. + * @throws DeserializationException if the test fails. */ + @Test + public void testLexingNumberWithDecimal() throws IOException, DeserializationException{ + StringReader lexable; + Yylex lexer; + Yytoken lexed; + lexable = new StringReader("-1234567890987654321.01234567890987654321"); + lexer = new Yylex(lexable); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals(new BigDecimal("-1234567890987654321.01234567890987654321"), lexed.getValue()); + } + + /** Ensures a number with an exponent is lexable. + * @throws IOException if the test fails. + * @throws DeserializationException if the test fails. */ + @Test + public void testLexingNumberWithExponent() throws IOException, DeserializationException{ + StringReader lexable; + Yylex lexer; + Yytoken lexed; + lexable = new StringReader("-1234567890987654321.01234567890987654321E-50"); + lexer = new Yylex(lexable); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals(new BigDecimal("-1234567890987654321.01234567890987654321E-50"), lexed.getValue()); + } + + /** Ensures a positive number is lexable. + * @throws IOException if the test fails. + * @throws DeserializationException if the test fails. */ + @Test + public void testLexingPositiveNumber() throws IOException, DeserializationException{ + StringReader lexable; + Yylex lexer; + Yytoken lexed; + lexable = new StringReader("123456789098765432101234567890987654321"); + lexer = new Yylex(lexable); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals(new BigDecimal("123456789098765432101234567890987654321"), lexed.getValue()); + } + + /** Ensures a String containing escaped characters and various unicode characters is lexable. + * @throws IOException if the test fails. + * @throws DeserializationException if the test fails. */ + @Test + public void testLexingStringContainingEscapedCharacters() throws IOException, DeserializationException{ + StringReader lexable; + Yylex lexer; + Yytoken lexed; + lexable = new StringReader("\"ABCDEFGHIJKLMNOPQRSTUVWXYZ<>:{}abcdefghijklmnopqrstuvwxyz,.;'[]\\/`123456789-=~!@#$%^&*_+()\\r\\b\\n\\t\\f\\\\К௪ၐᎺអὲ⍚❂⼒ぐ㋺ꁐꁚꑂ\""); + lexer = new Yylex(lexable); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals("ABCDEFGHIJKLMNOPQRSTUVWXYZ<>:{}abcdefghijklmnopqrstuvwxyz,.;'[]/`123456789-=~!@#$%^&*_+()\r\b\n\t\f\\К௪ၐᎺអὲ⍚❂⼒ぐ㋺ꁐꁚꑂ", lexed.getValue()); + } + + /** Ensures that unexpected characters are a problem between expected characters. + * @throws IOException if the test fails. + * @throws DeserializationException if the test fails. */ + @Test + public void testLexingUnexpectedCharacter() throws IOException, DeserializationException{ + StringReader lexable; + Yylex lexer; + Yytoken lexed; + lexable = new StringReader("{a : b}"); + lexer = new Yylex(lexable); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.LEFT_BRACE, lexed.getType()); + try{ + lexed = lexer.yylex(); + }catch(final DeserializationException caught){ + Assert.assertEquals(DeserializationException.Problems.UNEXPECTED_CHARACTER, caught.getProblemType()); + Assert.assertEquals(new Character('a'), caught.getUnexpectedObject()); + Assert.assertEquals(1, caught.getPosition()); + } + /* The exception should have left the lexed token unchanged. */ + Assert.assertEquals(Yytoken.Types.LEFT_BRACE, lexed.getType()); + } + + /** Ensure white space is ignored while lexing outside of Strings. + * @throws IOException if the test fails. + * @throws DeserializationException if the test fails. */ + @Test + public void testLexingWhiteSpace() throws IOException, DeserializationException{ + StringReader lexable; + Yylex lexer; + Yytoken lexed; + lexable = new StringReader("[\t \n\r\n{ \t \t\n\r}"); + lexer = new Yylex(lexable); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.LEFT_SQUARE, lexed.getType()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.LEFT_BRACE, lexed.getType()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.RIGHT_BRACE, lexed.getType()); + } + /** Ensure concatenated JSON values are lexable. + * @throws IOException if the test failed. + * @throws DeserializationException if the test failed. + */ + @Test + public void testLexingConcatenatedJsonValues() throws IOException, DeserializationException{ + StringReader lexable; + Yylex lexer; + Yytoken lexed; + lexable = new StringReader("nullnullnullnull12.33.21truetruenullfalse\"\"{}[]"); + lexer = new Yylex(lexable); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals(null, lexed.getValue()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals(null, lexed.getValue()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals(null, lexed.getValue()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals(null, lexed.getValue()); + try{ + lexed = lexer.yylex(); + }catch(DeserializationException caught){ + /* Concatenated numbers don't always work well. */ + Assert.assertEquals(DeserializationException.Problems.UNEXPECTED_EXCEPTION, caught.getProblemType()); + } + try{ + lexed = lexer.yylex(); + }catch(DeserializationException caught){ + /* Concatenated numbers don't always work well. */ + Assert.assertEquals(DeserializationException.Problems.UNEXPECTED_CHARACTER, caught.getProblemType()); + Assert.assertEquals(21, caught.getPosition()); + } + /* Instead of the 12.3 and 3.21 concatenated together we ended up with 21! */ + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals(new BigDecimal("21"), lexed.getValue()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals(true, lexed.getValue()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals(true, lexed.getValue()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals(null, lexed.getValue()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals(false, lexed.getValue()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.DATUM, lexed.getType()); + Assert.assertEquals("", lexed.getValue()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.LEFT_BRACE, lexed.getType()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.RIGHT_BRACE, lexed.getType()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.LEFT_SQUARE, lexed.getType()); + lexed = lexer.yylex(); + Assert.assertEquals(Yytoken.Types.RIGHT_SQUARE, lexed.getType()); + + } +} diff --git a/src/test/java/org/json/simple/parser/JSONParserTest.java b/src/test/java/org/json/simple/parser/JSONParserTest.java new file mode 100644 index 00000000..5a76f928 --- /dev/null +++ b/src/test/java/org/json/simple/parser/JSONParserTest.java @@ -0,0 +1,291 @@ +/* $Id: JSONParserTest.java,v 1.1 2006/04/15 14:40:06 platform Exp $ + * Created on 2006-4-15 */ +package org.json.simple.parser; + +import java.io.IOException; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; + +import org.json.simple.JSONArray; +import org.json.simple.JSONObject; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; + +/** Ensures that JSONParser hasn't regressed in functionality or breaks its API contract. Deprecated warnings are + * suppressed since it is intentionally testing deprecated code for backwards compatibility. */ +@SuppressWarnings("deprecation") +public class JSONParserTest{ + /** Called before each Test Method. */ + @Before + public void setUp(){ + /* All of the implemented tests use local variables in their own respective method. */ + } + + /** Called after each Test method. */ + @After + public void tearDown(){ + /* All of the implemented tests use local variables in their own respective method. */ + } + + /** Ensures a ContainerFactory can be provided. + * @throws Exception if the test fails. */ + @Test + public void testDecodeContainerFactory() throws Exception{ + JSONParser parser; + String input; + parser = new JSONParser(); + input = "{\"first\": 123, \"second\": [4, 5, 6], \"third\": 789}"; + final ContainerFactory containerFactory = new ContainerFactory(){ + @Override + public List creatArrayContainer(){ + return new LinkedList(); + } + + @Override + public Map createObjectContainer(){ + return new LinkedHashMap(); + } + }; + @SuppressWarnings("unchecked") + final Map json = (Map)parser.parse(input, containerFactory); + Assert.assertTrue(json instanceof LinkedHashMap); + Assert.assertTrue(json.get("second") instanceof LinkedList); + } + + /** Ensures a ContentHander can be used with the parser. + * @throws Exception if the test failed. */ + @Test + public void testDecodeContentHandler() throws Exception{ + JSONParser parser; + String input; + parser = new JSONParser(); + class KeyFinder implements ContentHandler{ + private boolean end = false; + private boolean found = false; + private String key; + private String matchKey; + private Object value; + + @Override + public boolean endArray() throws ParseException, IOException{ + return false; + } + + @Override + public void endJSON() throws ParseException, IOException{ + this.end = true; + } + + @Override + public boolean endObject() throws ParseException, IOException{ + return true; + } + + @Override + public boolean endObjectEntry() throws ParseException, IOException{ + return true; + } + + public Object getValue(){ + return this.value; + } + + public boolean isEnd(){ + return this.end; + } + + public boolean isFound(){ + return this.found; + } + + @Override + public boolean primitive(final Object value) throws ParseException, IOException{ + if(this.key != null){ + if(this.key.equals(this.matchKey)){ + this.found = true; + this.value = value; + this.key = null; + return false; + } + } + return true; + } + + public void setFound(final boolean found){ + this.found = found; + } + + public void setMatchKey(final String matchKey){ + this.matchKey = matchKey; + } + + @Override + public boolean startArray() throws ParseException, IOException{ + return true; + } + + @Override + public void startJSON() throws ParseException, IOException{ + this.found = false; + this.end = false; + } + + @Override + public boolean startObject() throws ParseException, IOException{ + return true; + } + + @Override + public boolean startObjectEntry(final String key) throws ParseException, IOException{ + this.key = key; + return true; + } + } + ; + input = "{\"first\": 123, \"second\": [{\"k1\":{\"id\":\"id1\"}}, 4, 5, 6, {\"id\": 123}], \"third\": 789, \"id\": null}"; + parser.reset(); + final KeyFinder keyFinder = new KeyFinder(); + keyFinder.setMatchKey("id"); + int i = 0; + while(!keyFinder.isEnd()){ + parser.parse(input, keyFinder, true); + if(keyFinder.isFound()){ + i++; + keyFinder.setFound(false); + if(i == 1){ + Assert.assertEquals("id1", keyFinder.getValue()); + } + if(i == 2){ + Assert.assertTrue(keyFinder.getValue() instanceof Number); + Assert.assertEquals("123", String.valueOf(keyFinder.getValue())); + } + if(i == 3){ + Assert.assertTrue(null == keyFinder.getValue()); + } + } + } + } + + /** Ensures booleans, JSONObject, JSONArray, null, Numbers, and Strings can be decoded. + * @throws Exception if the test failed. */ + @SuppressWarnings("unchecked") + @Test + public void testDecodeJsonValues() throws Exception{ + /* The method is unchecked since JSONArray and JSONObject don't have a parameterized type. */ + JSONParser parser; + Object deserialized; + String input; + JSONObject expectedObject; + JSONArray expectedArray; + expectedObject = new JSONObject(); + expectedArray = new JSONArray(); + parser = new JSONParser(); + input = "{}"; + deserialized = parser.parse(input); + Assert.assertEquals(expectedObject, deserialized); + parser = new JSONParser(); + input = "{,}"; + deserialized = parser.parse(input); + Assert.assertEquals(expectedObject, deserialized); + parser = new JSONParser(); + input = "[]"; + deserialized = parser.parse(input); + Assert.assertEquals(expectedArray, deserialized); + parser = new JSONParser(); + input = "[,]"; + deserialized = parser.parse(input); + Assert.assertEquals(expectedArray, deserialized); + parser = new JSONParser(); + input = "[5,]"; + expectedArray.add(5); + deserialized = parser.parse(input); + Assert.assertEquals(expectedArray.toString(), deserialized.toString()); + parser = new JSONParser(); + input = "[5,,2]"; + expectedArray.add(2); + deserialized = parser.parse(input); + Assert.assertEquals(expectedArray.toString(), deserialized.toString()); + parser = new JSONParser(); + input = "\"hello\\bworld\\\"abc\\tdef\\\\ghi\\rjkl\\n123\\u4e2d\""; + deserialized = parser.parse(input); + Assert.assertEquals("hello\bworld\"abc\tdef\\ghi\rjkl\n123中", deserialized.toString()); + parser = new JSONParser(); + input = "true"; + deserialized = parser.parse(input); + Assert.assertTrue(Boolean.TRUE == deserialized); + parser = new JSONParser(); + input = "false"; + deserialized = parser.parse(input); + Assert.assertTrue(Boolean.FALSE == deserialized); + parser = new JSONParser(); + input = "null"; + deserialized = parser.parse(input); + Assert.assertTrue(null == deserialized); + parser = new JSONParser(); + input = "9001"; + deserialized = parser.parse(input); + Assert.assertTrue(new Long("9001").equals(deserialized)); + parser = new JSONParser(); + input = "9000.1"; + deserialized = parser.parse(input); + Assert.assertTrue(new Double("9000.1").equals(deserialized)); + } + + /** Ensures a nested object is decoded. + * @throws Exception if the test failed. */ + @Test + public void testDecodeNestedObject() throws Exception{ + JSONParser parser; + Object deserialized; + JSONArray array; + JSONObject object; + String input; + parser = new JSONParser(); + input = "[0,{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}]"; + deserialized = parser.parse(input); + array = (JSONArray)deserialized; + Assert.assertEquals("{\"1\":{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}}", array.get(1).toString()); + object = (JSONObject)array.get(1); + Assert.assertEquals("{\"2\":{\"3\":{\"4\":[5,{\"6\":7}]}}}", object.get("1").toString()); + } + + /** Ensures problems are detected in the parse how they ought to. */ + @Test + public void testDecodeProblems(){ + JSONParser parser; + String input; + parser = new JSONParser(); + input = "{\"name\":"; + try{ + parser.parse(input); + }catch(final ParseException pe){ + Assert.assertEquals(ParseException.ERROR_UNEXPECTED_TOKEN, pe.getErrorType()); + Assert.assertEquals(8, pe.getPosition()); + } + input = "{\"name\":}"; + try{ + parser.parse(input); + }catch(final ParseException pe){ + Assert.assertEquals(ParseException.ERROR_UNEXPECTED_TOKEN, pe.getErrorType()); + Assert.assertEquals(8, pe.getPosition()); + } + input = "{\"name"; + try{ + parser.parse(input); + }catch(final ParseException pe){ + Assert.assertEquals(ParseException.ERROR_UNEXPECTED_TOKEN, pe.getErrorType()); + Assert.assertEquals(6, pe.getPosition()); + } + input = "[[null, 123.45, \"a\\\tb c\"}, true]"; + try{ + parser.parse(input); + }catch(final ParseException pe){ + Assert.assertEquals(ParseException.ERROR_UNEXPECTED_TOKEN, pe.getErrorType()); + Assert.assertEquals(24, pe.getPosition()); + } + } +} diff --git a/src/test/java/org/json/simple/parser/YylexTest.java b/src/test/java/org/json/simple/parser/YylexTest.java index ce317519..7e76c4c6 100644 --- a/src/test/java/org/json/simple/parser/YylexTest.java +++ b/src/test/java/org/json/simple/parser/YylexTest.java @@ -3,78 +3,82 @@ import java.io.IOException; import java.io.StringReader; -import junit.framework.TestCase; +import org.junit.After; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; -public class YylexTest extends TestCase { +/** Ensures that parser.Yylex hasn't regressed in functionality or breaks its API contract. Deprecated warnings are + * suppressed since it is intentionally testing deprecated code for backwards compatibility. */ +@SuppressWarnings("deprecation") +public class YylexTest{ + /** Called before each Test Method. */ + @Before + public void setUp(){ + /* All of the implemented tests use local variables in their own respective method. */ + } - public void testYylex() throws Exception{ - String s="\"\\/\""; - System.out.println(s); - StringReader in = new StringReader(s); - Yylex lexer=new Yylex(in); - Yytoken token=lexer.yylex(); - assertEquals(Yytoken.TYPE_VALUE,token.type); - assertEquals("/",token.value); - - s="\"abc\\/\\r\\b\\n\\t\\f\\\\\""; - System.out.println(s); - in = new StringReader(s); - lexer=new Yylex(in); - token=lexer.yylex(); - assertEquals(Yytoken.TYPE_VALUE,token.type); - assertEquals("abc/\r\b\n\t\f\\",token.value); - - s="[\t \n\r\n{ \t \t\n\r}"; - System.out.println(s); - in = new StringReader(s); - lexer=new Yylex(in); - token=lexer.yylex(); - assertEquals(Yytoken.TYPE_LEFT_SQUARE,token.type); - token=lexer.yylex(); - assertEquals(Yytoken.TYPE_LEFT_BRACE,token.type); - token=lexer.yylex(); - assertEquals(Yytoken.TYPE_RIGHT_BRACE,token.type); - - s="\b\f{"; - System.out.println(s); - in = new StringReader(s); - lexer=new Yylex(in); - ParseException err=null; - try{ - token=lexer.yylex(); - } - catch(ParseException e){ - err=e; - System.out.println("error:"+err); - assertEquals(ParseException.ERROR_UNEXPECTED_CHAR, e.getErrorType()); - assertEquals(0,e.getPosition()); - assertEquals(new Character('\b'),e.getUnexpectedObject()); - } - catch(IOException ie){ - throw ie; - } - assertTrue(err!=null); - - s="{a : b}"; - System.out.println(s); - in = new StringReader(s); - lexer=new Yylex(in); - err=null; - try{ - lexer.yylex(); - token=lexer.yylex(); - } - catch(ParseException e){ - err=e; - System.out.println("error:"+err); - assertEquals(ParseException.ERROR_UNEXPECTED_CHAR, e.getErrorType()); - assertEquals(new Character('a'),e.getUnexpectedObject()); - assertEquals(1,e.getPosition()); - } - catch(IOException ie){ - throw ie; - } - assertTrue(err!=null); - } + /** Called after each Test method. */ + @After + public void tearDown(){ + /* All of the implemented tests use local variables in their own respective method. */ + } + /** Ensures tokens are lexed. + * @throws Exception if the test failed. */ + @Test + public void testYylex() throws Exception{ + String s = "\"\\/\""; + StringReader in = new StringReader(s); + Yylex lexer = new Yylex(in); + Yytoken token = lexer.yylex(); + Assert.assertEquals(Yytoken.TYPE_VALUE, token.type); + Assert.assertEquals("/", token.value); + s = "\"abc\\/\\r\\b\\n\\t\\f\\\\\""; + in = new StringReader(s); + lexer = new Yylex(in); + token = lexer.yylex(); + Assert.assertEquals(Yytoken.TYPE_VALUE, token.type); + Assert.assertEquals("abc/\r\b\n\t\f\\", token.value); + s = "[\t \n\r\n{ \t \t\n\r}"; + in = new StringReader(s); + lexer = new Yylex(in); + token = lexer.yylex(); + Assert.assertEquals(Yytoken.TYPE_LEFT_SQUARE, token.type); + token = lexer.yylex(); + Assert.assertEquals(Yytoken.TYPE_LEFT_BRACE, token.type); + token = lexer.yylex(); + Assert.assertEquals(Yytoken.TYPE_RIGHT_BRACE, token.type); + s = "\b\f{"; + in = new StringReader(s); + lexer = new Yylex(in); + ParseException err = null; + try{ + token = lexer.yylex(); + }catch(final ParseException e){ + err = e; + Assert.assertEquals(ParseException.ERROR_UNEXPECTED_CHAR, e.getErrorType()); + Assert.assertEquals(0, e.getPosition()); + Assert.assertEquals(new Character('\b'), e.getUnexpectedObject()); + }catch(final IOException ie){ + throw ie; + } + Assert.assertTrue(err != null); + s = "{a : b}"; + in = new StringReader(s); + lexer = new Yylex(in); + err = null; + try{ + lexer.yylex(); + token = lexer.yylex(); + }catch(final ParseException e){ + err = e; + Assert.assertEquals(ParseException.ERROR_UNEXPECTED_CHAR, e.getErrorType()); + Assert.assertEquals(new Character('a'), e.getUnexpectedObject()); + Assert.assertEquals(1, e.getPosition()); + }catch(final IOException ie){ + throw ie; + } + Assert.assertTrue(err != null); + } } diff --git a/test.xml b/test.xml deleted file mode 100644 index 1af55bf8..00000000 --- a/test.xml +++ /dev/null @@ -1,48 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - From 97b3f01e4d8f758d8b843636800fd283c789cf87 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Wed, 31 Aug 2016 17:53:58 -0500 Subject: [PATCH 02/48] Project files were suppose to be removed from the repo. --- .classpath | 9 --------- .project | 14 -------------- 2 files changed, 23 deletions(-) delete mode 100644 .classpath delete mode 100644 .project diff --git a/.classpath b/.classpath deleted file mode 100644 index 159850db..00000000 --- a/.classpath +++ /dev/null @@ -1,9 +0,0 @@ - - - - - - - - - diff --git a/.project b/.project deleted file mode 100644 index 63ad8efc..00000000 --- a/.project +++ /dev/null @@ -1,14 +0,0 @@ - - - json-simple - A simple Java toolkit for JSON. NO_M2ECLIPSE_SUPPORT: Project files created with the maven-eclipse-plugin are not supported in M2Eclipse. - - - - org.eclipse.jdt.core.javabuilder - - - - org.eclipse.jdt.core.javanature - - \ No newline at end of file From 055f3d2f8a139c355ad45d52d5baa74eb3633886 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Wed, 31 Aug 2016 17:56:18 -0500 Subject: [PATCH 03/48] Added old version's github location. --- README.txt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/README.txt b/README.txt index cfe77531..c35ab5a7 100644 --- a/README.txt +++ b/README.txt @@ -308,4 +308,6 @@ Version 1.0 (2006/04/15) See the License for the specific language governing permissions and limitations under the License. -Please visit: http://code.google.com/p/json-simple/ for the old version of the library. +Please visit for the old version of this library: +https://github.com/fangyidong/json-simple +http://code.google.com/p/json-simple/ From c0460aa21a1f0592d6bc998d97b0dd4f561c2ddc Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Wed, 31 Aug 2016 17:57:59 -0500 Subject: [PATCH 04/48] .settings directory was suppose to be deleted. --- .settings/org.eclipse.core.resources.prefs | 3 --- 1 file changed, 3 deletions(-) delete mode 100644 .settings/org.eclipse.core.resources.prefs diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs deleted file mode 100644 index f707871d..00000000 --- a/.settings/org.eclipse.core.resources.prefs +++ /dev/null @@ -1,3 +0,0 @@ -#Mon Feb 06 00:32:07 CST 2012 -eclipse.preferences.version=1 -encoding/=UTF-8 From 742deb0961f8d6d399b6d2268cf9d1888fc1e089 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 1 Sep 2016 12:12:11 -0500 Subject: [PATCH 05/48] Group id matches old library. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 907b6955..f67578ce 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - com.googlecode.json-simple + com.googlecode.json.simple json-simple jar From 96dba8d0ef117f091759b14c9631181197b114b5 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 1 Sep 2016 14:06:21 -0500 Subject: [PATCH 06/48] Tweaked java docs. Map#getByDefault(Object) is only available in java 8. Serialize honors its flags in sub calls in all circumstances. --- .../json/simple/DeserializationException.java | 2 +- src/main/java/org/json/simple/JsonArray.java | 2 +- src/main/java/org/json/simple/JsonObject.java | 89 ++++++++++++++++--- src/main/java/org/json/simple/Jsoner.java | 45 +++++----- 4 files changed, 101 insertions(+), 37 deletions(-) diff --git a/src/main/java/org/json/simple/DeserializationException.java b/src/main/java/org/json/simple/DeserializationException.java index 35ed3e33..993e2ac6 100644 --- a/src/main/java/org/json/simple/DeserializationException.java +++ b/src/main/java/org/json/simple/DeserializationException.java @@ -1,7 +1,7 @@ /* See: README for this file's copyright, terms, and conditions. */ package org.json.simple; -/** DeserializationException explains why and where the exception occurs in source JSON text. +/** DeserializationException explains how and where the problem occurs in the source JSON text during deserialization. * * @since 2.0.0 */ public class DeserializationException extends Exception{ diff --git a/src/main/java/org/json/simple/JsonArray.java b/src/main/java/org/json/simple/JsonArray.java index 822e2f9a..006445b1 100644 --- a/src/main/java/org/json/simple/JsonArray.java +++ b/src/main/java/org/json/simple/JsonArray.java @@ -10,7 +10,7 @@ import java.util.Iterator; import java.util.Map; -/** JsonArray is a common non-thread safe data format for listing data. The contents of a JsonArray are only validated as +/** JsonArray is a common non-thread safe data format for a collection of data. The contents of a JsonArray are only validated as * JSON values on serialization. * @see Jsoner * @since 2.0.0 */ diff --git a/src/main/java/org/json/simple/JsonObject.java b/src/main/java/org/json/simple/JsonObject.java index fe202cca..6432aed9 100644 --- a/src/main/java/org/json/simple/JsonObject.java +++ b/src/main/java/org/json/simple/JsonObject.java @@ -45,7 +45,12 @@ public JsonObject(final Map map){ * @see BigDecimal * @see Number#doubleValue() */ public BigDecimal getBigDecimalOrDefault(final String key, final BigDecimal defaultValue){ - Object returnable = this.getOrDefault(key, defaultValue); + Object returnable; + if(this.containsKey(key)){ + returnable = this.get(key); + }else{ + returnable = defaultValue; + } if(returnable instanceof BigDecimal){ /* Success there was a BigDecimal or it defaulted. */ }else if(returnable instanceof Number){ @@ -64,7 +69,13 @@ public BigDecimal getBigDecimalOrDefault(final String key, final BigDecimal defa * @return the value stored at the key or the default provided if the key doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. */ public boolean getBooleanOrDefault(final String key, final boolean defaultValue){ - return (boolean)this.getOrDefault(key, defaultValue); + Object returnable; + if(this.containsKey(key)){ + returnable = this.get(key); + }else{ + returnable = defaultValue; + } + return (boolean)returnable; } /** A convenience method that assumes there is a Number value at the given key. @@ -75,7 +86,13 @@ public boolean getBooleanOrDefault(final String key, final boolean defaultValue) * @throws ClassCastException if there was a value but didn't match the assumed return type. * @see Number#byteValue() */ public float getByteOrDefault(final String key, final byte defaultValue){ - return ((Number)this.getOrDefault(key, defaultValue)).byteValue(); + Object returnable; + if(this.containsKey(key)){ + returnable = this.get(key); + }else{ + returnable = defaultValue; + } + return ((Number)returnable).byteValue(); } /** A convenience method that assumes there is a Number value at the given key. @@ -86,7 +103,13 @@ public float getByteOrDefault(final String key, final byte defaultValue){ * @throws ClassCastException if there was a value but didn't match the assumed return type. * @see Number#doubleValue() */ public double getDoubleOrDefault(final String key, final double defaultValue){ - return ((Number)this.getOrDefault(key, defaultValue)).doubleValue(); + Object returnable; + if(this.containsKey(key)){ + returnable = this.get(key); + }else{ + returnable = defaultValue; + } + return ((Number)returnable).doubleValue(); } /** A convenience method that assumes there is a String value at the given key representing a fully qualified name in @@ -158,7 +181,13 @@ public > T getEnumOrDefault(final String key, final T defaultV * @throws ClassCastException if there was a value but didn't match the assumed return type. * @see Number#floatValue() */ public float getFloatOrDefault(final String key, final float defaultValue){ - return ((Number)this.getOrDefault(key, defaultValue)).floatValue(); + Object returnable; + if(this.containsKey(key)){ + returnable = this.get(key); + }else{ + returnable = defaultValue; + } + return ((Number)returnable).floatValue(); } /** A convenience method that assumes there is a Number value at the given key. @@ -169,7 +198,13 @@ public float getFloatOrDefault(final String key, final float defaultValue){ * @throws ClassCastException if there was a value but didn't match the assumed return type. * @see Number#intValue() */ public int getIntegerOrDefault(final String key, final int defaultValue){ - return ((Number)this.getOrDefault(key, defaultValue)).intValue(); + Object returnable; + if(this.containsKey(key)){ + returnable = this.get(key); + }else{ + returnable = defaultValue; + } + return ((Number)returnable).intValue(); } /** A convenience method that assumes there is a Collection at the given key. @@ -181,7 +216,13 @@ public int getIntegerOrDefault(final String key, final int defaultValue){ @SuppressWarnings("unchecked") public > T getCollectionOrDefault(final String key, final T defaultValue){ /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will work. */ - return (T)this.getOrDefault(key, defaultValue); + Object returnable; + if(this.containsKey(key)){ + returnable = this.get(key); + }else{ + returnable = defaultValue; + } + return (T)returnable; } /** A convenience method that assumes there is a Map at the given key. @@ -193,7 +234,13 @@ public > T getCollectionOrDefault(final String key, fina @SuppressWarnings("unchecked") public > T getMapOrDefault(final String key, final T defaultValue){ /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will work. */ - return (T)this.getOrDefault(key, defaultValue); + Object returnable; + if(this.containsKey(key)){ + returnable = this.get(key); + }else{ + returnable = defaultValue; + } + return (T)returnable; } /** A convenience method that assumes there is a Number value at the given key. @@ -204,7 +251,13 @@ public > T getCollectionOrDefault(final String key, fina * @throws ClassCastException if there was a value but didn't match the assumed return type. * @see Number#longValue() */ public long getLongOrDefault(final String key, final long defaultValue){ - return ((Number)this.getOrDefault(key, defaultValue)).longValue(); + Object returnable; + if(this.containsKey(key)){ + returnable = this.get(key); + }else{ + returnable = defaultValue; + } + return ((Number)returnable).longValue(); } /** A convenience method that assumes there is a Number value at the given key. @@ -215,7 +268,13 @@ public long getLongOrDefault(final String key, final long defaultValue){ * @throws ClassCastException if there was a value but didn't match the assumed return type. * @see Number#shortValue() */ public short getShortOrDefault(final String key, final short defaultValue){ - return ((Number)this.getOrDefault(key, defaultValue)).shortValue(); + Object returnable; + if(this.containsKey(key)){ + returnable = this.get(key); + }else{ + returnable = defaultValue; + } + return ((Number)returnable).shortValue(); } /** A convenience method that assumes there is a String value at the given key. @@ -224,7 +283,13 @@ public short getShortOrDefault(final String key, final short defaultValue){ * @return the value stored at the key or the default provided if the key doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. */ public String getStringOrDefault(final String key, final String defaultValue){ - return (String)this.getOrDefault(key, defaultValue); + Object returnable; + if(this.containsKey(key)){ + returnable = this.get(key); + }else{ + returnable = defaultValue; + } + return (String)returnable; } /* (non-Javadoc) @@ -246,7 +311,7 @@ public String toJson(){ public void toJson(final Writer writable) throws IOException{ /* Writes the map in JSON object format. */ boolean isFirstEntry = true; - final Iterator> entries = this.entrySet().iterator(); + final Iterator> entries = this.entrySet().iterator(); writable.write('{'); while(entries.hasNext()){ if(isFirstEntry){ diff --git a/src/main/java/org/json/simple/Jsoner.java b/src/main/java/org/json/simple/Jsoner.java index 0ffa7dbd..47cfe23f 100644 --- a/src/main/java/org/json/simple/Jsoner.java +++ b/src/main/java/org/json/simple/Jsoner.java @@ -386,8 +386,7 @@ public static JsonObject deserializeJsonObject(final String deserializable, fina } /** A convenience method that assumes multiple RFC 4627 JSON values (except numbers) have been concatenated together - * for - * deserilization which will be collectively returned in a JsonArray wrapper. + * for deserilization which will be collectively returned in a JsonArray wrapper. * There may be numbers included, they just must not be concatenated together as it is prone to * NumberFormatExceptions (thus causing a DeserializationException) or the numbers no longer represent their * respective values. @@ -651,9 +650,9 @@ private static void serialize(final Object jsonSerializable, final Writer writab } @SuppressWarnings("rawtypes") final Map.Entry entry = (Map.Entry)entries.next(); - writableDestination.write(Jsoner.serialize(entry.getKey())); + Jsoner.serialize(entry.getKey(), writableDestination, flags); writableDestination.write(':'); - writableDestination.write(Jsoner.serialize(entry.getValue())); + Jsoner.serialize(entry.getValue(), writableDestination, flags); } writableDestination.write('}'); }else if(jsonSerializable instanceof Collection){ @@ -668,7 +667,7 @@ private static void serialize(final Object jsonSerializable, final Writer writab }else{ writableDestination.write(','); } - writableDestination.write(Jsoner.serialize(elements.next())); + Jsoner.serialize(elements.next(), writableDestination, flags); } writableDestination.write(']'); }else if(jsonSerializable instanceof byte[]){ @@ -678,9 +677,9 @@ private static void serialize(final Object jsonSerializable, final Writer writab writableDestination.write('['); for(int i = 1; i <= numberOfElements; i++){ if(i == numberOfElements){ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); }else{ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); writableDestination.write(','); } } @@ -692,9 +691,9 @@ private static void serialize(final Object jsonSerializable, final Writer writab writableDestination.write('['); for(int i = 1; i <= numberOfElements; i++){ if(i == numberOfElements){ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); }else{ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); writableDestination.write(','); } } @@ -706,9 +705,9 @@ private static void serialize(final Object jsonSerializable, final Writer writab writableDestination.write('['); for(int i = 1; i <= numberOfElements; i++){ if(i == numberOfElements){ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); }else{ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); writableDestination.write(','); } } @@ -720,9 +719,9 @@ private static void serialize(final Object jsonSerializable, final Writer writab writableDestination.write('['); for(int i = 1; i <= numberOfElements; i++){ if(i == numberOfElements){ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); }else{ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); writableDestination.write(','); } } @@ -734,9 +733,9 @@ private static void serialize(final Object jsonSerializable, final Writer writab writableDestination.write('['); for(int i = 1; i <= numberOfElements; i++){ if(i == numberOfElements){ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); }else{ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); writableDestination.write(','); } } @@ -748,9 +747,9 @@ private static void serialize(final Object jsonSerializable, final Writer writab writableDestination.write('['); for(int i = 1; i <= numberOfElements; i++){ if(i == numberOfElements){ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); }else{ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); writableDestination.write(','); } } @@ -762,9 +761,9 @@ private static void serialize(final Object jsonSerializable, final Writer writab writableDestination.write('['); for(int i = 1; i <= numberOfElements; i++){ if(i == numberOfElements){ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); }else{ - writableDestination.write(String.valueOf(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); writableDestination.write(','); } } @@ -776,9 +775,9 @@ private static void serialize(final Object jsonSerializable, final Writer writab writableDestination.write("[\""); for(int i = 1; i <= numberOfElements; i++){ if(i == numberOfElements){ - writableDestination.write(Jsoner.escape(String.valueOf(writableArray[i]))); + Jsoner.serialize(writableArray[i], writableDestination, flags); }else{ - writableDestination.write(Jsoner.escape(String.valueOf(writableArray[i]))); + Jsoner.serialize(writableArray[i], writableDestination, flags); writableDestination.write("\",\""); } } @@ -790,9 +789,9 @@ private static void serialize(final Object jsonSerializable, final Writer writab writableDestination.write('['); for(int i = 1; i <= numberOfElements; i++){ if(i == numberOfElements){ - writableDestination.write(Jsoner.serialize(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); }else{ - writableDestination.write(Jsoner.serialize(writableArray[i])); + Jsoner.serialize(writableArray[i], writableDestination, flags); writableDestination.write(","); } } From 05838c3969836fc335b0cbdb6cf0c8045cedbd77 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 1 Sep 2016 14:58:29 -0500 Subject: [PATCH 07/48] Ignore xml files. --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 5968b343..15ba1789 100644 --- a/.gitignore +++ b/.gitignore @@ -6,4 +6,4 @@ target .settings *.log *.java~ -json-simple* +*.xml From 115442d826aa27ba4d709e45391fbd6f7a9181d2 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 1 Sep 2016 15:28:53 -0500 Subject: [PATCH 08/48] POM generates sources on jar. Developer docs updated in README.txt --- README.txt | 2 +- pom.xml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.txt b/README.txt index c35ab5a7..f9a6fc12 100644 --- a/README.txt +++ b/README.txt @@ -28,7 +28,7 @@ mvn eclipse:eclipse Run unit tests: mvn test -Full build including javadocs: +Full build including javadocs and source: mvn clean compile install package [CHANGE LOG] diff --git a/pom.xml b/pom.xml index f67578ce..0e8cd939 100644 --- a/pom.xml +++ b/pom.xml @@ -74,7 +74,7 @@ attach-sources verify - jar-no-fork + jar From 9d650ca9757e975be3820955b66eefbbb0be2594 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 1 Sep 2016 15:41:55 -0500 Subject: [PATCH 09/48] Added developer notes about updating hg-pages. --- README.txt | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/README.txt b/README.txt index f9a6fc12..6cc85575 100644 --- a/README.txt +++ b/README.txt @@ -31,6 +31,11 @@ mvn test Full build including javadocs and source: mvn clean compile install package +Update gh-pages: +1) Replace latest offical build's target/ directory to the gh-pages branch. +2) Update the index.html hrefs if necessary. +3) commit and push to gh-pages. + [CHANGE LOG] Version 2.0.0 (2016/08/31) * Davin Loegering was added to the list of Authors. From fe7095d997d6c306793ce1b2941926350613bde7 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 1 Sep 2016 15:58:13 -0500 Subject: [PATCH 10/48] Made the group id the original value in the POM. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 0e8cd939..29bf2df4 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,6 @@ 4.0.0 - com.googlecode.json.simple + com.googlecode.json-simple json-simple jar From 35d54338ef9b3bdc289c7762cbfc9fa489c3eac5 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 1 Sep 2016 16:27:39 -0500 Subject: [PATCH 11/48] Updated group id, description, and project url. --- pom.xml | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/pom.xml b/pom.xml index 29bf2df4..6231c586 100644 --- a/pom.xml +++ b/pom.xml @@ -1,12 +1,12 @@ 4.0.0 - com.googlecode.json-simple + com.cliftonlabs json-simple jar JSON.simple - A simple Java toolkit for JSON - http://code.google.com/p/json-simple/ + Quickly develop RFC 4627 JSON compatible java 7+ applications based on com.googlecode.json-simple.json-simple + https://cliftonlabs.github.io/json-simple/ 2.0.0 @@ -28,10 +28,6 @@ - - Yidong - Yidong Fang - Davin Loegering davin.loegering@cliftonlabs.com From a8a11d434c28d51a67f654d45e98119d6d5af57f Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 1 Sep 2016 16:40:24 -0500 Subject: [PATCH 12/48] Added a field into the POM that was in the example POM for maven artifact uploading. --- pom.xml | 1 + 1 file changed, 1 insertion(+) diff --git a/pom.xml b/pom.xml index 6231c586..35e2235a 100644 --- a/pom.xml +++ b/pom.xml @@ -18,6 +18,7 @@ The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt + repo From f112f6ea5b2389f64fb682b5cc19c2ea1414e073 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 1 Sep 2016 20:21:23 -0500 Subject: [PATCH 13/48] POM prep for automated deploys to public repository. Updated developer section in README.txt --- .gitignore | 2 + README.txt | 15 +++++- pom.xml | 137 +++++++++++++++++++++++++++++++-------------------- settings.xml | 9 ++++ 4 files changed, 108 insertions(+), 55 deletions(-) create mode 100644 settings.xml diff --git a/.gitignore b/.gitignore index 15ba1789..075c0902 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,7 @@ bin target +pom.xml.releaseBackup +release.properties .project .classpath .metadata diff --git a/README.txt b/README.txt index 6cc85575..0b008aa7 100644 --- a/README.txt +++ b/README.txt @@ -25,11 +25,22 @@ Dave Hughes Generate json-simple project files for eclipse: mvn eclipse:eclipse +Build the project: +mvn compile + Run unit tests: mvn test -Full build including javadocs and source: -mvn clean compile install package +Build the project with javadocs and source: +mvn package + +Make the project available to other local projects via local repository: +mvn clean install + +Guided deploy of project with signed artifacts (jar, javadocs, and sources): +mvn release:clean +mvn release:prepare +mvn release:perform Update gh-pages: 1) Replace latest offical build's target/ directory to the gh-pages branch. diff --git a/pom.xml b/pom.xml index 35e2235a..5835f75f 100644 --- a/pom.xml +++ b/pom.xml @@ -1,33 +1,28 @@ - + 4.0.0 com.cliftonlabs json-simple jar - JSON.simple - Quickly develop RFC 4627 JSON compatible java 7+ applications based on com.googlecode.json-simple.json-simple + Quickly develop RFC 4627 JSON compatible java 7+ applications based on com.googlecode.json-simple.json-simple by Yidong Fang https://cliftonlabs.github.io/json-simple/ - - 2.0.0 - + 2.0.0-SNAPSHOT UTF-8 - + The Apache Software License, Version 2.0 http://www.apache.org/licenses/LICENSE-2.0.txt - repo - + scm:git:https://github.com/cliftonlabs/json-simple.git scm:git:https://github.com/cliftonlabs/json-simple.git https://github.com/cliftonlabs/json-simple.git - Davin Loegering @@ -35,25 +30,34 @@ Clifton Labs https://cliftonlabs.com + + Yidong Fang + - + junit junit 4.12 test + + + + ossrh + https://oss.sonatype.org/content/repositories/snapshots + + + ossrh + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + + - org.apache.felix - maven-bundle-plugin - 2.3.6 - true - - + org.apache.maven.plugins maven-compiler-plugin 2.3.2 @@ -63,33 +67,7 @@ - org.apache.maven.plugins - maven-source-plugin - 2.1.2 - - - attach-sources - verify - - jar - - - - - - org.apache.maven.plugins - maven-javadoc-plugin - 2.8.1 - - - attach-javadocs - - jar - - - - - + de.jflex maven-jflex-plugin 1.4.3 @@ -110,8 +88,10 @@ + org.apache.maven.plugins maven-jar-plugin + 3.0.2 @@ -121,23 +101,50 @@ + + + org.apache.maven.plugins + maven-source-plugin + 2.2.1 + + + attach-sources + verify + + jar-no-fork + + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.9.1 + + + attach-javadocs + + jar + + + + - release-sign-artifacts - - - performRelease - true - - + + release + + + org.apache.maven.plugins maven-gpg-plugin - 1.4 + 1.5 sign-artifacts @@ -148,9 +155,33 @@ + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ossrh + https://oss.sonatype.org/ + true + deploy + + + + + org.apache.maven.plugins + maven-release-plugin + 2.5 + + true + false + release + deploy + + - diff --git a/settings.xml b/settings.xml new file mode 100644 index 00000000..ba46e619 --- /dev/null +++ b/settings.xml @@ -0,0 +1,9 @@ + + + + ossrh + cliftonlabs + ??? + + + From 57cf9da5cd05713a74099102225ee7fe41472d2c Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 1 Sep 2016 20:30:04 -0500 Subject: [PATCH 14/48] Removed unneeded property. --- pom.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/pom.xml b/pom.xml index 5835f75f..97882fbb 100644 --- a/pom.xml +++ b/pom.xml @@ -177,7 +177,6 @@ true false release - deploy From 7bae9deb7d4850cd3ca5bfa3f323eac14af9974c Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 1 Sep 2016 20:33:39 -0500 Subject: [PATCH 15/48] Deploy options updated in README.txt. --- README.txt | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/README.txt b/README.txt index 0b008aa7..e2280ada 100644 --- a/README.txt +++ b/README.txt @@ -38,9 +38,12 @@ Make the project available to other local projects via local repository: mvn clean install Guided deploy of project with signed artifacts (jar, javadocs, and sources): -mvn release:clean -mvn release:prepare -mvn release:perform +mvn release:clean -P release +mvn release:prepare -P release +mvn release:perform -P release + +Manual deploy of a project with signed artifacts (jar, javadocs, and sources): +mvn clean deploy -P release Update gh-pages: 1) Replace latest offical build's target/ directory to the gh-pages branch. From 14bb306741e7889d1e37ba6e008d48fdfff96b80 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 1 Sep 2016 20:43:42 -0500 Subject: [PATCH 16/48] Decided a release profile was superfluous. --- README.txt | 13 +++----- pom.xml | 91 ++++++++++++++++++++++++------------------------------ 2 files changed, 46 insertions(+), 58 deletions(-) diff --git a/README.txt b/README.txt index e2280ada..109b86e3 100644 --- a/README.txt +++ b/README.txt @@ -34,16 +34,13 @@ mvn test Build the project with javadocs and source: mvn package -Make the project available to other local projects via local repository: +Make the signed artifacts available to other local projects: mvn clean install -Guided deploy of project with signed artifacts (jar, javadocs, and sources): -mvn release:clean -P release -mvn release:prepare -P release -mvn release:perform -P release - -Manual deploy of a project with signed artifacts (jar, javadocs, and sources): -mvn clean deploy -P release +Guided deploy of project with signed artifacts: +mvn release:clean +mvn release:prepare +mvn release:perform Update gh-pages: 1) Replace latest offical build's target/ directory to the gh-pages branch. diff --git a/pom.xml b/pom.xml index 97882fbb..55c71363 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,6 @@ - + 4.0.0 com.cliftonlabs json-simple @@ -130,57 +132,46 @@ + + + org.apache.maven.plugins + maven-gpg-plugin + 1.5 + + + sign-artifacts + verify + + sign + + + + + + + org.sonatype.plugins + nexus-staging-maven-plugin + 1.6.7 + true + + ossrh + https://oss.sonatype.org/ + true + deploy + + + + + org.apache.maven.plugins + maven-release-plugin + 2.5 + + true + true + + - - - release - - - - - - - org.apache.maven.plugins - maven-gpg-plugin - 1.5 - - - sign-artifacts - verify - - sign - - - - - - - org.sonatype.plugins - nexus-staging-maven-plugin - 1.6.7 - true - - ossrh - https://oss.sonatype.org/ - true - deploy - - - - - org.apache.maven.plugins - maven-release-plugin - 2.5 - - true - false - release - - - - - From 140e3968dff8f2935ac9595665208a9c53c245c4 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 1 Sep 2016 20:45:19 -0500 Subject: [PATCH 17/48] Added a post clean step to keep the local directory clean in the deploy process in the README.txt. --- README.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/README.txt b/README.txt index 109b86e3..7de3d6be 100644 --- a/README.txt +++ b/README.txt @@ -41,6 +41,7 @@ Guided deploy of project with signed artifacts: mvn release:clean mvn release:prepare mvn release:perform +mvn release:clean Update gh-pages: 1) Replace latest offical build's target/ directory to the gh-pages branch. From e9d7fe1f567c67600bb37efc262861f1c54ff283 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Fri, 2 Sep 2016 09:13:43 -0500 Subject: [PATCH 18/48] Waiting on sonatype approval for org.json group id. --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 55c71363..f05f3ec6 100644 --- a/pom.xml +++ b/pom.xml @@ -2,11 +2,11 @@ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - com.cliftonlabs + org.json json-simple jar JSON.simple - Quickly develop RFC 4627 JSON compatible java 7+ applications based on com.googlecode.json-simple.json-simple by Yidong Fang + Java 7+ toolkit to quickly develop RFC 4627 JSON compatible applications. https://cliftonlabs.github.io/json-simple/ 2.0.0-SNAPSHOT From 9f599dc2f3b3ffd49a91d68b83f086690bc968ea Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Fri, 2 Sep 2016 11:14:34 -0500 Subject: [PATCH 19/48] Removed examples from README.txt --- README.txt | 17 ----------------- 1 file changed, 17 deletions(-) diff --git a/README.txt b/README.txt index 7de3d6be..aca27dea 100644 --- a/README.txt +++ b/README.txt @@ -1,20 +1,3 @@ -[EXAMPLES] -/* Quickly serialize stuff in json-simple: */ -Object stuff = null; -String serialized = Jsoner.serialize(stuff); -/* Deserialize stuff in json-simple by handling a DeserializationException: */ -try{ - Object deserialized = Jsoner.deserialize(serialized); -}catch(DeserializationException caught){ - /* Oops bad JSON. */ -} -/* When you know you only want a JsonObject or an empty one if it fails: */ -JsonObject deserializedObject = Jsoner.deserializeJsonObject(serialized, new JsonObject()); -/* When you know you only want a JsonArray or an empty one if it fails: */ -JsonArray deserializedArray = Jsoner.deserializeJsonArray(serialized, new JsonArray()); -/* When you want it to look pretty: */ -String prettyPrinted = Jsoner.prettyPrint(serialized); - [AUTHORS] Davin Loegering Yidong Fang From f5f56c88b7501ff76b84bb08f53c1cb92f2ecc92 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Fri, 2 Sep 2016 11:40:22 -0500 Subject: [PATCH 20/48] Finalizing Jsoner API. --- src/main/java/org/json/simple/Jsoner.java | 6 +++--- src/test/java/org/json/simple/JsonerTest.java | 12 ++++++------ 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/main/java/org/json/simple/Jsoner.java b/src/main/java/org/json/simple/Jsoner.java index 47cfe23f..1c51c90a 100644 --- a/src/main/java/org/json/simple/Jsoner.java +++ b/src/main/java/org/json/simple/Jsoner.java @@ -344,7 +344,7 @@ public static Object deserialize(final String deserializable) throws Deserializa * @return a JsonArray that represents the deserializable, or the defaultValue if there isn't a JsonArray that * represents deserializable. * @see Jsoner#deserialize(Reader) */ - public static JsonArray deserializeJsonArray(final String deserializable, final JsonArray defaultValue){ + public static JsonArray deserialize(final String deserializable, final JsonArray defaultValue){ StringReader readable = null; JsonArray returnable; try{ @@ -368,7 +368,7 @@ public static JsonArray deserializeJsonArray(final String deserializable, final * @return a JsonObject that represents the deserializable, or the defaultValue if there isn't a JsonObject that * represents deserializable. * @see Jsoner#deserialize(Reader) */ - public static JsonObject deserializeJsonObject(final String deserializable, final JsonObject defaultValue){ + public static JsonObject deserialize(final String deserializable, final JsonObject defaultValue){ StringReader readable = null; JsonObject returnable; try{ @@ -408,7 +408,7 @@ public static JsonObject deserializeJsonObject(final String deserializable, fina * DeserializationException: fix the deserializable to no longer have an unexpected token and try again. * @throws IOException when the underlying reader encounters an I/O error. Ensure the reader is properly * instantiated, isn't closed, or that it is ready before trying again. */ - public static JsonArray deserializeMultipleJsonValues(final Reader deserializable) throws DeserializationException, IOException{ + public static JsonArray deserializeMany(final Reader deserializable) throws DeserializationException, IOException{ return Jsoner.deserialize(deserializable, EnumSet.of(DeserializationOptions.ALLOW_JSON_ARRAYS, DeserializationOptions.ALLOW_JSON_OBJECTS, DeserializationOptions.ALLOW_JSON_DATA, DeserializationOptions.ALLOW_CONCATENATED_JSON_VALUES)); } diff --git a/src/test/java/org/json/simple/JsonerTest.java b/src/test/java/org/json/simple/JsonerTest.java index b118c7bd..706fa443 100644 --- a/src/test/java/org/json/simple/JsonerTest.java +++ b/src/test/java/org/json/simple/JsonerTest.java @@ -50,10 +50,10 @@ public void testArrayDeserialization() throws DeserializationException{ /* Serializing JsonArrays directly requires a defaultValue in case it doesn't deserialize a JsonArray. */ defaultValue = new JsonArray(); defaultValue.add("default"); - deserialized = Jsoner.deserializeJsonArray("[,]", defaultValue); + deserialized = Jsoner.deserialize("[,]", defaultValue); Assert.assertEquals(new JsonArray(), deserialized); /* The call should return the defaultValue instead. */ - deserialized = Jsoner.deserializeJsonArray("[asdf,]", defaultValue); + deserialized = Jsoner.deserialize("[asdf,]", defaultValue); Assert.assertEquals(defaultValue, deserialized); } @@ -145,7 +145,7 @@ public void testEnumSerialization() throws IOException{ * @throws DeserializationException if the test fails. * @throws IOException if the test fails. */ @Test - public void testMultipleDeserialization() throws DeserializationException, IOException{ + public void testDeserializationMany() throws DeserializationException, IOException{ final StringBuilder deserializable = new StringBuilder(); JsonArray expected; Object deserialized; @@ -193,7 +193,7 @@ public void testMultipleDeserialization() throws DeserializationException, IOExc expected.add(new JsonArray()); deserializable.append("[]"); expected.add(new JsonArray()); - deserialized = Jsoner.deserializeMultipleJsonValues(new StringReader(deserializable.toString())); + deserialized = Jsoner.deserializeMany(new StringReader(deserializable.toString())); Assert.assertEquals(expected, deserialized); } @@ -418,10 +418,10 @@ public void testObjectDeserialization() throws DeserializationException{ /* Serializing JsonObjects directly requires a defaultValue in case it doesn't deserialize a JsonObject. */ defaultValue = new JsonObject(); defaultValue.put("default", -1); - deserialized = Jsoner.deserializeJsonObject("{,}", defaultValue); + deserialized = Jsoner.deserialize("{,}", defaultValue); Assert.assertEquals(new JsonObject(), deserialized); /* The call should return the defaultValue instead. */ - deserialized = Jsoner.deserializeJsonObject("{asdf,}", defaultValue); + deserialized = Jsoner.deserialize("{asdf,}", defaultValue); Assert.assertEquals(defaultValue, deserialized); } From 3dd58c253cad6f38f783e35f7efcf6ee9e7e3b17 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Fri, 2 Sep 2016 11:49:43 -0500 Subject: [PATCH 21/48] Added javadocs about IllegalArgumentException on serialize calls. --- src/main/java/org/json/simple/Jsoner.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/json/simple/Jsoner.java b/src/main/java/org/json/simple/Jsoner.java index 1c51c90a..b62d4d12 100644 --- a/src/main/java/org/json/simple/Jsoner.java +++ b/src/main/java/org/json/simple/Jsoner.java @@ -566,6 +566,7 @@ public static String prettyPrint(final String printable){ /** A convenience method that assumes a StringWriter. * @param jsonSerializable represents the object that should be serialized as a string in JSON format. * @return a string, in JSON format, that represents the object provided. + * @throws IllegalArgumentException if the jsonSerializable isn't serializable in JSON. * @see Jsoner#serialize(Object, Writer) * @see StringWriter */ public static String serialize(final Object jsonSerializable){ @@ -583,7 +584,8 @@ public static String serialize(final Object jsonSerializable){ * qualified name. * @param jsonSerializable represents the object that should be serialized in JSON format. * @param writableDestination represents where the resulting JSON text is written to. - * @throws IOException if the writableDestination encounters an I/O problem, like being closed while in use. */ + * @throws IOException if the writableDestination encounters an I/O problem, like being closed while in use. + * @throws IllegalArgumentException if the jsonSerializable isn't serializable in JSON. */ public static void serialize(final Object jsonSerializable, final Writer writableDestination) throws IOException{ Jsoner.serialize(jsonSerializable, writableDestination, EnumSet.of(SerializationOptions.ALLOW_JSONABLES, SerializationOptions.ALLOW_FULLY_QUALIFIED_ENUMERATIONS)); } From 87d2db2be3fc33de708052395405d39dd30caca7 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Fri, 2 Sep 2016 14:29:20 -0500 Subject: [PATCH 22/48] Authors -> Contributors. Change log moved to the front of the file. --- README.txt | 68 +++++++++++++++++++++++++++--------------------------- 1 file changed, 34 insertions(+), 34 deletions(-) diff --git a/README.txt b/README.txt index aca27dea..c90a4e7e 100644 --- a/README.txt +++ b/README.txt @@ -1,38 +1,5 @@ -[AUTHORS] -Davin Loegering -Yidong Fang -Chris Nokleberg -Dave Hughes - -[DEVELOPERS] -Generate json-simple project files for eclipse: -mvn eclipse:eclipse - -Build the project: -mvn compile - -Run unit tests: -mvn test - -Build the project with javadocs and source: -mvn package - -Make the signed artifacts available to other local projects: -mvn clean install - -Guided deploy of project with signed artifacts: -mvn release:clean -mvn release:prepare -mvn release:perform -mvn release:clean - -Update gh-pages: -1) Replace latest offical build's target/ directory to the gh-pages branch. -2) Update the index.html hrefs if necessary. -3) commit and push to gh-pages. - [CHANGE LOG] -Version 2.0.0 (2016/08/31) +Version 2.0.0 (2016/09/*) * Davin Loegering was added to the list of Authors. * Consolidated the author list, change log, and license files from the base directory into the README.txt file. * Removed ant build file. @@ -105,6 +72,39 @@ Version 1.01 (2008/08/26) Version 1.0 (2006/04/15) * Initial version +[CONTRIBUTORS] +Davin Loegering +Yidong Fang +Chris Nokleberg +Dave Hughes + +[DEVELOPERS] +Generate json-simple project files for eclipse: +mvn eclipse:eclipse + +Build the project: +mvn compile + +Run unit tests: +mvn test + +Build the project with javadocs and source: +mvn package + +Make the signed artifacts available to other local projects: +mvn clean install + +Guided deploy of project with signed artifacts: +mvn release:clean +mvn release:prepare +mvn release:perform +mvn release:clean + +Update gh-pages: +1) Replace latest offical build's target/ directory to the gh-pages branch. +2) Update the index.html hrefs if necessary. +3) commit and push to gh-pages. + [LICENSE] Apache License Version 2.0, January 2004 From 2b8aba7071c177c8236749128259c58dc46fcf50 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Fri, 2 Sep 2016 14:42:50 -0500 Subject: [PATCH 23/48] Added proper copyright notice for the Apache License 2.0 for Clifton Labs and Fang Yidong. --- .../json/simple/DeserializationException.java | 14 +++++++++++++- src/main/java/org/json/simple/ItemList.java | 17 +++++++++++++---- src/main/java/org/json/simple/JSONArray.java | 17 +++++++++++++---- src/main/java/org/json/simple/JSONAware.java | 13 +++++++++++++ src/main/java/org/json/simple/JSONObject.java | 17 +++++++++++++---- .../java/org/json/simple/JSONStreamAware.java | 13 +++++++++++++ src/main/java/org/json/simple/JSONValue.java | 17 +++++++++++++---- src/main/java/org/json/simple/JsonArray.java | 14 +++++++++++++- src/main/java/org/json/simple/JsonObject.java | 14 +++++++++++++- src/main/java/org/json/simple/Jsonable.java | 14 +++++++++++++- src/main/java/org/json/simple/Jsoner.java | 14 +++++++++++++- src/main/java/org/json/simple/Yytoken.java | 14 +++++++++++++- .../json/simple/parser/ContainerFactory.java | 13 +++++++++++++ .../org/json/simple/parser/ContentHandler.java | 13 +++++++++++++ .../java/org/json/simple/parser/JSONParser.java | 17 +++++++++++++---- .../org/json/simple/parser/ParseException.java | 13 +++++++++++++ .../java/org/json/simple/parser/Yytoken.java | 17 +++++++++++++---- 17 files changed, 221 insertions(+), 30 deletions(-) diff --git a/src/main/java/org/json/simple/DeserializationException.java b/src/main/java/org/json/simple/DeserializationException.java index 993e2ac6..090abc8f 100644 --- a/src/main/java/org/json/simple/DeserializationException.java +++ b/src/main/java/org/json/simple/DeserializationException.java @@ -1,4 +1,16 @@ -/* See: README for this file's copyright, terms, and conditions. */ +/* Copyright 2016 Clifton Labs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple; /** DeserializationException explains how and where the problem occurs in the source JSON text during deserialization. diff --git a/src/main/java/org/json/simple/ItemList.java b/src/main/java/org/json/simple/ItemList.java index ff748690..04029e6a 100644 --- a/src/main/java/org/json/simple/ItemList.java +++ b/src/main/java/org/json/simple/ItemList.java @@ -1,7 +1,16 @@ -/* - * $Id: ItemList.java,v 1.1 2006/04/15 14:10:48 platform Exp $ - * Created on 2006-3-24 - */ +/* Copyright 2006 FangYidong + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple; import java.util.ArrayList; diff --git a/src/main/java/org/json/simple/JSONArray.java b/src/main/java/org/json/simple/JSONArray.java index 14bbdb16..e64d79f3 100644 --- a/src/main/java/org/json/simple/JSONArray.java +++ b/src/main/java/org/json/simple/JSONArray.java @@ -1,7 +1,16 @@ -/* - * $Id: JSONArray.java,v 1.1 2006/04/15 14:10:48 platform Exp $ - * Created on 2006-4-10 - */ +/* Copyright 2006 FangYidong + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple; import java.io.IOException; diff --git a/src/main/java/org/json/simple/JSONAware.java b/src/main/java/org/json/simple/JSONAware.java index 187f3c92..62da3c4e 100644 --- a/src/main/java/org/json/simple/JSONAware.java +++ b/src/main/java/org/json/simple/JSONAware.java @@ -1,3 +1,16 @@ +/* Copyright 2006 FangYidong + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple; /** diff --git a/src/main/java/org/json/simple/JSONObject.java b/src/main/java/org/json/simple/JSONObject.java index bd69770b..53d80d51 100644 --- a/src/main/java/org/json/simple/JSONObject.java +++ b/src/main/java/org/json/simple/JSONObject.java @@ -1,7 +1,16 @@ -/* - * $Id: JSONObject.java,v 1.1 2006/04/15 14:10:48 platform Exp $ - * Created on 2006-4-10 - */ +/* Copyright 2006 FangYidong + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple; import java.io.IOException; diff --git a/src/main/java/org/json/simple/JSONStreamAware.java b/src/main/java/org/json/simple/JSONStreamAware.java index c9ed7b78..3250f212 100644 --- a/src/main/java/org/json/simple/JSONStreamAware.java +++ b/src/main/java/org/json/simple/JSONStreamAware.java @@ -1,3 +1,16 @@ +/* Copyright 2006 FangYidong + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple; import java.io.IOException; diff --git a/src/main/java/org/json/simple/JSONValue.java b/src/main/java/org/json/simple/JSONValue.java index 16091c4b..46fed4b8 100644 --- a/src/main/java/org/json/simple/JSONValue.java +++ b/src/main/java/org/json/simple/JSONValue.java @@ -1,7 +1,16 @@ -/* - * $Id: JSONValue.java,v 1.1 2006/04/15 14:37:04 platform Exp $ - * Created on 2006-4-15 - */ +/* Copyright 2006 FangYidong + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple; import java.io.IOException; diff --git a/src/main/java/org/json/simple/JsonArray.java b/src/main/java/org/json/simple/JsonArray.java index 006445b1..e1971443 100644 --- a/src/main/java/org/json/simple/JsonArray.java +++ b/src/main/java/org/json/simple/JsonArray.java @@ -1,4 +1,16 @@ -/* See: README for this file's copyright, terms, and conditions. */ +/* Copyright 2016 Clifton Labs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple; import java.io.IOException; diff --git a/src/main/java/org/json/simple/JsonObject.java b/src/main/java/org/json/simple/JsonObject.java index 6432aed9..98356fc6 100644 --- a/src/main/java/org/json/simple/JsonObject.java +++ b/src/main/java/org/json/simple/JsonObject.java @@ -1,4 +1,16 @@ -/* See: README for this file's copyright, terms, and conditions. */ +/* Copyright 2016 Clifton Labs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple; import java.io.IOException; diff --git a/src/main/java/org/json/simple/Jsonable.java b/src/main/java/org/json/simple/Jsonable.java index e8d8f127..947271aa 100644 --- a/src/main/java/org/json/simple/Jsonable.java +++ b/src/main/java/org/json/simple/Jsonable.java @@ -1,4 +1,16 @@ -/* See: README for this file's copyright, terms, and conditions. */ +/* Copyright 2016 Clifton Labs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple; import java.io.IOException; diff --git a/src/main/java/org/json/simple/Jsoner.java b/src/main/java/org/json/simple/Jsoner.java index b62d4d12..71ef68c5 100644 --- a/src/main/java/org/json/simple/Jsoner.java +++ b/src/main/java/org/json/simple/Jsoner.java @@ -1,4 +1,16 @@ -/* See: README for this file's copyright, terms, and conditions. */ +/* Copyright 2016 Clifton Labs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple; import java.io.IOException; diff --git a/src/main/java/org/json/simple/Yytoken.java b/src/main/java/org/json/simple/Yytoken.java index 9bc613f8..c9fd1719 100644 --- a/src/main/java/org/json/simple/Yytoken.java +++ b/src/main/java/org/json/simple/Yytoken.java @@ -1,4 +1,16 @@ -/* See: README for this file's copyright, terms, and conditions. */ +/* Copyright 2016 Clifton Labs + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple; /** Represents structural entities in JSON. diff --git a/src/main/java/org/json/simple/parser/ContainerFactory.java b/src/main/java/org/json/simple/parser/ContainerFactory.java index b763cd45..17073034 100644 --- a/src/main/java/org/json/simple/parser/ContainerFactory.java +++ b/src/main/java/org/json/simple/parser/ContainerFactory.java @@ -1,3 +1,16 @@ +/* Copyright 2006 FangYidong + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple.parser; import java.util.List; diff --git a/src/main/java/org/json/simple/parser/ContentHandler.java b/src/main/java/org/json/simple/parser/ContentHandler.java index a8f34bea..c8f12ba5 100644 --- a/src/main/java/org/json/simple/parser/ContentHandler.java +++ b/src/main/java/org/json/simple/parser/ContentHandler.java @@ -1,3 +1,16 @@ +/* Copyright 2006 FangYidong + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple.parser; import java.io.IOException; diff --git a/src/main/java/org/json/simple/parser/JSONParser.java b/src/main/java/org/json/simple/parser/JSONParser.java index 7d638585..629590ce 100644 --- a/src/main/java/org/json/simple/parser/JSONParser.java +++ b/src/main/java/org/json/simple/parser/JSONParser.java @@ -1,7 +1,16 @@ -/* - * $Id: JSONParser.java,v 1.1 2006/04/15 14:10:48 platform Exp $ - * Created on 2006-4-15 - */ +/* Copyright 2006 FangYidong + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple.parser; import java.io.IOException; diff --git a/src/main/java/org/json/simple/parser/ParseException.java b/src/main/java/org/json/simple/parser/ParseException.java index c562009a..38c26508 100644 --- a/src/main/java/org/json/simple/parser/ParseException.java +++ b/src/main/java/org/json/simple/parser/ParseException.java @@ -1,3 +1,16 @@ +/* Copyright 2006 FangYidong + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple.parser; /** diff --git a/src/main/java/org/json/simple/parser/Yytoken.java b/src/main/java/org/json/simple/parser/Yytoken.java index bb8dd302..c0f90161 100644 --- a/src/main/java/org/json/simple/parser/Yytoken.java +++ b/src/main/java/org/json/simple/parser/Yytoken.java @@ -1,7 +1,16 @@ -/* - * $Id: Yytoken.java,v 1.1 2006/04/15 14:10:48 platform Exp $ - * Created on 2006-4-15 - */ +/* Copyright 2006 FangYidong + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. */ package org.json.simple.parser; /** From 47e6abd2c7eec1c441d6012f890094af892e4b50 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 6 Sep 2016 18:11:17 -0500 Subject: [PATCH 24/48] Maven coordinates updated hoping/wishing org.json.simple groupId access is/was granted instead. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index f05f3ec6..3c04bd1d 100644 --- a/pom.xml +++ b/pom.xml @@ -2,7 +2,7 @@ xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> 4.0.0 - org.json + com.github.cliftonlabs json-simple jar JSON.simple From 3406633b972db5625a1169649eca5c6cca8a8c9a Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 6 Sep 2016 19:24:48 -0500 Subject: [PATCH 25/48] Removing deploy password placeholder since it listed as optional in deployment settings. --- settings.xml | 1 - 1 file changed, 1 deletion(-) diff --git a/settings.xml b/settings.xml index ba46e619..1e5a7375 100644 --- a/settings.xml +++ b/settings.xml @@ -3,7 +3,6 @@ ossrh cliftonlabs - ??? From b508be2bc6afae0d3616e15913caad982cbcf15a Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 6 Sep 2016 19:34:57 -0500 Subject: [PATCH 26/48] Not sure why the settings.xml and pom.xml file are not cooperating on release. --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index 3c04bd1d..5c171ef5 100644 --- a/pom.xml +++ b/pom.xml @@ -53,7 +53,7 @@ ossrh - https://oss.sonatype.org/service/local/staging/deploy/maven2/ + https://oss.sonatype.org/service/local/staging/deploy/maven2 From 42851642d1d30a34d0574924cccf30e6ee59aa92 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 6 Sep 2016 19:55:19 -0500 Subject: [PATCH 27/48] Settings.xml may not need to be part of the repo? --- settings.xml | 8 -------- 1 file changed, 8 deletions(-) delete mode 100644 settings.xml diff --git a/settings.xml b/settings.xml deleted file mode 100644 index 1e5a7375..00000000 --- a/settings.xml +++ /dev/null @@ -1,8 +0,0 @@ - - - - ossrh - cliftonlabs - - - From 24e531c89893f68fa702d44050240194222c451b Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 6 Sep 2016 19:56:43 -0500 Subject: [PATCH 28/48] [maven-release-plugin] prepare release json-simple-2.0.0 --- pom.xml | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/pom.xml b/pom.xml index 5c171ef5..efb9a577 100644 --- a/pom.xml +++ b/pom.xml @@ -1,6 +1,4 @@ - + 4.0.0 com.github.cliftonlabs json-simple @@ -8,7 +6,7 @@ JSON.simple Java 7+ toolkit to quickly develop RFC 4627 JSON compatible applications. https://cliftonlabs.github.io/json-simple/ - 2.0.0-SNAPSHOT + 2.0.0 UTF-8 @@ -24,7 +22,8 @@ scm:git:https://github.com/cliftonlabs/json-simple.git scm:git:https://github.com/cliftonlabs/json-simple.git https://github.com/cliftonlabs/json-simple.git - + json-simple-2.0.0 + Davin Loegering From 758bba42e1dc1cbbf64c7abd3748136e70fbee55 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 6 Sep 2016 19:57:01 -0500 Subject: [PATCH 29/48] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index efb9a577..47e9a43b 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ JSON.simple Java 7+ toolkit to quickly develop RFC 4627 JSON compatible applications. https://cliftonlabs.github.io/json-simple/ - 2.0.0 + 2.0.1-SNAPSHOT UTF-8 @@ -22,7 +22,7 @@ scm:git:https://github.com/cliftonlabs/json-simple.git scm:git:https://github.com/cliftonlabs/json-simple.git https://github.com/cliftonlabs/json-simple.git - json-simple-2.0.0 + HEAD From 98f221efa37c0c9f04f6ed0a8032b9e9c0763317 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 13 Sep 2016 20:32:46 -0500 Subject: [PATCH 30/48] JsonArray and JsonObject no longer return primitives. JsonObject has a get for each JSON value. JsonObject tests updated. --- src/main/java/org/json/simple/JsonArray.java | 80 ++--- src/main/java/org/json/simple/JsonObject.java | 278 +++++++++++++++--- .../java/org/json/simple/JsonObjectTest.java | 28 +- 3 files changed, 289 insertions(+), 97 deletions(-) diff --git a/src/main/java/org/json/simple/JsonArray.java b/src/main/java/org/json/simple/JsonArray.java index e1971443..7d2c0ce7 100644 --- a/src/main/java/org/json/simple/JsonArray.java +++ b/src/main/java/org/json/simple/JsonArray.java @@ -1,16 +1,13 @@ /* Copyright 2016 Clifton Labs - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. */ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.json.simple; import java.io.IOException; @@ -22,7 +19,8 @@ import java.util.Iterator; import java.util.Map; -/** JsonArray is a common non-thread safe data format for a collection of data. The contents of a JsonArray are only validated as +/** JsonArray is a common non-thread safe data format for a collection of data. The contents of a JsonArray are only + * validated as * JSON values on serialization. * @see Jsoner * @since 2.0.0 */ @@ -88,8 +86,8 @@ public BigDecimal getBigDecimal(final int index){ * @return the value at the index provided cast to a boolean. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. */ - public boolean getBoolean(final int index){ - return (boolean)this.get(index); + public Boolean getBoolean(final int index){ + return (Boolean)this.get(index); } /** A convenience method that assumes there is a Number value at the given index. @@ -98,17 +96,31 @@ public boolean getBoolean(final int index){ * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ - public byte getByte(final int index){ + public Byte getByte(final int index){ return ((Number)this.get(index)).byteValue(); } + /** A convenience method that assumes there is a Collection value at the given index. + * @param the kind of collection to expect at the index. + * @param index represents where the value is expected to be at. + * @return the value at the index provided cast to a Collection. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. + * @see Collection */ + @SuppressWarnings("unchecked") + public > T getCollection(final int index){ + /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will + * work. */ + return (T)this.get(index); + } + /** A convenience method that assumes there is a Number value at the given index. * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a double. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ - public double getDouble(final int index){ + public Double getDouble(final int index){ return ((Number)this.get(index)).doubleValue(); } @@ -171,7 +183,7 @@ public > T getEnum(final int index) throws ClassNotFoundExcept * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ - public float getFloat(final int index){ + public Float getFloat(final int index){ return ((Number)this.get(index)).floatValue(); } @@ -181,21 +193,18 @@ public float getFloat(final int index){ * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ - public int getInteger(final int index){ + public Integer getInteger(final int index){ return ((Number)this.get(index)).intValue(); } - /** A convenience method that assumes there is a Collection value at the given index. - * @param the kind of collection to expect at the index. + /** A convenience method that assumes there is a Number value at the given index. * @param index represents where the value is expected to be at. - * @return the value at the index provided cast to a Collection. + * @return the value at the index provided cast to a long. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. - * @see Collection */ - @SuppressWarnings("unchecked") - public > T getCollection(final int index){ - /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will work. */ - return (T)this.get(index); + * @see Number */ + public Long getLong(final int index){ + return ((Number)this.get(index)).longValue(); } /** A convenience method that assumes there is a Map value at the given index. @@ -206,28 +215,19 @@ public > T getCollection(final int index){ * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Map */ @SuppressWarnings("unchecked") - public > T getMap(final int index){ - /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will work. */ + public > T getMap(final int index){ + /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will + * work. */ return (T)this.get(index); } - /** A convenience method that assumes there is a Number value at the given index. - * @param index represents where the value is expected to be at. - * @return the value at the index provided cast to a long. - * @throws ClassCastException if there was a value but didn't match the assumed return type. - * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. - * @see Number */ - public long getLong(final int index){ - return ((Number)this.get(index)).longValue(); - } - /** A convenience method that assumes there is a Number value at the given index. * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a short. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ - public short getShort(final int index){ + public Short getShort(final int index){ return ((Number)this.get(index)).shortValue(); } diff --git a/src/main/java/org/json/simple/JsonObject.java b/src/main/java/org/json/simple/JsonObject.java index 98356fc6..2c9b6dce 100644 --- a/src/main/java/org/json/simple/JsonObject.java +++ b/src/main/java/org/json/simple/JsonObject.java @@ -1,16 +1,13 @@ /* Copyright 2016 Clifton Labs - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. */ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.json.simple; import java.io.IOException; @@ -47,15 +44,38 @@ public JsonObject(final Map map){ } /** A convenience method that assumes there is a BigDecimal, Number, or String at the given key. If a Number is there - * its Number#doubleValue() is used to construct a new BigDecimal(double). If a String is there it is used to + * its Number#toString() is used to construct a new BigDecimal(String). If a String is there it is used to + * construct a new BigDecimal(String). + * @param key representing where the value ought to be stored at. + * @return the value stored at the key. + * @throws ClassCastException if the value didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number represents the double or float Infinity or NaN. + * @see BigDecimal + * @see Number#toString() */ + public BigDecimal getBigDecimal(final String key){ + Object returnable = this.get(key); + if(returnable instanceof BigDecimal){ + /* Success there was a BigDecimal or it defaulted. */ + }else if(returnable instanceof Number){ + /* A number can be used to construct a BigDecimal */ + returnable = new BigDecimal(returnable.toString()); + }else if(returnable instanceof String){ + /* A number can be used to construct a BigDecimal */ + returnable = new BigDecimal((String)returnable); + } + return (BigDecimal)returnable; + } + + /** A convenience method that assumes there is a BigDecimal, Number, or String at the given key. If a Number is there + * its Number#toString() is used to construct a new BigDecimal(String). If a String is there it is used to * construct a new BigDecimal(String). * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. * @return the value stored at the key or the default provided if the key doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return types. - * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number represents the double or float Infinity or NaN. * @see BigDecimal - * @see Number#doubleValue() */ + * @see Number#toString() */ public BigDecimal getBigDecimalOrDefault(final String key, final BigDecimal defaultValue){ Object returnable; if(this.containsKey(key)){ @@ -74,20 +94,41 @@ public BigDecimal getBigDecimalOrDefault(final String key, final BigDecimal defa } return (BigDecimal)returnable; } + + /** A convenience method that assumes there is a boolean value at the given key. + * @param key representing where the value ought to be stored at. + * @return the value stored at the key. + * @throws ClassCastException if the value didn't match the assumed return type. */ + public Boolean getBoolean(final String key){ + return (Boolean)this.get(key); + } /** A convenience method that assumes there is a boolean value at the given key. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. * @return the value stored at the key or the default provided if the key doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. */ - public boolean getBooleanOrDefault(final String key, final boolean defaultValue){ + public Boolean getBooleanOrDefault(final String key, final boolean defaultValue){ Object returnable; if(this.containsKey(key)){ returnable = this.get(key); }else{ returnable = defaultValue; } - return (boolean)returnable; + return (Boolean)returnable; + } + + /** A convenience method that assumes there is a Number value at the given key. + * @param key representing where the value ought to be stored at. + * @return the value stored at the key (which may involve rounding or truncation). + * @throws ClassCastException if the value didn't match the assumed return type. + * @see Number#byteValue() */ + public Byte getByte(final String key){ + Object returnable = this.get(key); + if(returnable == null){ + return (Byte)returnable; + } + return ((Number)returnable).byteValue(); } /** A convenience method that assumes there is a Number value at the given key. @@ -97,7 +138,7 @@ public boolean getBooleanOrDefault(final String key, final boolean defaultValue) * doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @see Number#byteValue() */ - public float getByteOrDefault(final String key, final byte defaultValue){ + public Byte getByteOrDefault(final String key, final byte defaultValue){ Object returnable; if(this.containsKey(key)){ returnable = this.get(key); @@ -106,6 +147,50 @@ public float getByteOrDefault(final String key, final byte defaultValue){ } return ((Number)returnable).byteValue(); } + + /** A convenience method that assumes there is a Collection at the given key. + * @param the kind of collection to expect at the key. + * @param key representing where the value ought to be stored at. + * @return the value stored at the key. + * @throws ClassCastException if the value didn't match the assumed return type. */ + @SuppressWarnings("unchecked") + public > T getCollection(final String key){ + /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will + * work. */ + return (T)this.get(key); + } + + /** A convenience method that assumes there is a Collection at the given key. + * @param the kind of collection to expect at the key. + * @param key representing where the value ought to be stored at. + * @param defaultValue representing what is returned when the key isn't in the JsonObject. + * @return the value stored at the key or the default provided if the key doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return type. */ + @SuppressWarnings("unchecked") + public > T getCollectionOrDefault(final String key, final T defaultValue){ + /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will + * work. */ + Object returnable; + if(this.containsKey(key)){ + returnable = this.get(key); + }else{ + returnable = defaultValue; + } + return (T)returnable; + } + + /** A convenience method that assumes there is a Number value at the given key. + * @param key representing where the value ought to be stored at. + * @return the value stored at the key (which may involve rounding or truncation). + * @throws ClassCastException if the value didn't match the assumed return type. + * @see Number#doubleValue() */ + public Double getDouble(final String key){ + Object returnable = this.get(key); + if(returnable == null){ + return (Double)returnable; + } + return ((Number)returnable).doubleValue(); + } /** A convenience method that assumes there is a Number value at the given key. * @param key representing where the value ought to be stored at. @@ -114,7 +199,7 @@ public float getByteOrDefault(final String key, final byte defaultValue){ * doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @see Number#doubleValue() */ - public double getDoubleOrDefault(final String key, final double defaultValue){ + public Double getDoubleOrDefault(final String key, final double defaultValue){ Object returnable; if(this.containsKey(key)){ returnable = this.get(key); @@ -123,6 +208,58 @@ public double getDoubleOrDefault(final String key, final double defaultValue){ } return ((Number)returnable).doubleValue(); } + + /** A convenience method that assumes there is a String value at the given key representing a fully qualified name in + * dot notation of an enum. + * @param key representing where the value ought to be stored at. + * @param the Enum type the value at the key is expected to belong to. + * @return the enum based on the string found at the key. + * @throws ClassNotFoundException if the value was a String but the declaring enum type couldn't be determined with + * it. + * @throws ClassCastException if the element at the index was not a String or if the fully qualified enum name is of + * the wrong type. + * @throws IllegalArgumentException if an enum type was determined but it doesn't define an enum with the determined + * name. + * @see Enum static method valueOf(Class, String) */ + @SuppressWarnings("unchecked") + public > T getEnum(final String key) throws ClassNotFoundException{ + /* Supressing the unchecked warning because the returnType is dynamically identified and could lead to a + * ClassCastException when returnType is cast to Class, which is expected by the method's contract. */ + T returnable; + final String value; + final String[] splitValues; + final int numberOfSplitValues; + final StringBuilder returnTypeName; + final StringBuilder enumName; + final Class returnType; + /* Make sure the value at the key is a String. */ + value = this.getStringOrDefault(key, ""); + /* Get the package, class, and enum names. */ + splitValues = value.split("\\."); + numberOfSplitValues = splitValues.length; + returnTypeName = new StringBuilder(); + enumName = new StringBuilder(); + for(int i = 0; i < numberOfSplitValues; i++){ + if(i == (numberOfSplitValues - 1)){ + /* If it is the last split value then it should be the name of the Enum since dots are not allowed + * in enum names. */ + enumName.append(splitValues[i]); + }else if(i == (numberOfSplitValues - 2)){ + /* If it is the penultimate split value then it should be the end of the package/enum type and not + * need a dot appended to it. */ + returnTypeName.append(splitValues[i]); + }else{ + /* Must be part of the package/enum type and will need a dot appended to it since they got removed + * in the split. */ + returnTypeName.append(splitValues[i]); + returnTypeName.append("."); + } + } + /* Use the package/class and enum names to get the Enum. */ + returnType = (Class)Class.forName(returnTypeName.toString()); + returnable = Enum.valueOf(returnType, enumName.toString()); + return returnable; + } /** A convenience method that assumes there is a String value at the given key representing a fully qualified name in * dot notation of an enum. @@ -185,6 +322,19 @@ public > T getEnumOrDefault(final String key, final T defaultV return returnable; } + /** A convenience method that assumes there is a Number value at the given key. + * @param key representing where the value ought to be stored at. + * @return the value stored at the key (which may involve rounding or truncation). + * @throws ClassCastException if the value didn't match the assumed return type. + * @see Number#floatValue() */ + public Float getFloat(final String key){ + Object returnable = this.get(key); + if(returnable == null){ + return (Float)returnable; + } + return ((Number)returnable).floatValue(); + } + /** A convenience method that assumes there is a Number value at the given key. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. @@ -192,7 +342,7 @@ public > T getEnumOrDefault(final String key, final T defaultV * doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @see Number#floatValue() */ - public float getFloatOrDefault(final String key, final float defaultValue){ + public Float getFloatOrDefault(final String key, final float defaultValue){ Object returnable; if(this.containsKey(key)){ returnable = this.get(key); @@ -202,6 +352,19 @@ public float getFloatOrDefault(final String key, final float defaultValue){ return ((Number)returnable).floatValue(); } + /** A convenience method that assumes there is a Number value at the given key. + * @param key representing where the value ought to be stored at. + * @return the value stored at the key (which may involve rounding or truncation). + * @throws ClassCastException if the value didn't match the assumed return type. + * @see Number#intValue() */ + public Integer getInteger(final String key){ + Object returnable = this.get(key); + if(returnable == null){ + return (Integer)returnable; + } + return ((Number)returnable).intValue(); + } + /** A convenience method that assumes there is a Number value at the given key. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. @@ -209,7 +372,7 @@ public float getFloatOrDefault(final String key, final float defaultValue){ * doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @see Number#intValue() */ - public int getIntegerOrDefault(final String key, final int defaultValue){ + public Integer getIntegerOrDefault(final String key, final int defaultValue){ Object returnable; if(this.containsKey(key)){ returnable = this.get(key); @@ -219,22 +382,46 @@ public int getIntegerOrDefault(final String key, final int defaultValue){ return ((Number)returnable).intValue(); } - /** A convenience method that assumes there is a Collection at the given key. - * @param the kind of collection to expect at the key. + /** A convenience method that assumes there is a Number value at the given key. + * @param key representing where the value ought to be stored at. + * @return the value stored at the key (which may involve rounding or truncation). + * @throws ClassCastException if the value didn't match the assumed return type. + * @see Number#longValue() */ + public Long getLong(final String key){ + Object returnable = this.get(key); + if(returnable == null){ + return (Long)returnable; + } + return ((Number)returnable).longValue(); + } + + /** A convenience method that assumes there is a Number value at the given key. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. - * @return the value stored at the key or the default provided if the key doesn't exist. - * @throws ClassCastException if there was a value but didn't match the assumed return type. */ - @SuppressWarnings("unchecked") - public > T getCollectionOrDefault(final String key, final T defaultValue){ - /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will work. */ + * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key + * doesn't exist. + * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @see Number#longValue() */ + public Long getLongOrDefault(final String key, final long defaultValue){ Object returnable; if(this.containsKey(key)){ returnable = this.get(key); }else{ returnable = defaultValue; } - return (T)returnable; + return ((Number)returnable).longValue(); + } + + /** A convenience method that assumes there is a Map at the given key. + * @param the kind of map to expect at the key. + * @param key representing where the value ought to be stored at. + * @return the value stored at the key. + * @throws ClassCastException if the value didn't match the assumed return type. */ + @SuppressWarnings("unchecked") + public > T getMap(final String key){ + /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will + * work. */ + return (T)this.get(key); } /** A convenience method that assumes there is a Map at the given key. @@ -245,7 +432,8 @@ public > T getCollectionOrDefault(final String key, fina * @throws ClassCastException if there was a value but didn't match the assumed return type. */ @SuppressWarnings("unchecked") public > T getMapOrDefault(final String key, final T defaultValue){ - /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will work. */ + /* The unchecked warning is suppressed because there is no way of guaranteeing at compile time the cast will + * work. */ Object returnable; if(this.containsKey(key)){ returnable = this.get(key); @@ -257,19 +445,15 @@ public > T getCollectionOrDefault(final String key, fina /** A convenience method that assumes there is a Number value at the given key. * @param key representing where the value ought to be stored at. - * @param defaultValue representing what is returned when the key isn't in the JsonObject. - * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key - * doesn't exist. - * @throws ClassCastException if there was a value but didn't match the assumed return type. - * @see Number#longValue() */ - public long getLongOrDefault(final String key, final long defaultValue){ - Object returnable; - if(this.containsKey(key)){ - returnable = this.get(key); - }else{ - returnable = defaultValue; + * @return the value stored at the key (which may involve rounding or truncation). + * @throws ClassCastException if the value didn't match the assumed return type. + * @see Number#shortValue() */ + public Short getShort(final String key){ + Object returnable = this.get(key); + if(returnable == null){ + return (Short)returnable; } - return ((Number)returnable).longValue(); + return ((Number)returnable).shortValue(); } /** A convenience method that assumes there is a Number value at the given key. @@ -279,7 +463,7 @@ public long getLongOrDefault(final String key, final long defaultValue){ * doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @see Number#shortValue() */ - public short getShortOrDefault(final String key, final short defaultValue){ + public Short getShortOrDefault(final String key, final short defaultValue){ Object returnable; if(this.containsKey(key)){ returnable = this.get(key); @@ -289,6 +473,14 @@ public short getShortOrDefault(final String key, final short defaultValue){ return ((Number)returnable).shortValue(); } + /** A convenience method that assumes there is a String value at the given key. + * @param key representing where the value ought to be stored at. + * @return the value stored at the key. + * @throws ClassCastException if the value didn't match the assumed return type. */ + public String getString(final String key){ + return (String)this.get(key); + } + /** A convenience method that assumes there is a String value at the given key. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. diff --git a/src/test/java/org/json/simple/JsonObjectTest.java b/src/test/java/org/json/simple/JsonObjectTest.java index 47d1a597..38e84f88 100644 --- a/src/test/java/org/json/simple/JsonObjectTest.java +++ b/src/test/java/org/json/simple/JsonObjectTest.java @@ -58,7 +58,7 @@ public void testConstructor(){ /** Ensures a BigDecimal can be gotten if there is a BigDecimal, Number, or String at the key. */ @Test - public void testGetBigDecimalOrDefault(){ + public void testGetBigDecimal(){ final JsonObject json = new JsonObject(); final BigDecimal defaultValue = new BigDecimal("101"); json.put("big", new BigDecimal("0")); @@ -69,14 +69,14 @@ public void testGetBigDecimalOrDefault(){ json.put("short", new Short((short)0)); json.put("byte", new Byte((byte)0)); json.put("string", new String("0")); - Assert.assertEquals(new BigDecimal("0"), json.getBigDecimalOrDefault("big", defaultValue)); - Assert.assertEquals(new BigDecimal("0.0"), json.getBigDecimalOrDefault("double", defaultValue)); - Assert.assertEquals(new BigDecimal("0.0"), json.getBigDecimalOrDefault("float", defaultValue)); - Assert.assertEquals(new BigDecimal("0"), json.getBigDecimalOrDefault("long", defaultValue)); - Assert.assertEquals(new BigDecimal("0"), json.getBigDecimalOrDefault("int", defaultValue)); - Assert.assertEquals(new BigDecimal("0"), json.getBigDecimalOrDefault("short", defaultValue)); - Assert.assertEquals(new BigDecimal("0"), json.getBigDecimalOrDefault("byte", defaultValue)); - Assert.assertEquals(new BigDecimal("0"), json.getBigDecimalOrDefault("string", defaultValue)); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimal("big")); + Assert.assertEquals(new BigDecimal("0.0"), json.getBigDecimal("double")); + Assert.assertEquals(new BigDecimal("0.0"), json.getBigDecimal("float")); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimal("long")); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimal("int")); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimal("short")); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimal("byte")); + Assert.assertEquals(new BigDecimal("0"), json.getBigDecimal("string")); Assert.assertEquals(new BigDecimal("101"), json.getBigDecimalOrDefault("doesnotexist", defaultValue)); } @@ -123,12 +123,12 @@ public void testGetCollectionOrDefault(){ /** Ensures enums can be returned from a String value at an index. * @throws ClassNotFoundException if the test failed. */ @Test - public void testGetEnumOrDefault() throws ClassNotFoundException{ + public void testGetEnum() throws ClassNotFoundException{ final JsonObject json = new JsonObject(); json.put("key0", "org.json.simple.JsonObjectTest$TestStaticEnums.ONE"); json.put("key1", "org.json.simple.JsonObjectTest$TestEnums.A"); - Assert.assertEquals(JsonObjectTest.TestStaticEnums.ONE, json.getEnumOrDefault("key0", JsonObjectTest.TestStaticEnums.TWO)); - Assert.assertEquals(JsonObjectTest.TestEnums.A, json.getEnumOrDefault("key1", JsonObjectTest.TestEnums.B)); + Assert.assertEquals(JsonObjectTest.TestStaticEnums.ONE, json.getEnum("key0")); + Assert.assertEquals(JsonObjectTest.TestEnums.A, json.getEnum("key1")); Assert.assertEquals(JsonObjectTest.TestEnums.A, json.getEnumOrDefault("doesnotexist", JsonObjectTest.TestEnums.A)); } @@ -148,14 +148,14 @@ public void testGetMap(){ object.put("key5", 5); json.put("map", map); json.put("object", object); - output0 = json.> getMapOrDefault("map", new LinkedHashMap()); + output0 = json.> getMap("map"); Assert.assertTrue(output0.containsKey("key0")); Assert.assertTrue(output0.containsKey("key1")); Assert.assertTrue(output0.containsKey("key2")); Assert.assertTrue(output0.containsValue(0)); Assert.assertTrue(output0.containsValue(1)); Assert.assertTrue(output0.containsValue(2)); - output1 = json. getMapOrDefault("object", new JsonObject()); + output1 = json. getMap("object"); Assert.assertTrue(output1.containsKey("key3")); Assert.assertTrue(output1.containsKey("key4")); Assert.assertTrue(output1.containsKey("key5")); From 479f80e2dd75e6da7cacaa67bd9793cafef1ecbf Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 13 Sep 2016 20:33:47 -0500 Subject: [PATCH 31/48] Automated code cleanup. --- .../json/simple/DeserializationException.java | 154 ++++++++------- src/main/java/org/json/simple/Jsonable.java | 21 +- src/main/java/org/json/simple/Jsoner.java | 27 ++- src/main/java/org/json/simple/Yytoken.java | 180 +++++++++--------- 4 files changed, 184 insertions(+), 198 deletions(-) diff --git a/src/main/java/org/json/simple/DeserializationException.java b/src/main/java/org/json/simple/DeserializationException.java index 090abc8f..051cdc09 100644 --- a/src/main/java/org/json/simple/DeserializationException.java +++ b/src/main/java/org/json/simple/DeserializationException.java @@ -1,83 +1,79 @@ /* Copyright 2016 Clifton Labs + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ +package org.json.simple; - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at +/** DeserializationException explains how and where the problem occurs in the source JSON text during deserialization. + * @since 2.0.0 */ +public class DeserializationException extends Exception{ + /** The kinds of exceptions that can trigger a DeserializationException. */ + enum Problems{ + @SuppressWarnings("javadoc") + DISALLOWED_TOKEN, + @SuppressWarnings("javadoc") + UNEXPECTED_CHARACTER, + @SuppressWarnings("javadoc") + UNEXPECTED_EXCEPTION, + @SuppressWarnings("javadoc") + UNEXPECTED_TOKEN; + } - http://www.apache.org/licenses/LICENSE-2.0 + private static final long serialVersionUID = -7880698968187728547L; + private final int position; + private final Problems problemType; + private final Object unexpectedObject; - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. */ -package org.json.simple; - -/** DeserializationException explains how and where the problem occurs in the source JSON text during deserialization. - * - * @since 2.0.0 */ -public class DeserializationException extends Exception{ - /** The kinds of exceptions that can trigger a DeserializationException. */ - enum Problems{ - @SuppressWarnings("javadoc") - DISALLOWED_TOKEN, - @SuppressWarnings("javadoc") - UNEXPECTED_CHARACTER, - @SuppressWarnings("javadoc") - UNEXPECTED_EXCEPTION, - @SuppressWarnings("javadoc") - UNEXPECTED_TOKEN; - } - - private static final long serialVersionUID = -7880698968187728547L; - private final Problems problemType; - private final int position; - private final Object unexpectedObject; - - /** @param position where the exception occurred. - * @param problemType how the exception occurred. - * @param unexpectedObject what caused the exception. */ - public DeserializationException(final int position, final Problems problemType, final Object unexpectedObject){ - this.position = position; - this.problemType = problemType; - this.unexpectedObject = unexpectedObject; - } - - /** @return the enumeration for how the exception occurred. */ - public Problems getProblemType(){ - return this.problemType; - } - - @Override - public String getMessage(){ - final StringBuilder sb = new StringBuilder(); - switch(this.problemType){ - case DISALLOWED_TOKEN: - sb.append("The disallowed token (").append(this.unexpectedObject).append(") was found at position ").append(this.position).append(". If this is in error, try again with a parse that allows the token instead. Otherwise, fix the parsable string and try again."); - break; - case UNEXPECTED_CHARACTER: - sb.append("The unexpected character (").append(this.unexpectedObject).append(") was found at position ").append(this.position).append(". Fix the parsable string and try again."); - break; - case UNEXPECTED_TOKEN: - sb.append("The unexpected token ").append(this.unexpectedObject).append(" was found at position ").append(this.position).append(". Fix the parsable string and try again."); - break; - case UNEXPECTED_EXCEPTION: - sb.append("Please report this to the library's maintainer. The unexpected exception that should be addressed before trying again occurred at position ").append(this.position).append(": ").append(this.unexpectedObject); - break; - default: - sb.append("Please report this to the library's maintainer. An error at position ").append(this.position).append(" occurred. There are no recovery recommendations available."); - break; - } - return sb.toString(); - } - - /** @return an index of the string character the error type occurred at. */ - public int getPosition(){ - return this.position; - } - - /** @return a representation of what caused the exception. */ - public Object getUnexpectedObject(){ - return this.unexpectedObject; - } -} + /** @param position where the exception occurred. + * @param problemType how the exception occurred. + * @param unexpectedObject what caused the exception. */ + public DeserializationException(final int position, final Problems problemType, final Object unexpectedObject){ + this.position = position; + this.problemType = problemType; + this.unexpectedObject = unexpectedObject; + } + + @Override + public String getMessage(){ + final StringBuilder sb = new StringBuilder(); + switch(this.problemType){ + case DISALLOWED_TOKEN: + sb.append("The disallowed token (").append(this.unexpectedObject).append(") was found at position ").append(this.position).append(". If this is in error, try again with a parse that allows the token instead. Otherwise, fix the parsable string and try again."); + break; + case UNEXPECTED_CHARACTER: + sb.append("The unexpected character (").append(this.unexpectedObject).append(") was found at position ").append(this.position).append(". Fix the parsable string and try again."); + break; + case UNEXPECTED_TOKEN: + sb.append("The unexpected token ").append(this.unexpectedObject).append(" was found at position ").append(this.position).append(". Fix the parsable string and try again."); + break; + case UNEXPECTED_EXCEPTION: + sb.append("Please report this to the library's maintainer. The unexpected exception that should be addressed before trying again occurred at position ").append(this.position).append(": ").append(this.unexpectedObject); + break; + default: + sb.append("Please report this to the library's maintainer. An error at position ").append(this.position).append(" occurred. There are no recovery recommendations available."); + break; + } + return sb.toString(); + } + + /** @return an index of the string character the error type occurred at. */ + public int getPosition(){ + return this.position; + } + + /** @return the enumeration for how the exception occurred. */ + public Problems getProblemType(){ + return this.problemType; + } + + /** @return a representation of what caused the exception. */ + public Object getUnexpectedObject(){ + return this.unexpectedObject; + } +} diff --git a/src/main/java/org/json/simple/Jsonable.java b/src/main/java/org/json/simple/Jsonable.java index 947271aa..4cb3cd76 100644 --- a/src/main/java/org/json/simple/Jsonable.java +++ b/src/main/java/org/json/simple/Jsonable.java @@ -1,16 +1,13 @@ /* Copyright 2016 Clifton Labs - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. */ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.json.simple; import java.io.IOException; diff --git a/src/main/java/org/json/simple/Jsoner.java b/src/main/java/org/json/simple/Jsoner.java index 71ef68c5..f8c91cb4 100644 --- a/src/main/java/org/json/simple/Jsoner.java +++ b/src/main/java/org/json/simple/Jsoner.java @@ -1,16 +1,13 @@ /* Copyright 2016 Clifton Labs - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. */ + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ package org.json.simple; import java.io.IOException; @@ -273,7 +270,7 @@ private static JsonArray deserialize(final Reader deserializable, final SetgetCollection(0); + returnable = Jsoner.deserialize(readable, EnumSet.of(DeserializationOptions.ALLOW_JSON_ARRAYS)). getCollection(0); }catch(NullPointerException | IOException | DeserializationException caught){ /* Don't care, just return the default value. */ returnable = defaultValue; @@ -385,7 +382,7 @@ public static JsonObject deserialize(final String deserializable, final JsonObje JsonObject returnable; try{ readable = new StringReader(deserializable); - returnable = Jsoner.deserialize(readable, EnumSet.of(DeserializationOptions.ALLOW_JSON_OBJECTS)).getMap(0); + returnable = Jsoner.deserialize(readable, EnumSet.of(DeserializationOptions.ALLOW_JSON_OBJECTS)). getMap(0); }catch(NullPointerException | IOException | DeserializationException caught){ /* Don't care, just return the default value. */ returnable = defaultValue; diff --git a/src/main/java/org/json/simple/Yytoken.java b/src/main/java/org/json/simple/Yytoken.java index c9fd1719..11850d11 100644 --- a/src/main/java/org/json/simple/Yytoken.java +++ b/src/main/java/org/json/simple/Yytoken.java @@ -1,96 +1,92 @@ /* Copyright 2016 Clifton Labs + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * http://www.apache.org/licenses/LICENSE-2.0 + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. */ +package org.json.simple; - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at +/** Represents structural entities in JSON. + * @since 2.0.0 */ +class Yytoken{ + /** Represents the different kinds of tokens. */ + enum Types{ + /** Tokens of this type will always have a value of ":" */ + COLON, + /** Tokens of this type will always have a value of "," */ + COMMA, + /** Tokens of this type will always have a value that is a boolean, null, number, or string. */ + DATUM, + /** Tokens of this type will always have a value of "" */ + END, + /** Tokens of this type will always have a value of "{" */ + LEFT_BRACE, + /** Tokens of this type will always have a value of "[" */ + LEFT_SQUARE, + /** Tokens of this type will always have a value of "}" */ + RIGHT_BRACE, + /** Tokens of this type will always have a value of "]" */ + RIGHT_SQUARE; + } - http://www.apache.org/licenses/LICENSE-2.0 + private final Types type; + private final Object value; - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. */ -package org.json.simple; - -/** Represents structural entities in JSON. - * - * @since 2.0.0 */ -class Yytoken{ - /** Represents the different kinds of tokens. */ - enum Types{ - /** Tokens of this type will always have a value of ":" */ - COLON, - /** Tokens of this type will always have a value of "," */ - COMMA, - /** Tokens of this type will always have a value that is a boolean, null, number, or string. */ - DATUM, - /** Tokens of this type will always have a value of "" */ - END, - /** Tokens of this type will always have a value of "{" */ - LEFT_BRACE, - /** Tokens of this type will always have a value of "[" */ - LEFT_SQUARE, - /** Tokens of this type will always have a value of "}" */ - RIGHT_BRACE, - /** Tokens of this type will always have a value of "]" */ - RIGHT_SQUARE; - } - - private final Types type; - private final Object value; - - /** @param type represents the kind of token the instantiated token will be. - * @param value represents the value the token is associated with, will be ignored unless type is equal to - * Types.DATUM. - * @see Types */ - Yytoken(final Types type, final Object value){ - /* Sanity check. Make sure the value is ignored for the proper value unless it is a datum token. */ - switch(type){ - case COLON: - this.value = ":"; - break; - case COMMA: - this.value = ","; - break; - case END: - this.value = ""; - break; - case LEFT_BRACE: - this.value = "{"; - break; - case LEFT_SQUARE: - this.value = "["; - break; - case RIGHT_BRACE: - this.value = "}"; - break; - case RIGHT_SQUARE: - this.value = "]"; - break; - default: - this.value = value; - break; - } - this.type = type; - } - - /** @return which of the Types the token is. - * @see Types */ - Types getType(){ - return this.type; - } - - /** @return what the token is. - * @see Types */ - Object getValue(){ - return this.value; - } - - @Override - public String toString(){ - final StringBuffer sb = new StringBuffer(); - sb.append(this.type.toString()).append("(").append(this.value).append(")"); - return sb.toString(); - } -} + /** @param type represents the kind of token the instantiated token will be. + * @param value represents the value the token is associated with, will be ignored unless type is equal to + * Types.DATUM. + * @see Types */ + Yytoken(final Types type, final Object value){ + /* Sanity check. Make sure the value is ignored for the proper value unless it is a datum token. */ + switch(type){ + case COLON: + this.value = ":"; + break; + case COMMA: + this.value = ","; + break; + case END: + this.value = ""; + break; + case LEFT_BRACE: + this.value = "{"; + break; + case LEFT_SQUARE: + this.value = "["; + break; + case RIGHT_BRACE: + this.value = "}"; + break; + case RIGHT_SQUARE: + this.value = "]"; + break; + default: + this.value = value; + break; + } + this.type = type; + } + + /** @return which of the Types the token is. + * @see Types */ + Types getType(){ + return this.type; + } + + /** @return what the token is. + * @see Types */ + Object getValue(){ + return this.value; + } + + @Override + public String toString(){ + final StringBuffer sb = new StringBuffer(); + sb.append(this.type.toString()).append("(").append(this.value).append(")"); + return sb.toString(); + } +} From de60f10b237da8d5d9a7df5f2c03199c463b9389 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 13 Sep 2016 20:36:11 -0500 Subject: [PATCH 32/48] Fixed some README typos. --- README.txt | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/README.txt b/README.txt index c90a4e7e..e1db6faa 100644 --- a/README.txt +++ b/README.txt @@ -1,4 +1,9 @@ [CHANGE LOG] +Version 2.1.0 (2016/09/*) +* Bug fix: JsonObject#getDefaultByte(key, defaultValue) now properly returns a byte value instead of a float. +* Enhancement: JsonObject has typed gets for each JSON value type. +* Enhancement: JsonArray and JsonObject no longer return primitives. + Version 2.0.0 (2016/09/*) * Davin Loegering was added to the list of Authors. * Consolidated the author list, change log, and license files from the base directory into the README.txt file. @@ -18,7 +23,7 @@ Version 2.0.0 (2016/09/*) * Deprecated JSONStreamAware and JSONAware in favor of Jsonable. * Deprecated JSONObject in favor of JsonObject. * Deprecated JSONArray in favor of JsonArray. -* Deprecated org.json.simple.parser.ParseException for org.json.simple.ParseException. +* Deprecated org.json.simple.parser.ParseException for org.json.simple.DeserializationException. * Deprecated org.json.simple.parser.Yytoken for org.json.simple.Yytoken. * Deprecated org.json.simple.parser.Yylex for org.json.simple.Yylex. * Tests for deprecated classes have been reorganized and updated to ensure backwards compatibility is maintained throughout the 2.x release lifetime. @@ -26,7 +31,7 @@ Version 2.0.0 (2016/09/*) * Classes introduced in the 2.0 release have substantial javadocs to help projects heathily update ASAP. * The Jsonable interface allows others to define how their objects should be serialized in JSON. * The new ParseException has a new problem type for disallowed tokens. -* The new ParseException now recommends recovery actions based on the problem that caused the ParseException in its message. All recovery scenarios are basically the same so ParseException is still the only json-simple exception class. +* The new ParseException now recommends recovery actions based on the problem that caused the DeserializationException in its message. All recovery scenarios are basically the same so ParseException is still the only json-simple exception class. * The new Yytoken types are renamed. * The new Yytoken is robustly constructed only allowing a null value when it is a null value in the DATUM tokens. * Jsoner can escape strings provided to it to help with implementing the Jsonable interface. @@ -43,7 +48,7 @@ Version 2.0.0 (2016/09/*) * JsonArrays that are homogeneous can be cast and copied into a provided collection of the homogenous type. * JsonArray contains gets for each allowed data type in JSON and convenience methods for Collections, Enums, and Maps. Note that they will throw ClassCastExceptions in such cases since it is still indictitive of a programmer's error. * JsonObject is based on HashMap. -* JsonObject contains getOrDefaults for each allowed data type in JSON and convenience methods for Collections, Enums, and Maps. Note that they will throw ClassCastExceptions in such cases since it is still indictitive of a programmer's error. +* JsonObject contains getTypeOrDefault for each allowed data type in JSON and convenience methods for Collections, Enums, and Maps. Note that they will throw ClassCastExceptions in such cases since it is still indictitive of a programmer's error. Version 1.1.1 (2012/01/29) * Supports OSGi From eda23e77823e256c01f734f591083f8b19194703 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 13 Sep 2016 20:38:53 -0500 Subject: [PATCH 33/48] [maven-release-plugin] prepare release json-simple-2.1.0 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 47e9a43b..d10aae53 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ JSON.simple Java 7+ toolkit to quickly develop RFC 4627 JSON compatible applications. https://cliftonlabs.github.io/json-simple/ - 2.0.1-SNAPSHOT + 2.1.0 UTF-8 @@ -22,7 +22,7 @@ scm:git:https://github.com/cliftonlabs/json-simple.git scm:git:https://github.com/cliftonlabs/json-simple.git https://github.com/cliftonlabs/json-simple.git - HEAD + json-simple-2.1.0 From c6e0d3b2a5a540ee10c7549fef37c84875b88282 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 13 Sep 2016 20:39:14 -0500 Subject: [PATCH 34/48] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index d10aae53..dc2e9e3d 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ JSON.simple Java 7+ toolkit to quickly develop RFC 4627 JSON compatible applications. https://cliftonlabs.github.io/json-simple/ - 2.1.0 + 2.1.1-SNAPSHOT UTF-8 @@ -22,7 +22,7 @@ scm:git:https://github.com/cliftonlabs/json-simple.git scm:git:https://github.com/cliftonlabs/json-simple.git https://github.com/cliftonlabs/json-simple.git - json-simple-2.1.0 + HEAD From ea61f877bbc71efa604808d0eb222b01188b3cfb Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 13 Sep 2016 21:03:13 -0500 Subject: [PATCH 35/48] Updated gh-pages update process. --- README.txt | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/README.txt b/README.txt index e1db6faa..60d27950 100644 --- a/README.txt +++ b/README.txt @@ -106,9 +106,17 @@ mvn release:perform mvn release:clean Update gh-pages: -1) Replace latest offical build's target/ directory to the gh-pages branch. -2) Update the index.html hrefs if necessary. -3) commit and push to gh-pages. +1) switch to gh-pages +2) Delete target/ + +3) switch to latest json-simple release tag +4) mvn clean install + +5) switch back to gh-pages +6) git add target/ + +7) Update the index.html version references. +8) commit and push to gh-pages. [LICENSE] Apache License From 20d45a25988b3b8c2a62867c93bfd7d1d4b70b07 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 27 Sep 2016 21:01:29 -0500 Subject: [PATCH 36/48] Added a LICENSE and CHANGELOG file. README.txt -> README. Convenience getters are more flexible (with updated tests). --- CHANGELOG | 80 +++++++++ README.txt => LICENSE | 127 +------------- README | 38 +++++ src/main/java/org/json/simple/JsonArray.java | 80 ++++++--- src/main/java/org/json/simple/JsonObject.java | 156 +++++++++++++----- .../java/org/json/simple/JsonArrayTest.java | 38 +++++ .../java/org/json/simple/JsonObjectTest.java | 62 +++++++ 7 files changed, 394 insertions(+), 187 deletions(-) create mode 100644 CHANGELOG rename README.txt => LICENSE (61%) create mode 100644 README diff --git a/CHANGELOG b/CHANGELOG new file mode 100644 index 00000000..5f0d6c2f --- /dev/null +++ b/CHANGELOG @@ -0,0 +1,80 @@ +Version 2.2.0 (2016/09/*) +* Enhancement: JsonArray and JsonObject convenience gets are more flexible on their expected value. Booleans now allow Booleans or Strings. Numbers now allow Numbers or Strings. Strings now allow Booleans, Numbers, or Strings. + +Version 2.1.0 (2016/09/*) +* Bug fix: JsonObject#getDefaultByte(key, defaultValue) now properly returns a byte value instead of a float. +* Enhancement: JsonObject has typed gets for each JSON value type. +* Enhancement: JsonArray and JsonObject no longer return primitives. + +Version 2.0.0 (2016/09/*) +* Davin Loegering was added to the list of Authors. +* Consolidated the author list, change log, and license files from the base directory into the README.txt file. +* Removed ant build file. +* SCM section of the POM is updated with the github information since the svn repo urls were 404s. +* POM now defines the source at 1.7 instead of 1.2, and is the only cause for the major version increment. The 2.0.0 release of this library is otherwise 100% backwards compatible with the older versions. +* Minor code quality changes have been made to the old files of the project. +* JFlex plugin now included in POM. +* JFlex will produce a lexing class from all lex files in src/main/lex. +* Javadocs are now produced when the jar goal is executed. +* Moved lex files from doc/ to src/main/lex. +* Deprecated the old json.lex in favor of jsonstrict.lex. +* Deprecated ContentHandler and doesn't have a 2.0 equivalent. +* Deprecated ContainerFactory and doesn't have a 2.0 equivalent. +* Deprecated ItemList and doesn't have a 2.0 equivalent. +* Deprecated JSONParse and JSONValue in favor of Jsoner. +* Deprecated JSONStreamAware and JSONAware in favor of Jsonable. +* Deprecated JSONObject in favor of JsonObject. +* Deprecated JSONArray in favor of JsonArray. +* Deprecated org.json.simple.parser.ParseException for org.json.simple.DeserializationException. +* Deprecated org.json.simple.parser.Yytoken for org.json.simple.Yytoken. +* Deprecated org.json.simple.parser.Yylex for org.json.simple.Yylex. +* Tests for deprecated classes have been reorganized and updated to ensure backwards compatibility is maintained throughout the 2.x release lifetime. +* Classes that have been deprecated still have shoddy javadocs but were updated to not produce errors and warnings during the build process. +* Classes introduced in the 2.0 release have substantial javadocs to help projects heathily update ASAP. +* The Jsonable interface allows others to define how their objects should be serialized in JSON. +* The new ParseException has a new problem type for disallowed tokens. +* The new ParseException now recommends recovery actions based on the problem that caused the DeserializationException in its message. All recovery scenarios are basically the same so ParseException is still the only json-simple exception class. +* The new Yytoken types are renamed. +* The new Yytoken is robustly constructed only allowing a null value when it is a null value in the DATUM tokens. +* Jsoner can escape strings provided to it to help with implementing the Jsonable interface. +* Jsoner can pretty print JSON strings provided to it for logging and basic display purposes. +* Jsoner can serialize data defined in the RFC 4627 specification and objects that implement the Jsonable interface. If data could be serialized multiple ways the deepest Jsonable implementation in the heiarchy is preferred. Any defined Jsonable implementation will be preferred before falling back to a default serialization. +* Jsoner can serialize an Enum that doesn't implement Jsonable. +* Jsoner will deserialize any numerical value as a BigDecimal. +* Jsoner can deserialize JsonArrays, JsonObjects, Strings, Numbers, Booleans, and null from strings provided to it. +* Jsoner can deserialize a JsonArray and exception out if any other value would be returned. +* Jsoner can deserialize a JsonObject and exception out if any other value would be returned. +* Jsoner can deserialize multiple JsonArrays, JsonObjects, Strings, Numbers, Booleans, and nulls from a single string provided to it. +* Jsoner deserialization (parsing) is thread safe. +* JsonArray is based on ArrayList. So it won't produce code warnings and can be used to construct a more convenient Collection. +* JsonArrays that are homogeneous can be cast and copied into a provided collection of the homogenous type. +* JsonArray contains gets for each allowed data type in JSON and convenience methods for Collections, Enums, and Maps. Note that they will throw ClassCastExceptions in such cases since it is still indictitive of a programmer's error. +* JsonObject is based on HashMap. +* JsonObject contains getTypeOrDefault for each allowed data type in JSON and convenience methods for Collections, Enums, and Maps. Note that they will throw ClassCastExceptions in such cases since it is still indictitive of a programmer's error. + +Version 1.1.1 (2012/01/29) +* Supports OSGi +* Accepts a java.util.Map parameter in constructor of JSONObject + +Version 1.1 (2009/01/23) +* Supports stoppable SAX-like content handler for streaming of JSON text +* Added JSONStreamAware to support streaming JSON text +* Added ContainerFactory to support creating arbitrary Map and List as JSON object and JSON array container during decoding +* Supports any Map and List as JSON object and JSON array container during encoding +* Added interface JSONAware +* Added ParseException to get detail error report while parsing +* Added escaping for Unicode characters that cause problems for browser JS eval + +Version 1.02 (2009/01/10) +* Updated json.lex to improve performance of the lexer +* Removed Rope.java and related junit test + +Version 1.01 (2008/08/26) +* License changed to a more commerce friendly and clear one, Apache License 2.0 +* Use JFlex to generate a faster Yylex.java +* Added Rope.java to get faster string operations +* Separate test codes from source codes +* Added ant build file build.xml + +Version 1.0 (2006/04/15) +* Initial version diff --git a/README.txt b/LICENSE similarity index 61% rename from README.txt rename to LICENSE index 60d27950..be4c5c6b 100644 --- a/README.txt +++ b/LICENSE @@ -1,125 +1,4 @@ -[CHANGE LOG] -Version 2.1.0 (2016/09/*) -* Bug fix: JsonObject#getDefaultByte(key, defaultValue) now properly returns a byte value instead of a float. -* Enhancement: JsonObject has typed gets for each JSON value type. -* Enhancement: JsonArray and JsonObject no longer return primitives. - -Version 2.0.0 (2016/09/*) -* Davin Loegering was added to the list of Authors. -* Consolidated the author list, change log, and license files from the base directory into the README.txt file. -* Removed ant build file. -* SCM section of the POM is updated with the github information since the svn repo urls were 404s. -* POM now defines the source at 1.7 instead of 1.2, and is the only cause for the major version increment. The 2.0.0 release of this library is otherwise 100% backwards compatible with the older versions. -* Minor code quality changes have been made to the old files of the project. -* JFlex plugin now included in POM. -* JFlex will produce a lexing class from all lex files in src/main/lex. -* Javadocs are now produced when the jar goal is executed. -* Moved lex files from doc/ to src/main/lex. -* Deprecated the old json.lex in favor of jsonstrict.lex. -* Deprecated ContentHandler and doesn't have a 2.0 equivalent. -* Deprecated ContainerFactory and doesn't have a 2.0 equivalent. -* Deprecated ItemList and doesn't have a 2.0 equivalent. -* Deprecated JSONParse and JSONValue in favor of Jsoner. -* Deprecated JSONStreamAware and JSONAware in favor of Jsonable. -* Deprecated JSONObject in favor of JsonObject. -* Deprecated JSONArray in favor of JsonArray. -* Deprecated org.json.simple.parser.ParseException for org.json.simple.DeserializationException. -* Deprecated org.json.simple.parser.Yytoken for org.json.simple.Yytoken. -* Deprecated org.json.simple.parser.Yylex for org.json.simple.Yylex. -* Tests for deprecated classes have been reorganized and updated to ensure backwards compatibility is maintained throughout the 2.x release lifetime. -* Classes that have been deprecated still have shoddy javadocs but were updated to not produce errors and warnings during the build process. -* Classes introduced in the 2.0 release have substantial javadocs to help projects heathily update ASAP. -* The Jsonable interface allows others to define how their objects should be serialized in JSON. -* The new ParseException has a new problem type for disallowed tokens. -* The new ParseException now recommends recovery actions based on the problem that caused the DeserializationException in its message. All recovery scenarios are basically the same so ParseException is still the only json-simple exception class. -* The new Yytoken types are renamed. -* The new Yytoken is robustly constructed only allowing a null value when it is a null value in the DATUM tokens. -* Jsoner can escape strings provided to it to help with implementing the Jsonable interface. -* Jsoner can pretty print JSON strings provided to it for logging and basic display purposes. -* Jsoner can serialize data defined in the RFC 4627 specification and objects that implement the Jsonable interface. If data could be serialized multiple ways the deepest Jsonable implementation in the heiarchy is preferred. Any defined Jsonable implementation will be preferred before falling back to a default serialization. -* Jsoner can serialize an Enum that doesn't implement Jsonable. -* Jsoner will deserialize any numerical value as a BigDecimal. -* Jsoner can deserialize JsonArrays, JsonObjects, Strings, Numbers, Booleans, and null from strings provided to it. -* Jsoner can deserialize a JsonArray and exception out if any other value would be returned. -* Jsoner can deserialize a JsonObject and exception out if any other value would be returned. -* Jsoner can deserialize multiple JsonArrays, JsonObjects, Strings, Numbers, Booleans, and nulls from a single string provided to it. -* Jsoner deserialization (parsing) is thread safe. -* JsonArray is based on ArrayList. So it won't produce code warnings and can be used to construct a more convenient Collection. -* JsonArrays that are homogeneous can be cast and copied into a provided collection of the homogenous type. -* JsonArray contains gets for each allowed data type in JSON and convenience methods for Collections, Enums, and Maps. Note that they will throw ClassCastExceptions in such cases since it is still indictitive of a programmer's error. -* JsonObject is based on HashMap. -* JsonObject contains getTypeOrDefault for each allowed data type in JSON and convenience methods for Collections, Enums, and Maps. Note that they will throw ClassCastExceptions in such cases since it is still indictitive of a programmer's error. - -Version 1.1.1 (2012/01/29) -* Supports OSGi -* Accepts a java.util.Map parameter in constructor of JSONObject - -Version 1.1 (2009/01/23) -* Supports stoppable SAX-like content handler for streaming of JSON text -* Added JSONStreamAware to support streaming JSON text -* Added ContainerFactory to support creating arbitrary Map and List as JSON object and JSON array container during decoding -* Supports any Map and List as JSON object and JSON array container during encoding -* Added interface JSONAware -* Added ParseException to get detail error report while parsing -* Added escaping for Unicode characters that cause problems for browser JS eval - -Version 1.02 (2009/01/10) -* Updated json.lex to improve performance of the lexer -* Removed Rope.java and related junit test - -Version 1.01 (2008/08/26) -* License changed to a more commerce friendly and clear one, Apache License 2.0 -* Use JFlex to generate a faster Yylex.java -* Added Rope.java to get faster string operations -* Separate test codes from source codes -* Added ant build file build.xml - -Version 1.0 (2006/04/15) -* Initial version - -[CONTRIBUTORS] -Davin Loegering -Yidong Fang -Chris Nokleberg -Dave Hughes - -[DEVELOPERS] -Generate json-simple project files for eclipse: -mvn eclipse:eclipse - -Build the project: -mvn compile - -Run unit tests: -mvn test - -Build the project with javadocs and source: -mvn package - -Make the signed artifacts available to other local projects: -mvn clean install - -Guided deploy of project with signed artifacts: -mvn release:clean -mvn release:prepare -mvn release:perform -mvn release:clean - -Update gh-pages: -1) switch to gh-pages -2) Delete target/ - -3) switch to latest json-simple release tag -4) mvn clean install - -5) switch back to gh-pages -6) git add target/ - -7) Update the index.html version references. -8) commit and push to gh-pages. - -[LICENSE] - Apache License + Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ @@ -320,7 +199,3 @@ Update gh-pages: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. - -Please visit for the old version of this library: -https://github.com/fangyidong/json-simple -http://code.google.com/p/json-simple/ diff --git a/README b/README new file mode 100644 index 00000000..b9a136f1 --- /dev/null +++ b/README @@ -0,0 +1,38 @@ +For more information please visit: +https://cliftonlabs.github.io/json-simple/ + +[DEVELOPERS] +Generate json-simple project files for eclipse: +mvn eclipse:eclipse + +Build the project: +mvn compile + +Run unit tests: +mvn test + +Build the project with javadocs and source: +mvn package + +Make the signed artifacts available to other local projects: +mvn clean install + +Guided deploy of project with signed artifacts: +mvn release:clean +mvn release:prepare +mvn release:perform +mvn release:clean + +Update gh-pages: +1) switch to gh-pages +2) Delete target/ + +3) switch to latest json-simple release tag +4) mvn clean install + +5) switch back to gh-pages +6) git add target/ + +7) Update the index.html version references. +8) commit and push to gh-pages. + diff --git a/src/main/java/org/json/simple/JsonArray.java b/src/main/java/org/json/simple/JsonArray.java index 7d2c0ce7..0f19eb4d 100644 --- a/src/main/java/org/json/simple/JsonArray.java +++ b/src/main/java/org/json/simple/JsonArray.java @@ -72,36 +72,45 @@ public BigDecimal getBigDecimal(final int index){ if(returnable instanceof BigDecimal){ /* Success there was a BigDecimal. */ }else if(returnable instanceof Number){ - /* A number can be used to construct a BigDecimal */ + /* A number can be used to construct a BigDecimal. */ returnable = new BigDecimal(returnable.toString()); }else if(returnable instanceof String){ - /* A number can be used to construct a BigDecimal */ + /* A number can be used to construct a BigDecimal. */ returnable = new BigDecimal((String)returnable); } return (BigDecimal)returnable; } - /** A convenience method that assumes there is a boolean value at the given index. + /** A convenience method that assumes there is a Boolean or String value at the given index. * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a boolean. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. */ public Boolean getBoolean(final int index){ - return (Boolean)this.get(index); + Object returnable = this.get(index); + if(returnable instanceof String){ + returnable = Boolean.valueOf((String)returnable); + } + return (Boolean)returnable; } - /** A convenience method that assumes there is a Number value at the given index. + /** A convenience method that assumes there is a Number or String value at the given index. * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a byte. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ public Byte getByte(final int index){ - return ((Number)this.get(index)).byteValue(); + Object returnable = this.get(index); + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); + } + return ((Number)returnable).byteValue(); } /** A convenience method that assumes there is a Collection value at the given index. - * @param the kind of collection to expect at the index. + * @param the kind of collection to expect at the index. Note unless manually added, collection values will be a JsonArray. * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a Collection. * @throws ClassCastException if there was a value but didn't match the assumed return type. @@ -114,14 +123,19 @@ public > T getCollection(final int index){ return (T)this.get(index); } - /** A convenience method that assumes there is a Number value at the given index. + /** A convenience method that assumes there is a Number or String value at the given index. * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a double. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ public Double getDouble(final int index){ - return ((Number)this.get(index)).doubleValue(); + Object returnable = this.get(index); + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); + } + return ((Number)returnable).doubleValue(); } /** A convenience method that assumes there is a String value at the given index representing a fully qualified name @@ -177,38 +191,53 @@ public > T getEnum(final int index) throws ClassNotFoundExcept return returnable; } - /** A convenience method that assumes there is a Number value at the given index. + /** A convenience method that assumes there is a Number or String value at the given index. * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a float. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ public Float getFloat(final int index){ - return ((Number)this.get(index)).floatValue(); + Object returnable = this.get(index); + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); + } + return ((Number)returnable).floatValue(); } - /** A convenience method that assumes there is a Number value at the given index. + /** A convenience method that assumes there is a Number or String value at the given index. * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a int. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ public Integer getInteger(final int index){ - return ((Number)this.get(index)).intValue(); + Object returnable = this.get(index); + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); + } + return ((Number)returnable).intValue(); } - /** A convenience method that assumes there is a Number value at the given index. + /** A convenience method that assumes there is a Number or String value at the given index. * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a long. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ public Long getLong(final int index){ - return ((Number)this.get(index)).longValue(); + Object returnable = this.get(index); + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); + } + return ((Number)returnable).longValue(); } /** A convenience method that assumes there is a Map value at the given index. - * @param the kind of map to expect at the index. + * @param the kind of map to expect at the index. Note unless manually added, Map values will be a JsonObject. * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a Map. * @throws ClassCastException if there was a value but didn't match the assumed return type. @@ -221,23 +250,34 @@ public Long getLong(final int index){ return (T)this.get(index); } - /** A convenience method that assumes there is a Number value at the given index. + /** A convenience method that assumes there is a Number or String value at the given index. * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a short. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ public Short getShort(final int index){ - return ((Number)this.get(index)).shortValue(); + Object returnable = this.get(index); + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); + } + return ((Number)returnable).shortValue(); } - /** A convenience method that assumes there is a String value at the given index. + /** A convenience method that assumes there is a Boolean, Number, or String value at the given index. * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a String. * @throws ClassCastException if there was a value but didn't match the assumed return type. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. */ public String getString(final int index){ - return (String)this.get(index); + Object returnable = this.get(index); + if(returnable instanceof Boolean){ + returnable = returnable.toString(); + }else if(returnable instanceof Number){ + returnable = returnable.toString(); + } + return (String)returnable; } /* (non-Javadoc) diff --git a/src/main/java/org/json/simple/JsonObject.java b/src/main/java/org/json/simple/JsonObject.java index 2c9b6dce..c2b66e32 100644 --- a/src/main/java/org/json/simple/JsonObject.java +++ b/src/main/java/org/json/simple/JsonObject.java @@ -49,7 +49,8 @@ public JsonObject(final Map map){ * @param key representing where the value ought to be stored at. * @return the value stored at the key. * @throws ClassCastException if the value didn't match the assumed return type. - * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number represents the double or float Infinity or NaN. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see BigDecimal * @see Number#toString() */ public BigDecimal getBigDecimal(final String key){ @@ -73,7 +74,8 @@ public BigDecimal getBigDecimal(final String key){ * @param defaultValue representing what is returned when the key isn't in the JsonObject. * @return the value stored at the key or the default provided if the key doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return types. - * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number represents the double or float Infinity or NaN. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see BigDecimal * @see Number#toString() */ public BigDecimal getBigDecimalOrDefault(final String key, final BigDecimal defaultValue){ @@ -89,21 +91,25 @@ public BigDecimal getBigDecimalOrDefault(final String key, final BigDecimal defa /* A number can be used to construct a BigDecimal */ returnable = new BigDecimal(returnable.toString()); }else if(returnable instanceof String){ - /* A number can be used to construct a BigDecimal */ + /* A String can be used to construct a BigDecimal */ returnable = new BigDecimal((String)returnable); } return (BigDecimal)returnable; } - - /** A convenience method that assumes there is a boolean value at the given key. + + /** A convenience method that assumes there is a Boolean or String value at the given key. * @param key representing where the value ought to be stored at. * @return the value stored at the key. * @throws ClassCastException if the value didn't match the assumed return type. */ public Boolean getBoolean(final String key){ - return (Boolean)this.get(key); + Object returnable = this.get(key); + if(returnable instanceof String){ + returnable = Boolean.valueOf((String)returnable); + } + return (Boolean)returnable; } - /** A convenience method that assumes there is a boolean value at the given key. + /** A convenience method that assumes there is a Boolean or String value at the given key. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. * @return the value stored at the key or the default provided if the key doesn't exist. @@ -115,28 +121,36 @@ public Boolean getBooleanOrDefault(final String key, final boolean defaultValue) }else{ returnable = defaultValue; } + if(returnable instanceof String){ + returnable = Boolean.valueOf((String)returnable); + } return (Boolean)returnable; } - /** A convenience method that assumes there is a Number value at the given key. + /** A convenience method that assumes there is a Number or String value at the given key. * @param key representing where the value ought to be stored at. * @return the value stored at the key (which may involve rounding or truncation). * @throws ClassCastException if the value didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see Number#byteValue() */ public Byte getByte(final String key){ Object returnable = this.get(key); - if(returnable == null){ - return (Byte)returnable; + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); } return ((Number)returnable).byteValue(); } - /** A convenience method that assumes there is a Number value at the given key. + /** A convenience method that assumes there is a Number or String value at the given key. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key * doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see Number#byteValue() */ public Byte getByteOrDefault(final String key, final byte defaultValue){ Object returnable; @@ -145,11 +159,15 @@ public Byte getByteOrDefault(final String key, final byte defaultValue){ }else{ returnable = defaultValue; } + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); + } return ((Number)returnable).byteValue(); } - + /** A convenience method that assumes there is a Collection at the given key. - * @param the kind of collection to expect at the key. + * @param the kind of collection to expect at the key. Note unless manually added, collection values will be a JsonArray. * @param key representing where the value ought to be stored at. * @return the value stored at the key. * @throws ClassCastException if the value didn't match the assumed return type. */ @@ -161,7 +179,7 @@ public > T getCollection(final String key){ } /** A convenience method that assumes there is a Collection at the given key. - * @param the kind of collection to expect at the key. + * @param the kind of collection to expect at the key. Note unless manually added, collection values will be a JsonArray. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. * @return the value stored at the key or the default provided if the key doesn't exist. @@ -179,25 +197,30 @@ public > T getCollectionOrDefault(final String key, fina return (T)returnable; } - /** A convenience method that assumes there is a Number value at the given key. + /** A convenience method that assumes there is a Number or String value at the given key. * @param key representing where the value ought to be stored at. * @return the value stored at the key (which may involve rounding or truncation). * @throws ClassCastException if the value didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see Number#doubleValue() */ public Double getDouble(final String key){ Object returnable = this.get(key); - if(returnable == null){ - return (Double)returnable; + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); } return ((Number)returnable).doubleValue(); } - /** A convenience method that assumes there is a Number value at the given key. + /** A convenience method that assumes there is a Number or String value at the given key. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key * doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see Number#doubleValue() */ public Double getDoubleOrDefault(final String key, final double defaultValue){ Object returnable; @@ -206,9 +229,13 @@ public Double getDoubleOrDefault(final String key, final double defaultValue){ }else{ returnable = defaultValue; } + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); + } return ((Number)returnable).doubleValue(); } - + /** A convenience method that assumes there is a String value at the given key representing a fully qualified name in * dot notation of an enum. * @param key representing where the value ought to be stored at. @@ -322,25 +349,30 @@ public > T getEnumOrDefault(final String key, final T defaultV return returnable; } - /** A convenience method that assumes there is a Number value at the given key. + /** A convenience method that assumes there is a Number or String value at the given key. * @param key representing where the value ought to be stored at. * @return the value stored at the key (which may involve rounding or truncation). * @throws ClassCastException if the value didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see Number#floatValue() */ public Float getFloat(final String key){ Object returnable = this.get(key); - if(returnable == null){ - return (Float)returnable; + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); } return ((Number)returnable).floatValue(); } - /** A convenience method that assumes there is a Number value at the given key. + /** A convenience method that assumes there is a Number or String value at the given key. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key * doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see Number#floatValue() */ public Float getFloatOrDefault(final String key, final float defaultValue){ Object returnable; @@ -349,28 +381,37 @@ public Float getFloatOrDefault(final String key, final float defaultValue){ }else{ returnable = defaultValue; } + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); + } return ((Number)returnable).floatValue(); } - /** A convenience method that assumes there is a Number value at the given key. + /** A convenience method that assumes there is a Number or String value at the given key. * @param key representing where the value ought to be stored at. * @return the value stored at the key (which may involve rounding or truncation). * @throws ClassCastException if the value didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see Number#intValue() */ public Integer getInteger(final String key){ Object returnable = this.get(key); - if(returnable == null){ - return (Integer)returnable; + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); } return ((Number)returnable).intValue(); } - /** A convenience method that assumes there is a Number value at the given key. + /** A convenience method that assumes there is a Number or String value at the given key. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key * doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see Number#intValue() */ public Integer getIntegerOrDefault(final String key, final int defaultValue){ Object returnable; @@ -379,28 +420,37 @@ public Integer getIntegerOrDefault(final String key, final int defaultValue){ }else{ returnable = defaultValue; } + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); + } return ((Number)returnable).intValue(); } - /** A convenience method that assumes there is a Number value at the given key. + /** A convenience method that assumes there is a Number or String value at the given key. * @param key representing where the value ought to be stored at. * @return the value stored at the key (which may involve rounding or truncation). * @throws ClassCastException if the value didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see Number#longValue() */ public Long getLong(final String key){ Object returnable = this.get(key); - if(returnable == null){ - return (Long)returnable; + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); } return ((Number)returnable).longValue(); } - /** A convenience method that assumes there is a Number value at the given key. + /** A convenience method that assumes there is a Number or String value at the given key. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key * doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see Number#longValue() */ public Long getLongOrDefault(final String key, final long defaultValue){ Object returnable; @@ -409,11 +459,15 @@ public Long getLongOrDefault(final String key, final long defaultValue){ }else{ returnable = defaultValue; } + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); + } return ((Number)returnable).longValue(); } - + /** A convenience method that assumes there is a Map at the given key. - * @param the kind of map to expect at the key. + * @param the kind of map to expect at the key. Note unless manually added, Map values will be a JsonObject. * @param key representing where the value ought to be stored at. * @return the value stored at the key. * @throws ClassCastException if the value didn't match the assumed return type. */ @@ -425,7 +479,7 @@ public Long getLongOrDefault(final String key, final long defaultValue){ } /** A convenience method that assumes there is a Map at the given key. - * @param the kind of map to expect at the key. + * @param the kind of map to expect at the key. Note unless manually added, Map values will be a JsonObject. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. * @return the value stored at the key or the default provided if the key doesn't exist. @@ -443,25 +497,30 @@ public Long getLongOrDefault(final String key, final long defaultValue){ return (T)returnable; } - /** A convenience method that assumes there is a Number value at the given key. + /** A convenience method that assumes there is a Number or String value at the given key. * @param key representing where the value ought to be stored at. * @return the value stored at the key (which may involve rounding or truncation). * @throws ClassCastException if the value didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see Number#shortValue() */ public Short getShort(final String key){ Object returnable = this.get(key); - if(returnable == null){ - return (Short)returnable; + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); } return ((Number)returnable).shortValue(); } - /** A convenience method that assumes there is a Number value at the given key. + /** A convenience method that assumes there is a Number or String value at the given key. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. * @return the value stored at the key (which may involve rounding or truncation) or the default provided if the key * doesn't exist. * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @see Number#shortValue() */ public Short getShortOrDefault(final String key, final short defaultValue){ Object returnable; @@ -470,18 +529,28 @@ public Short getShortOrDefault(final String key, final short defaultValue){ }else{ returnable = defaultValue; } + if(returnable instanceof String){ + /* A String can be used to construct a BigDecimal. */ + returnable = new BigDecimal((String)returnable); + } return ((Number)returnable).shortValue(); } - /** A convenience method that assumes there is a String value at the given key. + /** A convenience method that assumes there is a Boolean, Number, or String value at the given key. * @param key representing where the value ought to be stored at. * @return the value stored at the key. * @throws ClassCastException if the value didn't match the assumed return type. */ public String getString(final String key){ - return (String)this.get(key); + Object returnable = this.get(key); + if(returnable instanceof Boolean){ + returnable = returnable.toString(); + }else if(returnable instanceof Number){ + returnable = returnable.toString(); + } + return (String)returnable; } - /** A convenience method that assumes there is a String value at the given key. + /** A convenience method that assumes there is a Boolean, Number, or String value at the given key. * @param key representing where the value ought to be stored at. * @param defaultValue representing what is returned when the key isn't in the JsonObject. * @return the value stored at the key or the default provided if the key doesn't exist. @@ -493,6 +562,11 @@ public String getStringOrDefault(final String key, final String defaultValue){ }else{ returnable = defaultValue; } + if(returnable instanceof Boolean){ + returnable = returnable.toString(); + }else if(returnable instanceof Number){ + returnable = returnable.toString(); + } return (String)returnable; } diff --git a/src/test/java/org/json/simple/JsonArrayTest.java b/src/test/java/org/json/simple/JsonArrayTest.java index 75790606..a7edef62 100644 --- a/src/test/java/org/json/simple/JsonArrayTest.java +++ b/src/test/java/org/json/simple/JsonArrayTest.java @@ -193,4 +193,42 @@ public void testGetMap(){ Assert.assertTrue(output1.containsValue(4)); Assert.assertTrue(output1.containsValue(5)); } + + /** Ensures basic JSON values can be gotten. */ + @Test + public void testOtherJsonGets(){ + final JsonArray json = new JsonArray(); + json.add("101"); + json.add(true); + json.add(101); + json.add(new BigDecimal("101")); + /* Booleans are gotten from strings and booleans. */ + Assert.assertEquals(true, json.getBoolean(1)); + Assert.assertEquals(false, json.getBoolean(0)); + /* Numbers are gotten from strings. */ + Assert.assertEquals(new Byte((byte)101), json.getByte(0)); + Assert.assertEquals(new Short((short)101), json.getShort(0)); + Assert.assertEquals(new Integer(101), json.getInteger(0)); + Assert.assertEquals(new Long(101), json.getLong(0)); + Assert.assertEquals(new Float(101), json.getFloat(0)); + Assert.assertEquals(new Double(101), json.getDouble(0)); + /* Numbers are gotten from numbers. */ + Assert.assertEquals(new Byte((byte)101), json.getByte(2)); + Assert.assertEquals(new Short((short)101), json.getShort(2)); + Assert.assertEquals(new Integer(101), json.getInteger(2)); + Assert.assertEquals(new Long(101), json.getLong(2)); + Assert.assertEquals(new Float(101), json.getFloat(2)); + Assert.assertEquals(new Double(101), json.getDouble(2)); + Assert.assertEquals(new Byte((byte)101), json.getByte(3)); + Assert.assertEquals(new Short((short)101), json.getShort(3)); + Assert.assertEquals(new Integer(101), json.getInteger(3)); + Assert.assertEquals(new Long(101), json.getLong(3)); + Assert.assertEquals(new Float(101), json.getFloat(3)); + Assert.assertEquals(new Double(101), json.getDouble(3)); + /* Strings are gotten from booleans, numbers, and strings. */ + Assert.assertEquals("101", json.getString(0)); + Assert.assertEquals("true", json.getString(1)); + Assert.assertEquals("101", json.getString(2)); + Assert.assertEquals("101", json.getString(3)); + } } diff --git a/src/test/java/org/json/simple/JsonObjectTest.java b/src/test/java/org/json/simple/JsonObjectTest.java index 38e84f88..c86b0028 100644 --- a/src/test/java/org/json/simple/JsonObjectTest.java +++ b/src/test/java/org/json/simple/JsonObjectTest.java @@ -164,4 +164,66 @@ public void testGetMap(){ Assert.assertTrue(output1.containsValue(5)); Assert.assertEquals(new JsonObject(), json.getMapOrDefault("doesnotexist", new JsonObject())); } + + /** Ensures basic JSON values can be gotten. */ + @Test + public void testOtherJsonGets(){ + final JsonObject json = new JsonObject(); + json.put("string", "101"); + json.put("boolean", true); + json.put("number", 101); + json.put("big", new BigDecimal("101")); + /* Booleans are gotten from strings and booleans. */ + Assert.assertEquals(true, json.getBoolean("boolean")); + Assert.assertEquals(false, json.getBoolean("string")); + Assert.assertEquals(true, json.getBooleanOrDefault("boolean", false)); + Assert.assertEquals(false, json.getBooleanOrDefault("string", true)); + /* Numbers are gotten from strings. */ + Assert.assertEquals(new Byte((byte)101), json.getByte("string")); + Assert.assertEquals(new Short((short)101), json.getShort("string")); + Assert.assertEquals(new Integer(101), json.getInteger("string")); + Assert.assertEquals(new Long(101), json.getLong("string")); + Assert.assertEquals(new Float(101), json.getFloat("string")); + Assert.assertEquals(new Double(101), json.getDouble("string")); + Assert.assertEquals(new Byte((byte)101), json.getByteOrDefault("string", (byte)0)); + Assert.assertEquals(new Short((short)101), json.getShortOrDefault("string", (short)0)); + Assert.assertEquals(new Integer(101), json.getIntegerOrDefault("string", 0)); + Assert.assertEquals(new Long(101), json.getLongOrDefault("string", 0)); + Assert.assertEquals(new Float(101), json.getFloatOrDefault("string", 0)); + Assert.assertEquals(new Double(101), json.getDoubleOrDefault("string", 0)); + /* Numbers are gotten from numbers. */ + Assert.assertEquals(new Byte((byte)101), json.getByte("number")); + Assert.assertEquals(new Short((short)101), json.getShort("number")); + Assert.assertEquals(new Integer(101), json.getInteger("number")); + Assert.assertEquals(new Long(101), json.getLong("number")); + Assert.assertEquals(new Float(101), json.getFloat("number")); + Assert.assertEquals(new Double(101), json.getDouble("number")); + Assert.assertEquals(new Byte((byte)101), json.getByteOrDefault("number", (byte)0)); + Assert.assertEquals(new Short((short)101), json.getShortOrDefault("number", (short)0)); + Assert.assertEquals(new Integer(101), json.getIntegerOrDefault("number", 0)); + Assert.assertEquals(new Long(101), json.getLongOrDefault("number", 0)); + Assert.assertEquals(new Float(101), json.getFloatOrDefault("number", 0)); + Assert.assertEquals(new Double(101), json.getDoubleOrDefault("number", 0)); + Assert.assertEquals(new Byte((byte)101), json.getByte("big")); + Assert.assertEquals(new Short((short)101), json.getShort("big")); + Assert.assertEquals(new Integer(101), json.getInteger("big")); + Assert.assertEquals(new Long(101), json.getLong("big")); + Assert.assertEquals(new Float(101), json.getFloat("big")); + Assert.assertEquals(new Double(101), json.getDouble("big")); + Assert.assertEquals(new Byte((byte)101), json.getByteOrDefault("big", (byte)0)); + Assert.assertEquals(new Short((short)101), json.getShortOrDefault("big", (short)0)); + Assert.assertEquals(new Integer(101), json.getIntegerOrDefault("big", 0)); + Assert.assertEquals(new Long(101), json.getLongOrDefault("big", 0)); + Assert.assertEquals(new Float(101), json.getFloatOrDefault("big", 0)); + Assert.assertEquals(new Double(101), json.getDoubleOrDefault("big", 0)); + /* Strings are gotten from booleans, numbers, and strings. */ + Assert.assertEquals("101", json.getString("string")); + Assert.assertEquals("true", json.getString("boolean")); + Assert.assertEquals("101", json.getString("number")); + Assert.assertEquals("101", json.getString("big")); + Assert.assertEquals("101", json.getStringOrDefault("string", "failed")); + Assert.assertEquals("true", json.getStringOrDefault("boolean", "failed")); + Assert.assertEquals("101", json.getStringOrDefault("number", "failed")); + Assert.assertEquals("101", json.getStringOrDefault("big", "failed")); + } } From beecc62ea8543529a0ffd029758c5f2f2ce53ad6 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 29 Sep 2016 11:50:31 -0500 Subject: [PATCH 37/48] JsonArray#get javadocs now mention the possibility of a NumberFormatException while getting a number from a String like the JsonObject. --- src/main/java/org/json/simple/JsonArray.java | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/main/java/org/json/simple/JsonArray.java b/src/main/java/org/json/simple/JsonArray.java index 0f19eb4d..fd51b2f3 100644 --- a/src/main/java/org/json/simple/JsonArray.java +++ b/src/main/java/org/json/simple/JsonArray.java @@ -98,6 +98,8 @@ public Boolean getBoolean(final int index){ * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a byte. * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ public Byte getByte(final int index){ @@ -127,6 +129,8 @@ public > T getCollection(final int index){ * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a double. * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ public Double getDouble(final int index){ @@ -195,6 +199,8 @@ public > T getEnum(final int index) throws ClassNotFoundExcept * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a float. * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ public Float getFloat(final int index){ @@ -210,6 +216,8 @@ public Float getFloat(final int index){ * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a int. * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ public Integer getInteger(final int index){ @@ -225,6 +233,8 @@ public Integer getInteger(final int index){ * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a long. * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ public Long getLong(final int index){ @@ -254,6 +264,8 @@ public Long getLong(final int index){ * @param index represents where the value is expected to be at. * @return the value at the index provided cast to a short. * @throws ClassCastException if there was a value but didn't match the assumed return type. + * @throws NumberFormatException if a String isn't a valid representation of a BigDecimal or if the Number + * represents the double or float Infinity or NaN. * @throws IndexOutOfBoundsException if the index is outside of the range of element indexes in the JsonArray. * @see Number */ public Short getShort(final int index){ From a6a3a660f7e80461c08fee4fc349dbbe52c7063b Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 29 Sep 2016 13:28:54 -0500 Subject: [PATCH 38/48] Separated a TODO from a comment about the code. --- src/main/java/org/json/simple/Jsoner.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/json/simple/Jsoner.java b/src/main/java/org/json/simple/Jsoner.java index f8c91cb4..f8f2d81c 100644 --- a/src/main/java/org/json/simple/Jsoner.java +++ b/src/main/java/org/json/simple/Jsoner.java @@ -819,8 +819,8 @@ private static void serialize(final Object jsonSerializable, final Writer writab * This feature would require another serialize method exposed to allow this serialization. * This feature (although perhaps useful on its own) would also include a method in the JsonObject where you * pass it a class and it would do its best to instantiate a POJO of the class using the keys in the - * JsonObject. / - * /* It cannot by any measure be safely serialized according to specification. */ + * JsonObject. */ + /* It cannot by any measure be safely serialized according to specification. */ if(flags.contains(SerializationOptions.ALLOW_INVALIDS)){ /* Can be helpful for debugging how it isn't valid. */ writableDestination.write(jsonSerializable.toString()); From 6985447ae20bcd4392857993a1ffe666d23a518c Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 29 Sep 2016 13:32:32 -0500 Subject: [PATCH 39/48] [maven-release-plugin] prepare release json-simple-2.1.1 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index dc2e9e3d..fc7d48be 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ JSON.simple Java 7+ toolkit to quickly develop RFC 4627 JSON compatible applications. https://cliftonlabs.github.io/json-simple/ - 2.1.1-SNAPSHOT + 2.1.1 UTF-8 @@ -22,7 +22,7 @@ scm:git:https://github.com/cliftonlabs/json-simple.git scm:git:https://github.com/cliftonlabs/json-simple.git https://github.com/cliftonlabs/json-simple.git - HEAD + json-simple-2.1.1 From 10ee77bf1c965f4ab6bbac95b492f108fc310f4b Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 29 Sep 2016 13:32:54 -0500 Subject: [PATCH 40/48] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index fc7d48be..6c25f6ac 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ JSON.simple Java 7+ toolkit to quickly develop RFC 4627 JSON compatible applications. https://cliftonlabs.github.io/json-simple/ - 2.1.1 + 2.1.2-SNAPSHOT UTF-8 @@ -22,7 +22,7 @@ scm:git:https://github.com/cliftonlabs/json-simple.git scm:git:https://github.com/cliftonlabs/json-simple.git https://github.com/cliftonlabs/json-simple.git - json-simple-2.1.1 + HEAD From e127ca881b8f8aae81b743970e4d77fca7266e49 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 29 Sep 2016 17:24:46 -0500 Subject: [PATCH 41/48] Corrected the latest version in the CHANGELOG. --- CHANGELOG | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG b/CHANGELOG index 5f0d6c2f..9d5ce7c8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,4 @@ -Version 2.2.0 (2016/09/*) +Version 2.1.1 (2016/09/*) * Enhancement: JsonArray and JsonObject convenience gets are more flexible on their expected value. Booleans now allow Booleans or Strings. Numbers now allow Numbers or Strings. Strings now allow Booleans, Numbers, or Strings. Version 2.1.0 (2016/09/*) From 3dea0b599cf8df2d2575f0832136b4ba2f074375 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Tue, 18 Oct 2016 18:45:42 -0500 Subject: [PATCH 42/48] Noted that the README was split. --- CHANGELOG | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG b/CHANGELOG index 9d5ce7c8..8482e483 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,4 +1,5 @@ Version 2.1.1 (2016/09/*) +* Separated the CHANGLOG and LICENSE from the README as they are recognized by tools like github. Most of the information in README is linked to on the project's website. * Enhancement: JsonArray and JsonObject convenience gets are more flexible on their expected value. Booleans now allow Booleans or Strings. Numbers now allow Numbers or Strings. Strings now allow Booleans, Numbers, or Strings. Version 2.1.0 (2016/09/*) From 418d8fbac0e43cd160f9a0961ca9296a5cb6553c Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Mon, 31 Oct 2016 18:00:28 -0500 Subject: [PATCH 43/48] Updated tests to ensure deserialization allows a missing colon in a key-value pair. Pretty print no longer quotes colons. --- CHANGELOG | 4 + src/main/java/org/json/simple/Jsoner.java | 3 + src/test/java/org/json/simple/JsonerTest.java | 103 +++++++++++------- 3 files changed, 71 insertions(+), 39 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index 8482e483..b30d0111 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -1,3 +1,7 @@ +Version 2.1.2 (2016/10/*) +* Bug fix: Jsoner#prettyPrint(printable) no longer quotes colons. +* Enhancement: for convenience a colon missing between a key value pair will officially continue to function as it has since the 1.* versions. Deserialization test cases have been updated. + Version 2.1.1 (2016/09/*) * Separated the CHANGLOG and LICENSE from the README as they are recognized by tools like github. Most of the information in README is linked to on the project's website. * Enhancement: JsonArray and JsonObject convenience gets are more flexible on their expected value. Booleans now allow Booleans or Strings. Numbers now allow Numbers or Strings. Strings now allow Booleans, Numbers, or Strings. diff --git a/src/main/java/org/json/simple/Jsoner.java b/src/main/java/org/json/simple/Jsoner.java index f8f2d81c..1bc97c18 100644 --- a/src/main/java/org/json/simple/Jsoner.java +++ b/src/main/java/org/json/simple/Jsoner.java @@ -520,6 +520,9 @@ public static String prettyPrint(final String printable){ do{ lexed = Jsoner.lexNextToken(lexer); switch(lexed.getType()){ + case COLON: + returnable.append(":"); + break; case COMMA: returnable.append(lexed.getValue()); returnable.append("\n"); diff --git a/src/test/java/org/json/simple/JsonerTest.java b/src/test/java/org/json/simple/JsonerTest.java index 706fa443..2e9e7aec 100644 --- a/src/test/java/org/json/simple/JsonerTest.java +++ b/src/test/java/org/json/simple/JsonerTest.java @@ -110,37 +110,6 @@ public void testBooleanSerialization() throws IOException{ Assert.assertEquals("false", serialized.toString()); } - /** Makes sure enums are serialized when appropriate. - * @throws IOException if the test fails. */ - @Test - public void testEnumSerialization() throws IOException{ - StringWriter serialized; - serialized = new StringWriter(); - Jsoner.serialize(TestStaticEnums.ONE, serialized); - Assert.assertEquals("\"org.json.simple.JsonerTest$TestStaticEnums.ONE\"", serialized.toString()); - serialized = new StringWriter(); - try{ - Jsoner.serializeStrictly(TestStaticEnums.ONE, serialized); - }catch(final IllegalArgumentException caught){ - /* Strictly doesn't allow enums. */ - } - serialized = new StringWriter(); - Jsoner.serializeCarelessly(TestStaticEnums.ONE, serialized); - Assert.assertEquals(TestStaticEnums.ONE.toString(), serialized.toString()); - serialized = new StringWriter(); - Jsoner.serialize(TestEnums.A, serialized); - Assert.assertEquals("\"org.json.simple.JsonerTest$TestEnums.A\"", serialized.toString()); - serialized = new StringWriter(); - try{ - Jsoner.serializeStrictly(TestEnums.A, serialized); - }catch(final IllegalArgumentException caught){ - /* Strictly doesn't allow enums. */ - } - serialized = new StringWriter(); - Jsoner.serializeCarelessly(TestEnums.A, serialized); - Assert.assertEquals(TestEnums.A.toString(), serialized.toString()); - } - /** Ensures multiple concatenated JSON values are directly deserializable. * @throws DeserializationException if the test fails. * @throws IOException if the test fails. */ @@ -197,6 +166,37 @@ public void testDeserializationMany() throws DeserializationException, IOExcepti Assert.assertEquals(expected, deserialized); } + /** Makes sure enums are serialized when appropriate. + * @throws IOException if the test fails. */ + @Test + public void testEnumSerialization() throws IOException{ + StringWriter serialized; + serialized = new StringWriter(); + Jsoner.serialize(TestStaticEnums.ONE, serialized); + Assert.assertEquals("\"org.json.simple.JsonerTest$TestStaticEnums.ONE\"", serialized.toString()); + serialized = new StringWriter(); + try{ + Jsoner.serializeStrictly(TestStaticEnums.ONE, serialized); + }catch(final IllegalArgumentException caught){ + /* Strictly doesn't allow enums. */ + } + serialized = new StringWriter(); + Jsoner.serializeCarelessly(TestStaticEnums.ONE, serialized); + Assert.assertEquals(TestStaticEnums.ONE.toString(), serialized.toString()); + serialized = new StringWriter(); + Jsoner.serialize(TestEnums.A, serialized); + Assert.assertEquals("\"org.json.simple.JsonerTest$TestEnums.A\"", serialized.toString()); + serialized = new StringWriter(); + try{ + Jsoner.serializeStrictly(TestEnums.A, serialized); + }catch(final IllegalArgumentException caught){ + /* Strictly doesn't allow enums. */ + } + serialized = new StringWriter(); + Jsoner.serializeCarelessly(TestEnums.A, serialized); + Assert.assertEquals(TestEnums.A.toString(), serialized.toString()); + } + /** Ensures booleans, JsonArray, JsonObject, null, numbers, and Strings are deserializable while inside a JsonObject * or JsonArray. * @throws DeserializationException if the test fails. */ @@ -411,16 +411,41 @@ public void testNumberSerialization() throws IOException{ public void testObjectDeserialization() throws DeserializationException{ JsonObject defaultValue; Object deserialized; + JsonObject expected; + expected = new JsonObject(); + defaultValue = new JsonObject(); + defaultValue.put("error", -1); /* Trailing commas are common causes of wasting time debugging JSON. Allowing it in deserialization will * inevitably make it feel more simple and save the user time debugging pointless things. */ deserialized = Jsoner.deserialize("{,}"); - Assert.assertEquals(new JsonObject(), deserialized); - /* Serializing JsonObjects directly requires a defaultValue in case it doesn't deserialize a JsonObject. */ - defaultValue = new JsonObject(); - defaultValue.put("default", -1); - deserialized = Jsoner.deserialize("{,}", defaultValue); - Assert.assertEquals(new JsonObject(), deserialized); - /* The call should return the defaultValue instead. */ + Assert.assertEquals(expected, deserialized); + /* A missing colon can be frustrating to track down and a waste of time debugging JSON. Allowing it in + * deserialization will inevitably make it feel more simple and save the user time debugging things that don't + * actually impede the library. */ + expected.put("key", "value"); + deserialized = Jsoner.deserialize("{\"key\"\"value\"}", defaultValue); + Assert.assertEquals(expected, deserialized); + /* Same thing but with numbers. */ + expected.remove("key"); + expected.put("key", new BigDecimal("234.0")); + deserialized = Jsoner.deserialize("{\"key\"234.0}", defaultValue); + Assert.assertEquals(expected, deserialized); + /* Same thing but with booleans. */ + expected.remove("key"); + expected.put("key", true); + deserialized = Jsoner.deserialize("{\"key\"true}", defaultValue); + Assert.assertEquals(expected, deserialized); + /* Same thing but with objects. */ + expected.remove("key"); + expected.put("key", new JsonObject()); + deserialized = Jsoner.deserialize("{\"key\"{}}", defaultValue); + Assert.assertEquals(expected, deserialized); + /* Same thing but with arrays. */ + expected.remove("key"); + expected.put("key", new JsonArray()); + deserialized = Jsoner.deserialize("{\"key\"[]}", defaultValue); + Assert.assertEquals(expected, deserialized); + /* Deserializing JsonObjects directly requires a defaultValue in case it doesn't deserialize a JsonObject. */ deserialized = Jsoner.deserialize("{asdf,}", defaultValue); Assert.assertEquals(defaultValue, deserialized); } @@ -445,7 +470,7 @@ public void testObjectSerialization() throws IOException{ /** Ensures arrays and objects can be printed in an easier to read format. */ @Test public void testPrettyPrint(){ - Assert.assertEquals("[\n\t0,\n\t1,\n\t2,\n\t{\n\t\t\"k0\"\":\"\"v0\",\n\t\t\"k1\"\":\"\"v1\"\n\t},\n\t[\n\t\t[\n\t\t\t\"\",\n\t\t\t\"\"\n\t\t]\n\t],\n\tnull,\n\ttrue,\n\tfalse\n]", Jsoner.prettyPrint("[0,1,2,{\"k0\":\"v0\",\"k1\":\"v1\"},[[\"\",\"\"]],null,true,false]")); + Assert.assertEquals("[\n\t0,\n\t1,\n\t2,\n\t{\n\t\t\"k0\":\"v0\",\n\t\t\"k1\":\"v1\"\n\t},\n\t[\n\t\t[\n\t\t\t\"\",\n\t\t\t\"\"\n\t\t]\n\t],\n\tnull,\n\ttrue,\n\tfalse\n]", Jsoner.prettyPrint("[0,1,2,{\"k0\":\"v0\",\"k1\":\"v1\"},[[\"\",\"\"]],null,true,false]")); } /** Ensures Strings are directly deserializable. From e4d85453ae25ee02dff36ca2e4d9743d3aeff7b3 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Mon, 31 Oct 2016 18:04:04 -0500 Subject: [PATCH 44/48] [maven-release-plugin] prepare release json-simple-2.1.2 --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index 6c25f6ac..a90664cd 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ JSON.simple Java 7+ toolkit to quickly develop RFC 4627 JSON compatible applications. https://cliftonlabs.github.io/json-simple/ - 2.1.2-SNAPSHOT + 2.1.2 UTF-8 @@ -22,7 +22,7 @@ scm:git:https://github.com/cliftonlabs/json-simple.git scm:git:https://github.com/cliftonlabs/json-simple.git https://github.com/cliftonlabs/json-simple.git - HEAD + json-simple-2.1.2 From 0c20efbdc4b9c635908614c1132c77324ff9ea24 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Mon, 31 Oct 2016 18:04:21 -0500 Subject: [PATCH 45/48] [maven-release-plugin] prepare for next development iteration --- pom.xml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pom.xml b/pom.xml index a90664cd..630653c1 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ JSON.simple Java 7+ toolkit to quickly develop RFC 4627 JSON compatible applications. https://cliftonlabs.github.io/json-simple/ - 2.1.2 + 2.1.3-SNAPSHOT UTF-8 @@ -22,7 +22,7 @@ scm:git:https://github.com/cliftonlabs/json-simple.git scm:git:https://github.com/cliftonlabs/json-simple.git https://github.com/cliftonlabs/json-simple.git - json-simple-2.1.2 + HEAD From bd12c837ce7f735e5bf2c2fddd9ce0387065d286 Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Wed, 2 Nov 2016 15:48:01 -0500 Subject: [PATCH 46/48] Added a direct URL to the javadocs in the README. --- README | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README b/README index b9a136f1..f0d8c259 100644 --- a/README +++ b/README @@ -1,6 +1,9 @@ For more information please visit: https://cliftonlabs.github.io/json-simple/ +For the javadocs please visit: +https://cliftonlabs.github.io/json-simple/target/apidocs/index.html + [DEVELOPERS] Generate json-simple project files for eclipse: mvn eclipse:eclipse From 12e57a8aae1a9c5c8de30c314701b219b9fc6ddf Mon Sep 17 00:00:00 2001 From: Davin Loegering Date: Thu, 10 Nov 2016 14:22:37 -0600 Subject: [PATCH 47/48] README now contains a heads up to developers that wish to contribute in case-insensitive file systems. --- README | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README b/README index f0d8c259..91bc2bb5 100644 --- a/README +++ b/README @@ -5,6 +5,8 @@ For the javadocs please visit: https://cliftonlabs.github.io/json-simple/target/apidocs/index.html [DEVELOPERS] +If you are developing on a system that has case-insensitve files then please review https://github.com/cliftonlabs/json-simple/issues/13 to get started. + Generate json-simple project files for eclipse: mvn eclipse:eclipse From b8f365fe2b1ff858f4764061898b1f4728344861 Mon Sep 17 00:00:00 2001 From: Davin Date: Thu, 8 Dec 2016 09:46:52 -0600 Subject: [PATCH 48/48] Update CHANGELOG --- CHANGELOG | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index b30d0111..1197a33f 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -37,8 +37,8 @@ Version 2.0.0 (2016/09/*) * Classes that have been deprecated still have shoddy javadocs but were updated to not produce errors and warnings during the build process. * Classes introduced in the 2.0 release have substantial javadocs to help projects heathily update ASAP. * The Jsonable interface allows others to define how their objects should be serialized in JSON. -* The new ParseException has a new problem type for disallowed tokens. -* The new ParseException now recommends recovery actions based on the problem that caused the DeserializationException in its message. All recovery scenarios are basically the same so ParseException is still the only json-simple exception class. +* DeserializationException has a new problem type for disallowed tokens. +* DeserializationException now recommends recovery actions based on the problem that caused the DeserializationException in its message. All recovery scenarios are basically the same so DeserializationException is still the only json-simple exception class. * The new Yytoken types are renamed. * The new Yytoken is robustly constructed only allowing a null value when it is a null value in the DATUM tokens. * Jsoner can escape strings provided to it to help with implementing the Jsonable interface.