Compare commits

..

596 Commits

Author SHA1 Message Date
Sean Leary
8439039da7 Update pom.xml
For the 20220924 release
2022-09-24 16:25:18 -05:00
Sean Leary
a6bdd081eb Update RELEASES.md 2022-09-24 16:13:11 -05:00
Sean Leary
a30d71fdca Update README.md 2022-09-24 16:11:12 -05:00
Sean Leary
cdd67b0aef Merge pull request #688 from stleary/update-copyright
#688 update copyright
2022-08-26 21:07:52 -05:00
stleary
89f6e7f6a6 Merge branch 'master' into update-copyright 2022-08-26 20:59:00 -05:00
Sean Leary
346fb26f2d Merge pull request #683 from spaffrath/Issue_682_JSONString_similarity
Issue 682 JSONString similarity
2022-08-26 20:57:22 -05:00
stleary
6daabb43ab update-copyright - Replace copyright and license restrictions with Public Domain 2022-08-23 20:00:25 -05:00
Sean Leary
57f785c42e Merge pull request #687 from schw1804/patch-1
Fix typo
2022-08-23 17:13:10 -05:00
Joshua Schwartz
3eecd67a3b Fix typo 2022-08-23 15:00:01 -05:00
Sean Leary
5a587bbdfd Merge pull request #685 from stleary/map-unit-tests
JSONObject map type unit tests
2022-08-23 07:59:35 -05:00
stleary
e0534b3ec7 initial attempt to test for inconsistent map types in JSONObject 2022-08-20 16:14:34 -05:00
spaffrath
7dd9e01dae Merge branch 'stleary:master' into Issue_682_JSONString_similarity 2022-08-20 07:51:30 -07:00
Sean Leary
88ca19042b Merge pull request #684 from stleary/pipeline-fix-1
pipeline-fix-1 remove v7 build from pipeline
2022-08-20 08:33:23 -05:00
stleary
b4036e6a8e pipeline-fix-1 remove v7 build from pipeline 2022-08-13 12:50:10 -05:00
Scott Paffrath
89f16ad0af Issue 682 JSONString similarity 2022-08-05 11:00:33 -07:00
Sean Leary
6f92a3ab4e Merge pull request #675 from johnjaylward/Iss-649-better-error-message
Updates value error messages to be consistent.
2022-03-24 20:32:31 -05:00
John J. Aylward
beae279b21 Updates tests to have updated message expectations 2022-03-21 13:06:19 -04:00
John J. Aylward
a642329314 Updates value error messages to be consistent.
Provide both the type and value that failed conversion. Tries not to
"toString" large value types like Arrays or Maps. For those types it
will just output the type and not a value.
2022-03-21 12:48:25 -04:00
Sean Leary
9abb35ad39 Update RELEASES.md 2022-03-20 09:34:12 -05:00
Sean Leary
c0a1d5f741 Update pom.xml 2022-03-20 09:28:19 -05:00
Sean Leary
04a765647e Update README.md 2022-03-20 09:27:38 -05:00
Sean Leary
4f78ec666a Update RELEASES.md 2022-03-20 09:25:53 -05:00
Sean Leary
7d6b76de37 Merge pull request #608 from artem-smotrakov/setup-codeql-scans
Include CodeQL scan in the commit checks
2022-02-06 12:19:41 -06:00
Sean Leary
5cfe216ffd Update codeql-analysis.yml
...
2022-02-04 08:08:41 -06:00
Sean Leary
c33ad9c062 Merge pull request #660 from johnjaylward/Issue654StackOverflowError
Wrap StackOverflow with JSONException to fix Issue #654
2022-01-31 08:54:53 -06:00
John J. Aylward
7a124d857d Add test cases for invalid input 2022-01-26 12:19:53 -05:00
Sean Leary
f1b0210b8a Update README.md 2021-12-05 10:36:03 -06:00
Sean Leary
8ef8e1463d Update pom.xml 2021-12-05 09:12:55 -06:00
Sean Leary
48b6aa3e4c Update RELEASES.md 2021-12-05 09:10:32 -06:00
Sean Leary
cff5cc6c74 Merge pull request #646 from Zetmas/feature/issue#595
XMLParserConfiguration support for xml to json arrays
2021-12-03 19:37:00 -06:00
Sean Leary
04e8ea84dc Merge pull request #651 from cushon/i650
Use IdentityHashSet for cycle detection
2021-12-03 19:35:26 -06:00
Liam Miller-Cushon
812955e39d Use IdentityHashSet for cycle detection
Fixes https://github.com/stleary/JSON-java/issues/650
2021-11-26 20:07:21 -05:00
Sean Leary
bc623e36d6 Merge pull request #645 from Zetmas/feature/issue#632
Detect and handle circular references when parsing Java beans
2021-11-21 11:31:48 -06:00
Zach
5dd78bc0b9 Test case passed with tags with multiple entries set forceList 2021-11-19 21:22:38 -06:00
Zach
e638955034 Pass test case for empty tag with forceList 2021-11-19 21:05:05 -06:00
Zach
3f9b53fee4 longer forcelist tests 2021-11-19 20:55:10 -06:00
Zach
a0f90b776d Passed simple test 2021-11-19 20:46:15 -06:00
Zach
fafaeb7aa6 Added simple test case 2021-11-19 20:32:36 -06:00
Zach
e356739a2f Added forceList configuration to XMLParserConfiguration 2021-11-19 19:42:00 -06:00
Zach
fca7e17b38 Added test cases for self recursion and complex but no recursion 2021-11-18 14:53:22 -06:00
Zach
fb96e870a9 add test case and modified old ones 2021-11-17 20:00:12 -06:00
Zach
638273af7a long circle test 2021-11-17 19:41:00 -06:00
Zach
1ffcf3915c successful test 2021-11-17 19:35:53 -06:00
Zach
4565bddcbb data class for recursive test 2021-11-17 17:23:40 -06:00
Zach
b5bcb68968 added set check logic 2021-11-17 16:57:41 -06:00
Zach
7823d3a4f3 locate the pace for cyclic check 2021-11-17 15:28:01 -06:00
Sean Leary
d6227c83d7 Merge pull request #640 from katldewitt/561-backslashes
Address #561: Add unit tests for multiple backslashes
2021-11-02 11:44:49 -05:00
Sean Leary
f54b5e4b0d Merge pull request #626 from loic5/patch-1
Create CODE_OF_CONDUCT.md
2021-10-29 15:49:43 -05:00
LoĂŻc Lengrand
30b3680050 Update CODE_OF_CONDUCT.md
I replaced the email address
2021-10-29 09:38:19 +02:00
katldewitt
3ed9154f63 fix: refactor tests
context: the backslash unit tests cannot be in the complete document as uriFragmentNotationRoot() will fail due to backslash handling
2021-10-28 05:59:22 -07:00
katldewitt
669316d29e chore: write unit tests for behavior 2021-10-28 05:45:23 -07:00
katldewitt
30a70c8886 chore: initial unit tests 2021-10-24 08:41:57 -07:00
Sean Leary
93f4b34890 Merge pull request #637 from Ronqn/master
Reorganized README.md
2021-10-17 20:44:46 -05:00
Ronqn
9c87d6e214 Updated README.md 2021-10-16 16:43:10 +02:00
Ronqn
f27e5fe04d Docs folder containing the contributions files 2021-10-16 16:42:55 +02:00
Sean Leary
2528e60b09 Merge pull request #634 from JanitSri/update-README
updated the README to include commands for Unix systems
2021-10-16 09:17:45 -05:00
Sean Leary
4e601fd46e Merge pull request #631 from sreekesh93/techdebt/refactor-test
Refactor JSONPointerTest
2021-10-14 16:58:45 -05:00
Janit Sriganeshaelankovan
9f19c22b77 updated the README to include commands for Unix systems 2021-10-14 16:43:30 -04:00
sreekesh93
9000901a11 Fix test to support oreder mismatch 2021-10-11 19:55:31 +05:30
sreekesh93
f03eb56071 Fix test to support oreder mismatch 2021-10-11 19:46:27 +05:30
sreekesh93
b4bbc58644 Refactor JSONPointerTest 2021-10-11 10:42:31 +05:30
Sean Leary
cf43419015 Update pipeline.yml
replace hardcoded Ubuntu version with "Ubuntu-latest"
2021-10-09 10:14:47 -05:00
LoĂŻc Lengrand
e896497602 Create CODE_OF_CONDUCT.md
hello i propose to create a Code of conduct :)
2021-10-08 16:35:55 +02:00
Sean Leary
d284c81e16 Update README.md 2021-10-05 21:01:55 -05:00
Sean Leary
a526b41b67 Create CONTRIBUTING.md 2021-10-05 20:56:25 -05:00
Sean Leary
9f07853f19 Merge pull request #622 from pedrombmachado/patch-1
Update README.md
2021-08-28 15:38:21 -05:00
Pedro Machado
e29c541353 Update README.md
corrected the backward slash into forwarding slash
2021-08-28 21:28:31 +01:00
Sean Leary
de5f768cff Merge pull request #621 from cushon/typos
Fix some typos
2021-08-25 20:10:30 -05:00
Liam Miller-Cushon
8ca8a80753 Fix some typos 2021-08-25 13:56:44 -07:00
Sean Leary
fb71d9d40f Merge pull request #606 from artem-smotrakov/fix-javadoc
Fix javadoc
2021-08-17 20:40:04 -05:00
Sean Leary
b80141a19c Merge pull request #607 from artem-smotrakov/add-security-policy
Added a security policy
2021-08-14 15:02:05 -05:00
Sean Leary
c0e467c848 Merge pull request #613 from stleary/fix-similar-check
Fixes Issue #611 JsonObject.similar() returns after number entry check
2021-07-26 18:12:44 -05:00
stleary
8680b10716 merge from master to pick up #616 and add one more test 2021-07-26 18:07:38 -05:00
stleary
2559114dbb Merge branch 'master' into fix-similar-check 2021-07-26 17:53:20 -05:00
Sean Leary
bb048e3ffb Merge pull request #617 from johnjaylward/issue-616-similar-bug
Fixes #616 similar() problem comparing double vs BigDecimal
2021-07-26 17:47:03 -05:00
John Aylward
579784d73e correct error in converting doubles to big decimals 2021-07-22 23:46:31 -04:00
John Aylward
c03054b1a6 Add test to show bug 2021-07-22 22:57:15 -04:00
John Aylward
4e0faebe62 fix javadoc errors that prevent compilation in Eclipse 2021-07-22 22:54:46 -04:00
stleary
c6089e53f5 Fixes Issue #611 JsonArray.similar() returns after number entry check 2021-07-18 19:53:23 -05:00
stleary
cfbc306673 Fixes Issue #611 JsonObject.similar() returns after number entry check 2021-07-18 10:32:49 -05:00
Sean Leary
449ec8745e Merge pull request #610 from tilds/optJSONObject-defaultValue
New JSONObject.optJSONObject method with defaultValue parameter
2021-06-28 22:01:37 -05:00
Niels Frederiksen
f91d0c8a52 New JSONObject.optJSONObject method with defaultValue parameter 2021-06-23 15:15:00 +02:00
stleary
4571978840 Merge branch 'master' of https://github.com/stleary/JSON-java 2021-06-22 19:46:44 -05:00
stleary
76ec2fe5a2 Revert accidentally changed file 2021-06-22 19:46:33 -05:00
Sean Leary
0200c984cc Update README.md 2021-06-22 19:41:31 -05:00
stleary
8f3e5ade18 Add logo image 2021-06-22 19:34:22 -05:00
Artem Smotrakov
20b4f85efe Updated build command in the CodeQL workflow 2021-05-31 15:30:20 +02:00
Artem Smotrakov
5bc8dae5d0 Setup CodeQL scans 2021-05-31 15:24:41 +02:00
Artem Smotrakov
8fa9be742c Added a security policy 2021-05-31 15:16:27 +02:00
Artem Smotrakov
b48abe6558 Suppress java/unchecked-cast-in-equals warning for JSONObject.Null.equals() 2021-05-31 15:00:29 +02:00
Artem Smotrakov
97023e1098 Fix Javadoc formatting in JSONObject and XMLParserConfiguration 2021-05-31 14:53:59 +02:00
Sean Leary
143db39d27 Merge pull request #604 from ianlovejoy/master
Fixed incorrect cast getting float from array
2021-05-01 08:50:54 -05:00
Ian Lovejoy
75894086e5 Fixed incorrect cast getting float from array
Added test for getting float from array
2021-04-27 19:03:35 -07:00
Sean Leary
fa46da45f4 Merge pull request #601 from AISS-2021-L5-G02/master
Added some examples for new-comers in a Markdown file
2021-04-21 00:31:12 -05:00
TheNeoStormZ
f912e5d1c4 Merge pull request #2 from TheNeoStormZ/master
Changed JSONExamples to a Markdown file (and another place) with mino…
2021-04-02 19:31:42 +02:00
Pablo MarĂ­n GĂłmez
6bf3d38889 Changed JSONExamples to a Markdown file (and another place) with minor tweaks 2021-04-02 19:28:37 +02:00
TheNeoStormZ
c62df81b3e Merge pull request #1 from TheNeoStormZ/master
Added some examples for new-comers
2021-04-02 11:28:25 +02:00
Pablo MarĂ­n GĂłmez
e1f69ff3fe Added some examples for new-comers 2021-04-02 11:25:57 +02:00
Sean Leary
50d619698f Merge pull request #594 from anton0xf/patch-1
JSONStringer.java: fix max nesting level in javadoc
2021-03-18 19:42:49 -05:00
anton0xf
29103e3228 JSONStringer.java: fix max nesting level in javadoc 2021-03-14 22:45:38 +05:00
Sean Leary
2630676f36 Update README.md 2021-03-09 19:54:54 -06:00
Sean Leary
7299b201f4 Update pom.xml 2021-03-07 21:11:48 -06:00
Sean Leary
8cc1e9830d Update README.md 2021-03-07 21:09:01 -06:00
Sean Leary
c43e21ae73 Merge pull request #588 from fossterer/563-jsonpointer-do-not-encode-quotes
JSONPointer should not process reverse solidus or double-quote chars in tokens
2021-03-06 10:00:32 -06:00
Shashank Sabniveesu
d6ccc64c79 Closes 563: As never defined in RFC 6901 Section 3, do not handle backslashes (\) and quotes(") as anything special 2021-02-28 16:03:14 -05:00
Sean Leary
7844eb79cd Merge pull request #583 from ek08/fix
Checked the length of key for checker framework
2021-02-01 19:48:06 -06:00
Ehtesham
5b531faa49 Improved the logic for checking the length of key 2021-01-28 15:31:23 +05:30
Ehtesham
31ff8a2291 Checked the length of key for checker framework 2021-01-27 11:35:38 +05:30
Sean Leary
e33f463179 Merge pull request #581 from valfirst/patch-1
Use built-in Gradle shorthand notation for Maven Central repository
2021-01-10 18:35:31 -06:00
Valery Yatsynovich
e77a77e841 Use built-in Gradle shorthand notation for Maven Central repository 2020-12-29 14:16:46 +03:00
Sean Leary
26f48484fd Merge pull request #577 from stranck/master
Added clear() methods to JSONObject and JSONArray
2020-12-07 16:54:18 -06:00
Stranck
efad1d73a7 Added UnitTests
(I hope they works :c)
2020-12-04 04:09:19 +01:00
Stranck
c7130d577a Oops 2020-12-04 01:09:18 +01:00
Stranck
d85eea53bb Update JSONArray.java 2020-12-04 01:07:29 +01:00
Stranck
57ad94ef5e Added clear() methods to JSONObject and JSONArray 2020-12-04 00:49:21 +01:00
Sean Leary
a57eff26d5 Merge pull request #575 from johnjaylward/fix-similar-compare-numbers
Fix similar compare numbers
2020-11-22 15:23:03 -06:00
John J. Aylward
68883b9ff8 update number handling to use new helper method for consistency. 2020-11-19 19:10:08 -05:00
John J. Aylward
11e6b1af7e fixes issue #573 by added specific compare of numeric types 2020-11-19 18:55:49 -05:00
John J. Aylward
e4b76d6588 Add test to demonstrate the issue. See #573 2020-11-19 18:18:27 -05:00
John J. Aylward
3a8193bea4 upgrade junit version 2020-11-19 18:18:02 -05:00
Sean Leary
6bf2692a94 Update README.md 2020-11-15 16:09:50 -06:00
Sean Leary
fdde43cd3b Update README.md 2020-11-15 12:48:51 -06:00
Sean Leary
6b779f8ca7 Merge pull request #570 from stleary/update-readme
Readme - fix spelling and usage, per Grammarly
2020-10-23 23:05:38 -05:00
stleary
59b7a7adff fix spelling and usage, per Grammarly 2020-10-16 08:58:04 -05:00
Sean Leary
7abd89b4bc Merge pull request #540 from kumar529/master
Added type conversion support
2020-09-17 07:37:31 -05:00
Rahul Kumar
56d4130a86 Added shallow copy for config map 2020-09-06 11:17:10 +05:30
Rahul Kumar
ed9658d5cb Corrected Javadoc 2020-09-04 16:51:55 +05:30
Rahul Kumar
310f18fcdc Addressed comment 2020-09-03 11:17:10 +05:30
Rahul Kumar
900a8cc945 Removed changes from depricated method 2020-08-06 07:29:32 +05:30
Rahul Kumar
0a8091c954 Added documentation 2020-08-05 22:25:45 +05:30
Rahul Kumar
61c1a882d6 Added configuration support for type conversion using Map 2020-08-03 08:54:59 +05:30
Rahul Kumar
250f74ef4d Added type conversion support 2020-08-03 08:18:20 +05:30
Sean Leary
5541a6d91d Merge pull request #552 from johnjaylward/JSONArrayCopyConstructor
Updates for JSONArray.putAll methods
2020-08-01 09:19:29 -05:00
John J. Aylward
d30ecad7f8 Update README for best practices when using putAll on JSONArray 2020-07-30 10:13:01 -04:00
John J. Aylward
f35194bc1d Updates the addAll methods to have optional wrapping.
When called from the constructor, the individual items in the
collection/array are wrapped as done originally before the `putAll`
methods were added.

However this commit changes how `putAll` works. The items are no longer
wrapped in order to keep consistency with the other `put` methods.

However this can lead to inconsistencies with expectations. For example
code like this will create a mixed JSONArray, some items wrapped, others
not:

```java
SomeBean[] myArr = new SomeBean[]{ new SomeBean(1), new SomeBean(2) };
JSONArray jArr = new JSONArray(myArr); // these will be wrapped
// these will not be wrapped
jArr.putAll(new SomeBean[]{ new SomeBean(3), new SomeBean(4) });
```

For consistency, it would be recommended that the above code is changed
to look like 1 of 2 ways.

Option 1:
```Java
SomeBean[] myArr = new SomeBean[]{ new SomeBean(1), new SomeBean(2) };
JSONArray jArr = new JSONArray();
jArr.putAll(myArr); // will not be wrapped
// these will not be wrapped
jArr.putAll(new SomeBean[]{ new SomeBean(3), new SomeBean(4) });
// our jArr is now consistent.
```

Option 2:
```Java
SomeBean[] myArr = new SomeBean[]{ new SomeBean(1), new SomeBean(2) };
JSONArray jArr = new JSONArray(myArr); // these will be wrapped
// these will be wrapped
jArr.putAll(new JSONArray(new SomeBean[]{ new SomeBean(3), new
SomeBean(4) }));
// our jArr is now consistent.
```
2020-07-30 10:10:06 -04:00
John J. Aylward
5d828d2c0b update comments and increase speed of merging JSONArray objects 2020-07-30 10:10:06 -04:00
John J. Aylward
c175a9eb62 remove clone 2020-07-30 10:10:06 -04:00
John J. Aylward
3c9573cc3d update some javadoc 2020-07-30 10:10:06 -04:00
John J. Aylward
f37c2d67c5 Update for JSONArray.putAll methods
* Adds a copy constructor for JSONArray
* Updates the JSONArray.addAll(Object) method to be more lenient
* Adds support for JSONArray.putAll of generic Iterables
* Adds support for JSONArray.putAll of another JSONArray
2020-07-30 10:10:06 -04:00
Sean Leary
6351fa63aa Merge pull request #549 from stleary/rewrite-readme
Update readme.md
2020-07-28 23:48:01 -05:00
Sean Leary
870fa03a19 Merge pull request #529 from ethauvin/master
Added putAll(Collection) and putAll(Array) methods.
2020-07-25 12:45:44 -05:00
Sean Leary
555f712a8c Update README.md 2020-07-25 12:41:03 -05:00
Sean Leary
db2d1714de Update README.md 2020-07-25 12:40:41 -05:00
Sean Leary
650f52501a Update README.md 2020-07-25 12:36:53 -05:00
Sean Leary
896674ae36 Update README.md 2020-07-25 12:35:58 -05:00
Sean Leary
8f0c3b0bf8 Update README.md 2020-07-25 12:35:12 -05:00
Sean Leary
0de8d0d2e0 Update README.md 2020-07-25 12:34:01 -05:00
Sean Leary
46fe58e912 Update README.md 2020-07-25 12:31:20 -05:00
Sean Leary
26cd17687f Update README.md 2020-07-25 12:31:02 -05:00
stleary
879fba3f7f rewrite - first commit 2020-07-25 12:27:20 -05:00
stleary
98cd8ef8b2 fix CI build error 2020-07-24 03:24:41 -05:00
Sean Leary
78528102d0 Merge pull request #543 from johnjaylward/RefactorXmlConfiguration
Refactor XMLConfiguration to use Builder Pattern
2020-07-24 02:49:28 -05:00
Sean Leary
0e34d8d383 Merge pull request #539 from stleary/unit-tests-1.6
Bring Junit tests to Java 1.6 compatibility
2020-07-24 02:48:38 -05:00
Sean Leary
880402120c Merge pull request #542 from johnjaylward/fixXmlHexEntityParse
Fix xml hex entity parse
2020-07-23 11:02:14 -05:00
Sean Leary
d10725dc92 Merge pull request #538 from stleary/readme-local-build
Explain local builds in the readme, fix a couple of typos
2020-07-23 11:00:25 -05:00
Erik C. Thauvin
0d13e56064 Added tests for consecutive calls to putAll. 2020-07-21 23:09:28 -07:00
Erik C. Thauvin
f1d354ce7b Increase array list capacity in addAll(collection) method to ensure it can hold additional elements. 2020-07-21 17:35:32 -07:00
Erik C. Thauvin
86e136afc9 Increase array list capacity in addAll method to ensure it can hold additional elements. 2020-07-21 17:11:24 -07:00
John J. Aylward
4f1c8b2d6f formatting 2020-07-21 11:30:35 -04:00
John J. Aylward
5a31f9ef5f Refs #541
Updates XML configuration to use a builder pattern instead of
constructors with many parameters
2020-07-21 11:08:40 -04:00
John J. Aylward
c136668f23 remove new lines from test file text blocks to prevent issues with the
parsing compare on different operating systems
2020-07-20 18:58:00 -04:00
John J. Aylward
e18f42becc fixes #537 corrects case-sensitive entity unescape 2020-07-20 18:38:35 -04:00
John J. Aylward
e0a6c2ef34 refs #537 Show error when unescaping all-caps entity directly 2020-07-20 18:36:52 -04:00
John J. Aylward
c98da43184 Refs #537 Add test cases to verify no issue 2020-07-20 18:25:51 -04:00
John J. Aylward
734f182242 Update error messages to use the built in assertEquals 2020-07-20 18:25:22 -04:00
stleary
c63e78bbc7 initial commit 2020-07-18 17:14:39 -05:00
stleary
db6ca7fbf3 even more formatting 2020-07-18 13:11:13 -05:00
stleary
9a3e7dd7c4 more formatting 2020-07-18 13:08:38 -05:00
stleary
79ff79ed70 initial commit 2020-07-18 13:05:55 -05:00
stleary
d14c7b9127 formatting 2020-07-18 13:02:51 -05:00
stleary
de4395dc5e initial commit 2020-07-18 12:59:34 -05:00
Sean Leary
6ddaa13c1e Merge pull request #532 from johnjaylward/CheckBigDecimalSupport
Verifies BigDecimal support does not have a regression
2020-06-25 17:02:18 -05:00
John J. Aylward
f9908a6adb adds comment on test case to document why it was added. 2020-06-25 11:51:46 -04:00
John J. Aylward
ba6c4089ea fixes #531
Add test result to confirm that #531 is working in latest version.
2020-06-25 11:42:07 -04:00
Erik C. Thauvin
aa0a5a7245 Added putAll(Collection) and putAll(Array) methods. 2020-06-16 14:55:16 -07:00
Sean Leary
9de97438ac Merge pull request #524 from viveksacademia4git/i516-JSONArray-ConstructParam-InitCapacity
Development for stleary#516 completed with rebased repository
2020-06-12 10:48:21 -05:00
Sean Leary
601114ee29 Merge pull request #527 from johnjaylward/GithubAction
Fixes for Unit tests and supports GitHub Actions
2020-06-05 18:39:48 -05:00
John J. Aylward
c11c006e88 fix tests to not depend on HashSet key order 2020-06-05 19:09:10 -04:00
John J. Aylward
96bf788515 update pipline to use matrix configuration 2020-06-05 18:55:48 -04:00
viveksacademia4git
f4261add91 Create pipeline.yml 2020-06-05 17:15:55 -04:00
Sean Leary
dced1b4a44 Merge pull request #526 from stleary/broken-unit-tests
comment out some broken unit tests
2020-06-03 21:25:50 -05:00
stleary
cf00d2f265 initial commit 2020-06-03 21:12:19 -05:00
Sean Leary
95c6373122 Merge pull request #525 from johnjaylward/unitTestFixes
Unit test fixes
2020-06-03 19:49:06 -05:00
John J. Aylward
b6ed0d4178 fix failing test case in Java1.7 2020-06-03 19:37:08 -04:00
John J. Aylward
75f656fd07 revert changes to build.gradle 2020-06-03 17:59:04 -04:00
viveksacademia4git
4b84ba2f66 Changes to make the Gradle work
- commented `java() {...}` within build.gradle
- added following files
   1. gradlew
   2. gradlew.bat (for windows)
   3. gradle/wrapper/gradle-wrapper.properties (for ./gradlew command execution)
   4. gradle/wrapper/gradle-wrapper.jar (for ./gradlew command execution)
2020-06-03 12:14:45 -04:00
vivek
d088cf014e Development for stleary#516 completed with rebased repository
- Introduced JSONObject(int) constructor.
   - int > Initial capacity of the underlying data structure

- Test for new introduced JSONArray(int) constructor.
   1. Checked with input parameter: 0
   2. Checked with input parameter: positive number
   3. Checked with positive number input parameter and compared length
   4. If input parameter is negative number JSONException is thrown:
         JSONArray initial capacity cannot be negative.
2020-06-03 11:46:48 +02:00
Sean Leary
19bb6fd606 Merge pull request #453 from johnjaylward/UseBigDecimalDefaultParse
changes number parsing to use BigDecimal as the backing type
2020-06-01 14:03:04 -05:00
Sean Leary
fee6ddb922 Merge pull request #521 from johnjaylward/CookieFlagSupport
Updates Cookie class to be more generic in attribute parsing and emit.
2020-05-29 09:59:27 -05:00
Sean Leary
5a32114792 Unified license for both src and test
All code in the project is covered by the original license
2020-05-27 08:23:09 -05:00
John J. Aylward
56d33b8061 changes number parsing to use BigDecimal as the backing type
* updated tests to support BigDecimal as the backing type for numbers
* updated some test resource handling to java7 try-with-resources format
* cleaned up some other minor compiler warnings
2020-05-26 10:10:36 -04:00
John J. Aylward
6029dece41 ensure key names are consistent when parsing the cookie string since
cookie-keys are not case sensitive, but json-keys are.
2020-05-26 09:11:10 -04:00
John J. Aylward
d334b58f45 Made more corrections to Cookie.ToString.
1. Made Cookie Name and Value properties case insensitive
2. Throws exception on illegal Cookie Name
3. Doesn't emit "false" flag values
4. Properly escape key-value attributes.
2020-05-26 08:55:19 -04:00
John J. Aylward
b4a75c7bf8 Updates Cookie class to be a more generic in attribute parsing and emit.
This is so the library can age better as new attributes are added to RFC
revisions.
2020-05-26 08:53:37 -04:00
Sean Leary
956bdfa5b7 Merge pull request #519 from stleary/gradle-support
Gradle support
2020-05-23 10:20:32 -05:00
stleary
8546e68e20 update readme 2020-05-22 11:44:21 -05:00
stleary
0832d1d873 gradle support 2020-05-22 11:24:20 -05:00
stleary
2b0a8838ef gradle support 2020-05-22 11:17:44 -05:00
Sean Leary
1da2b984cd Update README.md 2020-05-22 10:50:04 -05:00
Sean Leary
78901383a4 Update README.md 2020-05-22 10:41:55 -05:00
Sean Leary
3737c987a2 Merge pull request #515 from BGehrels/merge-tests-and-pom-and-code
Merge tests and pom and code
2020-05-22 10:40:48 -05:00
Benjamin Gehrels
82202dbf65 Added Jar plugin version to get rid of a warning 2020-04-30 12:23:39 +02:00
Benjamin Gehrels
89d4681e41 Added information on how to release to the pom 2020-04-29 21:02:52 +02:00
Benjamin Gehrels
1265897f4e Merge remote-tracking branch 'tests/master' into upstream 2020-04-29 20:26:05 +02:00
Benjamin Gehrels
74e4932cfc Transform the repository into standard maven format and merge the pom.xml of the release repo 2020-04-29 19:24:44 +02:00
Sean Leary
f07ddd93e5 Merge pull request #96 from Alanscut/bean-test
improve the confused assert message
2019-12-30 12:31:58 -06:00
Alan Wang
08719d4b3a Apply suggestions from code review
Co-Authored-By: Sean Leary <stleary@gmail.com>
2019-12-30 09:51:08 +08:00
Alanscut
16da56eb34 improve the confused assert message 2019-12-28 17:53:27 +08:00
Sean Leary
18eddf75c3 Merge pull request #95 from johnjaylward/StandardizeExceptionMessages
Test cases updates for standardized exception messages
2019-09-24 20:30:08 -05:00
Sean Leary
b8fd9d0082 Merge pull request #94 from johnjaylward/FixMLInfiniteLoop
new test case for issue 484
2019-09-23 17:57:16 -05:00
John J. Aylward
a24db2cce2 remove unused import 2019-09-17 11:15:25 -04:00
John J. Aylward
67e59888a2 add second case for data in #484 2019-09-17 11:14:41 -04:00
John J. Aylward
fb01575394 Test cases updates for standardized exception messages 2019-09-17 10:47:16 -04:00
John J. Aylward
3e7a0b13d1 new test case for issue 484 2019-09-17 10:36:48 -04:00
Sean Leary
6dcd82a72f Merge pull request #93 from meiskalt7/xsiNilToNull
add test for xsi:nil to null conversion
2019-04-22 08:34:15 -05:00
meiskalt7
fa173fa51a add test for xsi:nil to null conversion disabled 2019-04-21 00:53:39 +07:00
meiskalt7
614e8359b9 add test for xsi:nil to null conversion 2019-04-18 21:42:57 +07:00
Sean Leary
437ce10ee3 Merge pull request #91 from johnjaylward/FixEOF
Tests for https://github.com/stleary/JSON-java/pull/452
2018-12-13 09:14:39 -06:00
Sean Leary
cfec288fe8 Merge pull request #90 from stleary/tests-for-xml-config
xml parser config tests
2018-12-11 07:27:04 -06:00
John J. Aylward
e7f7d348cd * updates tests to cover more cases of tokenizing
* uncomments tests that should now work
2018-12-10 11:45:10 -05:00
Sean Leary
e699abb1c6 Merge pull request #61 from johnjaylward/XmlEscape
Test cases Xml escapes
2018-12-08 20:09:03 -06:00
stleary
d0ea807884 xml parser config tests 2018-12-08 14:51:01 -06:00
Sean Leary
0d053a000d Merge pull request #89 from stleary/update-timeNumberParsing-iterations
reduce number of iterations to shorten test time
2018-12-08 11:31:38 -06:00
stleary
e4186e072a reduce number of iterations to shorten test time 2018-12-08 11:29:44 -06:00
Sean Leary
4c64ad3d8a Merge pull request #88 from johnjaylward/FixForBigDecimal
Updated testcases for PR440
2018-10-06 14:52:13 -05:00
John J. Aylward
3e6c0a51bd update expected exception text in tests to match unified number getters 2018-10-04 16:02:50 -04:00
John J. Aylward
3b8b0a681c Update test cases to verify performance change and verify opt/getBigDecimal match 2018-10-02 12:38:17 -04:00
Sean Leary
dedb044f67 Merge pull request #86 from strkkk/add-isEmpty-method-usage
add usage of isEmpty method
2018-05-26 09:55:41 -05:00
Andrei Paikin
d00501eabd add usage of isEmpty method 2018-05-25 22:47:05 +03:00
Sean Leary
20d90bfb0b Merge pull request #85 from johnjaylward/JSONPointerTrailingSlash
Test cases for issue described in Issue 410
2018-03-27 07:45:17 -05:00
John J. Aylward
3fe4a767e6 Fixes incorrect syntax for JSONPointer in test. 2018-03-20 22:15:25 -04:00
John J. Aylward
43f3f5e80b Add another test 2018-03-19 09:49:42 -04:00
John J. Aylward
f4201cf318 Test cases for issue described in https://github.com/stleary/JSON-java/issues/410. 2018-03-19 09:34:13 -04:00
Sean Leary
770cb9c4e5 Merge pull request #84 from johnjaylward/FixBeanKeyNameing
New test cases for Bean Name customization
2018-03-14 21:19:11 -05:00
Sean Leary
37f1f4c8ca Merge pull request #83 from johnjaylward/FixNPE
add test cases for null keys
2018-03-11 15:59:21 -05:00
John J. Aylward
193a3823b5 new test cases to support bean annotation 2018-03-11 16:56:07 -04:00
John J. Aylward
aa5e80bc8d add test cases for null keys 2018-03-07 12:11:17 -05:00
Sean Leary
fc881e2631 Merge pull request #82 from billdeng/master
Correct the message to match the function
2018-02-02 23:56:36 -06:00
dengjianbao
cc2ed79e57 Correct the message to match the function 2018-02-02 22:54:08 +08:00
Sean Leary
77d142d494 Merge pull request #81 from johnjaylward/FixFalsePositiveSimilar
Test cases to verify Similar methods
2017-11-11 16:12:26 -06:00
John J. Aylward
dae88d7c5c fix method names 2017-11-06 10:35:49 -05:00
John J. Aylward
08d93f3eb5 test cases for issue https://github.com/stleary/JSON-java/issues/379 2017-11-06 10:27:45 -05:00
Sean Leary
bf26eba0d2 Merge pull request #80 from johnjaylward/UnclosedJSONArray
New test to verify unclosed array
2017-11-02 20:03:00 -05:00
Sean Leary
936db93445 Update README.md 2017-10-30 08:46:43 -05:00
Sean Leary
e0801befe5 Update README.md 2017-10-30 08:45:41 -05:00
Sean Leary
ee3aa03da1 Update README.md 2017-10-30 08:44:21 -05:00
Sean Leary
578a442ef7 Update README.md 2017-10-30 08:43:56 -05:00
John J. Aylward
dfa37a298f Add more tests for unclosed arrays 2017-10-30 08:53:50 -04:00
John J. Aylward
bde6ba1c52 Updates exception expected message 2017-10-30 08:53:50 -04:00
John J. Aylward
52ecc89702 New test to verify unclosed array 2017-10-30 08:53:50 -04:00
Sean Leary
af3b7dc443 Merge pull request #79 from johnjaylward/FixXMLUnescape
New tests for XML unescaping
2017-08-27 10:59:36 -05:00
John J. Aylward
2713f2e2a4 Adds testing for unicode entities 2017-08-19 18:45:53 -04:00
John J. Aylward
cb61bbf720 New tests for XML unescaping 2017-08-19 18:19:22 -04:00
Sean Leary
d0e2cf41a3 Merge pull request #78 from migueltt/tokener-error-message
Unit tests for constructor JSONObject(JSONTokener)
2017-08-17 21:29:13 -05:00
Miguel
b90bee0f22 Update error message location (+1)
`JSONTokener.back()` call removed from `JSONObject(JSONTokener)` constructor.
2017-08-14 13:05:23 -04:00
Miguel
68b262914d JSONObject(JSONTokener) now points to last character of duplicate key
Updating exception message accordingly (position -1)
2017-08-10 19:06:55 -04:00
Miguel
c365e2a774 Remov slf4j reference 2017-08-09 22:03:09 -04:00
Miguel
df466db7b9 Replacing tabs with 4 spaces 2017-08-09 21:59:08 -04:00
Miguel
1acb18091a Remove System.out.println 2017-08-09 21:57:10 -04:00
Miguel
fefd616d73 Unit tests for JSONTokener 2017-08-09 21:51:46 -04:00
Sean Leary
44c3e321b5 Merge pull request #77 from johnjaylward/FixJUnitGradleConfig
Fixes Gradle config so tests are only run once
2017-07-20 06:51:14 -05:00
John J. Aylward
f2f6ad3b1f * Fixes Gradle config so tests are only run once
* Adds missing test to the test suite
2017-07-19 20:34:59 -04:00
Sean Leary
cf411b3187 Merge pull request #75 from johnjaylward/PopulateMapMoreStrict
Populate map more strict
2017-07-19 18:57:55 -05:00
Sean Leary
1aeadd1765 Merge pull request #76 from johnjaylward/WriteJavadocUpdate
Update test for issue https://github.com/stleary/JSON-java/issues/356
2017-07-15 18:46:58 -05:00
John J. Aylward
aa562b5ec3 Update test for issue https://github.com/stleary/JSON-java/issues/356 2017-07-15 12:19:02 -04:00
John J. Aylward
38d11227ee Adds exception tests 2017-07-09 19:05:00 -04:00
John J. Aylward
e94783f91b Updates javadocs 2017-07-09 18:19:27 -04:00
John J. Aylward
7bc8f41023 Add override of the generic getter to generate a Bridge method. 2017-07-09 18:10:09 -04:00
John J. Aylward
49117f33dc Adds new tests for testing bean->JSONObject mapping 2017-07-09 17:57:46 -04:00
John J. Aylward
0e3f23d7a1 reorganize classes so test data is separate from test cases 2017-07-09 16:48:01 -04:00
Sean Leary
974a5f7d5d Merge pull request #74 from johnjaylward/AndroidSupport
Correct expected position information in error messages
2017-07-06 18:08:20 -05:00
John J. Aylward
899cf528df More test cases for position information 2017-06-24 13:10:14 -04:00
John J. Aylward
47ff774f5c Updates test coverage table 2017-06-23 23:55:22 -04:00
John J. Aylward
af39376d92 more fixes for testing postition information 2017-06-23 23:25:11 -04:00
John J. Aylward
0e612ba8a4 More test corrections for correct position reports in error messages 2017-06-21 19:56:00 -04:00
John J. Aylward
971614ac8b fix expected exception message 2017-06-21 18:28:04 -04:00
John J. Aylward
3081b4bd96 Fixes for failing tests due to android integration 2017-06-21 14:59:42 -04:00
Sean Leary
441fec7498 Merge pull request #73 from johnjaylward/BetterErrorHandling
Updates tests for better error handling changes
2017-06-11 14:12:56 -05:00
John J. Aylward
c5e4b91fa4 Updates tests for better error handling changes 2017-06-08 02:25:59 -04:00
Sean Leary
93ca7b176f Merge pull request #71 from johnjaylward/OptimizeOpt
Adjustments to tests for https://github.com/stleary/JSON-java/pull/337
2017-05-22 22:59:37 -05:00
Sean Leary
f5d3086c55 Merge pull request #70 from johnjaylward/fixSpelling
test support for Numeric enhancements, Refactoring, Fix spelling:  stleary/JSON-java/pull/336
2017-05-20 12:37:58 -05:00
John J. Aylward
04d76b638b split out tests for better readability 2017-05-19 15:01:37 -04:00
John J. Aylward
cfe6851d8c Adds testing for -0 with optNumber 2017-05-18 14:25:42 -04:00
John J. Aylward
1967bee236 expands the coercion tests a little more 2017-05-18 12:11:43 -04:00
John J. Aylward
0150639119 update the new coercion test to use actual values and show the parseDouble method is not robust enough for large numbers 2017-05-18 11:58:28 -04:00
John J. Aylward
bdb1163445 Adds conversion tests to ensure downward type coercions are handled sanely 2017-05-18 11:38:42 -04:00
John J. Aylward
2867aaa8c8 Updates test cases to support new optFloat and optNumber 2017-05-17 12:33:59 -04:00
John J. Aylward
49d47e3ff2 Adjustments to tests for https://github.com/stleary/JSON-java/pull/337/ 2017-05-16 19:42:46 -04:00
John J. Aylward
1d040ec407 fixes errors with tests relating to https://github.com/stleary/JSON-java/pull/336 2017-05-16 18:16:07 -04:00
Sean Leary
c945b53308 Merge pull request #69 from johnjaylward/TestCleanup
Couple of the files were difficult to identify the changes, but it was worth it to add the new tests. Thanks!!!
2017-04-28 01:04:56 -05:00
John J. Aylward
c233ae709e comment out second unreliable test 2017-04-27 12:52:02 -04:00
John J. Aylward
95da4246a2 fix spelling in comment 2017-04-27 12:48:43 -04:00
John J. Aylward
9df5d34bbe * Update link in the README to the main JSON-Java repo
* Cleans up some warnings
* Adds new test for bug https://github.com/stleary/JSON-java/issues/332
* Adds some resource handling for string writers using pre-java1.7
support. I know StringWriters don't need a close method called, but the
tests should still handle their resources properly.
2017-04-27 12:39:42 -04:00
Sean Leary
f6ab6d7b27 Merge pull request #68 from stleary/jsonpointer-query
unit tests for query-by-JSONPointer
2017-03-27 20:05:05 -05:00
stleary
d1a5f15f0c unit tests for query-by-JSONPointer 2017-03-26 15:03:09 -05:00
Sean Leary
82ff14ed8d Merge pull request #66 from stleary/document-unquoted-strings
add a test for unquoted values
2017-02-26 11:10:38 -06:00
stleary
e41972a574 add a test for unquoted values 2017-02-26 11:09:41 -06:00
Sean Leary
a66abf22a8 Merge pull request #64 from stleary/locale-tests-for-non-EN-keys
Locale tests for non en keys
2017-02-19 21:34:40 -06:00
stleary
f41e1d012a tests for locale-independent keys 2017-02-16 20:49:37 -06:00
stleary
928179a1f3 locale tests 2017-02-14 08:30:22 -06:00
Sean Leary
df9c27c53f Merge pull request #62 from erosb/master
testcase for stleary/JSON-java#292
2016-10-08 10:07:53 -05:00
Bence Erős
97e3d6c7ce testcase for stleary/JSON-java#292 and adding .idea to .gitiignore 2016-10-05 14:59:36 +02:00
John J. Aylward
f6a00e94c7 adds test for unicode that has surrogate pairs 2016-09-22 16:12:00 -04:00
John J. Aylward
2b87f334d0 Update test cases to support ISO Control encoding changes. 2016-09-22 14:13:48 -04:00
John J. Aylward
5027a283c1 Adds test for escaping from a JSONObject to XML 2016-09-22 13:09:32 -04:00
John J. Aylward
c8563ff93d new test case for XML changes 2016-09-22 12:38:30 -04:00
Sean Leary
474711c4ea Merge pull request #60 from stleary/fix-number-tests
fixed merge issues
2016-09-15 21:38:36 -05:00
stleary
58aebaa14f fixed merge issues 2016-09-15 21:31:28 -05:00
Sean Leary
3570890be7 Merge pull request #57 from johnjaylward/EnumCleanup
test updates to make sure Enums are handled consistently.
2016-08-19 11:43:20 -05:00
Sean Leary
59761f6f64 Merge pull request #58 from johnjaylward/SimplifyNumberWrap
Adds tests for numbers
2016-08-17 12:12:32 -05:00
John J. Aylward
0b1dbe9369 fixes test to not depend on key order 2016-08-17 12:15:16 -04:00
John J. Aylward
a66b97f60b fix test 2016-08-17 11:31:44 -04:00
johnjaylward
cbd0418704 Update JSONObjectTest.java
fixes test to be applicable
2016-08-16 21:33:54 -04:00
John J. Aylward
bbd3fd5571 Adds tests for numbers 2016-08-16 20:52:41 -04:00
John J. Aylward
5779400f26 test updates to make sure Enums are handled consistently. 2016-08-11 12:21:49 -04:00
Sean Leary
c400de3cfe Merge pull request #53 from run2000/master
valueToString() and write() tests
2016-08-10 21:55:33 -05:00
Sean Leary
a418d07460 Merge pull request #55 from johnjaylward/verifyOptMissingKeys
Updates tests to include all opt methods and verify for missing keys.
2016-08-10 09:04:27 -05:00
John J. Aylward
8bae09f81b removes unnecessary comparison to true 2016-08-09 16:11:46 -04:00
John J. Aylward
80e36eb63c Fixes error messages 2016-08-09 15:59:27 -04:00
John J. Aylward
a2c311527b Updates tests to include all opt methods and verify for missing keys. 2016-08-09 15:54:06 -04:00
Sean Leary
62524b531d Merge pull request #52 from johnjaylward/OptionalTypeConversion
updates Test cases to support new JSONML and XML conversion options
2016-07-31 21:09:34 -05:00
run2000
e57881f8fa Fail when exceptions are not thrown as expected
The idiom was started in the first few methods, but not continued further down where JSONException was expected. False success may have resulted.
2016-07-25 09:44:43 +10:00
Nicholas Cull
efe33a1e37 Fix comment. 2016-07-24 19:57:01 +10:00
Nicholas Cull
1246e12827 Factor out Writer from Appendable tests. 2016-07-24 19:39:52 +10:00
Nicholas Cull
ffcfa66d77 Add JSONString test class.
This set of tests demonstrates what happens when JSONString returns various results from its toJSONString() method. Tests for null returns and exceptions thrown. Also tests what happens for non-JSONString objects. The intent is to cover JSONObject's valueToString() and writeValue() methods.
2016-07-24 18:56:08 +10:00
Sean Leary
5d8ea6fa4e Update README.md 2016-07-23 10:13:21 -05:00
Sean Leary
cdfdaba95b Update README.md 2016-07-23 10:12:33 -05:00
Sean Leary
2307f6f85e Update README.md 2016-07-23 10:12:04 -05:00
Sean Leary
6b4edbd40c Update README.md 2016-07-23 10:02:19 -05:00
Nicholas Cull
ae77b5cd83 Tests for deep copy and mutability of toList() and toMap().
Both toMap() and toList() return deep copies, which are also mutable. That is, any changes to the JSONObject or JSONArray do not affect the newly create Map or List, and vice-versa. The resulting objects can be altered.
2016-07-23 22:51:50 +10:00
Nicholas Cull
72c2b911bf Tests for toString(), write(), toList(), and toMap().
Explicitly test variations of toString() and write() for different indent levels, and different method overloads. Also create some tests for the new toList() and toMap() methods for coverage improvements to JSONArray and JSONObject.
2016-07-23 22:33:19 +10:00
Nicholas Cull
c3ba4bdbe5 Nesting depth test works as expected. 2016-07-23 19:12:51 +10:00
John J. Aylward
215321cd28 updates Test cases to support new JSONML and XML conversion options 2016-07-18 15:04:03 -04:00
Sean Leary
71c1eba1e7 Merge pull request #51 from johnjaylward/VerifyOptConversions
Verify opt method conversions for JSONArray and JSONObject
2016-07-08 22:31:48 -05:00
John J. Aylward
c2de224711 Verify opt method conversions for JSONArray and JSONObject 2016-07-08 16:58:58 -04:00
Sean Leary
01af31718e Merge pull request #50 from johnjaylward/issue240
Tests for Issue #240 in JSON-Java
2016-06-17 09:36:42 -05:00
John J. Aylward
1204ea9dcf fixes a typo 2016-06-17 00:04:27 -04:00
John J. Aylward
c5deff636b updates README for new project layout 2016-06-16 23:59:34 -04:00
John J. Aylward
46a1c9acf9 Adds test case to confirm the parsing of control characters 2016-06-16 13:02:08 -04:00
John J. Aylward
80f9e48e64 Moves src folder to simplify build.gradle configuration. If JSON-Java source is merged, it's src fold would now be src/main/java/org.json/ instead of src/main/org.json as well. 2016-06-16 12:20:54 -04:00
johnjaylward
0e0f3f2167 Merge pull request #1 from stleary/master
update from origin
2016-06-16 11:44:09 -04:00
Sean Leary
40f170b508 Merge pull request #49 from madsager/master
Add test that an invalid escape sequence results in a JSONException a…
2016-06-07 21:29:25 -05:00
Mads Ager
c7fdada0fd Add test that an invalid escape sequence results in a JSONException and not a NumberFormatException. 2016-06-02 16:41:43 +02:00
Sean Leary
51bcbebaa8 Merge pull request #48 from erosb/master
unittests for stleary/JSON-Java#233
2016-05-20 21:12:12 -05:00
Bence Erős
a1893ebc02 unittests for stlear/JSON-Java#233 2016-05-16 14:54:01 +02:00
stleary
8ed0362683 convert remaining JsonPath expressions to JSONPointer 2016-05-14 13:38:46 -05:00
stleary
15f48a0500 convert tests to use JSONPointer where practical 2016-05-14 11:59:24 -05:00
stleary
45cbc66f5b add coverage for JSONObject, JSONArray queryFrom() 2016-05-14 09:26:03 -05:00
stleary
06ae87c456 exclude resources from test 2016-05-13 23:22:54 -05:00
Sean Leary
7038ea884e Merge pull request #47 from stleary/add-to-test-suite-and-fix-resource
add JSONPointerTest to test suite, fix resource for gradle build
2016-05-13 23:17:10 -05:00
stleary
0112d82755 add JSONPointerTest to test suite, fix resource for gradle build 2016-05-13 23:13:06 -05:00
Sean Leary
46044bfc51 Merge pull request #46 from erosb/master
Tests for JSON Pointers
2016-05-13 22:47:14 -05:00
Sean Leary
a9ff159c78 Update README.md 2016-05-13 15:17:22 -05:00
Sean Leary
b843d67a92 Update README.md 2016-05-07 07:03:50 -05:00
Sean Leary
691734f342 Update README.md 2016-05-07 07:03:30 -05:00
Sean Leary
ccc7a7af29 Update README.md 2016-05-07 07:02:50 -05:00
Bence Erős
adb3118d31 added test for checking if the JSONPointer is immutable 2016-05-05 16:00:15 +02:00
Bence Erős
2eed4be5fc one more test for null-check in Builder#append(String) 2016-05-03 23:42:26 +02:00
Bence Erős
6edc093803 adding unittests for JSPONPointer#toString(), toURIFragment() and its builder class 2016-05-03 23:20:17 +02:00
Sean Leary
77d0873abd Merge pull request #45 from captainIowa/master
Added unit tests for escaped quotes.
2016-05-01 22:55:49 -05:00
Sean Leary
052ce94a34 Update README.md 2016-05-01 22:53:53 -05:00
stleary
4a3565afb3 unit test integration 2016-05-01 22:47:23 -05:00
Bence Erős
e748c60eb1 tests for improved failure handling 2016-04-26 23:31:43 +02:00
Bence Erős
f857dda5d8 removing some deprecated commented code 2016-04-26 23:03:01 +02:00
Bence Erős
66f740eb45 rolling back unwanted gitignore change in previous commit 2016-04-26 23:02:26 +02:00
Bence Erős
6211384f87 tests for url fragment notation handling, moving test document to separate file 2016-04-26 23:01:18 +02:00
Brian Russell
e00191798e Added unit tests for escaped quotes. 2016-04-24 23:04:12 -04:00
Bence Erős
9c47ba299d initial test for JSONPointer class 2016-04-18 21:49:14 +02:00
Sean Leary
8f16e065c5 Merge pull request #39 from johnjaylward/FixNegativeZero
Fix negative zero
2016-01-30 15:47:06 -06:00
John J. Aylward
974c09b22a Fixes typo in assert 2016-01-27 15:02:37 -05:00
John J. Aylward
bd958e0830 fixes formatting 2016-01-27 11:36:15 -05:00
John J. Aylward
67d888e9be Adds test cases to verify that -0 and -0.0 are processed as Double 2016-01-27 11:32:11 -05:00
Sean Leary
d3b197b1b9 Merge pull request #37 from stleary/move-files-to-maven-friendly-dirs
Move files to maven friendly dirs. Hope it works...
2016-01-05 20:46:43 -06:00
stleary
706d898648 latest 2016-01-03 21:39:44 -06:00
stleary
ace08f1944 latest 2016-01-03 21:39:30 -06:00
stleary
280ce71285 tabs to spaces 2016-01-01 13:54:47 -06:00
Sean Leary
147343c51b Merge pull request #29 from johnjaylward/HandleArraysConsistently
Add tests to verify arrays are handled consistently.
2016-01-01 13:46:02 -06:00
Sean Leary
dc8c9e382d Merge pull request #35 from stleary/more-todo-cleanup
clean up a few more todos
2015-12-30 13:52:55 -06:00
stleary
871a3e46d7 clean up a few more todos 2015-12-30 13:50:51 -06:00
Sean Leary
4df6984233 Merge pull request #34 from stleary/util-cleanup
util cleanup
2015-12-30 01:03:31 -06:00
stleary
c88d06eede util cleanup 2015-12-30 01:01:43 -06:00
Sean Leary
0dc886d11b Merge pull request #33 from stleary/Fix-todos-and-cleanup
Fix some todos, clean up some tests, improve coverage
2015-12-30 00:03:37 -06:00
stleary
fc318a765c Fix some todos, clean up some tests, improve coverage 2015-12-30 00:00:58 -06:00
Sean Leary
0990f340db Update README.md 2015-12-30 00:00:14 -06:00
Sean Leary
4ddd6a19a7 Merge pull request #32 from stleary/refactor-test-classes-from-JSONObjectTest
refactor test classes to their own modules
2015-12-29 18:01:35 -06:00
stleary
7f83a51718 refactor test classes to their own modules 2015-12-29 17:56:43 -06:00
Sean Leary
95cf86688d Update README.md 2015-12-28 12:25:40 -06:00
Sean Leary
91fcd6092f Update README.md 2015-12-28 12:25:11 -06:00
Sean Leary
54cd97ded1 Update README.md 2015-12-28 12:24:46 -06:00
Sean Leary
633ab108e7 Update README.md 2015-12-28 12:22:29 -06:00
Sean Leary
472439546a Update README.md 2015-12-28 12:20:43 -06:00
Sean Leary
cfec741090 Merge pull request #31 from stleary/json-path-for-validation
Replace util compare method with JsonPath
2015-12-28 12:11:47 -06:00
stleary
abe421e6bb clean up code 2015-12-28 12:07:44 -06:00
stleary
48c872f66f Replace util compare method with JsonPath 2015-12-28 11:12:41 -06:00
stleary
7187006bae Replace util compare method with JsonPath 2015-12-27 17:01:42 -06:00
stleary
d329b6514c Replace util compare method with JsonPath 2015-12-27 15:17:01 -06:00
stleary
a5390a0685 Replace util compare method with JsonPath 2015-12-26 19:02:02 -06:00
stleary
c6204a9f01 Replace util compare method with JsonPath 2015-12-26 13:21:06 -06:00
Sean Leary
c578216844 Merge pull request #30 from stleary/confirmValueToStringFix
Fix tabs, add valueToString() test to JSONObjectTest
2015-10-31 04:00:52 -05:00
stleary
38cbc31624 Fix tabs, add valueToString() test to JSONObjectTest 2015-10-31 03:58:04 -05:00
Sean Leary
6406c7a379 Merge pull request #28 from johnjaylward/FixCtorGenerics
Test cases for PR #153 in JSON-Java
2015-10-29 18:08:21 -05:00
John J. Aylward
3850b5fd25 Add tests to verify arrays are handled consistently. 2015-10-26 18:35:53 -04:00
Sean Leary
0dbd9be0f1 Merge pull request #26 from johnjaylward/FixXMLNPE
Fixes NPE in XML for pull request #160 in the json-java project
2015-10-18 10:45:42 -05:00
John J. Aylward
4a2f9b8cd3 Adds test cases for corrected generic constructors and put methods 2015-10-14 15:15:24 -04:00
John J. Aylward
cb63a968fa fixes test case to validate the input/output of the function being tested 2015-10-12 14:49:18 -04:00
John J. Aylward
4b0db65877 Fixes NPE in XML 2015-10-12 14:33:43 -04:00
stleary
1a5718dc39 Commenting out some code until JSON-java supports XML.toJSONObject(Reader) 2015-09-27 23:55:32 -05:00
Sean Leary
3f78a85908 Merge pull request #22 from stleary/xml-reader-remote
sample tests for XML.toJSONObject(Reader)
2015-08-23 20:08:02 -05:00
Sean Leary
9dd0ca7b81 Merge pull request #23 from seanThomasLeary/master
Update README.md
2015-08-23 18:54:54 -05:00
seanThomasLeary
045fc74688 Update README.md 2015-08-23 18:54:10 -05:00
stleary
1f6e07c914 sample tests for XML.toJSONObject(Reader) 2015-08-19 19:16:22 -05:00
stleary
8f71e01ae3 Add method comments so JavaDoc will pick them up. 2015-08-09 18:30:16 -05:00
stleary
ccbec8127c Added some class documentation 2015-08-09 18:24:47 -05:00
stleary
1081ae092b Move method comments so JavaDoc will pick them up. 2015-08-09 18:19:51 -05:00
stleary
58d72fe20f Verify exception messages. Move method comments so JavaDoc will pick them up. 2015-08-09 18:19:32 -05:00
stleary
8e48caeb3d Verify exception messages. Move method comments so JavaDoc will pick them up. 2015-08-08 15:12:20 -05:00
stleary
4a3bbedc32 Verify exception messages. Move method comments so JavaDoc will pick them up. 2015-08-08 14:09:52 -05:00
stleary
41bfdad91f Move method comments so JavaDoc will pick them up. 2015-08-08 12:10:52 -05:00
stleary
6f5bcb32e5 Unit tests for JSON-Java HTTP.java. See RFC7230 2015-08-08 12:10:18 -05:00
stleary
9ce62b9540 Move method comments so JavaDoc will pick them up. 2015-08-08 10:30:20 -05:00
stleary
f66cc8d5c4 Verify exception messages. Move method comments so JavaDoc will pick them up. 2015-08-08 10:22:17 -05:00
stleary
a0108f3e8e Verify exception messages. Move method comments so JavaDoc will pick them up. 2015-08-08 09:32:15 -05:00
stleary
ee0a53d494 Verify exception messages. Move method comments so JavaDoc will pick them up. 2015-08-08 08:13:22 -05:00
stleary
f69466f4c2 recreate original documented issue 2015-07-22 21:21:23 -05:00
stleary
1f4e836863 few more enum support tests 2015-07-22 20:24:45 -05:00
stleary
8ac8c34e9f tests for enum-support 2015-07-22 20:12:10 -05:00
stleary
ec7eb25565 Merge branch 'master' of github.com:stleary/JSON-Java-unit-test 2015-07-22 19:47:38 -05:00
stleary
4e38ed01e5 tests for enum-support 2015-07-22 19:47:12 -05:00
Sean Leary
752f66746b Update README.md 2015-07-21 09:12:16 -05:00
stleary
0361cc58d6 one more test - and a bug? 2015-07-20 23:31:52 -05:00
stleary
b39c3df766 document behavior of content keyword 2015-07-20 23:14:15 -05:00
stleary
b9c6f335ee fixed comment location 2015-07-19 09:04:10 -05:00
stleary
f48b6439f6 manual merge of pull request #18 2015-07-19 09:02:27 -05:00
stleary
2c026eb5f8 Fixed test shouldHandleIllegalJSONNodeNames 2015-07-19 08:56:20 -05:00
Sean Leary
0d2d0e3f6c Merge pull request #19 from JaXt0r/illegal_JSON-node-names_during_conversion_to_XML
Showing issue of illegal node names with possible underscore-replacement. (Will currently assterted to an Exception).
2015-07-19 08:48:32 -05:00
JaXt0r
5eadebb797 Showing issue of illegal node names with possible underscore-replacement. (Will currently assterted to an Exception). 2015-07-19 14:24:06 +02:00
stleary
16fa69c0f6 investigate XML.toString() behavior with null JSONObject values 2015-07-17 22:04:01 -05:00
stleary
b06182cb73 investigate XML.toString() behavior with null JSONObject values 2015-07-17 22:01:52 -05:00
stleary
0056b1af94 investigate XML.toString() behavior with null JSONObject values 2015-07-17 21:58:42 -05:00
stleary
6cca292020 investigate XML.toString() behavior with null JSONObject values 2015-07-17 21:55:50 -05:00
Sean Leary
ab143af146 Update README.md 2015-07-07 23:20:55 -05:00
Sean Leary
27b22b4724 Update README.md 2015-07-07 23:19:37 -05:00
Sean Leary
7ed1f78f5f Update README.md 2015-07-07 23:18:31 -05:00
Sean Leary
6dd85ad5b6 Update README.md 2015-07-07 23:16:18 -05:00
Sean Leary
99927c5516 Update README.md 2015-07-07 23:15:06 -05:00
Sean Leary
3de0a0a70e Update README.md 2015-07-07 23:13:59 -05:00
Sean Leary
e056fc0881 Update README.md 2015-07-06 22:33:52 -05:00
stleary
355e832337 latest 2015-07-06 22:31:48 -05:00
stleary
6c48db010f bigInt and bigDec behavior 2015-06-20 23:35:48 -05:00
stleary
8c1a0c47b7 fixed test comment 2015-06-17 20:18:51 -05:00
Sean Leary
d27bf852e6 Merge pull request #16 from stleary/big-numbers
Document bigInt and bigDec behavior to determine what can be changed
2015-06-17 20:11:19 -05:00
stleary
c5173e7cc3 ip 2015-06-17 20:09:31 -05:00
stleary
9a9973c9ca Merge branch 'master' of https://github.com/stleary/JSON-Java-unit-test into more-numbers 2015-06-17 03:01:22 -05:00
stleary
0640856462 unexpected double behavior 2015-06-17 02:59:43 -05:00
Sean Leary
cb7b602f35 Update README.md 2015-06-13 14:53:43 -05:00
Sean Leary
44f98e6a13 Update README.md 2015-06-13 13:30:06 -05:00
stleary
994a19b831 Merge branch 'master' of github.com:stleary/JSON-Java-unit-test into continue-unit-testing 2015-06-07 22:22:51 -05:00
stleary
56aa2f8607 ongoing unit test improvement 2015-06-07 22:22:42 -05:00
stleary
9cf532828d confirm current behavior 2015-06-07 22:22:14 -05:00
Sean Leary
a5b00a5244 Merge pull request #14 from stleary/iterable-JSONArray
test iterable JSONArray
2015-06-07 10:52:51 -05:00
stleary
969e2d4fd5 test iterable 2015-06-04 22:29:55 -05:00
Sean Leary
f6bdc908d8 Update README.md 2015-06-03 22:55:35 -05:00
Sean Leary
67a0c734b6 Update README.md 2015-06-03 22:54:12 -05:00
Sean Leary
86f4bda2d4 Merge pull request #13 from stleary/enum-support
support enum testing
2015-06-03 22:52:38 -05:00
stleary
6b03f1bbe7 support enum testing 2015-06-03 22:50:08 -05:00
stleary
32ea7e0ba3 tests should succeed 2015-05-28 20:43:47 -05:00
Sean Leary
e9ea5ca98f Merge pull request #12 from FritzMock/master
Hidden typecast for Float objects in JSONobject.increment(String key)
2015-05-28 20:21:09 -05:00
dieter
fa79826f0c Better show what has to be expected and what goes wrong 2015-05-27 16:33:42 +02:00
dieter
88756c0490 Hidden typecast for Float objects in JSONobject.increment(String key) 2015-05-27 15:51:30 +02:00
Sean Leary
dc7c59b23b Merge pull request #11 from stleary/fix-JSONObjectTest
fix so numeric behavior is documented but tests succeed
2015-05-24 23:40:02 -05:00
stleary
60e84bff92 fix so numeric behavior is documented but tests succeed 2015-05-24 23:36:48 -05:00
Sean Leary
c72ac516a0 Merge pull request #10 from FritzMock/master
Playing numbers
2015-05-24 17:33:38 -05:00
dieter
327c0e177e Playing numbers 2015-05-22 12:47:28 +02:00
Sean Leary
a9dd8e7b1d Update README.md 2015-05-09 15:26:15 -05:00
stleary
481ecd7964 Merge branch 'master' of github.com:stleary/JSON-Java-unit-test 2015-05-09 15:25:21 -05:00
stleary
f2ef541c2d still in progress, 94% coverage 2015-05-09 15:25:06 -05:00
Sean Leary
0a995318e7 Delete MyBean.java 2015-05-09 15:24:21 -05:00
Sean Leary
fb36918d85 Update README.md 2015-05-08 23:30:41 -05:00
stleary
fcb8048038 deepened the testing a little bit, slow going 2015-05-07 23:04:44 -05:00
stleary
49d4985828 More trickery from the bean 2015-05-07 23:04:26 -05:00
stleary
ad440b4f11 Merge branch 'master' of github.com:stleary/JSON-Java-unit-test 2015-05-06 22:17:27 -05:00
stleary
95b8cd5b03 test improvements, in progress 2015-05-06 22:16:08 -05:00
Sean Leary
fbd07da05a Update README.md 2015-05-06 14:37:52 -05:00
stleary
6195bd248b added unit tests for suppress warning coverage 2015-05-05 21:53:51 -05:00
Sean Leary
43396cf603 Merge pull request #6 from stleary/JSONMLTest-for-toString-issue
Jsonml test for to string issue
2015-05-02 14:19:16 -05:00
Sean Leary
31614fe826 Update README.md 2015-04-27 15:01:27 -05:00
Sean Leary
31cadbd810 Merge pull request #7 from stleary/Rework-CookieListTest
Rework cookie list test
2015-04-27 14:56:59 -05:00
stleary
912350ec75 96.5% coverage 2015-04-27 14:56:01 -05:00
stleary
65ae3e663f Improving test case quality 2015-04-27 10:04:41 -05:00
Sean Leary
f115d6a3b8 Update README.md 2015-04-26 17:53:39 -05:00
Sean Leary
ee06176ab2 Update README.md 2015-04-26 17:49:04 -05:00
stleary
da2e548f56 98.9% coverage 2015-04-26 17:46:52 -05:00
Sean Leary
d2e19cc78c Update README.md 2015-04-24 16:40:42 -05:00
Sean Leary
571b1a79bb Update README.md 2015-04-24 00:27:34 -05:00
Sean Leary
3112e32089 Update README.md 2015-04-24 00:26:26 -05:00
Sean Leary
102d273be3 Update README.md 2015-04-24 00:25:53 -05:00
Sean Leary
15b5306f48 Update README.md 2015-04-23 22:01:33 -05:00
stleary
9f500c242c Merge branch 'master' of github.com:/stleary/JSON-Java-unit-test 2015-04-23 21:47:28 -05:00
stleary
9bca907208 added JSONArrayTest 2015-04-23 21:47:15 -05:00
Sean Leary
890fd4a397 Update README.md 2015-04-23 21:46:13 -05:00
stleary
30c86811c0 improved object comparison 2015-04-23 21:42:04 -05:00
stleary
5acbee2719 98% coverage 2015-04-23 21:41:46 -05:00
stleary
35a4fefd2e test JSONML.toString(JSONArray) 2015-04-19 17:11:51 -05:00
stleary
f0d175c5b2 Added JSONArrayTest 2015-04-19 17:11:05 -05:00
stleary
9df929963f added a trivial XML string compare method - still needs work 2015-04-19 17:10:47 -05:00
Sean Leary
d9e04ec5b6 Update README.md 2015-04-14 11:01:29 -05:00
Sean Leary
9e78cfc48d Update README.md 2015-04-14 11:00:42 -05:00
Sean Leary
0409c9bfb2 Update README.md 2015-04-14 10:59:19 -05:00
stleary
d75a96ae59 95.9% coverage 2015-04-14 01:12:08 -05:00
Sean Leary
e5c01e4ff8 Update README.md 2015-04-13 22:29:27 -05:00
Sean Leary
98cdaf6a39 Update README.md 2015-04-13 22:28:57 -05:00
Sean Leary
67fbfa12ea Update README.md 2015-04-13 22:27:48 -05:00
Sean Leary
9bffd5b3ca Update README.md 2015-04-13 22:25:13 -05:00
Sean Leary
51e8a2d1e5 Update README.md 2015-04-13 21:45:31 -05:00
stleary
76c30539cc 95.9% coverage 2015-04-13 21:39:26 -05:00
stleary
46a43b7b0d Merge branch 'master' of https://github.com/stleary/JSON-Java-unit-test 2015-04-12 23:34:45 -05:00
stleary
6a2c974581 90.9% coverage 2015-04-12 23:34:23 -05:00
Sean Leary
a857869522 Update README.md 2015-04-12 19:36:01 -05:00
Sean Leary
9835285f0c Update README.md 2015-04-12 19:35:34 -05:00
stleary
c4d9a9c5f9 90.8% coverage 2015-04-12 19:29:32 -05:00
stleary
dcaf5fa23a ip 2015-04-10 19:42:34 -05:00
stleary
2784c614d4 ip 2015-04-10 08:21:09 -05:00
stleary
bef37079dc in progress 2015-04-09 18:02:45 -05:00
stleary
a9bce1d6b2 in progress 2015-04-08 22:23:39 -05:00
stleary
22d5fd3aed in progress 2015-04-06 19:01:54 -05:00
Sean Leary
2219b5919b Update README.md 2015-04-04 14:05:06 -05:00
stleary
8168e6f52a 93.8% coverage 2015-04-04 14:01:52 -05:00
stleary
b2e0a77ae0 98.7% coverage 2015-04-04 14:01:29 -05:00
stleary
2db11cd4db add JSONStringerTest 2015-04-04 14:00:57 -05:00
Sean Leary
03d1f0af72 Update README.md 2015-04-03 19:18:13 -05:00
Sean Leary
702a918271 Update README.md 2015-04-03 19:16:45 -05:00
stleary
76cb83643d add http test 2015-04-03 19:12:41 -05:00
stleary
400bbd7fbf 98.7% coverage 2015-04-03 19:12:15 -05:00
stleary
837b7c3037 Merge branch 'master' of https://github.com/stleary/JSON-Java-unit-test 2015-04-03 14:47:12 -05:00
stleary
f7b51414b8 96.5% coverage 2015-04-03 14:46:51 -05:00
Sean Leary
83ac581f3d Update README.md 2015-04-03 14:46:45 -05:00
stleary
970e7a45a9 added cookielisttest 2015-04-03 14:36:40 -05:00
stleary
519c21c8b0 96.5% coverage 2015-04-03 14:36:18 -05:00
stleary
3406acd0aa 97.5% coverage 2015-04-03 14:35:59 -05:00
Sean Leary
ac8b1b098a Update README.md 2015-04-03 11:29:16 -05:00
stleary
5ee4a3fc12 fixed comment test 83.2% coverage 2015-04-02 21:44:35 -05:00
stleary
5fc222229f Merge branch 'master' of https://github.com/stleary/JSON-Java-unit-test 2015-04-02 21:42:11 -05:00
stleary
e80ded6ebe fixed comment test 83.2% coverage 2015-04-02 21:31:15 -05:00
Sean Leary
45d7503e24 Update README.md 2015-04-01 01:23:04 -05:00
stleary
de13c7de86 coverage 84.9% 2015-04-01 01:12:22 -05:00
stleary
9a6215c3be in progress 2015-03-31 22:53:52 -05:00
stleary
ef7e0c7d08 in progress 2015-03-30 08:14:34 -05:00
stleary
bc07b5196b starting jsonml test 2015-03-27 17:52:41 -05:00
Sean Leary
1ff945de69 Update README.md 2015-03-26 23:05:59 -05:00
Sean Leary
210bb41ba1 Update README.md 2015-03-26 23:05:07 -05:00
stleary
89f359e4f8 coverage XMLTest 81.2% / XMLTokener 82.2% 2015-03-26 22:58:11 -05:00
stleary
a18e9f7a25 in progress 2015-03-25 18:53:52 -05:00
stleary
2df27fc6e7 in progress 2015-03-25 08:27:29 -05:00
stleary
4c6da0e6f9 In progress 2015-03-23 19:23:22 -05:00
stleary
4fbe651e57 XMLTest, in progress 2015-03-22 20:37:24 -05:00
stleary
8b9c3cbf47 XMLTest, in progress 2015-03-22 20:36:55 -05:00
stleary
964cb540fb completed 94.8% coverage 2015-03-22 17:59:43 -05:00
Sean Leary
2876b27ec5 Update README.md 2015-03-22 17:48:21 -05:00
stleary
407e7fb8d6 Merge branch 'master' of https://github.com/stleary/JSON-Java-unit-test 2015-03-21 13:44:48 -05:00
stleary
30c31db095 Reverting to 4a5809910b until I have figured out the best way to refactor the code 2015-03-21 13:44:29 -05:00
stleary
231c3de79e Update README.md 2015-03-21 13:41:25 -05:00
stleary
d0223c2d08 Update README.md 2015-03-21 13:35:24 -05:00
stleary
25596c9578 Update README.md 2015-03-21 13:34:04 -05:00
stleary
e4ef254d8f Update README.md 2015-03-21 13:33:12 -05:00
stleary
e4ebd8c443 Update README.md 2015-03-21 13:32:47 -05:00
stleary
f8c37b1e05 Update README.md 2015-03-21 13:27:38 -05:00
stleary
e150039261 Update README.md 2015-03-21 13:23:49 -05:00
stleary
8374382947 Update README.md 2015-03-21 13:22:54 -05:00
stleary
2b0a9cc7c8 Update README.md 2015-03-21 13:19:58 -05:00
stleary
42ad66b032 Update README.md 2015-03-21 13:19:32 -05:00
stleary
09b5562ad9 Update README.md 2015-03-21 13:18:56 -05:00
stleary
b0ce7f3bd9 Update README.md 2015-03-21 13:15:46 -05:00
stleary
1bde00ed4c Update README.md 2015-03-21 13:14:23 -05:00
stleary
dca3726bf1 Update README.md 2015-03-21 13:13:44 -05:00
stleary
01a2fad7fb Merge branch 'master' of https://github.com/stleary/JSON-Java-unit-test 2015-03-20 18:01:52 -05:00
stleary
68e01afd7e first checkin 2015-03-20 18:01:27 -05:00
stleary
441a00afc9 CDLTest still in progress 2015-03-20 15:34:47 -05:00
stleary
b5b4961a9d cdltest refactor, in progress 2015-03-20 07:34:03 -05:00
stleary
fd56452f6b Update README.md 2015-03-19 17:35:16 -05:00
stleary
8d9783d574 Merge branch 'master' of https://github.com/stleary/JSON-Java-unit-test 2015-03-19 17:31:27 -05:00
stleary
e899a2970d PropertTest.java coverage 94.8% 2015-03-19 17:30:44 -05:00
stleary
fac377fc13 Update README.md 2015-03-19 16:12:47 -05:00
stleary
ab08db4ad6 CookieTest 97.5% coverage 2015-03-19 16:09:29 -05:00
stleary
b557180bca more cookie code, in progress 2015-03-19 11:27:45 -05:00
stleary
d75ad1f0c0 Merge branch 'master' of https://github.com/stleary/JSON-Java-unit-test 2015-03-18 22:40:40 -05:00
stleary
df68a7b593 test suite and cookie test 2015-03-18 22:39:54 -05:00
stleary
3d3325aaca Update README.md 2015-03-18 21:51:43 -05:00
stleary
d613203eec Update README.md 2015-03-18 21:51:08 -05:00
stleary
4a5809910b final, for now, 94.8% coverage 2015-03-18 20:54:46 -05:00
stleary
a859e4f547 few more tests 2015-03-18 18:16:19 -05:00
stleary
5fc0c4e1df 72% coverage! 2015-03-18 12:40:20 -05:00
stleary
6c5e25dcb9 added embedded quotes and escapes 2015-03-18 10:13:13 -05:00
stleary
5b56b57074 updating cdltest 2015-03-17 21:47:53 -05:00
stleary
03192b0162 adding this file 2015-03-17 00:38:08 -05:00
stleary
7559b574dd Add LICENSE file via addalicense.com 2015-03-16 12:06:41 -05:00
stleary
03bb6d08be Create README.md 2015-03-16 12:00:24 -05:00
95 changed files with 17601 additions and 1798 deletions

43
.github/workflows/codeql-analysis.yml vendored Normal file
View File

@@ -0,0 +1,43 @@
name: "CodeQL"
on:
push:
branches: [ master ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ master ]
schedule:
- cron: '18 18 * * 1'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'java' ]
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
# By default, queries listed here will override any specified in a config file.
# Prefix the list here with "+" to use these queries and those in the config file.
# queries: ./path/to/local/query, your-org/your-repo/queries@main
- run: "mvn clean compile -Dmaven.test.skip=true -Dmaven.site.skip=true -Dmaven.javadoc.skip=true"
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

74
.github/workflows/pipeline.yml vendored Normal file
View File

@@ -0,0 +1,74 @@
# This workflow will build a Java project with Maven
# For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
name: Java CI with Maven
on:
push:
# branches: [ master ]
pull_request:
branches: [ master ]
jobs:
# old-school build and jar method. No tests run or compiled.
build-1_6:
runs-on: ubuntu-latest
strategy:
matrix:
# build for java 1.6, however don't run any tests
java: [ 1.6 ]
name: Java ${{ matrix.java }}
steps:
- uses: actions/checkout@v2
- name: Setup java
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.java }}
- name: Compile Java ${{ matrix.java }}
run: |
mkdir -p target/classes
javac -d target/classes/ src/main/java/org/json/*.java
- name: Create java ${{ matrix.java }} JAR
run: |
jar cvf target/org.json.jar -C target/classes .
- name: Upload Java ${{ matrix.java }} JAR
uses: actions/upload-artifact@v1
with:
name: Java ${{ matrix.java }} JAR
path: target/org.json.jar
build:
runs-on: ubuntu-latest
strategy:
matrix:
# build against supported Java LTS versions:
java: [ 8, 11 ]
name: Java ${{ matrix.java }}
steps:
- uses: actions/checkout@v2
- name: Setup java
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.java }}
- name: Compile Java ${{ matrix.java }}
run: mvn clean compile -Dmaven.compiler.source=${{ matrix.java }} -Dmaven.compiler.target=${{ matrix.java }} -Dmaven.test.skip=true -Dmaven.site.skip=true -Dmaven.javadoc.skip=true
- name: Run Tests ${{ matrix.java }}
run: |
mvn test -Dmaven.compiler.source=${{ matrix.java }} -Dmaven.compiler.target=${{ matrix.java }}
- name: Build Test Report ${{ matrix.java }}
if: ${{ always() }}
run: |
mvn surefire-report:report-only -Dmaven.compiler.source=${{ matrix.java }} -Dmaven.compiler.target=${{ matrix.java }}
mvn site -DgenerateReports=false -Dmaven.compiler.source=${{ matrix.java }} -Dmaven.compiler.target=${{ matrix.java }}
- name: Upload Test Results ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v1
with:
name: Test Results ${{ matrix.java }}
path: target/surefire-reports/
- name: Upload Test Report ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v1
with:
name: Test Report ${{ matrix.java }}
path: target/site/

10
.gitignore vendored
View File

@@ -4,3 +4,13 @@
# ignore Intellij Idea project files
.idea
*.iml
/target/
/bin/
build
.settings/
/.gradle/
/gradle/
/gradlew
/gradlew.bat
.gitmodules

76
CODE_OF_CONDUCT.md Normal file
View File

@@ -0,0 +1,76 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* Trolling, insulting/derogatory comments, and personal or political attacks
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at jsonjava060@gmail.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq

22
CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,22 @@
# Contribution Guidelines
Feel free to work on any issue with a #hacktoberfest label.
If you discover an issue you would like to work on, you can add a new issue to the list. If it meets our criteria, a hacktoberfest label will be added.
# Who is allowed to submit pull requests for this project?
Anyone can submit pull requests for code, tests, or documentation.
# How do you decide which pull requests to accept?
* Does it call out a bug that needs to be fixed? If so, it goes to the top of the list.
* Does it fix a major user inconvenience? These are given high priority as well.
* Does it align with the specs? If not, it will probably not be accepted. It turns out there are gray areas in the specs. If this is in a gray area, it will likely be given the benefit of the doubt.
* Does it break the existing behavior of the lib? If so, it will not be accepted, unless it fixes an egregious bug. This is happening less frequently now.
# For more guidance, see these links:
[README.md (includes build instructions)](https://github.com/stleary/JSON-java#readme)
[FAQ - all your questions answered](https://github.com/stleary/JSON-java/wiki/FAQ)

View File

@@ -1,169 +0,0 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/**
* Convert a web browser cookie specification to a JSONObject and back.
* JSON and Cookies are both notations for name/value pairs.
* @author JSON.org
* @version 2015-12-09
*/
public class Cookie {
/**
* Produce a copy of a string in which the characters '+', '%', '=', ';'
* and control characters are replaced with "%hh". This is a gentle form
* of URL encoding, attempting to cause as little distortion to the
* string as possible. The characters '=' and ';' are meta characters in
* cookies. By convention, they are escaped using the URL-encoding. This is
* only a convention, not a standard. Often, cookies are expected to have
* encoded values. We encode '=' and ';' because we must. We encode '%' and
* '+' because they are meta characters in URL encoding.
* @param string The source string.
* @return The escaped result.
*/
public static String escape(String string) {
char c;
String s = string.trim();
int length = s.length();
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i += 1) {
c = s.charAt(i);
if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') {
sb.append('%');
sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16));
sb.append(Character.forDigit((char)(c & 0x0f), 16));
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
* Convert a cookie specification string into a JSONObject. The string
* will contain a name value pair separated by '='. The name and the value
* will be unescaped, possibly converting '+' and '%' sequences. The
* cookie properties may follow, separated by ';', also represented as
* name=value (except the secure property, which does not have a value).
* The name will be stored under the key "name", and the value will be
* stored under the key "value". This method does not do checking or
* validation of the parameters. It only converts the cookie string into
* a JSONObject.
* @param string The cookie specification string.
* @return A JSONObject containing "name", "value", and possibly other
* members.
* @throws JSONException
*/
public static JSONObject toJSONObject(String string) throws JSONException {
String name;
JSONObject jo = new JSONObject();
Object value;
JSONTokener x = new JSONTokener(string);
jo.put("name", x.nextTo('='));
x.next('=');
jo.put("value", x.nextTo(';'));
x.next();
while (x.more()) {
name = unescape(x.nextTo("=;"));
if (x.next() != '=') {
if (name.equals("secure")) {
value = Boolean.TRUE;
} else {
throw x.syntaxError("Missing '=' in cookie parameter.");
}
} else {
value = unescape(x.nextTo(';'));
x.next();
}
jo.put(name, value);
}
return jo;
}
/**
* Convert a JSONObject into a cookie specification string. The JSONObject
* must contain "name" and "value" members.
* If the JSONObject contains "expires", "domain", "path", or "secure"
* members, they will be appended to the cookie specification string.
* All other members are ignored.
* @param jo A JSONObject
* @return A cookie specification string
* @throws JSONException
*/
public static String toString(JSONObject jo) throws JSONException {
StringBuilder sb = new StringBuilder();
sb.append(escape(jo.getString("name")));
sb.append("=");
sb.append(escape(jo.getString("value")));
if (jo.has("expires")) {
sb.append(";expires=");
sb.append(jo.getString("expires"));
}
if (jo.has("domain")) {
sb.append(";domain=");
sb.append(escape(jo.getString("domain")));
}
if (jo.has("path")) {
sb.append(";path=");
sb.append(escape(jo.getString("path")));
}
if (jo.optBoolean("secure")) {
sb.append(";secure");
}
return sb.toString();
}
/**
* Convert <code>%</code><i>hh</i> sequences to single characters, and
* convert plus to space.
* @param string A string that may contain
* <code>+</code>&nbsp;<small>(plus)</small> and
* <code>%</code><i>hh</i> sequences.
* @return The unescaped string.
*/
public static String unescape(String string) {
int length = string.length();
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; ++i) {
char c = string.charAt(i);
if (c == '+') {
c = ' ';
} else if (c == '%' && i + 2 < length) {
int d = JSONTokener.dehexchar(string.charAt(i + 1));
int e = JSONTokener.dehexchar(string.charAt(i + 2));
if (d >= 0 && e >= 0) {
c = (char)(d * 16 + e);
i += 2;
}
}
sb.append(c);
}
return sb.toString();
}
}

433
Examples.md Normal file
View File

@@ -0,0 +1,433 @@
<h1>Examples</h1>
<p>Imports used in the examples: </p>
```
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
```
<p>This document's intention is to explain to new-comers the basics of this project</p>
<h2>Part 1: Creating a JSON document</h2>
<h3>Using JSONArray</h3>
```
private static void JSONExampleArray1() {
//We create a JSONObject from a String containing an array using JSONArray
//Firstly, we declare an Array in a String
String arrayStr =
"["+"true,"+"false,"+ "\"true\","+ "\"false\","+"\"hello\","+"23.45e-4,"+
"\"23.45\","+"42,"+"\"43\","+"["+"\"world\""+"],"+
"{"+
"\"key1\":\"value1\","+
"\"key2\":\"value2\","+
"\"key3\":\"value3\","+
"\"key4\":\"value4\""+
"},"+
"0,"+"\"-1\""+
"]";
//Then, we initializate the JSONArray thanks to its constructor
JSONArray array = new JSONArray(arrayStr);
System.out.println("Values array: "+ array);
//We convert that array into a JSONObject, but first, we need the labels, so we need another JSONArray with the labels.
//Here we will use an auxiliary function to get one for the example.
JSONArray list = listNumberArray(array.length());
System.out.println("Label Array: "+ list.toString());
//Now, we construct the JSONObject using both the value array and the label array.
JSONObject object = array.toJSONObject(list);
System.out.println("Final JSONOBject: " + object);
}
//This method creates an JSONArray of labels in which those are generated by their positions
private static JSONArray listNumberArray(int max){
JSONArray res = new JSONArray();
for (int i=0; i<max;i++) {
//The value of the labels must be an String in order to make it work
res.put(String.valueOf(i));
}
return res;
}
```
```
private static void JSONExampleArray2() {
//We can also create an Array without a String by creating an empty array and adding elements to it
JSONArray array = new JSONArray();
//Adding elements with .put()
array.put("value");
array.put(5);
array.put(-23.45e67);
array.put(true);
//We convert it to JSONObject providing a label arrray like last time
JSONArray list = listNumberArray(array.length());
JSONObject object = array.toJSONObject(list);
System.out.println("Final JSONOBject: " + object);
}
```
<h3>Using JSONStringer</h3>
```
private static void JSONExampleStringer() {
//We initializate the JSONStringer
JSONStringer jsonStringer = new JSONStringer();
//Now we start the process of adding elements with .object()
jsonStringer.object();
//We can now add elements as keys and values with .values () and .key()
jsonStringer.key("trueValue").value(true);
jsonStringer.key("falseValue").value(false);
jsonStringer.key("nullValue").value(null);
jsonStringer.key("stringValue").value("hello world!");
jsonStringer.key("complexStringValue").value("h\be\tllo w\u1234orld!");
jsonStringer.key("intValue").value(42);
jsonStringer.key("doubleValue").value(-23.45e67);
//We end this prcedure with .ednObject
jsonStringer.endObject();
//Once we have a JSONStringer, we convert it to JSONObject generating a String and using JSONObject's contructor.
String str = jsonStringer.toString();
JSONObject jsonObject = new JSONObject(str);
System.out.println("Final JSONOBject: " + jsonObject);
}
```
<h3>Using JSONObject</h3>
```
private static void JSONExampleObject1() {
//We can create a JSONObject from a String with the class builder
String string = "{\"0\":\"value\",\"1\":5,\"2\":-2.345E68,\"3\":true}";
JSONObject example = new JSONObject(string);
System.out.println("Final JSONObject: " + example);
}
```
```
private static void JSONExampleObject2() {
//We can also create a JSONObject directly without messing around with any of the other functions.
JSONObject example = new JSONObject();
//Now we add the keys and values in a similar way as the Stringer method
example.put("key", "value");
//As you can see, the first entry is the key and the second would be its associeted value.
example.put("key2", 5);
example.put("key3", -23.45e67);
example.put("trueValue", true);
//We can't add null values thougth
//example.put("nullValue", null); //This is not possible
System.out.println("Final JSONOBject: " + example);
}
```
```
private static void JSONExampleObject3() {
//We can also create a JSONObject with a Java Map
//YoU will need a Map whose keys are Strings. The values can be whatever you want
Map<String,Double> map = new HashMap<String, Double>();
map.put("key1", 1.0);
map.put("key2", -23.45e67);
//We create the JSONObject with the map with its class builder
JSONObject example = new JSONObject(map);
System.out.println("Final JSONOBject: " + example);
}
```
<h3>Using JSONWriter</h3>
```
private static void JSONExamplWriter() {
//This method works in a very similar way to Object and Stringer in the construction of the JSON.
//The difference is that it needs a Java object called "Appendable" like StringBuilder
StringBuilder write = new StringBuilder();
JSONWriter jsonWriter = new JSONWriter(write);
//We behave now the same way as Stringer
jsonWriter.object();
jsonWriter.key("trueValue").value(true);
jsonWriter.key("falseValue").value(false);
jsonWriter.key("nullValue").value(null);
jsonWriter.key("stringValue").value("hello world!");
jsonWriter.key("complexStringValue").value("h\be\tllo w\u1234orld!");
jsonWriter.key("intValue").value(42);
jsonWriter.key("doubleValue").value(-23.45e67);
jsonWriter.endObject();
//The resoult should be in the "write" object
System.out.println("JSON: " + write.toString());
//The difference is that we don't get a JSONObject in this one.
}
```
```
private static void JSONExampleTokener() {
//A partir de una String podemos crear un JSONTokener, que lo podemos usar alternativamente para JSONArray,JSONObject
String string = "this is not a valid JSON string";
JSONTokener token = new JSONTokener(string);
//Now you can use the token in JSONObject and Array the same way as a String
JSONObject object = new JSONObject(token);
JSONArray array = new JSONArray(token);
}
```
<h2>Part 2: Conversion methods</h2>
<p>We don't need to have a JSON document to work. This project also admits conversions from other type of files.</p>
<p>Secondly, we can also convert from JSON to those type of files.</p>
<h3>Extra: Conversion to JSONArray</h3>
```
private static void JSONObjectToArray() {
//We start with a JSONObject
String string = "{\"0\":\"value\",\"1\":5,\"2\":-2.345E68,\"3\":true}";
JSONObject example = new JSONObject(string);
//We need a list of key strings like the reverse operation
JSONArray keyStrings = listNumberArray(example.length());
//Then we convert to the Array using both elelements
JSONArray array = example.toJSONArray(keyStrings);
System.out.println("Final JSONArray: " + array);
}
```
<h3>XML Conversions</h3>
```
private static void XMLToExampleConversion() {
//We start with a JSONObject
String string = "{\"0\":\"value\",\"1\":5,\"2\":-2.345E68,\"3\":true}";
JSONObject example = new JSONObject(string);
//We obtain a String with XML format with toString()
String output = XML.toString(example);
System.out.println("Final XML: " + output);
}
```
```
private static void XMLFromExampleConversion() {
//We start with a string with the XML format
String string = "<0>value</0><1>5</1><2>-2.345E+68</2><3>true</3>";
//We obtain a JSONObject with toJSONOBject()
JSONObject output = XML.toJSONObject(string);
System.out.println("Final JSONObject: " + output);
}
```
<h3>Cookie Conversions</h3>
```
private static void CookieToExampleConversion() {
//We start with a JSONObject
//The JSONOBject needs to entries that gives the cookie a name and gives the field "name" a name too.
//The Cokkie format doesn't support booleans
String string = "{\"name\":\"Cookie-Name\",\"value\":\"name\",\"1\":5,\"2\":-2.345E68,\"3\":'true'}";
JSONObject example = new JSONObject(string);
//We obtain a String with Cookie format with toString()
String output = Cookie.toString(example);
System.out.println("Final Cookie: " + output);
}
```
```
private static void CookieFromExampleConversion() {
//We start with a string with the Cookie format
String string = "Cookie-Name=name;1=5;2=-2.345E%2b68;3=true";
//We obtain a JSONObject with toJSONOBject()
JSONObject output = Cookie.toJSONObject(string);
System.out.println("Final JSONObject: " + output);
}
```
<h3>HTTP Conversions</h3>
```
private static void HTTPToExampleConversion() {
//We start with a JSONObject
//The JSONObject must have the minimun header for a HTTP request or header
String string = "{\"Method\":\"POST\",\"Request-URI\":'/',\"HTTP-Version\":'HTTP/1.1',\"Value1\":true,\"Value2\":2,\"Value3\":-2.345E68}";
JSONObject example = new JSONObject(string);
//We obtain a String with HTTP format with toString()
String output = HTTP.toString(example);
System.out.println("Final HTTP: " + output);
}
```
```
private static void HTTPFromExampleConversion() {
//We start with a string with the HTTP format
String string = "Final HTTP: POST '/' HTTP/1.1 Value3: -2.345E+68 Value1: true Value2: 2";
//We obtain a JSONObject with toJSONOBject()
JSONObject output = HTTP.toJSONObject(string);
System.out.println("Final JSONObject: " + output);
}
```
<h3>CDL Conversions</h3>
```
private static void CDLToExampleConversion() {
//We start with some JSONObjects with the same values in the keys but different values in the "values"
String string = "{\"0\":\"value\",\"1\":5,\"2\":-2.345E68,\"3\":true}";
JSONObject example = new JSONObject(string);
String string2 = "{\"0\":\"value2\",\"1\":6,\"2\":-8.345E68,\"3\":false}";
JSONObject example2 = new JSONObject(string2);
//We need now a JSONArray with those JSONObjects
JSONArray array = new JSONArray();
array.put(example);
array.put(example2);
//We obtain a String with XML format with toString()
String output = CDL.toString(array);
System.out.println("Final CDL: \r\n" + output);
}
```
```
private static void CDLFromExampleConversion() {
//We start wtih a String with the CDL format
String string = "0,1,2,3\n"
+ "value,5,-2.345E+68,true\n"
+ "value2,6,-8.345E+68,false";
//We obtain a JSONArray with toJSONOBject()
JSONArray output = CDL.toJSONArray(string);
System.out.println("Final JSONArray: " + output);
}
```
<h3>Properties Conversions</h3>
```
private static Properties PropertyToExampleConversion() {
//We start with a JSONObject
String string = "{\"0\":\"value\",\"1\":5,\"2\":-2.345E68,\"3\":true}";
JSONObject example = new JSONObject(string);
//We obtain a String with Properties format with toString()
Properties output = Property.toProperties(example);
System.out.println("Final Properties: " + output);
return output;
}
```
```
private static void PropertyFromExampleConversion() {
//We start with a Properties object
Properties input = PropertyToExampleConversion();
//We obtain a JSONObject with toJSONOBject()
JSONObject output = Property.toJSONObject(input);
System.out.println("Final JSONObject: " + output);
}
```
<h2>List of all examples methods</h2>
```
public static void main(String[] args) {
//JSONObjectToArray();
//JSONExampleArray1();
//JSONExampleArray2();
//JSONExampleStringer();
//JSONExampleObject1();
//JSONExampleObject2();
//JSONExampleObject3();
//JSONExamplWriter();
//XMLToExampleConversion();
//XMLFromExampleConversion();
//CookieToExampleConversion();
//CookieFromExampleConversion();
//HTTPToExampleConversion();
//HTTPFromExampleConversion();
//CDLToExampleConversion();
//CDLFromExampleConversion();
//PropertyToExampleConversion();
//PropertyFromExampleConversion();
}
```

View File

@@ -1,45 +0,0 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/**
* The JSONPointerException is thrown by {@link JSONPointer} if an error occurs
* during evaluating a pointer.
*
* @author JSON.org
* @version 2016-05-13
*/
public class JSONPointerException extends JSONException {
private static final long serialVersionUID = 8872944667561856751L;
public JSONPointerException(String message) {
super(message);
}
public JSONPointerException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -1,43 +0,0 @@
package org.json;
/*
Copyright (c) 2018 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Retention(RUNTIME)
@Target({METHOD})
/**
* Use this annotation on a getter method to override the Bean name
* parser for Bean -&gt; JSONObject mapping. If this annotation is
* present at any level in the class hierarchy, then the method will
* not be serialized from the bean into the JSONObject.
*/
public @interface JSONPropertyIgnore { }

View File

@@ -1,47 +0,0 @@
package org.json;
/*
Copyright (c) 2018 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Retention(RUNTIME)
@Target({METHOD})
/**
* Use this annotation on a getter method to override the Bean name
* parser for Bean -&gt; JSONObject mapping. A value set to empty string <code>""</code>
* will have the Bean parser fall back to the default field name processing.
*/
public @interface JSONPropertyName {
/**
* @return The name of the property as to be used in the JSON Object.
*/
String value();
}

View File

@@ -1,43 +0,0 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/**
* The <code>JSONString</code> interface allows a <code>toJSONString()</code>
* method so that a class can change the behavior of
* <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>,
* and <code>JSONWriter.value(</code>Object<code>)</code>. The
* <code>toJSONString</code> method will be used instead of the default behavior
* of using the Object's <code>toString()</code> method and quoting the result.
*/
public interface JSONString {
/**
* The <code>toJSONString</code> method allows a class to produce its own JSON
* serialization.
*
* @return A strictly syntactically correct JSON text.
*/
public String toJSONString();
}

23
LICENSE
View File

@@ -1,23 +1,2 @@
============================================================================
Public Domain.
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

189
README.md
View File

@@ -1,150 +1,107 @@
![Json-Java logo](https://github.com/stleary/JSON-java/blob/master/images/JsonJava.png?raw=true)
<sub><sup>image credit: Ismael Pérez Ortiz</sup></sub>
JSON in Java [package org.json]
===============================
[![Maven Central](https://img.shields.io/maven-central/v/org.json/json.svg)](https://mvnrepository.com/artifact/org.json/json)
**[Click here if you just want the latest release jar file.](https://repo1.maven.org/maven2/org/json/json/20190722/json-20190722.jar)**
JSON is a light-weight, language independent, data interchange format.
See http://www.JSON.org/
The files in this package implement JSON encoders/decoders in Java.
It also includes the capability to convert between JSON and XML, HTTP
headers, Cookies, and CDL.
This is a reference implementation. There is a large number of JSON packages
in Java. Perhaps someday the Java community will standardize on one. Until
then, choose carefully.
The license includes this restriction: "The software shall be used for good,
not evil." If your conscience cannot live with that, then choose a different
package.
The package compiles on Java 1.6-1.8.
**[Click here if you just want the latest release jar file.](https://search.maven.org/remotecontent?filepath=org/json/json/20220924/json-20220924.jar)**
**JSONObject.java**: The `JSONObject` can parse text from a `String` or a `JSONTokener`
to produce a map-like object. The object provides methods for manipulating its
contents, and for producing a JSON compliant object serialization.
# Overview
**JSONArray.java**: The `JSONArray` can parse text from a String or a `JSONTokener`
to produce a vector-like object. The object provides methods for manipulating
its contents, and for producing a JSON compliant array serialization.
[JSON](http://www.JSON.org/) is a light-weight language-independent data interchange format.
**JSONTokener.java**: The `JSONTokener` breaks a text into a sequence of individual
tokens. It can be constructed from a `String`, `Reader`, or `InputStream`. It also can
parse text from a `String`, `Number`, `Boolean` or `null` like `"hello"`, `42`, `true`,
`null` to produce a simple json object.
The JSON-Java package is a reference implementation that demonstrates how to parse JSON documents into Java objects and how to generate new JSON documents from the Java classes.
**JSONException.java**: The `JSONException` is the standard exception type thrown
by this package.
Project goals include:
* Reliable and consistent results
* Adherence to the JSON specification
* Easy to build, use, and include in other projects
* No external dependencies
* Fast execution and low memory footprint
* Maintain backward compatibility
* Designed and tested to use on Java versions 1.6 - 1.11
**JSONPointer.java**: Implementation of
[JSON Pointer (RFC 6901)](https://tools.ietf.org/html/rfc6901). Supports
JSON Pointers both in the form of string representation and URI fragment
representation.
The files in this package implement JSON encoders and decoders. The package can also convert between JSON and XML, HTTP headers, Cookies, and CDL.
**JSONPropertyIgnore.java**: Annotation class that can be used on Java Bean getter methods.
When used on a bean method that would normally be serialized into a `JSONObject`, it
overrides the getter-to-key-name logic and forces the property to be excluded from the
resulting `JSONObject`.
# If you would like to contribute to this project
**JSONPropertyName.java**: Annotation class that can be used on Java Bean getter methods.
When used on a bean method that would normally be serialized into a `JSONObject`, it
overrides the getter-to-key-name logic and uses the value of the annotation. The Bean
processor will look through the class hierarchy. This means you can use the annotation on
a base class or interface and the value of the annotation will be used even if the getter
is overridden in a child class.
For more information on contributions, please see [CONTRIBUTING.md](https://github.com/stleary/JSON-java/blob/master/docs/CONTRIBUTING.md)
**JSONString.java**: The `JSONString` interface requires a `toJSONString` method,
allowing an object to provide its own serialization.
Bug fixes, code improvements, and unit test coverage changes are welcome! Because this project is currently in the maintenance phase, the kinds of changes that can be accepted are limited. For more information, please read the [FAQ](https://github.com/stleary/JSON-java/wiki/FAQ).
**JSONStringer.java**: The `JSONStringer` provides a convenient facility for
building JSON strings.
# Build Instructions
**JSONWriter.java**: The `JSONWriter` provides a convenient facility for building
JSON text through a writer.
The org.json package can be built from the command line, Maven, and Gradle. The unit tests can be executed from Maven, Gradle, or individually in an IDE e.g. Eclipse.
**Building from the command line**
*Build the class files from the package root directory src/main/java*
````
javac org/json/*.java
````
**CDL.java**: `CDL` provides support for converting between JSON and comma
delimited lists.
*Create the jar file in the current directory*
````
jar cf json-java.jar org/json/*.class
````
**Cookie.java**: `Cookie` provides support for converting between JSON and cookies.
*Compile a program that uses the jar (see example code below)*
````
javac -cp .;json-java.jar Test.java (Windows)
javac -cp .:json-java.jar Test.java (Unix Systems)
````
**CookieList.java**: `CookieList` provides support for converting between JSON and
cookie lists.
*Test file contents*
**HTTP.java**: `HTTP` provides support for converting between JSON and HTTP headers.
````
import org.json.JSONObject;
public class Test {
public static void main(String args[]){
JSONObject jo = new JSONObject("{ \"abc\" : \"def\" }");
System.out.println(jo.toString());
}
}
````
**HTTPTokener.java**: `HTTPTokener` extends `JSONTokener` for parsing HTTP headers.
*Execute the Test file*
````
java -cp .;json-java.jar Test (Windows)
java -cp .:json-java.jar Test (Unix Systems)
````
**XML.java**: `XML` provides support for converting between JSON and XML.
*Expected output*
**JSONML.java**: `JSONML` provides support for converting between JSONML and XML.
````
{"abc":"def"}
````
**XMLTokener.java**: `XMLTokener` extends `JSONTokener` for parsing XML text.
**Tools to build the package and execute the unit tests**
Unit tests are maintained in a separate project. Contributing developers can test
JSON-java pull requests with the code in this project:
https://github.com/stleary/JSON-Java-unit-test
Execute the test suite with Maven:
```
mvn clean test
```
Numeric types in this package comply with
[ECMA-404: The JSON Data Interchange Format](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf) and
[RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc8259#section-6).
This package fully supports `Integer`, `Long`, and `Double` Java types. Partial support
for `BigInteger` and `BigDecimal` values in `JSONObject` and `JSONArray` objects is provided
in the form of `get()`, `opt()`, and `put()` API methods.
Execute the test suite with Gradlew:
Although 1.6 compatibility is currently supported, it is not a project goal and may be
removed in some future release.
```
gradlew clean build test
```
In compliance with RFC8259 page 10 section 9, the parser is more lax with what is valid
JSON than the Generator. For Example, the tab character (U+0009) is allowed when reading
JSON Text strings, but when output by the Generator, tab is properly converted to \t in
the string. Other instances may occur where reading invalid JSON text does not cause an
error to be generated. Malformed JSON Texts such as missing end " (quote) on strings or
invalid number formats (1.2e6.3) will cause errors as such documents can not be read
reliably.
# Notes
Some notible exceptions that the JSON Parser in this library accepts are:
* Unquoted keys `{ key: "value" }`
* Unquoted values `{ "key": value }`
* Unescaped literals like "tab" in string values `{ "key": "value with an unescaped tab" }`
* Numbers out of range for `Double` or `Long` are parsed as strings
For more information, please see [NOTES.md](https://github.com/stleary/JSON-java/blob/master/docs/NOTES.md)
Release history:
# Files
~~~
20200518 Recent commits and snapshot before project structure change
For more information on files, please see [FILES.md](https://github.com/stleary/JSON-java/blob/master/docs/FILES.md)
20190722 Recent commits
# Release history:
20180813 POM change to include Automatic-Module-Name (#431)
20180130 Recent commits
20171018 Checkpoint for recent commits.
20170516 Roll up recent commits.
20160810 Revert code that was breaking opt*() methods.
20160807 This release contains a bug in the JSONObject.opt*() and JSONArray.opt*() methods,
it is not recommended for use.
Java 1.6 compatability fixed, JSONArray.toList() and JSONObject.toMap(),
RFC4180 compatibility, JSONPointer, some exception fixes, optional XML type conversion.
Contains the latest code as of 7 Aug, 2016
20160212 Java 1.6 compatibility, OSGi bundle. Contains the latest code as of 12 Feb, 2016.
20151123 JSONObject and JSONArray initialization with generics. Contains the
latest code as of 23 Nov, 2015.
20150729 Checkpoint for Maven central repository release. Contains the latest code
as of 29 July, 2015.
~~~
JSON-java releases can be found by searching the Maven repository for groupId "org.json"
and artifactId "json". For example:
https://search.maven.org/search?q=g:org.json%20AND%20a:json&core=gav
For the release history, please see [RELEASES.md](https://github.com/stleary/JSON-java/blob/master/docs/RELEASES.md)

5
SECURITY.md Normal file
View File

@@ -0,0 +1,5 @@
# Security Policy
## Reporting a Vulnerability
Please follow the instructions in the ["How are vulnerabilities and exploits handled?"](https://github.com/stleary/JSON-java/wiki/FAQ#how-are-vulnerabilities-and-exploits-handled) section in the FAQ.

View File

@@ -1,107 +0,0 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/**
* Configuration object for the XML parser.
* @author AylwardJ
*
*/
public class XMLParserConfiguration {
/** Original Configuration of the XML Parser. */
public static final XMLParserConfiguration ORIGINAL = new XMLParserConfiguration();
/** Original configuration of the XML Parser except that values are kept as strings. */
public static final XMLParserConfiguration KEEP_STRINGS = new XMLParserConfiguration(true);
/**
* When parsing the XML into JSON, specifies if values should be kept as strings (true), or if
* they should try to be guessed into JSON values (numeric, boolean, string)
*/
public final boolean keepStrings;
/**
* The name of the key in a JSON Object that indicates a CDATA section. Historically this has
* been the value "content" but can be changed. Use <code>null</code> to indicate no CDATA
* processing.
*/
public final String cDataTagName;
/**
* When parsing the XML into JSON, specifies if values with attribute xsi:nil="true"
* should be kept as attribute(false), or they should be converted to null(true)
*/
public final boolean convertNilAttributeToNull;
/**
* Default parser configuration. Does not keep strings, and the CDATA Tag Name is "content".
*/
public XMLParserConfiguration () {
this(false, "content", false);
}
/**
* Configure the parser string processing and use the default CDATA Tag Name as "content".
* @param keepStrings <code>true</code> to parse all values as string.
* <code>false</code> to try and convert XML string values into a JSON value.
*/
public XMLParserConfiguration (final boolean keepStrings) {
this(keepStrings, "content", false);
}
/**
* Configure the parser string processing to try and convert XML values to JSON values and
* use the passed CDATA Tag Name the processing value. Pass <code>null</code> to
* disable CDATA processing
* @param cDataTagName<code>null</code> to disable CDATA processing. Any other value
* to use that value as the JSONObject key name to process as CDATA.
*/
public XMLParserConfiguration (final String cDataTagName) {
this(false, cDataTagName, false);
}
/**
* Configure the parser to use custom settings.
* @param keepStrings <code>true</code> to parse all values as string.
* <code>false</code> to try and convert XML string values into a JSON value.
* @param cDataTagName<code>null</code> to disable CDATA processing. Any other value
* to use that value as the JSONObject key name to process as CDATA.
*/
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName) {
this.keepStrings = keepStrings;
this.cDataTagName = cDataTagName;
this.convertNilAttributeToNull = false;
}
/**
* Configure the parser to use custom settings.
* @param keepStrings <code>true</code> to parse all values as string.
* <code>false</code> to try and convert XML string values into a JSON value.
* @param cDataTagName <code>null</code> to disable CDATA processing. Any other value
* to use that value as the JSONObject key name to process as CDATA.
* @param convertNilAttributeToNull <code>true</code> to parse values with attribute xsi:nil="true" as null.
* <code>false</code> to parse values with attribute xsi:nil="true" as {"xsi:nil":true}.
*/
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName, final boolean convertNilAttributeToNull) {
this.keepStrings = keepStrings;
this.cDataTagName = cDataTagName;
this.convertNilAttributeToNull = convertNilAttributeToNull;
}
}

55
build.gradle Normal file
View File

@@ -0,0 +1,55 @@
/*
* This file was generated by the Gradle 'init' task.
*/
apply plugin: 'java'
apply plugin: 'eclipse'
// apply plugin: 'jacoco'
apply plugin: 'maven-publish'
//plugins {
// id 'java'
//id 'maven-publish'
// }
repositories {
mavenLocal()
mavenCentral()
maven {
url = uri('https://oss.sonatype.org/content/repositories/snapshots')
}
}
dependencies {
testImplementation 'junit:junit:4.13.1'
testImplementation 'com.jayway.jsonpath:json-path:2.1.0'
testImplementation 'org.mockito:mockito-core:1.9.5'
}
subprojects {
tasks.withType(Javadoc).all { enabled = false }
}
group = 'org.json'
version = 'v20211205-SNAPSHOT'
description = 'JSON in Java'
sourceCompatibility = '1.7'
configurations.all {
}
java {
withSourcesJar()
withJavadocJar()
}
publishing {
publications {
maven(MavenPublication) {
from(components.java)
}
}
}
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}

22
docs/CONTRIBUTING.md Normal file
View File

@@ -0,0 +1,22 @@
# Contribution Guidelines
Feel free to work on any issue with a #hacktoberfest label.
If you discover an issue you would like to work on, you can add a new issue to the list. If it meets our criteria, a hacktoberfest label will be added.
# Who is allowed to submit pull requests for this project?
Anyone can submit pull requests for code, tests, or documentation.
# How do you decide which pull requests to accept?
* Does it call out a bug that needs to be fixed? If so, it goes to the top of the list.
* Does it fix a major user inconvenience? These are given high priority as well.
* Does it align with the specs? If not, it will probably not be accepted. It turns out there are gray areas in the specs. If this is in a gray area, it will likely be given the benefit of the doubt.
* Does it break the existing behavior of the lib? If so, it will not be accepted, unless it fixes an egregious bug. This is happening less frequently now.
# For more guidance, see these links:
[README.md (includes build instructions)](https://github.com/stleary/JSON-java#readme)
[FAQ - all your questions answered](https://github.com/stleary/JSON-java/wiki/FAQ)

62
docs/FILES.md Normal file
View File

@@ -0,0 +1,62 @@
# Files
**JSONObject.java**: The `JSONObject` can parse text from a `String` or a `JSONTokener`
to produce a map-like object. The object provides methods for manipulating its
contents, and for producing a JSON compliant object serialization.
**JSONArray.java**: The `JSONArray` can parse text from a String or a `JSONTokener`
to produce a vector-like object. The object provides methods for manipulating
its contents, and for producing a JSON compliant array serialization.
**JSONTokener.java**: The `JSONTokener` breaks a text into a sequence of individual
tokens. It can be constructed from a `String`, `Reader`, or `InputStream`. It also can
parse text from a `String`, `Number`, `Boolean` or `null` like `"hello"`, `42`, `true`,
`null` to produce a simple json object.
**JSONException.java**: The `JSONException` is the standard exception type thrown
by this package.
**JSONPointer.java**: Implementation of
[JSON Pointer (RFC 6901)](https://tools.ietf.org/html/rfc6901). Supports
JSON Pointers both in the form of string representation and URI fragment
representation.
**JSONPropertyIgnore.java**: Annotation class that can be used on Java Bean getter methods.
When used on a bean method that would normally be serialized into a `JSONObject`, it
overrides the getter-to-key-name logic and forces the property to be excluded from the
resulting `JSONObject`.
**JSONPropertyName.java**: Annotation class that can be used on Java Bean getter methods.
When used on a bean method that would normally be serialized into a `JSONObject`, it
overrides the getter-to-key-name logic and uses the value of the annotation. The Bean
processor will look through the class hierarchy. This means you can use the annotation on
a base class or interface and the value of the annotation will be used even if the getter
is overridden in a child class.
**JSONString.java**: The `JSONString` interface requires a `toJSONString` method,
allowing an object to provide its own serialization.
**JSONStringer.java**: The `JSONStringer` provides a convenient facility for
building JSON strings.
**JSONWriter.java**: The `JSONWriter` provides a convenient facility for building
JSON text through a writer.
**CDL.java**: `CDL` provides support for converting between JSON and comma
delimited lists.
**Cookie.java**: `Cookie` provides support for converting between JSON and cookies.
**CookieList.java**: `CookieList` provides support for converting between JSON and
cookie lists.
**HTTP.java**: `HTTP` provides support for converting between JSON and HTTP headers.
**HTTPTokener.java**: `HTTPTokener` extends `JSONTokener` for parsing HTTP headers.
**XML.java**: `XML` provides support for converting between JSON and XML.
**JSONML.java**: `JSONML` provides support for converting between JSONML and XML.
**XMLTokener.java**: `XMLTokener` extends `JSONTokener` for parsing XML text.

87
docs/NOTES.md Normal file
View File

@@ -0,0 +1,87 @@
# Notes
**Recent directory structure change**
_Due to a recent commit - [#515 Merge tests and pom and code](https://github.com/stleary/JSON-java/pull/515) - the structure of the project has changed from a flat directory containing all of the Java files to a directory structure that includes unit tests and several tools used to build the project jar and run the unit tests. If you have difficulty using the new structure, please open an issue so we can work through it._
**Implementation notes**
Numeric types in this package comply with
[ECMA-404: The JSON Data Interchange Format](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf) and
[RFC 8259: The JavaScript Object Notation (JSON) Data Interchange Format](https://tools.ietf.org/html/rfc8259#section-6).
This package fully supports `Integer`, `Long`, and `Double` Java types. Partial support
for `BigInteger` and `BigDecimal` values in `JSONObject` and `JSONArray` objects is provided
in the form of `get()`, `opt()`, and `put()` API methods.
Although 1.6 compatibility is currently supported, it is not a project goal and might be
removed in some future release.
In compliance with RFC8259 page 10 section 9, the parser is more lax with what is valid
JSON then the Generator. For Example, the tab character (U+0009) is allowed when reading
JSON Text strings, but when output by the Generator, the tab is properly converted to \t in
the string. Other instances may occur where reading invalid JSON text does not cause an
error to be generated. Malformed JSON Texts such as missing end " (quote) on strings or
invalid number formats (1.2e6.3) will cause errors as such documents can not be read
reliably.
Some notable exceptions that the JSON Parser in this library accepts are:
* Unquoted keys `{ key: "value" }`
* Unquoted values `{ "key": value }`
* Unescaped literals like "tab" in string values `{ "key": "value with an unescaped tab" }`
* Numbers out of range for `Double` or `Long` are parsed as strings
Recent pull requests added a new method `putAll` on the JSONArray. The `putAll` method
works similarly to other `put` methods in that it does not call `JSONObject.wrap` for items
added. This can lead to inconsistent object representation in JSONArray structures.
For example, code like this will create a mixed JSONArray, some items wrapped, others
not:
```java
SomeBean[] myArr = new SomeBean[]{ new SomeBean(1), new SomeBean(2) };
// these will be wrapped
JSONArray jArr = new JSONArray(myArr);
// these will not be wrapped
jArr.putAll(new SomeBean[]{ new SomeBean(3), new SomeBean(4) });
```
For structure consistency, it would be recommended that the above code is changed
to look like 1 of 2 ways.
Option 1:
```Java
SomeBean[] myArr = new SomeBean[]{ new SomeBean(1), new SomeBean(2) };
JSONArray jArr = new JSONArray();
// these will not be wrapped
jArr.putAll(myArr);
// these will not be wrapped
jArr.putAll(new SomeBean[]{ new SomeBean(3), new SomeBean(4) });
// our jArr is now consistent.
```
Option 2:
```Java
SomeBean[] myArr = new SomeBean[]{ new SomeBean(1), new SomeBean(2) };
// these will be wrapped
JSONArray jArr = new JSONArray(myArr);
// these will be wrapped
jArr.putAll(new JSONArray(new SomeBean[]{ new SomeBean(3), new SomeBean(4) }));
// our jArr is now consistent.
```
**Unit Test Conventions**
Test filenames should consist of the name of the module being tested, with the suffix "Test".
For example, <b>Cookie.java</b> is tested by <b>CookieTest.java</b>.
<b>The fundamental issues with JSON-Java testing are:</b><br>
* <b>JSONObjects</b> are unordered, making simple string comparison ineffective.
* Comparisons via **equals()** is not currently supported. Neither <b>JSONArray</b> nor <b>JSONObject</b> override <b>hashCode()</b> or <b>equals()</b>, so comparison defaults to the <b>Object</b> equals(), which is not useful.
* Access to the <b>JSONArray</b> and <b>JSONObject</b> internal containers for comparison is not currently available.
<b>General issues with unit testing are:</b><br>
* Just writing tests to make coverage goals tends to result in poor tests.
* Unit tests are a form of documentation - how a given method works is demonstrated by the test. So for a code reviewer or future developer looking at code a good test helps explain how a function is supposed to work according to the original author. This can be difficult if you are not the original developer.
* It is difficult to evaluate unit tests in a vacuum. You also need to see the code being tested to understand if a test is good.
* Without unit tests, it is hard to feel confident about the quality of the code, especially when fixing bugs or refactoring. Good tests prevent regressions and keep the intent of the code correct.
* If you have unit test results along with pull requests, the reviewer has an easier time understanding your code and determining if it works as intended.

44
docs/RELEASES.md Normal file
View File

@@ -0,0 +1,44 @@
# Release history:
JSON-java releases can be found by searching the Maven repository for groupId "org.json"
and artifactId "json". For example:
[https://search.maven.org/search?q=g:org.json%20AND%20a:json&core=gav](https://search.maven.org/search?q=g:org.json%20AND%20a:json&core=gav)
~~~
20220924 New License - public domain, and some minor updates
20220320 Wrap StackOverflow with JSONException
20211205 Recent commits and some bug fixes for similar()
20210307 Recent commits and potentially breaking fix to JSONPointer
20201115 Recent commits and first release after project structure change
20200518 Recent commits and snapshot before project structure change
20190722 Recent commits
20180813 POM change to include Automatic-Module-Name (#431)
20180130 Recent commits
20171018 Checkpoint for recent commits.
20170516 Roll up recent commits.
20160810 Revert code that was breaking opt*() methods.
20160807 This release contains a bug in the JSONObject.opt*() and JSONArray.opt*() methods,
it is not recommended for use.
Java 1.6 compatability fixed, JSONArray.toList() and JSONObject.toMap(),
RFC4180 compatibility, JSONPointer, some exception fixes, optional XML type conversion.
Contains the latest code as of 7 Aug 2016
20160212 Java 1.6 compatibility, OSGi bundle. Contains the latest code as of 12 Feb 2016.
20151123 JSONObject and JSONArray initialization with generics. Contains the latest code as of 23 Nov 2015.
20150729 Checkpoint for Maven central repository release. Contains the latest code
as of 29 July 2015.
~~~

5
docs/SECURITY.md Normal file
View File

@@ -0,0 +1,5 @@
# Security Policy
## Reporting a Vulnerability
Please follow the instructions in the ["How are vulnerabilities and exploits handled?"](https://github.com/stleary/JSON-java/wiki/FAQ#how-are-vulnerabilities-and-exploits-handled) section in the FAQ.

BIN
gradle/wrapper/gradle-wrapper.jar vendored Normal file

Binary file not shown.

View File

@@ -0,0 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-6.3-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

183
gradlew vendored Normal file
View File

@@ -0,0 +1,183 @@
#!/usr/bin/env sh
#
# Copyright 2015 the original author or authors.
#
# 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
#
# https://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.
#
##############################################################################
##
## Gradle start up script for UN*X
##
##############################################################################
# Attempt to set APP_HOME
# Resolve links: $0 may be a link
PRG="$0"
# Need this for relative symlinks.
while [ -h "$PRG" ] ; do
ls=`ls -ld "$PRG"`
link=`expr "$ls" : '.*-> \(.*\)$'`
if expr "$link" : '/.*' > /dev/null; then
PRG="$link"
else
PRG=`dirname "$PRG"`"/$link"
fi
done
SAVED="`pwd`"
cd "`dirname \"$PRG\"`/" >/dev/null
APP_HOME="`pwd -P`"
cd "$SAVED" >/dev/null
APP_NAME="Gradle"
APP_BASE_NAME=`basename "$0"`
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
MAX_FD="maximum"
warn () {
echo "$*"
}
die () {
echo
echo "$*"
echo
exit 1
}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
case "`uname`" in
CYGWIN* )
cygwin=true
;;
Darwin* )
darwin=true
;;
MINGW* )
msys=true
;;
NONSTOP* )
nonstop=true
;;
esac
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
JAVACMD="$JAVA_HOME/jre/sh/java"
else
JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
JAVACMD="java"
which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
# Increase the maximum file descriptors if we can.
if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
MAX_FD_LIMIT=`ulimit -H -n`
if [ $? -eq 0 ] ; then
if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
MAX_FD="$MAX_FD_LIMIT"
fi
ulimit -n $MAX_FD
if [ $? -ne 0 ] ; then
warn "Could not set maximum file descriptor limit: $MAX_FD"
fi
else
warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
fi
fi
# For Darwin, add options to specify how the application appears in the dock
if $darwin; then
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
fi
# For Cygwin or MSYS, switch paths to Windows format before running java
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
JAVACMD=`cygpath --unix "$JAVACMD"`
# We build the pattern for arguments to be converted via cygpath
ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
SEP=""
for dir in $ROOTDIRSRAW ; do
ROOTDIRS="$ROOTDIRS$SEP$dir"
SEP="|"
done
OURCYGPATTERN="(^($ROOTDIRS))"
# Add a user-defined pattern to the cygpath arguments
if [ "$GRADLE_CYGPATTERN" != "" ] ; then
OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
i=0
for arg in "$@" ; do
CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
else
eval `echo args$i`="\"$arg\""
fi
i=`expr $i + 1`
done
case $i in
0) set -- ;;
1) set -- "$args0" ;;
2) set -- "$args0" "$args1" ;;
3) set -- "$args0" "$args1" "$args2" ;;
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
esac
fi
# Escape application args
save () {
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
echo " "
}
APP_ARGS=`save "$@"`
# Collect all arguments for the java command, following the shell quoting and substitution rules
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"

103
gradlew.bat vendored Normal file
View File

@@ -0,0 +1,103 @@
@rem
@rem Copyright 2015 the original author or authors.
@rem
@rem Licensed under the Apache License, Version 2.0 (the "License");
@rem you may not use this file except in compliance with the License.
@rem You may obtain a copy of the License at
@rem
@rem https://www.apache.org/licenses/LICENSE-2.0
@rem
@rem Unless required by applicable law or agreed to in writing, software
@rem distributed under the License is distributed on an "AS IS" BASIS,
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@rem
@rem ##########################################################################
@rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
@rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init
echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init
echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo.
echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation.
goto fail
:init
@rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args
@rem Slurp the command line arguments.
set CMD_LINE_ARGS=
set _SKIP=2
:win9xME_args_slurp
if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%*
:execute
@rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end
@rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
:omega

BIN
images/JsonJava.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 15 KiB

170
pom.xml Normal file
View File

@@ -0,0 +1,170 @@
<project 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/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20220924</version>
<packaging>bundle</packaging>
<name>JSON in Java</name>
<description>
JSON is a light-weight, language independent, data interchange format.
See http://www.JSON.org/
The files in this package implement JSON encoders/decoders in Java.
It also includes the capability to convert between JSON and XML, HTTP
headers, Cookies, and CDL.
This is a reference implementation. There is a large number of JSON packages
in Java. Perhaps someday the Java community will standardize on one. Until
then, choose carefully.
</description>
<url>https://github.com/douglascrockford/JSON-java</url>
<parent>
<groupId>org.sonatype.oss</groupId>
<artifactId>oss-parent</artifactId>
<version>9</version>
</parent>
<scm>
<url>https://github.com/douglascrockford/JSON-java.git</url>
<connection>scm:git:git://github.com/douglascrockford/JSON-java.git</connection>
<developerConnection>scm:git:git@github.com:douglascrockford/JSON-java.git</developerConnection>
</scm>
<licenses>
<license>
<name>Public Domain</name>
<url>https://github.com/stleary/JSON-java/blob/master/LICENSE</url>
<distribution>repo</distribution>
</license>
</licenses>
<developers>
<developer>
<name>Douglas Crockford</name>
<email>douglas@crockford.com</email>
</developer>
</developers>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.1.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.5</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.0.1</version>
<extensions>true</extensions>
<configuration>
<instructions>
<Export-Package>
org.json
</Export-Package>
<Bundle-SymbolicName>${project.artifactId}</Bundle-SymbolicName>
</instructions>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar-no-fork</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.7</version>
<executions>
<execution>
<id>attach-javadocs</id>
<goals>
<goal>jar</goal>
</goals>
<configuration>
<additionalparam>-Xdoclint:none</additionalparam>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<executions>
<execution>
<id>sign-artifacts</id>
<phase>verify</phase>
<goals>
<goal>sign</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.sonatype.plugins</groupId>
<artifactId>nexus-staging-maven-plugin</artifactId>
<version>1.6.3</version>
<extensions>true</extensions>
<configuration>
<serverId>ossrh</serverId>
<nexusUrl>https://oss.sonatype.org/</nexusUrl>
<autoReleaseAfterClose>false</autoReleaseAfterClose>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-jar-plugin</artifactId>
<version>3.2.0</version>
<configuration>
<archive>
<manifestEntries>
<Automatic-Module-Name>org.json</Automatic-Module-Name>
</manifestEntries>
</archive>
</configuration>
</plugin>
</plugins>
</build>
</project>

View File

@@ -1,27 +1,7 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
/**
@@ -98,7 +78,7 @@ public class CDL {
* Produce a JSONArray of strings from a row of comma delimited values.
* @param x A JSONTokener of the source text.
* @return A JSONArray of strings.
* @throws JSONException
* @throws JSONException if a called function fails
*/
public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException {
JSONArray ja = new JSONArray();
@@ -134,7 +114,7 @@ public class CDL {
* method.
* @param x A JSONTokener of the source text.
* @return A JSONObject combining the names and values.
* @throws JSONException
* @throws JSONException if a called function fails
*/
public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x)
throws JSONException {
@@ -184,7 +164,7 @@ public class CDL {
* using the first row as a source of names.
* @param string The comma delimited text.
* @return A JSONArray of JSONObjects.
* @throws JSONException
* @throws JSONException if a called function fails
*/
public static JSONArray toJSONArray(String string) throws JSONException {
return toJSONArray(new JSONTokener(string));
@@ -195,7 +175,7 @@ public class CDL {
* using the first row as a source of names.
* @param x The JSONTokener containing the comma delimited text.
* @return A JSONArray of JSONObjects.
* @throws JSONException
* @throws JSONException if a called function fails
*/
public static JSONArray toJSONArray(JSONTokener x) throws JSONException {
return toJSONArray(rowToJSONArray(x), x);
@@ -207,7 +187,7 @@ public class CDL {
* @param names A JSONArray of strings.
* @param string The comma delimited text.
* @return A JSONArray of JSONObjects.
* @throws JSONException
* @throws JSONException if a called function fails
*/
public static JSONArray toJSONArray(JSONArray names, String string)
throws JSONException {
@@ -220,7 +200,7 @@ public class CDL {
* @param names A JSONArray of strings.
* @param x A JSONTokener of the source text.
* @return A JSONArray of JSONObjects.
* @throws JSONException
* @throws JSONException if a called function fails
*/
public static JSONArray toJSONArray(JSONArray names, JSONTokener x)
throws JSONException {
@@ -248,7 +228,7 @@ public class CDL {
* JSONObject.
* @param ja A JSONArray of JSONObjects.
* @return A comma delimited text.
* @throws JSONException
* @throws JSONException if a called function fails
*/
public static String toString(JSONArray ja) throws JSONException {
JSONObject jo = ja.optJSONObject(0);
@@ -268,7 +248,7 @@ public class CDL {
* @param names A JSONArray of strings.
* @param ja A JSONArray of JSONObjects.
* @return A comma delimited text.
* @throws JSONException
* @throws JSONException if a called function fails
*/
public static String toString(JSONArray names, JSONArray ja)
throws JSONException {

View File

@@ -0,0 +1,204 @@
package org.json;
import java.util.Locale;
/*
Public Domain.
*/
/**
* Convert a web browser cookie specification to a JSONObject and back.
* JSON and Cookies are both notations for name/value pairs.
* See also: <a href="https://tools.ietf.org/html/rfc6265">https://tools.ietf.org/html/rfc6265</a>
* @author JSON.org
* @version 2015-12-09
*/
public class Cookie {
/**
* Produce a copy of a string in which the characters '+', '%', '=', ';'
* and control characters are replaced with "%hh". This is a gentle form
* of URL encoding, attempting to cause as little distortion to the
* string as possible. The characters '=' and ';' are meta characters in
* cookies. By convention, they are escaped using the URL-encoding. This is
* only a convention, not a standard. Often, cookies are expected to have
* encoded values. We encode '=' and ';' because we must. We encode '%' and
* '+' because they are meta characters in URL encoding.
* @param string The source string.
* @return The escaped result.
*/
public static String escape(String string) {
char c;
String s = string.trim();
int length = s.length();
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; i += 1) {
c = s.charAt(i);
if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') {
sb.append('%');
sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16));
sb.append(Character.forDigit((char)(c & 0x0f), 16));
} else {
sb.append(c);
}
}
return sb.toString();
}
/**
* Convert a cookie specification string into a JSONObject. The string
* must contain a name value pair separated by '='. The name and the value
* will be unescaped, possibly converting '+' and '%' sequences. The
* cookie properties may follow, separated by ';', also represented as
* name=value (except the Attribute properties like "Secure" or "HttpOnly",
* which do not have a value. The value {@link Boolean#TRUE} will be used for these).
* The name will be stored under the key "name", and the value will be
* stored under the key "value". This method does not do checking or
* validation of the parameters. It only converts the cookie string into
* a JSONObject. All attribute names are converted to lower case keys in the
* JSONObject (HttpOnly =&gt; httponly). If an attribute is specified more than
* once, only the value found closer to the end of the cookie-string is kept.
* @param string The cookie specification string.
* @return A JSONObject containing "name", "value", and possibly other
* members.
* @throws JSONException If there is an error parsing the Cookie String.
* Cookie strings must have at least one '=' character and the 'name'
* portion of the cookie must not be blank.
*/
public static JSONObject toJSONObject(String string) {
final JSONObject jo = new JSONObject();
String name;
Object value;
JSONTokener x = new JSONTokener(string);
name = unescape(x.nextTo('=').trim());
//per RFC6265, if the name is blank, the cookie should be ignored.
if("".equals(name)) {
throw new JSONException("Cookies must have a 'name'");
}
jo.put("name", name);
// per RFC6265, if there is no '=', the cookie should be ignored.
// the 'next' call here throws an exception if the '=' is not found.
x.next('=');
jo.put("value", unescape(x.nextTo(';')).trim());
// discard the ';'
x.next();
// parse the remaining cookie attributes
while (x.more()) {
name = unescape(x.nextTo("=;")).trim().toLowerCase(Locale.ROOT);
// don't allow a cookies attributes to overwrite its name or value.
if("name".equalsIgnoreCase(name)) {
throw new JSONException("Illegal attribute name: 'name'");
}
if("value".equalsIgnoreCase(name)) {
throw new JSONException("Illegal attribute name: 'value'");
}
// check to see if it's a flag property
if (x.next() != '=') {
value = Boolean.TRUE;
} else {
value = unescape(x.nextTo(';')).trim();
x.next();
}
// only store non-blank attributes
if(!"".equals(name) && !"".equals(value)) {
jo.put(name, value);
}
}
return jo;
}
/**
* Convert a JSONObject into a cookie specification string. The JSONObject
* must contain "name" and "value" members (case insensitive).
* If the JSONObject contains other members, they will be appended to the cookie
* specification string. User-Agents are instructed to ignore unknown attributes,
* so ensure your JSONObject is using only known attributes.
* See also: <a href="https://tools.ietf.org/html/rfc6265">https://tools.ietf.org/html/rfc6265</a>
* @param jo A JSONObject
* @return A cookie specification string
* @throws JSONException thrown if the cookie has no name.
*/
public static String toString(JSONObject jo) throws JSONException {
StringBuilder sb = new StringBuilder();
String name = null;
Object value = null;
for(String key : jo.keySet()){
if("name".equalsIgnoreCase(key)) {
name = jo.getString(key).trim();
}
if("value".equalsIgnoreCase(key)) {
value=jo.getString(key).trim();
}
if(name != null && value != null) {
break;
}
}
if(name == null || "".equals(name.trim())) {
throw new JSONException("Cookie does not have a name");
}
if(value == null) {
value = "";
}
sb.append(escape(name));
sb.append("=");
sb.append(escape((String)value));
for(String key : jo.keySet()){
if("name".equalsIgnoreCase(key)
|| "value".equalsIgnoreCase(key)) {
// already processed above
continue;
}
value = jo.opt(key);
if(value instanceof Boolean) {
if(Boolean.TRUE.equals(value)) {
sb.append(';').append(escape(key));
}
// don't emit false values
} else {
sb.append(';')
.append(escape(key))
.append('=')
.append(escape(value.toString()));
}
}
return sb.toString();
}
/**
* Convert <code>%</code><i>hh</i> sequences to single characters, and
* convert plus to space.
* @param string A string that may contain
* <code>+</code>&nbsp;<small>(plus)</small> and
* <code>%</code><i>hh</i> sequences.
* @return The unescaped string.
*/
public static String unescape(String string) {
int length = string.length();
StringBuilder sb = new StringBuilder(length);
for (int i = 0; i < length; ++i) {
char c = string.charAt(i);
if (c == '+') {
c = ' ';
} else if (c == '%' && i + 2 < length) {
int d = JSONTokener.dehexchar(string.charAt(i + 1));
int e = JSONTokener.dehexchar(string.charAt(i + 2));
if (d >= 0 && e >= 0) {
c = (char)(d * 16 + e);
i += 2;
}
}
sb.append(c);
}
return sb.toString();
}
}

View File

@@ -1,27 +1,7 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
/**
@@ -42,7 +22,7 @@ public class CookieList {
* cookieJSONObject.getString("value"));
* @param string A cookie list string
* @return A JSONObject
* @throws JSONException
* @throws JSONException if a called function fails
*/
public static JSONObject toJSONObject(String string) throws JSONException {
JSONObject jo = new JSONObject();
@@ -63,7 +43,7 @@ public class CookieList {
* in the names and values are replaced by "%hh".
* @param jo A JSONObject
* @return A cookie list string
* @throws JSONException
* @throws JSONException if a called function fails
*/
public static String toString(JSONObject jo) throws JSONException {
boolean b = false;

View File

@@ -1,162 +1,142 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import java.util.Locale;
/**
* Convert an HTTP header to a JSONObject and back.
* @author JSON.org
* @version 2015-12-09
*/
public class HTTP {
/** Carriage return/line feed. */
public static final String CRLF = "\r\n";
/**
* Convert an HTTP header string into a JSONObject. It can be a request
* header or a response header. A request header will contain
* <pre>{
* Method: "POST" (for example),
* "Request-URI": "/" (for example),
* "HTTP-Version": "HTTP/1.1" (for example)
* }</pre>
* A response header will contain
* <pre>{
* "HTTP-Version": "HTTP/1.1" (for example),
* "Status-Code": "200" (for example),
* "Reason-Phrase": "OK" (for example)
* }</pre>
* In addition, the other parameters in the header will be captured, using
* the HTTP field names as JSON names, so that <pre>
* Date: Sun, 26 May 2002 18:06:04 GMT
* Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
* Cache-Control: no-cache</pre>
* become
* <pre>{...
* Date: "Sun, 26 May 2002 18:06:04 GMT",
* Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
* "Cache-Control": "no-cache",
* ...}</pre>
* It does no further checking or conversion. It does not parse dates.
* It does not do '%' transforms on URLs.
* @param string An HTTP header string.
* @return A JSONObject containing the elements and attributes
* of the XML string.
* @throws JSONException
*/
public static JSONObject toJSONObject(String string) throws JSONException {
JSONObject jo = new JSONObject();
HTTPTokener x = new HTTPTokener(string);
String token;
token = x.nextToken();
if (token.toUpperCase(Locale.ROOT).startsWith("HTTP")) {
// Response
jo.put("HTTP-Version", token);
jo.put("Status-Code", x.nextToken());
jo.put("Reason-Phrase", x.nextTo('\0'));
x.next();
} else {
// Request
jo.put("Method", token);
jo.put("Request-URI", x.nextToken());
jo.put("HTTP-Version", x.nextToken());
}
// Fields
while (x.more()) {
String name = x.nextTo(':');
x.next(':');
jo.put(name, x.nextTo('\0'));
x.next();
}
return jo;
}
/**
* Convert a JSONObject into an HTTP header. A request header must contain
* <pre>{
* Method: "POST" (for example),
* "Request-URI": "/" (for example),
* "HTTP-Version": "HTTP/1.1" (for example)
* }</pre>
* A response header must contain
* <pre>{
* "HTTP-Version": "HTTP/1.1" (for example),
* "Status-Code": "200" (for example),
* "Reason-Phrase": "OK" (for example)
* }</pre>
* Any other members of the JSONObject will be output as HTTP fields.
* The result will end with two CRLF pairs.
* @param jo A JSONObject
* @return An HTTP header string.
* @throws JSONException if the object does not contain enough
* information.
*/
public static String toString(JSONObject jo) throws JSONException {
StringBuilder sb = new StringBuilder();
if (jo.has("Status-Code") && jo.has("Reason-Phrase")) {
sb.append(jo.getString("HTTP-Version"));
sb.append(' ');
sb.append(jo.getString("Status-Code"));
sb.append(' ');
sb.append(jo.getString("Reason-Phrase"));
} else if (jo.has("Method") && jo.has("Request-URI")) {
sb.append(jo.getString("Method"));
sb.append(' ');
sb.append('"');
sb.append(jo.getString("Request-URI"));
sb.append('"');
sb.append(' ');
sb.append(jo.getString("HTTP-Version"));
} else {
throw new JSONException("Not enough material for an HTTP header.");
}
sb.append(CRLF);
// Don't use the new entrySet API to maintain Android support
for (final String key : jo.keySet()) {
String value = jo.optString(key);
if (!"HTTP-Version".equals(key) && !"Status-Code".equals(key) &&
!"Reason-Phrase".equals(key) && !"Method".equals(key) &&
!"Request-URI".equals(key) && !JSONObject.NULL.equals(value)) {
sb.append(key);
sb.append(": ");
sb.append(jo.optString(key));
sb.append(CRLF);
}
}
sb.append(CRLF);
return sb.toString();
}
}
package org.json;
/*
Public Domain.
*/
import java.util.Locale;
/**
* Convert an HTTP header to a JSONObject and back.
* @author JSON.org
* @version 2015-12-09
*/
public class HTTP {
/** Carriage return/line feed. */
public static final String CRLF = "\r\n";
/**
* Convert an HTTP header string into a JSONObject. It can be a request
* header or a response header. A request header will contain
* <pre>{
* Method: "POST" (for example),
* "Request-URI": "/" (for example),
* "HTTP-Version": "HTTP/1.1" (for example)
* }</pre>
* A response header will contain
* <pre>{
* "HTTP-Version": "HTTP/1.1" (for example),
* "Status-Code": "200" (for example),
* "Reason-Phrase": "OK" (for example)
* }</pre>
* In addition, the other parameters in the header will be captured, using
* the HTTP field names as JSON names, so that <pre>{@code
* Date: Sun, 26 May 2002 18:06:04 GMT
* Cookie: Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s
* Cache-Control: no-cache}</pre>
* become
* <pre>{@code
* Date: "Sun, 26 May 2002 18:06:04 GMT",
* Cookie: "Q=q2=PPEAsg--; B=677gi6ouf29bn&b=2&f=s",
* "Cache-Control": "no-cache",
* ...}</pre>
* It does no further checking or conversion. It does not parse dates.
* It does not do '%' transforms on URLs.
* @param string An HTTP header string.
* @return A JSONObject containing the elements and attributes
* of the XML string.
* @throws JSONException if a called function fails
*/
public static JSONObject toJSONObject(String string) throws JSONException {
JSONObject jo = new JSONObject();
HTTPTokener x = new HTTPTokener(string);
String token;
token = x.nextToken();
if (token.toUpperCase(Locale.ROOT).startsWith("HTTP")) {
// Response
jo.put("HTTP-Version", token);
jo.put("Status-Code", x.nextToken());
jo.put("Reason-Phrase", x.nextTo('\0'));
x.next();
} else {
// Request
jo.put("Method", token);
jo.put("Request-URI", x.nextToken());
jo.put("HTTP-Version", x.nextToken());
}
// Fields
while (x.more()) {
String name = x.nextTo(':');
x.next(':');
jo.put(name, x.nextTo('\0'));
x.next();
}
return jo;
}
/**
* Convert a JSONObject into an HTTP header. A request header must contain
* <pre>{
* Method: "POST" (for example),
* "Request-URI": "/" (for example),
* "HTTP-Version": "HTTP/1.1" (for example)
* }</pre>
* A response header must contain
* <pre>{
* "HTTP-Version": "HTTP/1.1" (for example),
* "Status-Code": "200" (for example),
* "Reason-Phrase": "OK" (for example)
* }</pre>
* Any other members of the JSONObject will be output as HTTP fields.
* The result will end with two CRLF pairs.
* @param jo A JSONObject
* @return An HTTP header string.
* @throws JSONException if the object does not contain enough
* information.
*/
public static String toString(JSONObject jo) throws JSONException {
StringBuilder sb = new StringBuilder();
if (jo.has("Status-Code") && jo.has("Reason-Phrase")) {
sb.append(jo.getString("HTTP-Version"));
sb.append(' ');
sb.append(jo.getString("Status-Code"));
sb.append(' ');
sb.append(jo.getString("Reason-Phrase"));
} else if (jo.has("Method") && jo.has("Request-URI")) {
sb.append(jo.getString("Method"));
sb.append(' ');
sb.append('"');
sb.append(jo.getString("Request-URI"));
sb.append('"');
sb.append(' ');
sb.append(jo.getString("HTTP-Version"));
} else {
throw new JSONException("Not enough material for an HTTP header.");
}
sb.append(CRLF);
// Don't use the new entrySet API to maintain Android support
for (final String key : jo.keySet()) {
String value = jo.optString(key);
if (!"HTTP-Version".equals(key) && !"Status-Code".equals(key) &&
!"Reason-Phrase".equals(key) && !"Method".equals(key) &&
!"Request-URI".equals(key) && !JSONObject.NULL.equals(value)) {
sb.append(key);
sb.append(": ");
sb.append(jo.optString(key));
sb.append(CRLF);
}
}
sb.append(CRLF);
return sb.toString();
}
}

View File

@@ -1,27 +1,7 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
/**
@@ -43,8 +23,8 @@ public class HTTPTokener extends JSONTokener {
/**
* Get the next token or string. This is used in parsing HTTP headers.
* @throws JSONException
* @return A String.
* @throws JSONException if a syntax error occurs
*/
public String nextToken() throws JSONException {
char c;

View File

@@ -1,27 +1,7 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import java.io.IOException;
@@ -173,9 +153,37 @@ public class JSONArray implements Iterable<Object> {
this.myArrayList = new ArrayList<Object>();
} else {
this.myArrayList = new ArrayList<Object>(collection.size());
for (Object o: collection){
this.myArrayList.add(JSONObject.wrap(o));
}
this.addAll(collection, true);
}
}
/**
* Construct a JSONArray from an Iterable. This is a shallow copy.
*
* @param iter
* A Iterable collection.
*/
public JSONArray(Iterable<?> iter) {
this();
if (iter == null) {
return;
}
this.addAll(iter, true);
}
/**
* Construct a JSONArray from another JSONArray. This is a shallow copy.
*
* @param array
* A array.
*/
public JSONArray(JSONArray array) {
if (array == null) {
this.myArrayList = new ArrayList<Object>();
} else {
// shallow copy directly the internal array lists as any wrapping
// should have been done already in the original JSONArray
this.myArrayList = new ArrayList<Object>(array.myArrayList);
}
}
@@ -193,16 +201,27 @@ public class JSONArray implements Iterable<Object> {
*/
public JSONArray(Object array) throws JSONException {
this();
if (array.getClass().isArray()) {
int length = Array.getLength(array);
this.myArrayList.ensureCapacity(length);
for (int i = 0; i < length; i += 1) {
this.put(JSONObject.wrap(Array.get(array, i)));
}
} else {
if (!array.getClass().isArray()) {
throw new JSONException(
"JSONArray initial value should be a string or collection or array.");
}
this.addAll(array, true);
}
/**
* Construct a JSONArray with the specified initial capacity.
*
* @param initialCapacity
* the initial capacity of the JSONArray.
* @throws JSONException
* If the initial capacity is negative.
*/
public JSONArray(int initialCapacity) throws JSONException {
if (initialCapacity < 0) {
throw new JSONException(
"JSONArray initial capacity cannot be negative.");
}
this.myArrayList = new ArrayList<Object>(initialCapacity);
}
@Override
@@ -249,7 +268,7 @@ public class JSONArray implements Iterable<Object> {
.equalsIgnoreCase("true"))) {
return true;
}
throw wrongValueFormatException(index, "boolean", null);
throw wrongValueFormatException(index, "boolean", object, null);
}
/**
@@ -270,7 +289,7 @@ public class JSONArray implements Iterable<Object> {
try {
return Double.parseDouble(object.toString());
} catch (Exception e) {
throw wrongValueFormatException(index, "double", e);
throw wrongValueFormatException(index, "double", object, e);
}
}
@@ -287,12 +306,12 @@ public class JSONArray implements Iterable<Object> {
public float getFloat(int index) throws JSONException {
final Object object = this.get(index);
if(object instanceof Number) {
return ((Float)object).floatValue();
return ((Number)object).floatValue();
}
try {
return Float.parseFloat(object.toString());
} catch (Exception e) {
throw wrongValueFormatException(index, "float", e);
throw wrongValueFormatException(index, "float", object, e);
}
}
@@ -314,7 +333,7 @@ public class JSONArray implements Iterable<Object> {
}
return JSONObject.stringToNumber(object.toString());
} catch (Exception e) {
throw wrongValueFormatException(index, "number", e);
throw wrongValueFormatException(index, "number", object, e);
}
}
@@ -339,14 +358,14 @@ public class JSONArray implements Iterable<Object> {
// If it did, I would re-implement this with the Enum.valueOf
// method and place any thrown exception in the JSONException
throw wrongValueFormatException(index, "enum of type "
+ JSONObject.quote(clazz.getSimpleName()), null);
+ JSONObject.quote(clazz.getSimpleName()), opt(index), null);
}
return val;
}
/**
* Get the BigDecimal value associated with an index. If the value is float
* or double, the the {@link BigDecimal#BigDecimal(double)} constructor
* or double, the {@link BigDecimal#BigDecimal(double)} constructor
* will be used. See notes on the constructor for conversion issues that
* may arise.
*
@@ -402,7 +421,7 @@ public class JSONArray implements Iterable<Object> {
try {
return Integer.parseInt(object.toString());
} catch (Exception e) {
throw wrongValueFormatException(index, "int", e);
throw wrongValueFormatException(index, "int", object, e);
}
}
@@ -421,7 +440,7 @@ public class JSONArray implements Iterable<Object> {
if (object instanceof JSONArray) {
return (JSONArray) object;
}
throw wrongValueFormatException(index, "JSONArray", null);
throw wrongValueFormatException(index, "JSONArray", object, null);
}
/**
@@ -439,7 +458,7 @@ public class JSONArray implements Iterable<Object> {
if (object instanceof JSONObject) {
return (JSONObject) object;
}
throw wrongValueFormatException(index, "JSONObject", null);
throw wrongValueFormatException(index, "JSONObject", object, null);
}
/**
@@ -460,7 +479,7 @@ public class JSONArray implements Iterable<Object> {
try {
return Long.parseLong(object.toString());
} catch (Exception e) {
throw wrongValueFormatException(index, "long", e);
throw wrongValueFormatException(index, "long", object, e);
}
}
@@ -478,7 +497,7 @@ public class JSONArray implements Iterable<Object> {
if (object instanceof String) {
return (String) object;
}
throw wrongValueFormatException(index, "String", null);
throw wrongValueFormatException(index, "String", object, null);
}
/**
@@ -528,6 +547,14 @@ public class JSONArray implements Iterable<Object> {
return this.myArrayList.size();
}
/**
* Removes all of the elements from this JSONArray.
* The JSONArray will be empty after this call returns.
*/
public void clear() {
this.myArrayList.clear();
}
/**
* Get the optional object value associated with an index.
*
@@ -745,7 +772,7 @@ public class JSONArray implements Iterable<Object> {
* Get the optional BigDecimal value associated with an index. The
* defaultValue is returned if there is no value for the index, or if the
* value is not a number and cannot be converted to a number. If the value
* is float or double, the the {@link BigDecimal#BigDecimal(double)}
* is float or double, the {@link BigDecimal#BigDecimal(double)}
* constructor will be used. See notes on the constructor for conversion
* issues that may arise.
*
@@ -1110,7 +1137,7 @@ public class JSONArray implements Iterable<Object> {
* The Map value.
* @return this.
* @throws JSONException
* If the index is negative or if the the value is an invalid
* If the index is negative or if the value is an invalid
* number.
* @throws NullPointerException
* If a key in the map is <code>null</code>
@@ -1133,7 +1160,7 @@ public class JSONArray implements Iterable<Object> {
* String, or the JSONObject.NULL object.
* @return this.
* @throws JSONException
* If the index is negative or if the the value is an invalid
* If the index is negative or if the value is an invalid
* number.
*/
public JSONArray put(int index, Object value) throws JSONException {
@@ -1158,6 +1185,62 @@ public class JSONArray implements Iterable<Object> {
}
return this.put(value);
}
/**
* Put a collection's elements in to the JSONArray.
*
* @param collection
* A Collection.
* @return this.
*/
public JSONArray putAll(Collection<?> collection) {
this.addAll(collection, false);
return this;
}
/**
* Put an Iterable's elements in to the JSONArray.
*
* @param iter
* An Iterable.
* @return this.
*/
public JSONArray putAll(Iterable<?> iter) {
this.addAll(iter, false);
return this;
}
/**
* Put a JSONArray's elements in to the JSONArray.
*
* @param array
* A JSONArray.
* @return this.
*/
public JSONArray putAll(JSONArray array) {
// directly copy the elements from the source array to this one
// as all wrapping should have been done already in the source.
this.myArrayList.addAll(array.myArrayList);
return this;
}
/**
* Put an array's elements in to the JSONArray.
*
* @param array
* Array. If the parameter passed is null, or not an array or Iterable, an
* exception will be thrown.
* @return this.
*
* @throws JSONException
* If not an array, JSONArray, Iterable or if an value is non-finite number.
* @throws NullPointerException
* Thrown if the array parameter is null.
*/
public JSONArray putAll(Object array) throws JSONException {
this.addAll(array, false);
return this;
}
/**
* Creates a JSONPointer using an initialization string and tries to
@@ -1279,6 +1362,14 @@ public class JSONArray implements Iterable<Object> {
if (!((JSONArray)valueThis).similar(valueOther)) {
return false;
}
} else if (valueThis instanceof Number && valueOther instanceof Number) {
if (!JSONObject.isNumberSimilar((Number)valueThis, (Number)valueOther)) {
return false;
}
} else if (valueThis instanceof JSONString && valueOther instanceof JSONString) {
if (!((JSONString) valueThis).toJSONString().equals(((JSONString) valueOther).toJSONString())) {
return false;
}
} else if (!valueThis.equals(valueOther)) {
return false;
}
@@ -1333,7 +1424,7 @@ public class JSONArray implements Iterable<Object> {
/**
* Make a pretty-printed JSON text of this JSONArray.
*
* <p>If <code>indentFactor > 0</code> and the {@link JSONArray} has only
* <p>If <pre> {@code indentFactor > 0}</pre> and the {@link JSONArray} has only
* one element, then the array will be output on a single line:
* <pre>{@code [1]}</pre>
*
@@ -1355,8 +1446,9 @@ public class JSONArray implements Iterable<Object> {
* object, beginning with <code>[</code>&nbsp;<small>(left
* bracket)</small> and ending with <code>]</code>
* &nbsp;<small>(right bracket)</small>.
* @throws JSONException
* @throws JSONException if a called function fails
*/
@SuppressWarnings("resource")
public String toString(int indentFactor) throws JSONException {
StringWriter sw = new StringWriter();
synchronized (sw.getBuffer()) {
@@ -1370,9 +1462,9 @@ public class JSONArray implements Iterable<Object> {
* <p><b>
* Warning: This method assumes that the data structure is acyclical.
*</b>
*
* @param writer the writer object
* @return The writer.
* @throws JSONException
* @throws JSONException if a called function fails
*/
public Writer write(Writer writer) throws JSONException {
return this.write(writer, 0, 0);
@@ -1381,7 +1473,7 @@ public class JSONArray implements Iterable<Object> {
/**
* Write the contents of the JSONArray as JSON text to a writer.
*
* <p>If <code>indentFactor > 0</code> and the {@link JSONArray} has only
* <p>If <pre>{@code indentFactor > 0}</pre> and the {@link JSONArray} has only
* one element, then the array will be output on a single line:
* <pre>{@code [1]}</pre>
*
@@ -1404,8 +1496,9 @@ public class JSONArray implements Iterable<Object> {
* @param indent
* The indentation of the top level.
* @return The writer.
* @throws JSONException
* @throws JSONException if a called function fails or unable to write
*/
@SuppressWarnings("resource")
public Writer write(Writer writer, int indentFactor, int indent)
throws JSONException {
try {
@@ -1484,21 +1577,93 @@ public class JSONArray implements Iterable<Object> {
public boolean isEmpty() {
return this.myArrayList.isEmpty();
}
/**
* Add a collection's elements to the JSONArray.
*
* @param collection
* A Collection.
* @param wrap
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
* {@code false} to add the items directly
*
*/
private void addAll(Collection<?> collection, boolean wrap) {
this.myArrayList.ensureCapacity(this.myArrayList.size() + collection.size());
if (wrap) {
for (Object o: collection){
this.put(JSONObject.wrap(o));
}
} else {
for (Object o: collection){
this.put(o);
}
}
}
/**
* Add an Iterable's elements to the JSONArray.
*
* @param iter
* An Iterable.
* @param wrap
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
* {@code false} to add the items directly
*/
private void addAll(Iterable<?> iter, boolean wrap) {
if (wrap) {
for (Object o: iter){
this.put(JSONObject.wrap(o));
}
} else {
for (Object o: iter){
this.put(o);
}
}
}
/**
* Create a new JSONException in a common format for incorrect conversions.
* @param idx index of the item
* @param valueType the type of value being coerced to
* @param cause optional cause of the coercion failure
* @return JSONException that can be thrown.
* Add an array's elements to the JSONArray.
*
* @param array
* Array. If the parameter passed is null, or not an array,
* JSONArray, Collection, or Iterable, an exception will be
* thrown.
* @param wrap
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
* {@code false} to add the items directly
*
* @throws JSONException
* If not an array or if an array value is non-finite number.
* @throws NullPointerException
* Thrown if the array parameter is null.
*/
private static JSONException wrongValueFormatException(
int idx,
String valueType,
Throwable cause) {
return new JSONException(
"JSONArray[" + idx + "] is not a " + valueType + "."
, cause);
private void addAll(Object array, boolean wrap) throws JSONException {
if (array.getClass().isArray()) {
int length = Array.getLength(array);
this.myArrayList.ensureCapacity(this.myArrayList.size() + length);
if (wrap) {
for (int i = 0; i < length; i += 1) {
this.put(JSONObject.wrap(Array.get(array, i)));
}
} else {
for (int i = 0; i < length; i += 1) {
this.put(Array.get(array, i));
}
}
} else if (array instanceof JSONArray) {
// use the built in array list `addAll` as all object
// wrapping should have been completed in the original
// JSONArray
this.myArrayList.addAll(((JSONArray)array).myArrayList);
} else if (array instanceof Collection) {
this.addAll((Collection<?>)array, wrap);
} else if (array instanceof Iterable) {
this.addAll((Iterable<?>)array, wrap);
} else {
throw new JSONException(
"JSONArray initial value should be a string or collection or array.");
}
}
/**
@@ -1513,8 +1678,19 @@ public class JSONArray implements Iterable<Object> {
String valueType,
Object value,
Throwable cause) {
if(value == null) {
return new JSONException(
"JSONArray[" + idx + "] is not a " + valueType + " (null)."
, cause);
}
// don't try to toString collections or known object types that could be large.
if(value instanceof Map || value instanceof Iterable || value instanceof JSONObject) {
return new JSONException(
"JSONArray[" + idx + "] is not a " + valueType + " (" + value.getClass() + ")."
, cause);
}
return new JSONException(
"JSONArray[" + idx + "] is not a " + valueType + " (" + value + ")."
"JSONArray[" + idx + "] is not a " + valueType + " (" + value.getClass() + " : " + value + ")."
, cause);
}

View File

@@ -1,27 +1,7 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
/**

View File

@@ -1,27 +1,7 @@
package org.json;
/*
Copyright (c) 2008 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
/**
@@ -41,7 +21,7 @@ public class JSONML {
* if we are at the outermost level.
* @param keepStrings Don't type-convert text nodes and attribute values
* @return A JSONArray if the value is the outermost tag, otherwise null.
* @throws JSONException
* @throws JSONException if a parsing error occurs
*/
private static Object parse(
XMLTokener x,
@@ -238,7 +218,7 @@ public class JSONML {
* attributes, then the second element will be JSONObject containing the
* name/value pairs. If the tag contains children, then strings and
* JSONArrays will represent the child tags.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* Comments, prologs, DTDs, and <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param string The source string.
* @return A JSONArray containing the structured data from the XML string.
* @throws JSONException Thrown on error converting to a JSONArray
@@ -258,7 +238,7 @@ public class JSONML {
* As opposed to toJSONArray this method does not attempt to convert
* any text node or attribute value to any type
* but just leaves it as a string.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* Comments, prologs, DTDs, and <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param string The source string.
* @param keepStrings If true, then values will not be coerced into boolean
* or numeric values and will instead be left as strings
@@ -280,7 +260,7 @@ public class JSONML {
* As opposed to toJSONArray this method does not attempt to convert
* any text node or attribute value to any type
* but just leaves it as a string.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* Comments, prologs, DTDs, and <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param x An XMLTokener.
* @param keepStrings If true, then values will not be coerced into boolean
* or numeric values and will instead be left as strings
@@ -299,7 +279,7 @@ public class JSONML {
* attributes, then the second element will be JSONObject containing the
* name/value pairs. If the tag contains children, then strings and
* JSONArrays will represent the child content and tags.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* Comments, prologs, DTDs, and <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param x An XMLTokener.
* @return A JSONArray containing the structured data from the XML string.
* @throws JSONException Thrown on error converting to a JSONArray
@@ -317,7 +297,7 @@ public class JSONML {
* contains children, the object will have a "childNodes" property which
* will be an array of strings and JsonML JSONObjects.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* Comments, prologs, DTDs, and <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param string The XML source text.
* @return A JSONObject containing the structured data from the XML string.
* @throws JSONException Thrown on error converting to a JSONObject
@@ -335,7 +315,7 @@ public class JSONML {
* contains children, the object will have a "childNodes" property which
* will be an array of strings and JsonML JSONObjects.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* Comments, prologs, DTDs, and <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param string The XML source text.
* @param keepStrings If true, then values will not be coerced into boolean
* or numeric values and will instead be left as strings
@@ -355,7 +335,7 @@ public class JSONML {
* contains children, the object will have a "childNodes" property which
* will be an array of strings and JsonML JSONObjects.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* Comments, prologs, DTDs, and <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param x An XMLTokener of the XML source text.
* @return A JSONObject containing the structured data from the XML string.
* @throws JSONException Thrown on error converting to a JSONObject
@@ -373,7 +353,7 @@ public class JSONML {
* contains children, the object will have a "childNodes" property which
* will be an array of strings and JsonML JSONObjects.
* Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code> are ignored.
* Comments, prologs, DTDs, and <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param x An XMLTokener of the XML source text.
* @param keepStrings If true, then values will not be coerced into boolean
* or numeric values and will instead be left as strings

View File

@@ -1,31 +1,10 @@
package org.json;
import java.io.Closeable;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
Public Domain.
*/
import java.io.Closeable;
import java.io.IOException;
import java.io.StringWriter;
import java.io.Writer;
@@ -37,8 +16,10 @@ import java.lang.reflect.Modifier;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Collection;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Locale;
import java.util.Map;
@@ -128,6 +109,7 @@ public class JSONObject {
* null.
*/
@Override
@SuppressWarnings("lgtm[java/unchecked-cast-in-equals]")
public boolean equals(Object object) {
return object == null || object == this;
}
@@ -151,10 +133,10 @@ public class JSONObject {
return "null";
}
}
/**
* Regular Expression Pattern that matches JSON Numbers. This is primarily used for
* output to guarantee that we are always writing valid JSON.
* output to guarantee that we are always writing valid JSON.
*/
static final Pattern NUMBER_PATTERN = Pattern.compile("-?(?:0|[1-9]\\d*)(?:\\.\\d+)?(?:[eE][+-]?\\d+)?");
@@ -163,6 +145,10 @@ public class JSONObject {
*/
private final Map<String, Object> map;
public Class<? extends Map> getMapType() {
return map.getClass();
}
/**
* It is sometimes more convenient and less ambiguous to have a
* <code>NULL</code> object than to use Java's <code>null</code> value.
@@ -175,10 +161,10 @@ public class JSONObject {
* Construct an empty JSONObject.
*/
public JSONObject() {
// HashMap is used on purpose to ensure that elements are unordered by
// HashMap is used on purpose to ensure that elements are unordered by
// the specification.
// JSON tends to be a portable transfer format to allows the container
// implementations to rearrange their items for a faster element
// JSON tends to be a portable transfer format to allows the container
// implementations to rearrange their items for a faster element
// retrieval based on associative access.
// Therefore, an implementation mustn't rely on the order of the item.
this.map = new HashMap<String, Object>();
@@ -222,12 +208,19 @@ public class JSONObject {
throw x.syntaxError("A JSONObject text must begin with '{'");
}
for (;;) {
char prev = x.getPrevious();
c = x.nextClean();
switch (c) {
case 0:
throw x.syntaxError("A JSONObject text must end with '}'");
case '}':
return;
case '{':
case '[':
if(prev=='{') {
throw x.syntaxError("A JSON Object can not directly nest another JSON Object or JSON Array.");
}
// fall through
default:
x.back();
key = x.nextValue().toString();
@@ -239,9 +232,9 @@ public class JSONObject {
if (c != ':') {
throw x.syntaxError("Expected a ':' after a key");
}
// Use syntaxError(..) to include error location
if (key != null) {
// Check if key exists
if (this.opt(key) != null) {
@@ -350,11 +343,11 @@ public class JSONObject {
* method from being serialized:
* <pre>
* &#64;JSONPropertyName("FullName")
* &#64;JSONPropertyIgnore
* &#64;JSONPropertyIgnore
* public String getName() { return this.name; }
* </pre>
* <p>
*
*
* @param bean
* An object that has getter methods that should be used to make
* a JSONObject.
@@ -364,6 +357,11 @@ public class JSONObject {
this.populateMap(bean);
}
private JSONObject(Object bean, Set<Object> objectsRecord) {
this();
this.populateMap(bean, objectsRecord);
}
/**
* Construct a JSONObject from an Object, using reflection to find the
* public members. The resulting JSONObject's keys will be the strings from
@@ -448,12 +446,12 @@ public class JSONObject {
}
}
}
/**
* Constructor to specify an initial capacity of the internal map. Useful for library
* Constructor to specify an initial capacity of the internal map. Useful for library
* internal calls where we know, or at least can best guess, how big this JSONObject
* will be.
*
*
* @param initialCapacity initial capacity of the internal map.
*/
protected JSONObject(int initialCapacity){
@@ -576,7 +574,7 @@ public class JSONObject {
/**
* Get the enum value associated with a key.
*
*
* @param <E>
* Enum Type
* @param clazz
@@ -594,7 +592,7 @@ public class JSONObject {
// JSONException should really take a throwable argument.
// If it did, I would re-implement this with the Enum.valueOf
// method and place any thrown exception in the JSONException
throw wrongValueFormatException(key, "enum of type " + quote(clazz.getSimpleName()), null);
throw wrongValueFormatException(key, "enum of type " + quote(clazz.getSimpleName()), opt(key), null);
}
return val;
}
@@ -620,7 +618,7 @@ public class JSONObject {
.equalsIgnoreCase("true"))) {
return true;
}
throw wrongValueFormatException(key, "Boolean", null);
throw wrongValueFormatException(key, "Boolean", object, null);
}
/**
@@ -630,7 +628,7 @@ public class JSONObject {
* A key string.
* @return The numeric value.
* @throws JSONException
* if the key is not found or if the value cannot
* if the key is not found or if the value cannot
* be converted to BigInteger.
*/
public BigInteger getBigInteger(String key) throws JSONException {
@@ -644,7 +642,7 @@ public class JSONObject {
/**
* Get the BigDecimal value associated with a key. If the value is float or
* double, the the {@link BigDecimal#BigDecimal(double)} constructor will
* double, the {@link BigDecimal#BigDecimal(double)} constructor will
* be used. See notes on the constructor for conversion issues that may
* arise.
*
@@ -682,7 +680,7 @@ public class JSONObject {
try {
return Double.parseDouble(object.toString());
} catch (Exception e) {
throw wrongValueFormatException(key, "double", e);
throw wrongValueFormatException(key, "double", object, e);
}
}
@@ -704,7 +702,7 @@ public class JSONObject {
try {
return Float.parseFloat(object.toString());
} catch (Exception e) {
throw wrongValueFormatException(key, "float", e);
throw wrongValueFormatException(key, "float", object, e);
}
}
@@ -726,7 +724,7 @@ public class JSONObject {
}
return stringToNumber(object.toString());
} catch (Exception e) {
throw wrongValueFormatException(key, "number", e);
throw wrongValueFormatException(key, "number", object, e);
}
}
@@ -748,7 +746,7 @@ public class JSONObject {
try {
return Integer.parseInt(object.toString());
} catch (Exception e) {
throw wrongValueFormatException(key, "int", e);
throw wrongValueFormatException(key, "int", object, e);
}
}
@@ -766,7 +764,7 @@ public class JSONObject {
if (object instanceof JSONArray) {
return (JSONArray) object;
}
throw wrongValueFormatException(key, "JSONArray", null);
throw wrongValueFormatException(key, "JSONArray", object, null);
}
/**
@@ -783,7 +781,7 @@ public class JSONObject {
if (object instanceof JSONObject) {
return (JSONObject) object;
}
throw wrongValueFormatException(key, "JSONObject", null);
throw wrongValueFormatException(key, "JSONObject", object, null);
}
/**
@@ -804,7 +802,7 @@ public class JSONObject {
try {
return Long.parseLong(object.toString());
} catch (Exception e) {
throw wrongValueFormatException(key, "long", e);
throw wrongValueFormatException(key, "long", object, e);
}
}
@@ -860,7 +858,7 @@ public class JSONObject {
if (object instanceof String) {
return (String) object;
}
throw wrongValueFormatException(key, "string", null);
throw wrongValueFormatException(key, "string", object, null);
}
/**
@@ -929,7 +927,7 @@ public class JSONObject {
* modify the JSONObject. Use with caution.
*
* @see Set#iterator()
*
*
* @return An iterator of the keys.
*/
public Iterator<String> keys() {
@@ -950,10 +948,10 @@ public class JSONObject {
/**
* Get a set of entries of the JSONObject. These are raw values and may not
* match what is returned by the JSONObject get* and opt* functions. Modifying
* match what is returned by the JSONObject get* and opt* functions. Modifying
* the returned EntrySet or the Entry objects contained therein will modify the
* backing JSONObject. This does not return a clone or a read-only view.
*
*
* Use with caution.
*
* @see Map#entrySet()
@@ -973,6 +971,14 @@ public class JSONObject {
return this.map.size();
}
/**
* Removes all of the elements from this JSONObject.
* The JSONObject will be empty after this call returns.
*/
public void clear() {
this.map.clear();
}
/**
* Check if JSONObject is empty.
*
@@ -1039,7 +1045,7 @@ public class JSONObject {
/**
* Get the enum value associated with a key.
*
*
* @param <E>
* Enum Type
* @param clazz
@@ -1054,7 +1060,7 @@ public class JSONObject {
/**
* Get the enum value associated with a key.
*
*
* @param <E>
* Enum Type
* @param clazz
@@ -1148,9 +1154,21 @@ public class JSONObject {
* @param val value to convert
* @param defaultValue default value to return is the conversion doesn't work or is null.
* @return BigDecimal conversion of the original value, or the defaultValue if unable
* to convert.
* to convert.
*/
static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue) {
return objectToBigDecimal(val, defaultValue, true);
}
/**
* @param val value to convert
* @param defaultValue default value to return is the conversion doesn't work or is null.
* @param exact When <code>true</code>, then {@link Double} and {@link Float} values will be converted exactly.
* When <code>false</code>, they will be converted to {@link String} values before converting to {@link BigDecimal}.
* @return BigDecimal conversion of the original value, or the defaultValue if unable
* to convert.
*/
static BigDecimal objectToBigDecimal(Object val, BigDecimal defaultValue, boolean exact) {
if (NULL.equals(val)) {
return defaultValue;
}
@@ -1161,11 +1179,16 @@ public class JSONObject {
return new BigDecimal((BigInteger) val);
}
if (val instanceof Double || val instanceof Float){
final double d = ((Number) val).doubleValue();
if(Double.isNaN(d)) {
if (!numberIsFinite((Number)val)) {
return defaultValue;
}
return new BigDecimal(((Number) val).doubleValue());
if (exact) {
return new BigDecimal(((Number)val).doubleValue());
}
// use the string constructor so that we maintain "nice" values for doubles and floats
// the double constructor will translate doubles to "exact" values instead of the likely
// intended representation
return new BigDecimal(val.toString());
}
if (val instanceof Long || val instanceof Integer
|| val instanceof Short || val instanceof Byte){
@@ -1199,7 +1222,7 @@ public class JSONObject {
* @param val value to convert
* @param defaultValue default value to return is the conversion doesn't work or is null.
* @return BigInteger conversion of the original value, or the defaultValue if unable
* to convert.
* to convert.
*/
static BigInteger objectToBigInteger(Object val, BigInteger defaultValue) {
if (NULL.equals(val)) {
@@ -1212,11 +1235,10 @@ public class JSONObject {
return ((BigDecimal) val).toBigInteger();
}
if (val instanceof Double || val instanceof Float){
final double d = ((Number) val).doubleValue();
if(Double.isNaN(d)) {
if (!numberIsFinite((Number)val)) {
return defaultValue;
}
return new BigDecimal(d).toBigInteger();
return new BigDecimal(((Number) val).doubleValue()).toBigInteger();
}
if (val instanceof Long || val instanceof Integer
|| val instanceof Short || val instanceof Byte){
@@ -1224,7 +1246,7 @@ public class JSONObject {
}
// don't check if it's a string in case of unchecked Number subclasses
try {
// the other opt functions handle implicit conversions, i.e.
// the other opt functions handle implicit conversions, i.e.
// jo.put("double",1.1d);
// jo.optInt("double"); -- will return 1, not an error
// this conversion to BigDecimal then to BigInteger is to maintain
@@ -1364,9 +1386,21 @@ public class JSONObject {
* A key string.
* @return A JSONObject which is the value.
*/
public JSONObject optJSONObject(String key) {
public JSONObject optJSONObject(String key) { return this.optJSONObject(key, null); }
/**
* Get an optional JSONObject associated with a key, or the default if there
* is no such key or if the value is not a JSONObject.
*
* @param key
* A key string.
* @param defaultValue
* The default.
* @return An JSONObject which is the value.
*/
public JSONObject optJSONObject(String key, JSONObject defaultValue) {
Object object = this.opt(key);
return object instanceof JSONObject ? (JSONObject) object : null;
return object instanceof JSONObject ? (JSONObject) object : defaultValue;
}
/**
@@ -1398,10 +1432,10 @@ public class JSONObject {
if (val == null) {
return defaultValue;
}
return val.longValue();
}
/**
* Get an optional {@link Number} value associated with a key, or <code>null</code>
* if there is no such key or if the value is not a number. If the value is a string,
@@ -1436,14 +1470,14 @@ public class JSONObject {
if (val instanceof Number){
return (Number) val;
}
try {
return stringToNumber(val.toString());
} catch (Exception e) {
return defaultValue;
}
}
/**
* Get an optional string associated with a key. It returns an empty string
* if there is no such key. If the value is not a string and is not null,
@@ -1482,6 +1516,10 @@ public class JSONObject {
* the bean
*/
private void populateMap(Object bean) {
populateMap(bean, Collections.newSetFromMap(new IdentityHashMap<Object, Boolean>()));
}
private void populateMap(Object bean, Set<Object> objectsRecord) {
Class<?> klass = bean.getClass();
// If klass is a System class then set includeSuperClass to false.
@@ -1502,10 +1540,22 @@ public class JSONObject {
try {
final Object result = method.invoke(bean);
if (result != null) {
this.map.put(key, wrap(result));
// check cyclic dependency and throw error if needed
// the wrap and populateMap combination method is
// itself DFS recursive
if (objectsRecord.contains(result)) {
throw recursivelyDefinedObjectException(key);
}
objectsRecord.add(result);
this.map.put(key, wrap(result, objectsRecord));
objectsRecord.remove(result);
// we don't use the result anywhere outside of wrap
// if it's a resource we should be sure to close it
// after calling toString
// after calling toString
if (result instanceof Closeable) {
try {
((Closeable) result).close();
@@ -1552,7 +1602,7 @@ public class JSONObject {
// if the first letter in the key is not uppercase, then skip.
// This is to maintain backwards compatibility before PR406
// (https://github.com/stleary/JSON-java/pull/406/)
if (Character.isLowerCase(key.charAt(0))) {
if (key.length() == 0 || Character.isLowerCase(key.charAt(0))) {
return null;
}
if (key.length() == 1) {
@@ -1575,7 +1625,7 @@ public class JSONObject {
* @param annotationClass
* annotation to look for
* @return the {@link Annotation} if the annotation exists on the current method
* or one of it's super class definitions
* or one of its super class definitions
*/
private static <A extends Annotation> A getAnnotation(final Method m, final Class<A> annotationClass) {
// if we have invalid data the result is null
@@ -1621,9 +1671,6 @@ public class JSONObject {
* implementations and interfaces has the annotation. Returns the depth of the
* annotation in the hierarchy.
*
* @param <A>
* type of the annotation
*
* @param m
* method to check
* @param annotationClass
@@ -1729,7 +1776,7 @@ public class JSONObject {
public JSONObject put(String key, double value) throws JSONException {
return this.put(key, Double.valueOf(value));
}
/**
* Put a key/float pair in the JSONObject.
*
@@ -1873,7 +1920,7 @@ public class JSONObject {
}
/**
* Creates a JSONPointer using an initialization string and tries to
* Creates a JSONPointer using an initialization string and tries to
* match it to an item within this JSONObject. For example, given a
* JSONObject initialized with this document:
* <pre>
@@ -1881,13 +1928,13 @@ public class JSONObject {
* "a":{"b":"c"}
* }
* </pre>
* and this JSONPointer string:
* and this JSONPointer string:
* <pre>
* "/a/b"
* </pre>
* Then this method will return the String "c".
* A JSONPointerException may be thrown from code called by this method.
*
*
* @param jsonPointer string that can be used to create a JSONPointer
* @return the item matched by the JSONPointer, otherwise null
*/
@@ -1895,7 +1942,7 @@ public class JSONObject {
return query(new JSONPointer(jsonPointer));
}
/**
* Uses a user initialized JSONPointer and tries to
* Uses a user initialized JSONPointer and tries to
* match it to an item within this JSONObject. For example, given a
* JSONObject initialized with this document:
* <pre>
@@ -1903,24 +1950,24 @@ public class JSONObject {
* "a":{"b":"c"}
* }
* </pre>
* and this JSONPointer:
* and this JSONPointer:
* <pre>
* "/a/b"
* </pre>
* Then this method will return the String "c".
* A JSONPointerException may be thrown from code called by this method.
*
*
* @param jsonPointer string that can be used to create a JSONPointer
* @return the item matched by the JSONPointer, otherwise null
*/
public Object query(JSONPointer jsonPointer) {
return jsonPointer.queryFrom(this);
}
/**
* Queries and returns a value from this object using {@code jsonPointer}, or
* returns null if the query fails due to a missing key.
*
*
* @param jsonPointer the string representation of the JSON pointer
* @return the queried value or {@code null}
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
@@ -1928,11 +1975,11 @@ public class JSONObject {
public Object optQuery(String jsonPointer) {
return optQuery(new JSONPointer(jsonPointer));
}
/**
* Queries and returns a value from this object using {@code jsonPointer}, or
* returns null if the query fails due to a missing key.
*
*
* @param jsonPointer The JSON pointer
* @return the queried value or {@code null}
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
@@ -1956,6 +2003,7 @@ public class JSONObject {
* A String
* @return A String correctly formatted for insertion in a JSON text.
*/
@SuppressWarnings("resource")
public static String quote(String string) {
StringWriter sw = new StringWriter();
synchronized (sw.getBuffer()) {
@@ -2073,6 +2121,14 @@ public class JSONObject {
if (!((JSONArray)valueThis).similar(valueOther)) {
return false;
}
} else if (valueThis instanceof Number && valueOther instanceof Number) {
if (!isNumberSimilar((Number)valueThis, (Number)valueOther)) {
return false;
}
} else if (valueThis instanceof JSONString && valueOther instanceof JSONString) {
if (!((JSONString) valueThis).toJSONString().equals(((JSONString) valueOther).toJSONString())) {
return false;
}
} else if (!valueThis.equals(valueOther)) {
return false;
}
@@ -2082,10 +2138,59 @@ public class JSONObject {
return false;
}
}
/**
* Compares two numbers to see if they are similar.
*
* If either of the numbers are Double or Float instances, then they are checked to have
* a finite value. If either value is not finite (NaN or &#177;infinity), then this
* function will always return false. If both numbers are finite, they are first checked
* to be the same type and implement {@link Comparable}. If they do, then the actual
* {@link Comparable#compareTo(Object)} is called. If they are not the same type, or don't
* implement Comparable, then they are converted to {@link BigDecimal}s. Finally the
* BigDecimal values are compared using {@link BigDecimal#compareTo(BigDecimal)}.
*
* @param l the Left value to compare. Can not be <code>null</code>.
* @param r the right value to compare. Can not be <code>null</code>.
* @return true if the numbers are similar, false otherwise.
*/
static boolean isNumberSimilar(Number l, Number r) {
if (!numberIsFinite(l) || !numberIsFinite(r)) {
// non-finite numbers are never similar
return false;
}
// if the classes are the same and implement Comparable
// then use the built in compare first.
if(l.getClass().equals(r.getClass()) && l instanceof Comparable) {
@SuppressWarnings({ "rawtypes", "unchecked" })
int compareTo = ((Comparable)l).compareTo(r);
return compareTo==0;
}
// BigDecimal should be able to handle all of our number types that we support through
// documentation. Convert to BigDecimal first, then use the Compare method to
// decide equality.
final BigDecimal lBigDecimal = objectToBigDecimal(l, null, false);
final BigDecimal rBigDecimal = objectToBigDecimal(r, null, false);
if (lBigDecimal == null || rBigDecimal == null) {
return false;
}
return lBigDecimal.compareTo(rBigDecimal) == 0;
}
private static boolean numberIsFinite(Number n) {
if (n instanceof Double && (((Double) n).isInfinite() || ((Double) n).isNaN())) {
return false;
} else if (n instanceof Float && (((Float) n).isInfinite() || ((Float) n).isNaN())) {
return false;
}
return true;
}
/**
* Tests if the value should be tried as a decimal. It makes no test if there are actual digits.
*
*
* @param val value to test
* @return true if the string is "-0" or if it contains '.', 'e', or 'E', false otherwise.
*/
@@ -2093,12 +2198,12 @@ public class JSONObject {
return val.indexOf('.') > -1 || val.indexOf('e') > -1
|| val.indexOf('E') > -1 || "-0".equals(val);
}
/**
* Converts a string to a number using the narrowest possible type. Possible
* Converts a string to a number using the narrowest possible type. Possible
* returns for this function are BigDecimal, Double, BigInteger, Long, and Integer.
* When a Double is returned, it should always be a valid Double and not NaN or +-infinity.
*
*
* @param val value to convert
* @return Number representation of the value.
* @throws NumberFormatException thrown if the value is not a valid number. A public
@@ -2109,48 +2214,54 @@ public class JSONObject {
if ((initial >= '0' && initial <= '9') || initial == '-') {
// decimal representation
if (isDecimalNotation(val)) {
// quick dirty way to see if we need a BigDecimal instead of a Double
// this only handles some cases of overflow or underflow
if (val.length()>14) {
return new BigDecimal(val);
// Use a BigDecimal all the time so we keep the original
// representation. BigDecimal doesn't support -0.0, ensure we
// keep that by forcing a decimal.
try {
BigDecimal bd = new BigDecimal(val);
if(initial == '-' && BigDecimal.ZERO.compareTo(bd)==0) {
return Double.valueOf(-0.0);
}
return bd;
} catch (NumberFormatException retryAsDouble) {
// this is to support "Hex Floats" like this: 0x1.0P-1074
try {
Double d = Double.valueOf(val);
if(d.isNaN() || d.isInfinite()) {
throw new NumberFormatException("val ["+val+"] is not a valid number.");
}
return d;
} catch (NumberFormatException ignore) {
throw new NumberFormatException("val ["+val+"] is not a valid number.");
}
}
final Double d = Double.valueOf(val);
if (d.isInfinite() || d.isNaN()) {
// if we can't parse it as a double, go up to BigDecimal
// this is probably due to underflow like 4.32e-678
// or overflow like 4.65e5324. The size of the string is small
// but can't be held in a Double.
return new BigDecimal(val);
}
// block items like 00 01 etc. Java number parsers treat these as Octal.
if(initial == '0' && val.length() > 1) {
char at1 = val.charAt(1);
if(at1 >= '0' && at1 <= '9') {
throw new NumberFormatException("val ["+val+"] is not a valid number.");
}
} else if (initial == '-' && val.length() > 2) {
char at1 = val.charAt(1);
char at2 = val.charAt(2);
if(at1 == '0' && at2 >= '0' && at2 <= '9') {
throw new NumberFormatException("val ["+val+"] is not a valid number.");
}
return d;
}
// integer representation.
// This will narrow any values to the smallest reasonable Object representation
// (Integer, Long, or BigInteger)
// string version
// The compare string length method reduces GC,
// but leads to smaller integers being placed in larger wrappers even though not
// needed. i.e. 1,000,000,000 -> Long even though it's an Integer
// 1,000,000,000,000,000,000 -> BigInteger even though it's a Long
//if(val.length()<=9){
// return Integer.valueOf(val);
//}
//if(val.length()<=18){
// return Long.valueOf(val);
//}
//return new BigInteger(val);
// BigInteger version: We use a similar bitLength compare as
// BigInteger down conversion: We use a similar bitLength compare as
// BigInteger#intValueExact uses. Increases GC, but objects hold
// only what they need. i.e. Less runtime overhead if the value is
// long lived. Which is the better tradeoff? This is closer to what's
// in stringToValue.
// long lived.
BigInteger bi = new BigInteger(val);
if(bi.bitLength()<=31){
if(bi.bitLength() <= 31){
return Integer.valueOf(bi.intValue());
}
if(bi.bitLength()<=63){
if(bi.bitLength() <= 63){
return Long.valueOf(bi.longValue());
}
return bi;
@@ -2194,23 +2305,7 @@ public class JSONObject {
char initial = string.charAt(0);
if ((initial >= '0' && initial <= '9') || initial == '-') {
try {
// if we want full Big Number support the contents of this
// `try` block can be replaced with:
// return stringToNumber(string);
if (isDecimalNotation(string)) {
Double d = Double.valueOf(string);
if (!d.isInfinite() && !d.isNaN()) {
return d;
}
} else {
Long myLong = Long.valueOf(string);
if (string.equals(myLong.toString())) {
if (myLong.longValue() == myLong.intValue()) {
return Integer.valueOf(myLong.intValue());
}
return myLong;
}
}
return stringToNumber(string);
} catch (Exception ignore) {
}
}
@@ -2226,18 +2321,8 @@ public class JSONObject {
* If o is a non-finite number.
*/
public static void testValidity(Object o) throws JSONException {
if (o != null) {
if (o instanceof Double) {
if (((Double) o).isInfinite() || ((Double) o).isNaN()) {
throw new JSONException(
"JSON does not allow non-finite numbers.");
}
} else if (o instanceof Float) {
if (((Float) o).isInfinite() || ((Float) o).isNaN()) {
throw new JSONException(
"JSON does not allow non-finite numbers.");
}
}
if (o instanceof Number && !numberIsFinite((Number) o)) {
throw new JSONException("JSON does not allow non-finite numbers.");
}
}
@@ -2270,7 +2355,7 @@ public class JSONObject {
* <p><b>
* Warning: This method assumes that the data structure is acyclical.
* </b>
*
*
* @return a printable, displayable, portable, transmittable representation
* of the object, beginning with <code>{</code>&nbsp;<small>(left
* brace)</small> and ending with <code>}</code>&nbsp;<small>(right
@@ -2287,17 +2372,17 @@ public class JSONObject {
/**
* Make a pretty-printed JSON text of this JSONObject.
*
* <p>If <code>indentFactor > 0</code> and the {@link JSONObject}
*
* <p>If <pre>{@code indentFactor > 0}</pre> and the {@link JSONObject}
* has only one key, then the object will be output on a single line:
* <pre>{@code {"key": 1}}</pre>
*
*
* <p>If an object has 2 or more keys, then it will be output across
* multiple lines: <code><pre>{
* multiple lines: <pre>{@code {
* "key1": 1,
* "key2": "value 2",
* "key3": 3
* }</pre></code>
* }}</pre>
* <p><b>
* Warning: This method assumes that the data structure is acyclical.
* </b>
@@ -2311,6 +2396,7 @@ public class JSONObject {
* @throws JSONException
* If the object contains an invalid number.
*/
@SuppressWarnings("resource")
public String toString(int indentFactor) throws JSONException {
StringWriter w = new StringWriter();
synchronized (w.getBuffer()) {
@@ -2363,8 +2449,12 @@ public class JSONObject {
* @return The wrapped value
*/
public static Object wrap(Object object) {
return wrap(object, null);
}
private static Object wrap(Object object, Set<Object> objectsRecord) {
try {
if (object == null) {
if (NULL.equals(object)) {
return NULL;
}
if (object instanceof JSONObject || object instanceof JSONArray
@@ -2397,7 +2487,13 @@ public class JSONObject {
|| object.getClass().getClassLoader() == null) {
return object.toString();
}
if (objectsRecord != null) {
return new JSONObject(object, objectsRecord);
}
return new JSONObject(object);
}
catch (JSONException exception) {
throw exception;
} catch (Exception exception) {
return null;
}
@@ -2409,14 +2505,15 @@ public class JSONObject {
* <p><b>
* Warning: This method assumes that the data structure is acyclical.
* </b>
*
* @param writer the writer object
* @return The writer.
* @throws JSONException
* @throws JSONException if a called function has an error
*/
public Writer write(Writer writer) throws JSONException {
return this.write(writer, 0, 0);
}
@SuppressWarnings("resource")
static final Writer writeValue(Writer writer, Object value,
int indentFactor, int indent) throws JSONException, IOException {
if (value == null || value.equals(null)) {
@@ -2469,17 +2566,17 @@ public class JSONObject {
/**
* Write the contents of the JSONObject as JSON text to a writer.
*
* <p>If <code>indentFactor > 0</code> and the {@link JSONObject}
*
* <p>If <pre>{@code indentFactor > 0}</pre> and the {@link JSONObject}
* has only one key, then the object will be output on a single line:
* <pre>{@code {"key": 1}}</pre>
*
*
* <p>If an object has 2 or more keys, then it will be output across
* multiple lines: <code><pre>{
* multiple lines: <pre>{@code {
* "key1": 1,
* "key2": "value 2",
* "key3": 3
* }</pre></code>
* }}</pre>
* <p><b>
* Warning: This method assumes that the data structure is acyclical.
* </b>
@@ -2491,8 +2588,10 @@ public class JSONObject {
* @param indent
* The indentation of the top level.
* @return The writer.
* @throws JSONException
* @throws JSONException if a called function has an error or a write error
* occurs
*/
@SuppressWarnings("resource")
public Writer write(Writer writer, int indentFactor, int indent)
throws JSONException {
try {
@@ -2574,23 +2673,7 @@ public class JSONObject {
}
return results;
}
/**
* Create a new JSONException in a common format for incorrect conversions.
* @param key name of the key
* @param valueType the type of value being coerced to
* @param cause optional cause of the coercion failure
* @return JSONException that can be thrown.
*/
private static JSONException wrongValueFormatException(
String key,
String valueType,
Throwable cause) {
return new JSONException(
"JSONObject[" + quote(key) + "] is not a " + valueType + "."
, cause);
}
/**
* Create a new JSONException in a common format for incorrect conversions.
* @param key name of the key
@@ -2603,8 +2686,31 @@ public class JSONObject {
String valueType,
Object value,
Throwable cause) {
if(value == null) {
return new JSONException(
"JSONObject[" + quote(key) + "] is not a " + valueType + " (null)."
, cause);
}
// don't try to toString collections or known object types that could be large.
if(value instanceof Map || value instanceof Iterable || value instanceof JSONObject) {
return new JSONException(
"JSONObject[" + quote(key) + "] is not a " + valueType + " (" + value.getClass() + ")."
, cause);
}
return new JSONException(
"JSONObject[" + quote(key) + "] is not a " + valueType + " (" + value + ")."
"JSONObject[" + quote(key) + "] is not a " + valueType + " (" + value.getClass() + " : " + value + ")."
, cause);
}
/**
* Create a new JSONException in a common format for recursive object definition.
* @param key name of the key
* @return JSONException that can be thrown.
*/
private static JSONException recursivelyDefinedObjectException(String key) {
return new JSONException(
"JavaBean object contains recursively defined member variable of key " + quote(key)
);
}
}

View File

@@ -10,27 +10,7 @@ import java.util.Collections;
import java.util.List;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
/**
@@ -68,6 +48,7 @@ public class JSONPointer {
/**
* Creates a {@code JSONPointer} instance using the tokens previously set using the
* {@link #append(String)} method calls.
* @return a JSONPointer object
*/
public JSONPointer build() {
return new JSONPointer(this.refTokens);
@@ -186,10 +167,11 @@ public class JSONPointer {
this.refTokens = new ArrayList<String>(refTokens);
}
/**
* @see <a href="https://tools.ietf.org/html/rfc6901#section-3">rfc6901 section 3</a>
*/
private static String unescape(String token) {
return token.replace("~1", "/").replace("~0", "~")
.replace("\\\"", "\"")
.replace("\\\\", "\\");
return token.replace("~1", "/").replace("~0", "~");
}
/**
@@ -262,21 +244,21 @@ public class JSONPointer {
/**
* Escapes path segment values to an unambiguous form.
* The escape char to be inserted is '~'. The chars to be escaped
* are ~, which maps to ~0, and /, which maps to ~1. Backslashes
* and double quote chars are also escaped.
* are ~, which maps to ~0, and /, which maps to ~1.
* @param token the JSONPointer segment value to be escaped
* @return the escaped value for the token
*
* @see <a href="https://tools.ietf.org/html/rfc6901#section-3">rfc6901 section 3</a>
*/
private static String escape(String token) {
return token.replace("~", "~0")
.replace("/", "~1")
.replace("\\", "\\\\")
.replace("\"", "\\\"");
.replace("/", "~1");
}
/**
* Returns a string representing the JSONPointer path value using URI
* fragment identifier representation
* @return a uri fragment string
*/
public String toURIFragment() {
try {

View File

@@ -0,0 +1,25 @@
package org.json;
/*
Public Domain.
*/
/**
* The JSONPointerException is thrown by {@link JSONPointer} if an error occurs
* during evaluating a pointer.
*
* @author JSON.org
* @version 2016-05-13
*/
public class JSONPointerException extends JSONException {
private static final long serialVersionUID = 8872944667561856751L;
public JSONPointerException(String message) {
super(message);
}
public JSONPointerException(String message, Throwable cause) {
super(message, cause);
}
}

View File

@@ -0,0 +1,23 @@
package org.json;
/*
Public Domain.
*/
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Retention(RUNTIME)
@Target({METHOD})
/**
* Use this annotation on a getter method to override the Bean name
* parser for Bean -&gt; JSONObject mapping. If this annotation is
* present at any level in the class hierarchy, then the method will
* not be serialized from the bean into the JSONObject.
*/
public @interface JSONPropertyIgnore { }

View File

@@ -0,0 +1,27 @@
package org.json;
/*
Public Domain.
*/
import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;
import java.lang.annotation.Documented;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;
@Documented
@Retention(RUNTIME)
@Target({METHOD})
/**
* Use this annotation on a getter method to override the Bean name
* parser for Bean -&gt; JSONObject mapping. A value set to empty string <code>""</code>
* will have the Bean parser fall back to the default field name processing.
*/
public @interface JSONPropertyName {
/**
* @return The name of the property as to be used in the JSON Object.
*/
String value();
}

View File

@@ -0,0 +1,23 @@
package org.json;
/*
Public Domain.
*/
/**
* The <code>JSONString</code> interface allows a <code>toJSONString()</code>
* method so that a class can change the behavior of
* <code>JSONObject.toString()</code>, <code>JSONArray.toString()</code>,
* and <code>JSONWriter.value(</code>Object<code>)</code>. The
* <code>toJSONString</code> method will be used instead of the default behavior
* of using the Object's <code>toString()</code> method and quoting the result.
*/
public interface JSONString {
/**
* The <code>toJSONString</code> method allows a class to produce its own JSON
* serialization.
*
* @return A strictly syntactically correct JSON text.
*/
public String toJSONString();
}

View File

@@ -1,79 +1,59 @@
package org.json;
/*
Copyright (c) 2006 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
import java.io.StringWriter;
/**
* JSONStringer provides a quick and convenient way of producing JSON text.
* The texts produced strictly conform to JSON syntax rules. No whitespace is
* added, so the results are ready for transmission or storage. Each instance of
* JSONStringer can produce one JSON text.
* <p>
* A JSONStringer instance provides a <code>value</code> method for appending
* values to the
* text, and a <code>key</code>
* method for adding keys before values in objects. There are <code>array</code>
* and <code>endArray</code> methods that make and bound array values, and
* <code>object</code> and <code>endObject</code> methods which make and bound
* object values. All of these methods return the JSONWriter instance,
* permitting cascade style. For example, <pre>
* myString = new JSONStringer()
* .object()
* .key("JSON")
* .value("Hello, World!")
* .endObject()
* .toString();</pre> which produces the string <pre>
* {"JSON":"Hello, World!"}</pre>
* <p>
* The first method called must be <code>array</code> or <code>object</code>.
* There are no methods for adding commas or colons. JSONStringer adds them for
* you. Objects and arrays can be nested up to 20 levels deep.
* <p>
* This can sometimes be easier than using a JSONObject to build a string.
* @author JSON.org
* @version 2015-12-09
*/
public class JSONStringer extends JSONWriter {
/**
* Make a fresh JSONStringer. It can be used to build one JSON text.
*/
public JSONStringer() {
super(new StringWriter());
}
/**
* Return the JSON text. This method is used to obtain the product of the
* JSONStringer instance. It will return <code>null</code> if there was a
* problem in the construction of the JSON text (such as the calls to
* <code>array</code> were not properly balanced with calls to
* <code>endArray</code>).
* @return The JSON text.
*/
@Override
public String toString() {
return this.mode == 'd' ? this.writer.toString() : null;
}
}
package org.json;
/*
Public Domain.
*/
import java.io.StringWriter;
/**
* JSONStringer provides a quick and convenient way of producing JSON text.
* The texts produced strictly conform to JSON syntax rules. No whitespace is
* added, so the results are ready for transmission or storage. Each instance of
* JSONStringer can produce one JSON text.
* <p>
* A JSONStringer instance provides a <code>value</code> method for appending
* values to the
* text, and a <code>key</code>
* method for adding keys before values in objects. There are <code>array</code>
* and <code>endArray</code> methods that make and bound array values, and
* <code>object</code> and <code>endObject</code> methods which make and bound
* object values. All of these methods return the JSONWriter instance,
* permitting cascade style. For example, <pre>
* myString = new JSONStringer()
* .object()
* .key("JSON")
* .value("Hello, World!")
* .endObject()
* .toString();</pre> which produces the string <pre>
* {"JSON":"Hello, World!"}</pre>
* <p>
* The first method called must be <code>array</code> or <code>object</code>.
* There are no methods for adding commas or colons. JSONStringer adds them for
* you. Objects and arrays can be nested up to 200 levels deep.
* <p>
* This can sometimes be easier than using a JSONObject to build a string.
* @author JSON.org
* @version 2015-12-09
*/
public class JSONStringer extends JSONWriter {
/**
* Make a fresh JSONStringer. It can be used to build one JSON text.
*/
public JSONStringer() {
super(new StringWriter());
}
/**
* Return the JSON text. This method is used to obtain the product of the
* JSONStringer instance. It will return <code>null</code> if there was a
* problem in the construction of the JSON text (such as the calls to
* <code>array</code> were not properly balanced with calls to
* <code>endArray</code>).
* @return The JSON text.
*/
@Override
public String toString() {
return this.mode == 'd' ? this.writer.toString() : null;
}
}

View File

@@ -8,27 +8,7 @@ import java.io.Reader;
import java.io.StringReader;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
/**
@@ -209,6 +189,12 @@ public class JSONTokener {
this.previous = (char) c;
return this.previous;
}
/**
* Get the last character read from the input or '\0' if nothing has been read yet.
* @return the last character read from the input.
*/
protected char getPrevious() { return this.previous;}
/**
* Increments the internal indexes according to the previous character
@@ -428,10 +414,18 @@ public class JSONTokener {
return this.nextString(c);
case '{':
this.back();
return new JSONObject(this);
try {
return new JSONObject(this);
} catch (StackOverflowError e) {
throw new JSONException("JSON Array or Object depth too large to process.", e);
}
case '[':
this.back();
return new JSONArray(this);
try {
return new JSONArray(this);
} catch (StackOverflowError e) {
throw new JSONException("JSON Array or Object depth too large to process.", e);
}
}
/*

View File

@@ -1,413 +1,394 @@
package org.json;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
/*
Copyright (c) 2006 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
*/
/**
* JSONWriter provides a quick and convenient way of producing JSON text.
* The texts produced strictly conform to JSON syntax rules. No whitespace is
* added, so the results are ready for transmission or storage. Each instance of
* JSONWriter can produce one JSON text.
* <p>
* A JSONWriter instance provides a <code>value</code> method for appending
* values to the
* text, and a <code>key</code>
* method for adding keys before values in objects. There are <code>array</code>
* and <code>endArray</code> methods that make and bound array values, and
* <code>object</code> and <code>endObject</code> methods which make and bound
* object values. All of these methods return the JSONWriter instance,
* permitting a cascade style. For example, <pre>
* new JSONWriter(myWriter)
* .object()
* .key("JSON")
* .value("Hello, World!")
* .endObject();</pre> which writes <pre>
* {"JSON":"Hello, World!"}</pre>
* <p>
* The first method called must be <code>array</code> or <code>object</code>.
* There are no methods for adding commas or colons. JSONWriter adds them for
* you. Objects and arrays can be nested up to 200 levels deep.
* <p>
* This can sometimes be easier than using a JSONObject to build a string.
* @author JSON.org
* @version 2016-08-08
*/
public class JSONWriter {
private static final int maxdepth = 200;
/**
* The comma flag determines if a comma should be output before the next
* value.
*/
private boolean comma;
/**
* The current mode. Values:
* 'a' (array),
* 'd' (done),
* 'i' (initial),
* 'k' (key),
* 'o' (object).
*/
protected char mode;
/**
* The object/array stack.
*/
private final JSONObject stack[];
/**
* The stack top index. A value of 0 indicates that the stack is empty.
*/
private int top;
/**
* The writer that will receive the output.
*/
protected Appendable writer;
/**
* Make a fresh JSONWriter. It can be used to build one JSON text.
*/
public JSONWriter(Appendable w) {
this.comma = false;
this.mode = 'i';
this.stack = new JSONObject[maxdepth];
this.top = 0;
this.writer = w;
}
/**
* Append a value.
* @param string A string value.
* @return this
* @throws JSONException If the value is out of sequence.
*/
private JSONWriter append(String string) throws JSONException {
if (string == null) {
throw new JSONException("Null pointer");
}
if (this.mode == 'o' || this.mode == 'a') {
try {
if (this.comma && this.mode == 'a') {
this.writer.append(',');
}
this.writer.append(string);
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
if (this.mode == 'o') {
this.mode = 'k';
}
this.comma = true;
return this;
}
throw new JSONException("Value out of sequence.");
}
/**
* Begin appending a new array. All values until the balancing
* <code>endArray</code> will be appended to this array. The
* <code>endArray</code> method must be called to mark the array's end.
* @return this
* @throws JSONException If the nesting is too deep, or if the object is
* started in the wrong place (for example as a key or after the end of the
* outermost array or object).
*/
public JSONWriter array() throws JSONException {
if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
this.push(null);
this.append("[");
this.comma = false;
return this;
}
throw new JSONException("Misplaced array.");
}
/**
* End something.
* @param m Mode
* @param c Closing character
* @return this
* @throws JSONException If unbalanced.
*/
private JSONWriter end(char m, char c) throws JSONException {
if (this.mode != m) {
throw new JSONException(m == 'a'
? "Misplaced endArray."
: "Misplaced endObject.");
}
this.pop(m);
try {
this.writer.append(c);
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
this.comma = true;
return this;
}
/**
* End an array. This method most be called to balance calls to
* <code>array</code>.
* @return this
* @throws JSONException If incorrectly nested.
*/
public JSONWriter endArray() throws JSONException {
return this.end('a', ']');
}
/**
* End an object. This method most be called to balance calls to
* <code>object</code>.
* @return this
* @throws JSONException If incorrectly nested.
*/
public JSONWriter endObject() throws JSONException {
return this.end('k', '}');
}
/**
* Append a key. The key will be associated with the next value. In an
* object, every value must be preceded by a key.
* @param string A key string.
* @return this
* @throws JSONException If the key is out of place. For example, keys
* do not belong in arrays or if the key is null.
*/
public JSONWriter key(String string) throws JSONException {
if (string == null) {
throw new JSONException("Null key.");
}
if (this.mode == 'k') {
try {
JSONObject topObject = this.stack[this.top - 1];
// don't use the built in putOnce method to maintain Android support
if(topObject.has(string)) {
throw new JSONException("Duplicate key \"" + string + "\"");
}
topObject.put(string, true);
if (this.comma) {
this.writer.append(',');
}
this.writer.append(JSONObject.quote(string));
this.writer.append(':');
this.comma = false;
this.mode = 'o';
return this;
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
}
throw new JSONException("Misplaced key.");
}
/**
* Begin appending a new object. All keys and values until the balancing
* <code>endObject</code> will be appended to this object. The
* <code>endObject</code> method must be called to mark the object's end.
* @return this
* @throws JSONException If the nesting is too deep, or if the object is
* started in the wrong place (for example as a key or after the end of the
* outermost array or object).
*/
public JSONWriter object() throws JSONException {
if (this.mode == 'i') {
this.mode = 'o';
}
if (this.mode == 'o' || this.mode == 'a') {
this.append("{");
this.push(new JSONObject());
this.comma = false;
return this;
}
throw new JSONException("Misplaced object.");
}
/**
* Pop an array or object scope.
* @param c The scope to close.
* @throws JSONException If nesting is wrong.
*/
private void pop(char c) throws JSONException {
if (this.top <= 0) {
throw new JSONException("Nesting error.");
}
char m = this.stack[this.top - 1] == null ? 'a' : 'k';
if (m != c) {
throw new JSONException("Nesting error.");
}
this.top -= 1;
this.mode = this.top == 0
? 'd'
: this.stack[this.top - 1] == null
? 'a'
: 'k';
}
/**
* Push an array or object scope.
* @param jo The scope to open.
* @throws JSONException If nesting is too deep.
*/
private void push(JSONObject jo) throws JSONException {
if (this.top >= maxdepth) {
throw new JSONException("Nesting too deep.");
}
this.stack[this.top] = jo;
this.mode = jo == null ? 'a' : 'k';
this.top += 1;
}
/**
* Make a JSON text of an Object value. If the object has an
* value.toJSONString() method, then that method will be used to produce the
* JSON text. The method is required to produce a strictly conforming text.
* If the object does not contain a toJSONString method (which is the most
* common case), then a text will be produced by other means. If the value
* is an array or Collection, then a JSONArray will be made from it and its
* toJSONString method will be called. If the value is a MAP, then a
* JSONObject will be made from it and its toJSONString method will be
* called. Otherwise, the value's toString method will be called, and the
* result will be quoted.
*
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
* @param value
* The value to be serialized.
* @return a printable, displayable, transmittable representation of the
* object, beginning with <code>{</code>&nbsp;<small>(left
* brace)</small> and ending with <code>}</code>&nbsp;<small>(right
* brace)</small>.
* @throws JSONException
* If the value is or contains an invalid number.
*/
public static String valueToString(Object value) throws JSONException {
if (value == null || value.equals(null)) {
return "null";
}
if (value instanceof JSONString) {
String object;
try {
object = ((JSONString) value).toJSONString();
} catch (Exception e) {
throw new JSONException(e);
}
if (object != null) {
return object;
}
throw new JSONException("Bad value from toJSONString: " + object);
}
if (value instanceof Number) {
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
final String numberAsString = JSONObject.numberToString((Number) value);
if(JSONObject.NUMBER_PATTERN.matcher(numberAsString).matches()) {
// Close enough to a JSON number that we will return it unquoted
return numberAsString;
}
// The Number value is not a valid JSON number.
// Instead we will quote it as a string
return JSONObject.quote(numberAsString);
}
if (value instanceof Boolean || value instanceof JSONObject
|| value instanceof JSONArray) {
return value.toString();
}
if (value instanceof Map) {
Map<?, ?> map = (Map<?, ?>) value;
return new JSONObject(map).toString();
}
if (value instanceof Collection) {
Collection<?> coll = (Collection<?>) value;
return new JSONArray(coll).toString();
}
if (value.getClass().isArray()) {
return new JSONArray(value).toString();
}
if(value instanceof Enum<?>){
return JSONObject.quote(((Enum<?>)value).name());
}
return JSONObject.quote(value.toString());
}
/**
* Append either the value <code>true</code> or the value
* <code>false</code>.
* @param b A boolean.
* @return this
* @throws JSONException
*/
public JSONWriter value(boolean b) throws JSONException {
return this.append(b ? "true" : "false");
}
/**
* Append a double value.
* @param d A double.
* @return this
* @throws JSONException If the number is not finite.
*/
public JSONWriter value(double d) throws JSONException {
return this.value(Double.valueOf(d));
}
/**
* Append a long value.
* @param l A long.
* @return this
* @throws JSONException
*/
public JSONWriter value(long l) throws JSONException {
return this.append(Long.toString(l));
}
/**
* Append an object value.
* @param object The object to append. It can be null, or a Boolean, Number,
* String, JSONObject, or JSONArray, or an object that implements JSONString.
* @return this
* @throws JSONException If the value is out of sequence.
*/
public JSONWriter value(Object object) throws JSONException {
return this.append(valueToString(object));
}
}
package org.json;
import java.io.IOException;
import java.util.Collection;
import java.util.Map;
/*
Public Domain.
*/
/**
* JSONWriter provides a quick and convenient way of producing JSON text.
* The texts produced strictly conform to JSON syntax rules. No whitespace is
* added, so the results are ready for transmission or storage. Each instance of
* JSONWriter can produce one JSON text.
* <p>
* A JSONWriter instance provides a <code>value</code> method for appending
* values to the
* text, and a <code>key</code>
* method for adding keys before values in objects. There are <code>array</code>
* and <code>endArray</code> methods that make and bound array values, and
* <code>object</code> and <code>endObject</code> methods which make and bound
* object values. All of these methods return the JSONWriter instance,
* permitting a cascade style. For example, <pre>
* new JSONWriter(myWriter)
* .object()
* .key("JSON")
* .value("Hello, World!")
* .endObject();</pre> which writes <pre>
* {"JSON":"Hello, World!"}</pre>
* <p>
* The first method called must be <code>array</code> or <code>object</code>.
* There are no methods for adding commas or colons. JSONWriter adds them for
* you. Objects and arrays can be nested up to 200 levels deep.
* <p>
* This can sometimes be easier than using a JSONObject to build a string.
* @author JSON.org
* @version 2016-08-08
*/
public class JSONWriter {
private static final int maxdepth = 200;
/**
* The comma flag determines if a comma should be output before the next
* value.
*/
private boolean comma;
/**
* The current mode. Values:
* 'a' (array),
* 'd' (done),
* 'i' (initial),
* 'k' (key),
* 'o' (object).
*/
protected char mode;
/**
* The object/array stack.
*/
private final JSONObject stack[];
/**
* The stack top index. A value of 0 indicates that the stack is empty.
*/
private int top;
/**
* The writer that will receive the output.
*/
protected Appendable writer;
/**
* Make a fresh JSONWriter. It can be used to build one JSON text.
* @param w an appendable object
*/
public JSONWriter(Appendable w) {
this.comma = false;
this.mode = 'i';
this.stack = new JSONObject[maxdepth];
this.top = 0;
this.writer = w;
}
/**
* Append a value.
* @param string A string value.
* @return this
* @throws JSONException If the value is out of sequence.
*/
private JSONWriter append(String string) throws JSONException {
if (string == null) {
throw new JSONException("Null pointer");
}
if (this.mode == 'o' || this.mode == 'a') {
try {
if (this.comma && this.mode == 'a') {
this.writer.append(',');
}
this.writer.append(string);
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
if (this.mode == 'o') {
this.mode = 'k';
}
this.comma = true;
return this;
}
throw new JSONException("Value out of sequence.");
}
/**
* Begin appending a new array. All values until the balancing
* <code>endArray</code> will be appended to this array. The
* <code>endArray</code> method must be called to mark the array's end.
* @return this
* @throws JSONException If the nesting is too deep, or if the object is
* started in the wrong place (for example as a key or after the end of the
* outermost array or object).
*/
public JSONWriter array() throws JSONException {
if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
this.push(null);
this.append("[");
this.comma = false;
return this;
}
throw new JSONException("Misplaced array.");
}
/**
* End something.
* @param m Mode
* @param c Closing character
* @return this
* @throws JSONException If unbalanced.
*/
private JSONWriter end(char m, char c) throws JSONException {
if (this.mode != m) {
throw new JSONException(m == 'a'
? "Misplaced endArray."
: "Misplaced endObject.");
}
this.pop(m);
try {
this.writer.append(c);
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
this.comma = true;
return this;
}
/**
* End an array. This method most be called to balance calls to
* <code>array</code>.
* @return this
* @throws JSONException If incorrectly nested.
*/
public JSONWriter endArray() throws JSONException {
return this.end('a', ']');
}
/**
* End an object. This method most be called to balance calls to
* <code>object</code>.
* @return this
* @throws JSONException If incorrectly nested.
*/
public JSONWriter endObject() throws JSONException {
return this.end('k', '}');
}
/**
* Append a key. The key will be associated with the next value. In an
* object, every value must be preceded by a key.
* @param string A key string.
* @return this
* @throws JSONException If the key is out of place. For example, keys
* do not belong in arrays or if the key is null.
*/
public JSONWriter key(String string) throws JSONException {
if (string == null) {
throw new JSONException("Null key.");
}
if (this.mode == 'k') {
try {
JSONObject topObject = this.stack[this.top - 1];
// don't use the built in putOnce method to maintain Android support
if(topObject.has(string)) {
throw new JSONException("Duplicate key \"" + string + "\"");
}
topObject.put(string, true);
if (this.comma) {
this.writer.append(',');
}
this.writer.append(JSONObject.quote(string));
this.writer.append(':');
this.comma = false;
this.mode = 'o';
return this;
} catch (IOException e) {
// Android as of API 25 does not support this exception constructor
// however we won't worry about it. If an exception is happening here
// it will just throw a "Method not found" exception instead.
throw new JSONException(e);
}
}
throw new JSONException("Misplaced key.");
}
/**
* Begin appending a new object. All keys and values until the balancing
* <code>endObject</code> will be appended to this object. The
* <code>endObject</code> method must be called to mark the object's end.
* @return this
* @throws JSONException If the nesting is too deep, or if the object is
* started in the wrong place (for example as a key or after the end of the
* outermost array or object).
*/
public JSONWriter object() throws JSONException {
if (this.mode == 'i') {
this.mode = 'o';
}
if (this.mode == 'o' || this.mode == 'a') {
this.append("{");
this.push(new JSONObject());
this.comma = false;
return this;
}
throw new JSONException("Misplaced object.");
}
/**
* Pop an array or object scope.
* @param c The scope to close.
* @throws JSONException If nesting is wrong.
*/
private void pop(char c) throws JSONException {
if (this.top <= 0) {
throw new JSONException("Nesting error.");
}
char m = this.stack[this.top - 1] == null ? 'a' : 'k';
if (m != c) {
throw new JSONException("Nesting error.");
}
this.top -= 1;
this.mode = this.top == 0
? 'd'
: this.stack[this.top - 1] == null
? 'a'
: 'k';
}
/**
* Push an array or object scope.
* @param jo The scope to open.
* @throws JSONException If nesting is too deep.
*/
private void push(JSONObject jo) throws JSONException {
if (this.top >= maxdepth) {
throw new JSONException("Nesting too deep.");
}
this.stack[this.top] = jo;
this.mode = jo == null ? 'a' : 'k';
this.top += 1;
}
/**
* Make a JSON text of an Object value. If the object has an
* value.toJSONString() method, then that method will be used to produce the
* JSON text. The method is required to produce a strictly conforming text.
* If the object does not contain a toJSONString method (which is the most
* common case), then a text will be produced by other means. If the value
* is an array or Collection, then a JSONArray will be made from it and its
* toJSONString method will be called. If the value is a MAP, then a
* JSONObject will be made from it and its toJSONString method will be
* called. Otherwise, the value's toString method will be called, and the
* result will be quoted.
*
* <p>
* Warning: This method assumes that the data structure is acyclical.
*
* @param value
* The value to be serialized.
* @return a printable, displayable, transmittable representation of the
* object, beginning with <code>{</code>&nbsp;<small>(left
* brace)</small> and ending with <code>}</code>&nbsp;<small>(right
* brace)</small>.
* @throws JSONException
* If the value is or contains an invalid number.
*/
public static String valueToString(Object value) throws JSONException {
if (value == null || value.equals(null)) {
return "null";
}
if (value instanceof JSONString) {
String object;
try {
object = ((JSONString) value).toJSONString();
} catch (Exception e) {
throw new JSONException(e);
}
if (object != null) {
return object;
}
throw new JSONException("Bad value from toJSONString: " + object);
}
if (value instanceof Number) {
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
final String numberAsString = JSONObject.numberToString((Number) value);
if(JSONObject.NUMBER_PATTERN.matcher(numberAsString).matches()) {
// Close enough to a JSON number that we will return it unquoted
return numberAsString;
}
// The Number value is not a valid JSON number.
// Instead we will quote it as a string
return JSONObject.quote(numberAsString);
}
if (value instanceof Boolean || value instanceof JSONObject
|| value instanceof JSONArray) {
return value.toString();
}
if (value instanceof Map) {
Map<?, ?> map = (Map<?, ?>) value;
return new JSONObject(map).toString();
}
if (value instanceof Collection) {
Collection<?> coll = (Collection<?>) value;
return new JSONArray(coll).toString();
}
if (value.getClass().isArray()) {
return new JSONArray(value).toString();
}
if(value instanceof Enum<?>){
return JSONObject.quote(((Enum<?>)value).name());
}
return JSONObject.quote(value.toString());
}
/**
* Append either the value <code>true</code> or the value
* <code>false</code>.
* @param b A boolean.
* @return this
* @throws JSONException if a called function has an error
*/
public JSONWriter value(boolean b) throws JSONException {
return this.append(b ? "true" : "false");
}
/**
* Append a double value.
* @param d A double.
* @return this
* @throws JSONException If the number is not finite.
*/
public JSONWriter value(double d) throws JSONException {
return this.value(Double.valueOf(d));
}
/**
* Append a long value.
* @param l A long.
* @return this
* @throws JSONException if a called function has an error
*/
public JSONWriter value(long l) throws JSONException {
return this.append(Long.toString(l));
}
/**
* Append an object value.
* @param object The object to append. It can be null, or a Boolean, Number,
* String, JSONObject, or JSONArray, or an object that implements JSONString.
* @return this
* @throws JSONException If the value is out of sequence.
*/
public JSONWriter value(Object object) throws JSONException {
return this.append(valueToString(object));
}
}

View File

@@ -1,27 +1,7 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import java.util.Enumeration;
@@ -37,7 +17,7 @@ public class Property {
* Converts a property file object into a JSONObject. The property file object is a table of name value pairs.
* @param properties java.util.Properties
* @return JSONObject
* @throws JSONException
* @throws JSONException if a called function has an error
*/
public static JSONObject toJSONObject(java.util.Properties properties) throws JSONException {
// can't use the new constructor for Android support
@@ -57,7 +37,7 @@ public class Property {
* Converts the JSONObject into a property file object.
* @param jo JSONObject
* @return java.util.Properties
* @throws JSONException
* @throws JSONException if a called function has an error
*/
public static Properties toProperties(JSONObject jo) throws JSONException {
Properties properties = new Properties();

View File

@@ -1,33 +1,16 @@
package org.json;
/*
Copyright (c) 2015 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import java.io.Reader;
import java.io.StringReader;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Iterator;
/**
* This provides static methods to convert an XML text into a JSONObject, and to
* covert a JSONObject into an XML text.
@@ -50,7 +33,7 @@ public class XML {
/** The Character '='. */
public static final Character EQ = '=';
/** The Character '>'. */
/** The Character <pre>{@code '>'. }</pre>*/
public static final Character GT = '>';
/** The Character '&lt;'. */
@@ -70,6 +53,8 @@ public class XML {
*/
public static final String NULL_ATTR = "xsi:nil";
public static final String TYPE_ATTR = "xsi:type";
/**
* Creates an iterator for navigating Code Points in a string instead of
* characters. Once Java7 support is dropped, this can be replaced with
@@ -113,13 +98,13 @@ public class XML {
/**
* Replace special characters with XML escapes:
*
* <pre>
* &amp; <small>(ampersand)</small> is replaced by &amp;amp;
* &lt; <small>(less than)</small> is replaced by &amp;lt;
* &gt; <small>(greater than)</small> is replaced by &amp;gt;
* &quot; <small>(double quote)</small> is replaced by &amp;quot;
* &apos; <small>(single quote / apostrophe)</small> is replaced by &amp;apos;
* </pre>
* <pre>{@code
* &amp; (ampersand) is replaced by &amp;amp;
* &lt; (less than) is replaced by &amp;lt;
* &gt; (greater than) is replaced by &amp;gt;
* &quot; (double quote) is replaced by &amp;quot;
* &apos; (single quote / apostrophe) is replaced by &amp;apos;
* }</pre>
*
* @param string
* The string to be escaped.
@@ -255,6 +240,7 @@ public class XML {
String string;
String tagName;
Object token;
XMLXsiTypeConverter<?> xmlXsiTypeConverter;
// Test for and skip past these forms:
// <!-- ... -->
@@ -284,7 +270,7 @@ public class XML {
if (x.next() == '[') {
string = x.nextCDATA();
if (string.length() > 0) {
context.accumulate(config.cDataTagName, string);
context.accumulate(config.getcDataTagName(), string);
}
return false;
}
@@ -334,6 +320,7 @@ public class XML {
token = null;
jsonObject = new JSONObject();
boolean nilAttributeFound = false;
xmlXsiTypeConverter = null;
for (;;) {
if (token == null) {
token = x.nextToken();
@@ -348,13 +335,16 @@ public class XML {
throw x.syntaxError("Missing value");
}
if (config.convertNilAttributeToNull
if (config.isConvertNilAttributeToNull()
&& NULL_ATTR.equals(string)
&& Boolean.parseBoolean((String) token)) {
nilAttributeFound = true;
} else if(config.getXsiTypeMap() != null && !config.getXsiTypeMap().isEmpty()
&& TYPE_ATTR.equals(string)) {
xmlXsiTypeConverter = config.getXsiTypeMap().get(token);
} else if (!nilAttributeFound) {
jsonObject.accumulate(string,
config.keepStrings
config.isKeepStrings()
? ((String) token)
: stringToValue((String) token));
}
@@ -369,12 +359,23 @@ public class XML {
if (x.nextToken() != GT) {
throw x.syntaxError("Misshaped tag");
}
if (nilAttributeFound) {
context.accumulate(tagName, JSONObject.NULL);
} else if (jsonObject.length() > 0) {
context.accumulate(tagName, jsonObject);
if (config.getForceList().contains(tagName)) {
// Force the value to be an array
if (nilAttributeFound) {
context.append(tagName, JSONObject.NULL);
} else if (jsonObject.length() > 0) {
context.append(tagName, jsonObject);
} else {
context.put(tagName, new JSONArray());
}
} else {
context.accumulate(tagName, "");
if (nilAttributeFound) {
context.accumulate(tagName, JSONObject.NULL);
} else if (jsonObject.length() > 0) {
context.accumulate(tagName, jsonObject);
} else {
context.accumulate(tagName, "");
}
}
return false;
@@ -390,21 +391,39 @@ public class XML {
} else if (token instanceof String) {
string = (String) token;
if (string.length() > 0) {
jsonObject.accumulate(config.cDataTagName,
config.keepStrings ? string : stringToValue(string));
if(xmlXsiTypeConverter != null) {
jsonObject.accumulate(config.getcDataTagName(),
stringToValue(string, xmlXsiTypeConverter));
} else {
jsonObject.accumulate(config.getcDataTagName(),
config.isKeepStrings() ? string : stringToValue(string));
}
}
} else if (token == LT) {
// Nested element
if (parse(x, jsonObject, tagName, config)) {
if (jsonObject.length() == 0) {
context.accumulate(tagName, "");
} else if (jsonObject.length() == 1
&& jsonObject.opt(config.cDataTagName) != null) {
context.accumulate(tagName, jsonObject.opt(config.cDataTagName));
if (config.getForceList().contains(tagName)) {
// Force the value to be an array
if (jsonObject.length() == 0) {
context.put(tagName, new JSONArray());
} else if (jsonObject.length() == 1
&& jsonObject.opt(config.getcDataTagName()) != null) {
context.append(tagName, jsonObject.opt(config.getcDataTagName()));
} else {
context.append(tagName, jsonObject);
}
} else {
context.accumulate(tagName, jsonObject);
if (jsonObject.length() == 0) {
context.accumulate(tagName, "");
} else if (jsonObject.length() == 1
&& jsonObject.opt(config.getcDataTagName()) != null) {
context.accumulate(tagName, jsonObject.opt(config.getcDataTagName()));
} else {
context.accumulate(tagName, jsonObject);
}
}
return false;
}
}
@@ -416,6 +435,19 @@ public class XML {
}
}
/**
* This method tries to convert the given string value to the target object
* @param string String to convert
* @param typeConverter value converter to convert string to integer, boolean e.t.c
* @return JSON value of this string or the string
*/
public static Object stringToValue(String string, XMLXsiTypeConverter<?> typeConverter) {
if(typeConverter != null) {
return typeConverter.convert(string);
}
return stringToValue(string);
}
/**
* This method is the same as {@link JSONObject#stringToValue(String)}.
*
@@ -424,17 +456,20 @@ public class XML {
*/
// To maintain compatibility with the Android API, this method is a direct copy of
// the one in JSONObject. Changes made here should be reflected there.
// This method should not make calls out of the XML object.
public static Object stringToValue(String string) {
if (string.equals("")) {
if ("".equals(string)) {
return string;
}
if (string.equalsIgnoreCase("true")) {
// check JSON key words true/false/null
if ("true".equalsIgnoreCase(string)) {
return Boolean.TRUE;
}
if (string.equalsIgnoreCase("false")) {
if ("false".equalsIgnoreCase(string)) {
return Boolean.FALSE;
}
if (string.equalsIgnoreCase("null")) {
if ("null".equalsIgnoreCase(string)) {
return JSONObject.NULL;
}
@@ -446,28 +481,84 @@ public class XML {
char initial = string.charAt(0);
if ((initial >= '0' && initial <= '9') || initial == '-') {
try {
// if we want full Big Number support this block can be replaced with:
// return stringToNumber(string);
if (string.indexOf('.') > -1 || string.indexOf('e') > -1
|| string.indexOf('E') > -1 || "-0".equals(string)) {
Double d = Double.valueOf(string);
if (!d.isInfinite() && !d.isNaN()) {
return d;
}
} else {
Long myLong = Long.valueOf(string);
if (string.equals(myLong.toString())) {
if (myLong.longValue() == myLong.intValue()) {
return Integer.valueOf(myLong.intValue());
}
return myLong;
}
}
return stringToNumber(string);
} catch (Exception ignore) {
}
}
return string;
}
/**
* direct copy of {@link JSONObject#stringToNumber(String)} to maintain Android support.
*/
private static Number stringToNumber(final String val) throws NumberFormatException {
char initial = val.charAt(0);
if ((initial >= '0' && initial <= '9') || initial == '-') {
// decimal representation
if (isDecimalNotation(val)) {
// Use a BigDecimal all the time so we keep the original
// representation. BigDecimal doesn't support -0.0, ensure we
// keep that by forcing a decimal.
try {
BigDecimal bd = new BigDecimal(val);
if(initial == '-' && BigDecimal.ZERO.compareTo(bd)==0) {
return Double.valueOf(-0.0);
}
return bd;
} catch (NumberFormatException retryAsDouble) {
// this is to support "Hex Floats" like this: 0x1.0P-1074
try {
Double d = Double.valueOf(val);
if(d.isNaN() || d.isInfinite()) {
throw new NumberFormatException("val ["+val+"] is not a valid number.");
}
return d;
} catch (NumberFormatException ignore) {
throw new NumberFormatException("val ["+val+"] is not a valid number.");
}
}
}
// block items like 00 01 etc. Java number parsers treat these as Octal.
if(initial == '0' && val.length() > 1) {
char at1 = val.charAt(1);
if(at1 >= '0' && at1 <= '9') {
throw new NumberFormatException("val ["+val+"] is not a valid number.");
}
} else if (initial == '-' && val.length() > 2) {
char at1 = val.charAt(1);
char at2 = val.charAt(2);
if(at1 == '0' && at2 >= '0' && at2 <= '9') {
throw new NumberFormatException("val ["+val+"] is not a valid number.");
}
}
// integer representation.
// This will narrow any values to the smallest reasonable Object representation
// (Integer, Long, or BigInteger)
// BigInteger down conversion: We use a similar bitLength compare as
// BigInteger#intValueExact uses. Increases GC, but objects hold
// only what they need. i.e. Less runtime overhead if the value is
// long lived.
BigInteger bi = new BigInteger(val);
if(bi.bitLength() <= 31){
return Integer.valueOf(bi.intValue());
}
if(bi.bitLength() <= 63){
return Long.valueOf(bi.longValue());
}
return bi;
}
throw new NumberFormatException("val ["+val+"] is not a valid number.");
}
/**
* direct copy of {@link JSONObject#isDecimalNotation(String)} to maintain Android support.
*/
private static boolean isDecimalNotation(final String val) {
return val.indexOf('.') > -1 || val.indexOf('e') > -1
|| val.indexOf('E') > -1 || "-0".equals(val);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
@@ -477,7 +568,8 @@ public class XML {
* name/value pairs and arrays of values. JSON does not does not like to
* distinguish between elements and attributes. Sequences of similar
* elements are represented as JSONArrays. Content text may be placed in a
* "content" member. Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code>
* "content" member. Comments, prologs, DTDs, and <pre>{@code
* &lt;[ [ ]]>}</pre>
* are ignored.
*
* @param string
@@ -497,7 +589,8 @@ public class XML {
* name/value pairs and arrays of values. JSON does not does not like to
* distinguish between elements and attributes. Sequences of similar
* elements are represented as JSONArrays. Content text may be placed in a
* "content" member. Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code>
* "content" member. Comments, prologs, DTDs, and <pre>{@code
* &lt;[ [ ]]>}</pre>
* are ignored.
*
* @param reader The XML source reader.
@@ -516,7 +609,8 @@ public class XML {
* name/value pairs and arrays of values. JSON does not does not like to
* distinguish between elements and attributes. Sequences of similar
* elements are represented as JSONArrays. Content text may be placed in a
* "content" member. Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code>
* "content" member. Comments, prologs, DTDs, and <pre>{@code
* &lt;[ [ ]]>}</pre>
* are ignored.
*
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
@@ -543,7 +637,8 @@ public class XML {
* name/value pairs and arrays of values. JSON does not does not like to
* distinguish between elements and attributes. Sequences of similar
* elements are represented as JSONArrays. Content text may be placed in a
* "content" member. Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code>
* "content" member. Comments, prologs, DTDs, and <pre>{@code
* &lt;[ [ ]]>}</pre>
* are ignored.
*
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
@@ -574,7 +669,8 @@ public class XML {
* name/value pairs and arrays of values. JSON does not does not like to
* distinguish between elements and attributes. Sequences of similar
* elements are represented as JSONArrays. Content text may be placed in a
* "content" member. Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code>
* "content" member. Comments, prologs, DTDs, and <pre>{@code
* &lt;[ [ ]]>}</pre>
* are ignored.
*
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
@@ -599,7 +695,8 @@ public class XML {
* name/value pairs and arrays of values. JSON does not does not like to
* distinguish between elements and attributes. Sequences of similar
* elements are represented as JSONArrays. Content text may be placed in a
* "content" member. Comments, prologs, DTDs, and <code>&lt;[ [ ]]></code>
* "content" member. Comments, prologs, DTDs, and <pre>{@code
* &lt;[ [ ]]>}</pre>
* are ignored.
*
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
@@ -681,7 +778,7 @@ public class XML {
}
// Emit content in body
if (key.equals(config.cDataTagName)) {
if (key.equals(config.getcDataTagName())) {
if (value instanceof JSONArray) {
ja = (JSONArray) value;
int jaLength = ja.length();

View File

@@ -0,0 +1,300 @@
package org.json;
/*
Public Domain.
*/
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
* Configuration object for the XML parser. The configuration is immutable.
* @author AylwardJ
*/
@SuppressWarnings({""})
public class XMLParserConfiguration {
/** Original Configuration of the XML Parser. */
public static final XMLParserConfiguration ORIGINAL
= new XMLParserConfiguration();
/** Original configuration of the XML Parser except that values are kept as strings. */
public static final XMLParserConfiguration KEEP_STRINGS
= new XMLParserConfiguration().withKeepStrings(true);
/**
* When parsing the XML into JSON, specifies if values should be kept as strings (<code>true</code>), or if
* they should try to be guessed into JSON values (numeric, boolean, string)
*/
private boolean keepStrings;
/**
* The name of the key in a JSON Object that indicates a CDATA section. Historically this has
* been the value "content" but can be changed. Use <code>null</code> to indicate no CDATA
* processing.
*/
private String cDataTagName;
/**
* When parsing the XML into JSON, specifies if values with attribute xsi:nil="true"
* should be kept as attribute(<code>false</code>), or they should be converted to
* <code>null</code>(<code>true</code>)
*/
private boolean convertNilAttributeToNull;
/**
* This will allow type conversion for values in XML if xsi:type attribute is defined
*/
private Map<String, XMLXsiTypeConverter<?>> xsiTypeMap;
/**
* When parsing the XML into JSON, specifies the tags whose values should be converted
* to arrays
*/
private Set<String> forceList;
/**
* Default parser configuration. Does not keep strings (tries to implicitly convert
* values), and the CDATA Tag Name is "content".
*/
public XMLParserConfiguration () {
this.keepStrings = false;
this.cDataTagName = "content";
this.convertNilAttributeToNull = false;
this.xsiTypeMap = Collections.emptyMap();
this.forceList = Collections.emptySet();
}
/**
* Configure the parser string processing and use the default CDATA Tag Name as "content".
* @param keepStrings <code>true</code> to parse all values as string.
* <code>false</code> to try and convert XML string values into a JSON value.
* @deprecated This constructor has been deprecated in favor of using the new builder
* pattern for the configuration.
* This constructor may be removed in a future release.
*/
@Deprecated
public XMLParserConfiguration (final boolean keepStrings) {
this(keepStrings, "content", false);
}
/**
* Configure the parser string processing to try and convert XML values to JSON values and
* use the passed CDATA Tag Name the processing value. Pass <code>null</code> to
* disable CDATA processing
* @param cDataTagName <code>null</code> to disable CDATA processing. Any other value
* to use that value as the JSONObject key name to process as CDATA.
* @deprecated This constructor has been deprecated in favor of using the new builder
* pattern for the configuration.
* This constructor may be removed in a future release.
*/
@Deprecated
public XMLParserConfiguration (final String cDataTagName) {
this(false, cDataTagName, false);
}
/**
* Configure the parser to use custom settings.
* @param keepStrings <code>true</code> to parse all values as string.
* <code>false</code> to try and convert XML string values into a JSON value.
* @param cDataTagName <code>null</code> to disable CDATA processing. Any other value
* to use that value as the JSONObject key name to process as CDATA.
* @deprecated This constructor has been deprecated in favor of using the new builder
* pattern for the configuration.
* This constructor may be removed in a future release.
*/
@Deprecated
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName) {
this.keepStrings = keepStrings;
this.cDataTagName = cDataTagName;
this.convertNilAttributeToNull = false;
}
/**
* Configure the parser to use custom settings.
* @param keepStrings <code>true</code> to parse all values as string.
* <code>false</code> to try and convert XML string values into a JSON value.
* @param cDataTagName <code>null</code> to disable CDATA processing. Any other value
* to use that value as the JSONObject key name to process as CDATA.
* @param convertNilAttributeToNull <code>true</code> to parse values with attribute xsi:nil="true" as null.
* <code>false</code> to parse values with attribute xsi:nil="true" as {"xsi:nil":true}.
* @deprecated This constructor has been deprecated in favor of using the new builder
* pattern for the configuration.
* This constructor may be removed or marked private in a future release.
*/
@Deprecated
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName, final boolean convertNilAttributeToNull) {
this.keepStrings = keepStrings;
this.cDataTagName = cDataTagName;
this.convertNilAttributeToNull = convertNilAttributeToNull;
}
/**
* Configure the parser to use custom settings.
* @param keepStrings <code>true</code> to parse all values as string.
* <code>false</code> to try and convert XML string values into a JSON value.
* @param cDataTagName <code>null</code> to disable CDATA processing. Any other value
* to use that value as the JSONObject key name to process as CDATA.
* @param convertNilAttributeToNull <code>true</code> to parse values with attribute xsi:nil="true" as null.
* <code>false</code> to parse values with attribute xsi:nil="true" as {"xsi:nil":true}.
* @param xsiTypeMap <code>new HashMap<String, XMLXsiTypeConverter<?>>()</code> to parse values with attribute
* xsi:type="integer" as integer, xsi:type="string" as string
* @param forceList <code>new HashSet<String>()</code> to parse the provided tags' values as arrays
*/
private XMLParserConfiguration (final boolean keepStrings, final String cDataTagName,
final boolean convertNilAttributeToNull, final Map<String, XMLXsiTypeConverter<?>> xsiTypeMap, final Set<String> forceList ) {
this.keepStrings = keepStrings;
this.cDataTagName = cDataTagName;
this.convertNilAttributeToNull = convertNilAttributeToNull;
this.xsiTypeMap = Collections.unmodifiableMap(xsiTypeMap);
this.forceList = Collections.unmodifiableSet(forceList);
}
/**
* Provides a new instance of the same configuration.
*/
@Override
protected XMLParserConfiguration clone() {
// future modifications to this method should always ensure a "deep"
// clone in the case of collections. i.e. if a Map is added as a configuration
// item, a new map instance should be created and if possible each value in the
// map should be cloned as well. If the values of the map are known to also
// be immutable, then a shallow clone of the map is acceptable.
return new XMLParserConfiguration(
this.keepStrings,
this.cDataTagName,
this.convertNilAttributeToNull,
this.xsiTypeMap,
this.forceList
);
}
/**
* When parsing the XML into JSON, specifies if values should be kept as strings (<code>true</code>), or if
* they should try to be guessed into JSON values (numeric, boolean, string)
*
* @return The <code>keepStrings</code> configuration value.
*/
public boolean isKeepStrings() {
return this.keepStrings;
}
/**
* When parsing the XML into JSON, specifies if values should be kept as strings (<code>true</code>), or if
* they should try to be guessed into JSON values (numeric, boolean, string)
*
* @param newVal
* new value to use for the <code>keepStrings</code> configuration option.
*
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public XMLParserConfiguration withKeepStrings(final boolean newVal) {
XMLParserConfiguration newConfig = this.clone();
newConfig.keepStrings = newVal;
return newConfig;
}
/**
* The name of the key in a JSON Object that indicates a CDATA section. Historically this has
* been the value "content" but can be changed. Use <code>null</code> to indicate no CDATA
* processing.
*
* @return The <code>cDataTagName</code> configuration value.
*/
public String getcDataTagName() {
return this.cDataTagName;
}
/**
* The name of the key in a JSON Object that indicates a CDATA section. Historically this has
* been the value "content" but can be changed. Use <code>null</code> to indicate no CDATA
* processing.
*
* @param newVal
* new value to use for the <code>cDataTagName</code> configuration option.
*
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public XMLParserConfiguration withcDataTagName(final String newVal) {
XMLParserConfiguration newConfig = this.clone();
newConfig.cDataTagName = newVal;
return newConfig;
}
/**
* When parsing the XML into JSON, specifies if values with attribute xsi:nil="true"
* should be kept as attribute(<code>false</code>), or they should be converted to
* <code>null</code>(<code>true</code>)
*
* @return The <code>convertNilAttributeToNull</code> configuration value.
*/
public boolean isConvertNilAttributeToNull() {
return this.convertNilAttributeToNull;
}
/**
* When parsing the XML into JSON, specifies if values with attribute xsi:nil="true"
* should be kept as attribute(<code>false</code>), or they should be converted to
* <code>null</code>(<code>true</code>)
*
* @param newVal
* new value to use for the <code>convertNilAttributeToNull</code> configuration option.
*
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public XMLParserConfiguration withConvertNilAttributeToNull(final boolean newVal) {
XMLParserConfiguration newConfig = this.clone();
newConfig.convertNilAttributeToNull = newVal;
return newConfig;
}
/**
* When parsing the XML into JSON, specifies that the values with attribute xsi:type
* will be converted to target type defined to client in this configuration
* {@code Map<String, XMLXsiTypeConverter<?>>} to parse values with attribute
* xsi:type="integer" as integer, xsi:type="string" as string
* @return <code>xsiTypeMap</code> unmodifiable configuration map.
*/
public Map<String, XMLXsiTypeConverter<?>> getXsiTypeMap() {
return this.xsiTypeMap;
}
/**
* When parsing the XML into JSON, specifies that the values with attribute xsi:type
* will be converted to target type defined to client in this configuration
* {@code Map<String, XMLXsiTypeConverter<?>>} to parse values with attribute
* xsi:type="integer" as integer, xsi:type="string" as string
* @param xsiTypeMap {@code new HashMap<String, XMLXsiTypeConverter<?>>()} to parse values with attribute
* xsi:type="integer" as integer, xsi:type="string" as string
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public XMLParserConfiguration withXsiTypeMap(final Map<String, XMLXsiTypeConverter<?>> xsiTypeMap) {
XMLParserConfiguration newConfig = this.clone();
Map<String, XMLXsiTypeConverter<?>> cloneXsiTypeMap = new HashMap<String, XMLXsiTypeConverter<?>>(xsiTypeMap);
newConfig.xsiTypeMap = Collections.unmodifiableMap(cloneXsiTypeMap);
return newConfig;
}
/**
* When parsing the XML into JSON, specifies that tags that will be converted to arrays
* in this configuration {@code Set<String>} to parse the provided tags' values as arrays
* @return <code>forceList</code> unmodifiable configuration set.
*/
public Set<String> getForceList() {
return this.forceList;
}
/**
* When parsing the XML into JSON, specifies that tags that will be converted to arrays
* in this configuration {@code Set<String>} to parse the provided tags' values as arrays
* @param forceList {@code new HashSet<String>()} to parse the provided tags' values as arrays
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public XMLParserConfiguration withForceList(final Set<String> forceList) {
XMLParserConfiguration newConfig = this.clone();
Set<String> cloneForceList = new HashSet<String>(forceList);
newConfig.forceList = Collections.unmodifiableSet(cloneForceList);
return newConfig;
}
}

View File

@@ -1,27 +1,7 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import java.io.Reader;
@@ -90,12 +70,13 @@ public class XMLTokener extends JSONTokener {
/**
* Get the next XML outer token, trimming whitespace. There are two kinds
* of tokens: the '<' character which begins a markup tag, and the content
* of tokens: the <pre>{@code '<' }</pre> character which begins a markup
* tag, and the content
* text between markup tags.
*
* @return A string, or a '<' Character, or null if there is no more
* source text.
* @throws JSONException
* @return A string, or a <pre>{@code '<' }</pre> Character, or null if
* there is no more source text.
* @throws JSONException if a called function has an error
*/
public Object nextContent() throws JSONException {
char c;
@@ -129,8 +110,10 @@ public class XMLTokener extends JSONTokener {
/**
* <pre>{@code
* Return the next entity. These entities are translated to Characters:
* <code>&amp; &apos; &gt; &lt; &quot;</code>.
* &amp; &apos; &gt; &lt; &quot;.
* }</pre>
* @param ampersand An ampersand character.
* @return A Character or an entity String if the entity is not recognized.
* @throws JSONException If missing ';' in XML entity.
@@ -164,7 +147,7 @@ public class XMLTokener extends JSONTokener {
// if our entity is an encoded unicode point, parse it.
if (e.charAt(0) == '#') {
int cp;
if (e.charAt(1) == 'x') {
if (e.charAt(1) == 'x' || e.charAt(1) == 'X') {
// hex encoded unicode
cp = Integer.parseInt(e.substring(2), 16);
} else {
@@ -183,11 +166,14 @@ public class XMLTokener extends JSONTokener {
/**
* <pre>{@code
* Returns the next XML meta token. This is used for skipping over <!...>
* and <?...?> structures.
* @return Syntax characters (<code>< > / = ! ?</code>) are returned as
* }</pre>
* @return <pre>{@code Syntax characters (< > / = ! ?) are returned as
* Character, and strings and names are returned as Boolean. We don't care
* what the values actually are.
* }</pre>
* @throws JSONException If a string is not properly closed or if the XML
* is badly structured.
*/
@@ -250,10 +236,12 @@ public class XMLTokener extends JSONTokener {
/**
* <pre>{@code
* Get the next XML Token. These tokens are found inside of angle
* brackets. It may be one of these characters: <code>/ > = ! ?</code> or it
* brackets. It may be one of these characters: / > = ! ? or it
* may be a string wrapped in single quotes or double quotes, or it may be a
* name.
* }</pre>
* @return a String or a Character.
* @throws JSONException If the XML is not well formed.
*/

View File

@@ -0,0 +1,46 @@
package org.json;
/*
Public Domain.
*/
/**
* Type conversion configuration interface to be used with xsi:type attributes.
* <pre>
* <b>XML Sample</b>
* {@code
* <root>
* <asString xsi:type="string">12345</asString>
* <asInt xsi:type="integer">54321</asInt>
* </root>
* }
* <b>JSON Output</b>
* {@code
* {
* "root" : {
* "asString" : "12345",
* "asInt": 54321
* }
* }
* }
*
* <b>Usage</b>
* {@code
* Map<String, XMLXsiTypeConverter<?>> xsiTypeMap = new HashMap<String, XMLXsiTypeConverter<?>>();
* xsiTypeMap.put("string", new XMLXsiTypeConverter<String>() {
* &#64;Override public String convert(final String value) {
* return value;
* }
* });
* xsiTypeMap.put("integer", new XMLXsiTypeConverter<Integer>() {
* &#64;Override public Integer convert(final String value) {
* return Integer.valueOf(value);
* }
* });
* }
* </pre>
* @author kumar529
* @param <T> return type of convert method
*/
public interface XMLXsiTypeConverter<T> {
T convert(String value);
}

View File

@@ -0,0 +1,304 @@
package org.json.junit;
/*
Public Domain.
*/
import static org.junit.Assert.*;
import org.junit.Test;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONArray;
import org.json.CDL;
/**
* Tests for CDL.java.
* CDL provides an application level API, but it is not used by the
* reference app. To test it, strings will be converted to JSON-Java classes
* and then converted back.
*/
public class CDLTest {
/**
* String of lines where the column names are in the first row,
* and all subsequent rows are values. All keys and values should be legal.
*/
String lines = new String(
"Col 1, Col 2, \tCol 3, Col 4, Col 5, Col 6, Col 7\n" +
"val1, val2, val3, val4, val5, val6, val7\n" +
"1, 2, 3, 4\t, 5, 6, 7\n" +
"true, false, true, true, false, false, false\n" +
"0.23, 57.42, 5e27, -234.879, 2.34e5, 0.0, 9e-3\n" +
"\"va\tl1\", \"v\bal2\", \"val3\", \"val\f4\", \"val5\", va\'l6, val7\n"
);
/**
* CDL.toJSONArray() adds all values as strings, with no filtering or
* conversions. For testing, this means that the expected JSONObject
* values all must be quoted in the cases where the JSONObject parsing
* might normally convert the value into a non-string.
*/
String expectedLines = new String(
"[{Col 1:val1, Col 2:val2, Col 3:val3, Col 4:val4, Col 5:val5, Col 6:val6, Col 7:val7}, "+
"{Col 1:\"1\", Col 2:\"2\", Col 3:\"3\", Col 4:\"4\", Col 5:\"5\", Col 6:\"6\", Col 7:\"7\"}, "+
"{Col 1:\"true\", Col 2:\"false\", Col 3:\"true\", Col 4:\"true\", Col 5:\"false\", Col 6:\"false\", Col 7:\"false\"}, "+
"{Col 1:\"0.23\", Col 2:\"57.42\", Col 3:\"5e27\", Col 4:\"-234.879\", Col 5:\"2.34e5\", Col 6:\"0.0\", Col 7:\"9e-3\"}, "+
"{Col 1:\"va\tl1\", Col 2:\"v\bal2\", Col 3:val3, Col 4:\"val\f4\", Col 5:val5, Col 6:va\'l6, Col 7:val7}]");
/**
* Attempts to create a JSONArray from a null string.
* Expect a NullPointerException.
*/
@Test(expected=NullPointerException.class)
public void exceptionOnNullString() {
String nullStr = null;
CDL.toJSONArray(nullStr);
}
/**
* Attempts to create a JSONArray from a string with unbalanced quotes
* in column title line. Expects a JSONException.
*/
@Test
public void unbalancedQuoteInName() {
String badLine = "Col1, \"Col2\nVal1, Val2";
try {
CDL.toJSONArray(badLine);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Missing close quote '\"'. at 12 [character 0 line 2]",
e.getMessage());
}
}
/**
* Attempts to create a JSONArray from a string with unbalanced quotes
* in value line. Expects a JSONException.
*/
@Test
public void unbalancedQuoteInValue() {
String badLine = "Col1, Col2\n\"Val1, Val2";
try {
CDL.toJSONArray(badLine);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Missing close quote '\"'. at 22 [character 11 line 2]",
e.getMessage());
}
}
/**
* Attempts to create a JSONArray from a string with null char
* in column title line. Expects a JSONException.
*/
@Test
public void nullInName() {
String badLine = "C\0ol1, Col2\nVal1, Val2";
try {
CDL.toJSONArray(badLine);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Bad character 'o' (111). at 2 [character 3 line 1]",
e.getMessage());
}
}
/**
* Attempt to create a JSONArray with unbalanced quotes and a properly escaped doubled quote.
* Expects a JSONException.
*/
@Test
public void unbalancedEscapedQuote(){
String badLine = "Col1, Col2\n\"Val1, \"\"Val2\"\"";
try {
CDL.toJSONArray(badLine);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Missing close quote '\"'. at 26 [character 15 line 2]",
e.getMessage());
}
}
/**
* Assert that there is no error for a single escaped quote within a properly embedded quote.
*/
@Test
public void singleEscapedQuote(){
String singleEscape = "Col1, Col2\nVal1, \"\"\"Val2\"";
JSONArray jsonArray = CDL.toJSONArray(singleEscape);
String cdlStr = CDL.toString(jsonArray);
assertTrue(cdlStr.contains("Col1"));
assertTrue(cdlStr.contains("Col2"));
assertTrue(cdlStr.contains("Val1"));
assertTrue(cdlStr.contains("\"Val2"));
}
/**
* Assert that there is no error for a single escaped quote within a properly
* embedded quote when not the last value.
*/
@Test
public void singleEscapedQuoteMiddleString(){
String singleEscape = "Col1, Col2\nVal1, \"\"\"Val2\"\nVal 3,Val 4";
JSONArray jsonArray = CDL.toJSONArray(singleEscape);
String cdlStr = CDL.toString(jsonArray);
assertTrue(cdlStr.contains("Col1"));
assertTrue(cdlStr.contains("Col2"));
assertTrue(cdlStr.contains("Val1"));
assertTrue(cdlStr.contains("\"Val2"));
}
/**
* Attempt to create a JSONArray with an escape quote and no enclosing quotes.
* Expects a JSONException.
*/
@Test
public void badEscapedQuote(){
String badLine = "Col1, Col2\nVal1, \"\"Val2";
try {
CDL.toJSONArray(badLine);
fail("Expecting an exception");
} catch (JSONException e) {
//System.out.println("Message" + e.getMessage());
assertEquals("Expecting an exception message",
"Bad character 'V' (86). at 20 [character 9 line 2]",
e.getMessage());
}
}
/**
* call toString with a null array
*/
@Test(expected=NullPointerException.class)
public void nullJSONArrayToString() {
CDL.toString((JSONArray)null);
}
/**
* Create a JSONArray from an empty string
*/
@Test
public void emptyString() {
String emptyStr = "";
JSONArray jsonArray = CDL.toJSONArray(emptyStr);
assertTrue("CDL should return null when the input string is empty",
jsonArray == null);
}
/**
* Create a JSONArray with only 1 row
*/
@Test
public void onlyColumnNames() {
String columnNameStr = "col1, col2, col3";
JSONArray jsonArray = CDL.toJSONArray(columnNameStr);
assertNull("CDL should return null when only 1 row is given",
jsonArray);
}
/**
* Create a JSONArray from string containing only whitespace and commas
*/
@Test
public void emptyLinesToJSONArray() {
String str = " , , , \n , , , ";
JSONArray jsonArray = CDL.toJSONArray(str);
assertNull("JSONArray should be null for no content",
jsonArray);
}
/**
* call toString with a null array
*/
@Test
public void emptyJSONArrayToString() {
JSONArray jsonArray = new JSONArray();
String str = CDL.toString(jsonArray);
assertNull("CDL should return null for toString(null)",
str);
}
/**
* call toString with a null arrays for names and values
*/
@Test
public void nullJSONArraysToString() {
String str = CDL.toString(null, null);
assertNull("CDL should return null for toString(null)",
str);
}
/**
* Given a JSONArray that was not built by CDL, some chars may be
* found that would otherwise be filtered out by CDL.
*/
@Test
public void checkSpecialChars() {
JSONArray jsonArray = new JSONArray();
JSONObject jsonObject = new JSONObject();
jsonArray.put(jsonObject);
// \r will be filtered from name
jsonObject.put("Col \r1", "V1");
// \r will be filtered from value
jsonObject.put("Col 2", "V2\r");
assertTrue("expected length should be 1",jsonArray.length() == 1);
String cdlStr = CDL.toString(jsonArray);
jsonObject = jsonArray.getJSONObject(0);
assertTrue(cdlStr.contains("\"Col 1\""));
assertTrue(cdlStr.contains("Col 2"));
assertTrue(cdlStr.contains("V1"));
assertTrue(cdlStr.contains("\"V2\""));
}
/**
* Create a JSONArray from a string of lines
*/
@Test
public void textToJSONArray() {
JSONArray jsonArray = CDL.toJSONArray(this.lines);
JSONArray expectedJsonArray = new JSONArray(this.expectedLines);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
}
/**
* Create a JSONArray from a JSONArray of titles and a
* string of value lines
*/
@Test
public void jsonArrayToJSONArray() {
String nameArrayStr = "[Col1, Col2]";
String values = "V1, V2";
JSONArray nameJSONArray = new JSONArray(nameArrayStr);
JSONArray jsonArray = CDL.toJSONArray(nameJSONArray, values);
JSONArray expectedJsonArray = new JSONArray("[{Col1:V1,Col2:V2}]");
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
}
/**
* Create a JSONArray from a string of lines,
* then convert to string and then back to JSONArray
*/
@Test
public void textToJSONArrayAndBackToString() {
JSONArray jsonArray = CDL.toJSONArray(this.lines);
String jsonStr = CDL.toString(jsonArray);
JSONArray finalJsonArray = CDL.toJSONArray(jsonStr);
JSONArray expectedJsonArray = new JSONArray(this.expectedLines);
Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
}
}

View File

@@ -0,0 +1,190 @@
package org.json.junit;
/*
Public Domain.
*/
import static org.junit.Assert.*;
import java.util.*;
import org.json.*;
import org.junit.Test;
import com.jayway.jsonpath.*;
/**
* HTTP cookie specification RFC6265: http://tools.ietf.org/html/rfc6265
* <p>
* A cookie list is a JSONObject whose members are presumed to be cookie
* name/value pairs. Entries are unescaped while being added, and escaped in
* the toString() output.
* Unescaping means to convert %hh hex strings to the ascii equivalent
* and converting '+' to ' '.
* Escaping converts '+', '%', '=', ';' and ascii control chars to %hh hex strings.
* <p>
* CookieList should not be considered as just a list of Cookie objects:<br>
* - CookieList stores a cookie name/value pair as a single entry; Cookie stores
* it as 2 entries (key="name" and key="value").<br>
* - CookieList requires multiple name/value pairs as input; Cookie allows the
* 'secure' name with no associated value<br>
* - CookieList has no special handling for attribute name/value pairs.<br>
*/
public class CookieListTest {
/**
* Attempts to create a CookieList from a null string.
* Expects a NullPointerException.
*/
@Test(expected=NullPointerException.class)
public void nullCookieListException() {
String cookieStr = null;
CookieList.toJSONObject(cookieStr);
}
/**
* Attempts to create a CookieList from a malformed string.
* Expects a JSONException.
*/
@Test
public void malFormedCookieListException() {
String cookieStr = "thisCookieHasNoEqualsChar";
try {
CookieList.toJSONObject(cookieStr);
fail("should throw an exception");
} catch (JSONException e) {
/**
* Not sure of the missing char, but full string compare fails
*/
assertEquals("Expecting an exception message",
"Expected '=' and instead saw '' at 25 [character 26 line 1]",
e.getMessage());
}
}
/**
* Creates a CookieList from an empty string.
*/
@Test
public void emptyStringCookieList() {
String cookieStr = "";
JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
assertTrue(jsonObject.isEmpty());
}
/**
* CookieList with the simplest cookie - a name/value pair with no delimiter.
*/
@Test
public void simpleCookieList() {
String cookieStr = "SID=31d4d96e407aad42";
JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("Expected 1 top level item", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 1);
assertTrue("expected 31d4d96e407aad42", "31d4d96e407aad42".equals(jsonObject.query("/SID")));
}
/**
* CookieList with a single a cookie which has a name/value pair and delimiter.
*/
@Test
public void simpleCookieListWithDelimiter() {
String cookieStr = "SID=31d4d96e407aad42;";
JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("Expected 1 top level item", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 1);
assertTrue("expected 31d4d96e407aad42", "31d4d96e407aad42".equals(jsonObject.query("/SID")));
}
/**
* CookieList with multiple cookies consisting of name/value pairs
* with delimiters.
*/
@Test
public void multiPartCookieList() {
String cookieStr =
"name1=myCookieValue1; "+
" name2=myCookieValue2;"+
"name3=myCookieValue3;"+
" name4=myCookieValue4; "+
"name5=myCookieValue5;"+
" name6=myCookieValue6;";
JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("Expected 6 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 6);
assertTrue("expected myCookieValue1", "myCookieValue1".equals(jsonObject.query("/name1")));
assertTrue("expected myCookieValue2", "myCookieValue2".equals(jsonObject.query("/name2")));
assertTrue("expected myCookieValue3", "myCookieValue3".equals(jsonObject.query("/name3")));
assertTrue("expected myCookieValue4", "myCookieValue4".equals(jsonObject.query("/name4")));
assertTrue("expected myCookieValue5", "myCookieValue5".equals(jsonObject.query("/name5")));
assertTrue("expected myCookieValue6", "myCookieValue6".equals(jsonObject.query("/name6")));
}
/**
* CookieList from a JSONObject with valid key and null value
*/
@Test
public void convertCookieListWithNullValueToString() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("key", JSONObject.NULL);
String cookieToStr = CookieList.toString(jsonObject);
assertTrue("toString() should be empty", "".equals(cookieToStr));
}
/**
* CookieList with multiple entries converted to a JSON document.
*/
@Test
public void convertCookieListToString() {
String cookieStr =
"name1=myCookieValue1; "+
" name2=myCookieValue2;"+
"name3=myCookieValue3;"+
" name4=myCookieValue4; "+
"name5=myCookieValue5;"+
" name6=myCookieValue6;";
JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
// exercise CookieList.toString()
String cookieListString = CookieList.toString(jsonObject);
// have to convert it back for validation
jsonObject = CookieList.toJSONObject(cookieListString);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("Expected 6 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 6);
assertTrue("expected myCookieValue1", "myCookieValue1".equals(jsonObject.query("/name1")));
assertTrue("expected myCookieValue2", "myCookieValue2".equals(jsonObject.query("/name2")));
assertTrue("expected myCookieValue3", "myCookieValue3".equals(jsonObject.query("/name3")));
assertTrue("expected myCookieValue4", "myCookieValue4".equals(jsonObject.query("/name4")));
assertTrue("expected myCookieValue5", "myCookieValue5".equals(jsonObject.query("/name5")));
assertTrue("expected myCookieValue6", "myCookieValue6".equals(jsonObject.query("/name6")));
}
/**
* CookieList with multiple entries and some '+' chars and URL-encoded
* values converted to a JSON document.
*/
@Test
public void convertEncodedCookieListToString() {
String cookieStr =
"name1=myCookieValue1; "+
" name2=my+Cookie+Value+2;"+
"name3=my%2BCookie%26Value%3B3%3D;"+
" name4=my%25CookieValue4; "+
"name5=myCookieValue5;"+
" name6=myCookieValue6;";
JSONObject jsonObject = CookieList.toJSONObject(cookieStr);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("Expected 6 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 6);
assertTrue("expected myCookieValue1", "myCookieValue1".equals(jsonObject.query("/name1")));
assertTrue("expected my Cookie Value 2", "my Cookie Value 2".equals(jsonObject.query("/name2")));
assertTrue("expected my+Cookie&Value;3=", "my+Cookie&Value;3=".equals(jsonObject.query("/name3")));
assertTrue("expected my%CookieValue4", "my%CookieValue4".equals(jsonObject.query("/name4")));
assertTrue("expected my%CookieValue5", "myCookieValue5".equals(jsonObject.query("/name5")));
assertTrue("expected myCookieValue6", "myCookieValue6".equals(jsonObject.query("/name6")));
}
}

View File

@@ -0,0 +1,242 @@
package org.json.junit;
/*
Public Domain.
*/
import static org.junit.Assert.*;
import org.json.*;
import org.junit.Test;
/**
* HTTP cookie specification: RFC6265
* <p>
* At its most basic, a cookie is a name=value pair. The value may be subdivided
* into other cookies, but that is not tested here. The cookie may also include
* certain named attributes, delimited by semicolons.
* <p>
* The Cookie.toString() method emits certain attributes if present: expires,
* domain, path, secure. All but secure are name-value pairs. Other attributes
* are not included in the toString() output.
* <p>
* A JSON-Java encoded cookie escapes '+', '%', '=', ';' with %hh values.
*/
public class CookieTest {
/**
* Attempts to create a JSONObject from a null string.
* Expects a NullPointerException.
*/
@Test(expected=NullPointerException.class)
public void nullCookieException() {
String cookieStr = null;
Cookie.toJSONObject(cookieStr);
}
/**
* Attempts to create a JSONObject from a cookie string with
* no '=' char.
* Expects a JSONException.
*/
@Test
public void malFormedNameValueException() {
String cookieStr = "thisCookieHasNoEqualsChar";
try {
Cookie.toJSONObject(cookieStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Expected '=' and instead saw '' at 25 [character 26 line 1]",
e.getMessage());
}
}
/**
* Attempts to create a JSONObject from a cookie string
* with embedded ';' char.
* Expects a JSONException.
*/
@Test
public void booleanAttribute() {
String cookieStr = "this=Cookie;myAttribute";
JSONObject jo = Cookie.toJSONObject(cookieStr);
assertTrue("has key 'name'", jo.has("name"));
assertTrue("has key 'value'", jo.has("value"));
assertTrue("has key 'myAttribute'", jo.has("myattribute"));
}
/**
* Attempts to create a JSONObject from an empty cookie string.<br>
* Note: Cookie throws an exception, but CookieList does not.<br>
* Expects a JSONException
*/
@Test
public void emptyStringCookieException() {
String cookieStr = "";
try {
Cookie.toJSONObject(cookieStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Cookies must have a 'name'",
e.getMessage());
}
}
/**
*
* Attempts to create a JSONObject from an cookie string where the name is blank.<br>
* Note: Cookie throws an exception, but CookieList does not.<br>
* Expects a JSONException
*/
@Test
public void emptyNameCookieException() {
String cookieStr = " = value ";
try {
Cookie.toJSONObject(cookieStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Cookies must have a 'name'",
e.getMessage());
}
}
/**
* Cookie from a simple name/value pair with no delimiter
*/
@Test
public void simpleCookie() {
String cookieStr = "SID=31d4d96e407aad42";
String expectedCookieStr = "{\"name\":\"SID\",\"value\":\"31d4d96e407aad42\"}";
JSONObject jsonObject = Cookie.toJSONObject(cookieStr);
JSONObject expectedJsonObject = new JSONObject(expectedCookieStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Store a cookie with all of the supported attributes in a
* JSONObject. The secure attribute, which has no value, is treated
* as a boolean.
*/
@Test
public void multiPartCookie() {
String cookieStr =
"PH=deleted; "+
" expires=Wed, 19-Mar-2014 17:53:53 GMT;"+
"path=/; "+
" domain=.yahoo.com;"+
"secure";
String expectedCookieStr =
"{"+
"\"name\":\"PH\","+
"\"value\":\"deleted\","+
"\"path\":\"/\","+
"\"expires\":\"Wed, 19-Mar-2014 17:53:53 GMT\","+
"\"domain\":\".yahoo.com\","+
"\"secure\":true"+
"}";
JSONObject jsonObject = Cookie.toJSONObject(cookieStr);
JSONObject expectedJsonObject = new JSONObject(expectedCookieStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Cookie.toString() will emit the non-standard "thiswont=beIncluded"
* attribute, and the attribute is still stored in the JSONObject.
* This test confirms both behaviors.
*/
@Test
public void convertCookieToString() {
String cookieStr =
"PH=deleted; "+
" expires=Wed, 19-Mar-2014 17:53:53 GMT;"+
"path=/; "+
" domain=.yahoo.com;"+
"thisWont=beIncluded;"+
"secure";
String expectedCookieStr =
"{\"thiswont\":\"beIncluded\","+
"\"path\":\"/\","+
"\"expires\":\"Wed, 19-Mar-2014 17:53:53 GMT\","+
"\"domain\":\".yahoo.com\","+
"\"name\":\"PH\","+
"\"secure\":true,"+
"\"value\":\"deleted\"}";
// Add the nonstandard attribute to the expected cookie string
String expectedDirectCompareCookieStr = expectedCookieStr;
// convert all strings into JSONObjects
JSONObject jsonObject = Cookie.toJSONObject(cookieStr);
JSONObject expectedJsonObject = new JSONObject(expectedCookieStr);
JSONObject expectedDirectCompareJsonObject =
new JSONObject(expectedDirectCompareCookieStr);
// emit the string
String cookieToStr = Cookie.toString(jsonObject);
// create a final JSONObject from the string
JSONObject finalJsonObject = Cookie.toJSONObject(cookieToStr);
// JSONObject should contain the nonstandard string
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedDirectCompareJsonObject);
// JSONObject -> string -> JSONObject should not contain the nonstandard string
Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
}
/**
* A string may be URL-encoded when converting to JSONObject.
* If found, '+' is converted to ' ', and %hh hex strings are converted
* to their ascii char equivalents. This test confirms the decoding
* behavior.
*/
@Test
public void convertEncodedCookieToString() {
String cookieStr =
"PH=deleted; "+
" expires=Wed,+19-Mar-2014+17:53:53+GMT;"+
"path=/%2Bthis/is%26/a/spec%3Bsegment%3D; "+
" domain=.yahoo.com;"+
"secure";
String expectedCookieStr =
"{\"path\":\"/+this/is&/a/spec;segment=\","+
"\"expires\":\"Wed, 19-Mar-2014 17:53:53 GMT\","+
"\"domain\":\".yahoo.com\","+
"\"name\":\"PH\","+
"\"secure\":true,"+
"\"value\":\"deleted\"}";
JSONObject jsonObject = Cookie.toJSONObject(cookieStr);
JSONObject expectedJsonObject = new JSONObject(expectedCookieStr);
String cookieToStr = Cookie.toString(jsonObject);
JSONObject finalJsonObject = Cookie.toJSONObject(cookieToStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
}
/**
* A public API method performs a URL encoding for selected chars
* in a string. Control chars, '+', '%', '=', ';' are all encoded
* as %hh hex strings. The string is also trimmed.
* This test confirms that behavior.
*/
@Test
public void escapeString() {
String str = " +%\r\n\t\b%=;;; ";
String expectedStr = "%2b%25%0d%0a%09%08%25%3d%3b%3b%3b";
String actualStr = Cookie.escape(str);
assertTrue("expect escape() to encode correctly. Actual: " +actualStr+
" expected: " +expectedStr, expectedStr.equals(actualStr));
}
/**
* A public API method performs URL decoding for strings.
* '+' is converted to space and %hh hex strings are converted to
* their ascii equivalent values. The string is not trimmed.
* This test confirms that behavior.
*/
@Test
public void unescapeString() {
String str = " +%2b%25%0d%0a%09%08%25%3d%3b%3b%3b+ ";
String expectedStr = " +%\r\n\t\b%=;;; ";
String actualStr = Cookie.unescape(str);
assertTrue("expect unescape() to decode correctly. Actual: " +actualStr+
" expected: " +expectedStr, expectedStr.equals(actualStr));
}
}

View File

@@ -0,0 +1,433 @@
package org.json.junit;
/*
Public Domain.
*/
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.junit.data.MyEnum;
import org.json.junit.data.MyEnumClass;
import org.json.junit.data.MyEnumField;
import org.junit.Test;
import com.jayway.jsonpath.Configuration;
import com.jayway.jsonpath.JsonPath;
/**
* Enums are not explicitly supported in JSON-Java. But because enums act like
* classes, all required behavior is already be present in some form.
* These tests explore how enum serialization works with JSON-Java.
*/
public class EnumTest {
/**
* To serialize an enum by its getters, use the JSONObject Object constructor.
* The JSONObject ctor handles enum like any other bean. A JSONobject
* is created whose entries are the getter name/value pairs.
*/
@Test
public void jsonObjectFromEnum() {
// If there are no getters then the object is empty.
MyEnum myEnum = MyEnum.VAL2;
JSONObject jsonObject = new JSONObject(myEnum);
assertTrue("simple enum has no getters", jsonObject.isEmpty());
// enum with a getters should create a non-empty object
MyEnumField myEnumField = MyEnumField.VAL2;
jsonObject = new JSONObject(myEnumField);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider()
.parse(jsonObject.toString());
assertTrue("expecting 2 items in top level object", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expecting val 2", "val 2".equals(jsonObject.query("/value")));
assertTrue("expecting 2", Integer.valueOf(2).equals(jsonObject.query("/intVal")));
/**
* class which contains enum instances. Each enum should be stored
* in its own JSONObject
*/
MyEnumClass myEnumClass = new MyEnumClass();
myEnumClass.setMyEnum(MyEnum.VAL1);
myEnumClass.setMyEnumField(MyEnumField.VAL3);
jsonObject = new JSONObject(myEnumClass);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 2 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected 2 myEnumField items", "VAL3".equals((JsonPath.read(doc, "$.myEnumField"))));
assertTrue("expected 0 myEnum items", "VAL1".equals((JsonPath.read(doc, "$.myEnum"))));
assertTrue("expecting MyEnumField.VAL3", MyEnumField.VAL3.equals(jsonObject.query("/myEnumField")));
assertTrue("expecting MyEnum.VAL1", MyEnum.VAL1.equals(jsonObject.query("/myEnum")));
}
/**
* To serialize an enum by its set of allowed values, use getNames()
* and the JSONObject Object with names constructor.
*/
@Test
public void jsonObjectFromEnumWithNames() {
String [] names;
JSONObject jsonObject;
MyEnum myEnum = MyEnum.VAL1;
names = JSONObject.getNames(myEnum);
// The values will be MyEnum fields
jsonObject = new JSONObject(myEnum, names);
// validate JSON object
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 3 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 3);
assertTrue("expected VAL1", MyEnum.VAL1.equals(jsonObject.query("/VAL1")));
assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonObject.query("/VAL2")));
assertTrue("expected VAL3", MyEnum.VAL3.equals(jsonObject.query("/VAL3")));
MyEnumField myEnumField = MyEnumField.VAL3;
names = JSONObject.getNames(myEnumField);
// The values will be MyEnmField fields
jsonObject = new JSONObject(myEnumField, names);
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 3 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 3);
assertTrue("expected VAL1", MyEnumField.VAL1.equals(jsonObject.query("/VAL1")));
assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonObject.query("/VAL2")));
assertTrue("expected VAL3", MyEnumField.VAL3.equals(jsonObject.query("/VAL3")));
}
/**
* Verify that enums are handled consistently between JSONArray and JSONObject
*/
@Test
public void verifyEnumConsistency(){
JSONObject jo = new JSONObject();
jo.put("value", MyEnumField.VAL2);
String expected="{\"value\":\"VAL2\"}";
String actual = jo.toString();
assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
jo.accumulate("value", MyEnumField.VAL1);
expected="{\"value\":[\"VAL2\",\"VAL1\"]}";
actual = jo.toString();
assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
jo.remove("value");
jo.append("value", MyEnumField.VAL1);
expected="{\"value\":[\"VAL1\"]}";
actual = jo.toString();
assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
jo.put("value", EnumSet.of(MyEnumField.VAL2));
expected="{\"value\":[\"VAL2\"]}";
actual = jo.toString();
assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
JSONArray ja = new JSONArray();
ja.put(MyEnumField.VAL2);
jo.put("value", ja);
actual = jo.toString();
assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
jo.put("value", new MyEnumField[]{MyEnumField.VAL2});
actual = jo.toString();
assertTrue("Expected "+expected+" but actual was "+actual, expected.equals(actual));
}
/**
* To serialize by assigned value, use the put() methods. The value
* will be stored as a enum type.
*/
@Test
public void enumPut() {
JSONObject jsonObject = new JSONObject();
MyEnum myEnum = MyEnum.VAL2;
jsonObject.put("myEnum", myEnum);
MyEnumField myEnumField = MyEnumField.VAL1;
jsonObject.putOnce("myEnumField", myEnumField);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 2 top level objects", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonObject.query("/myEnum")));
assertTrue("expected VAL1", MyEnumField.VAL1.equals(jsonObject.query("/myEnumField")));
JSONArray jsonArray = new JSONArray();
jsonArray.put(myEnum);
jsonArray.put(1, myEnumField);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
assertTrue("expected 2 top level objects", ((List<?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonArray.query("/0")));
assertTrue("expected VAL1", MyEnumField.VAL1.equals(jsonArray.query("/1")));
/**
* Leaving these tests because they exercise get, opt, and remove
*/
assertTrue("expecting myEnum value", MyEnum.VAL2.equals(jsonArray.get(0)));
assertTrue("expecting myEnumField value", MyEnumField.VAL1.equals(jsonArray.opt(1)));
assertTrue("expecting myEnumField value", MyEnumField.VAL1.equals(jsonArray.remove(1)));
}
/**
* The default action of valueToString() is to call object.toString().
* For enums, this means the assigned value will be returned as a string.
*/
@Test
public void enumValueToString() {
String expectedStr1 = "\"VAL1\"";
String expectedStr2 = "\"VAL1\"";
MyEnum myEnum = MyEnum.VAL1;
MyEnumField myEnumField = MyEnumField.VAL1;
MyEnumClass myEnumClass = new MyEnumClass();
String str1 = JSONObject.valueToString(myEnum);
assertTrue("actual myEnum: "+str1+" expected: "+expectedStr1,
str1.equals(expectedStr1));
String str2 = JSONObject.valueToString(myEnumField);
assertTrue("actual myEnumField: "+str2+" expected: "+expectedStr2,
str2.equals(expectedStr2));
/**
* However, an enum within another class will not be rendered
* unless that class overrides default toString()
*/
String expectedStr3 = "\"org.json.junit.data.MyEnumClass@";
myEnumClass.setMyEnum(MyEnum.VAL1);
myEnumClass.setMyEnumField(MyEnumField.VAL1);
String str3 = JSONObject.valueToString(myEnumClass);
assertTrue("actual myEnumClass: "+str3+" expected: "+expectedStr3,
str3.startsWith(expectedStr3));
}
/**
* In whatever form the enum was added to the JSONObject or JSONArray,
* json[Object|Array].toString should serialize it in a reasonable way.
*/
@Test
public void enumToString() {
MyEnum myEnum = MyEnum.VAL2;
JSONObject jsonObject = new JSONObject(myEnum);
String expectedStr = "{}";
assertTrue("myEnum toString() should be empty", expectedStr.equals(jsonObject.toString()));
MyEnumField myEnumField = MyEnumField.VAL2;
jsonObject = new JSONObject(myEnumField);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 2 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected val 2", "val 2".equals(jsonObject.query("/value")));
assertTrue("expected 2", Integer.valueOf(2).equals(jsonObject.query("/intVal")));
MyEnumClass myEnumClass = new MyEnumClass();
myEnumClass.setMyEnum(MyEnum.VAL1);
myEnumClass.setMyEnumField(MyEnumField.VAL3);
jsonObject = new JSONObject(myEnumClass);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 2 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected VAL3", "VAL3".equals((JsonPath.read(doc, "$.myEnumField"))));
assertTrue("expected VAL1", "VAL1".equals((JsonPath.read(doc, "$.myEnum"))));
String [] names = JSONObject.getNames(myEnum);
jsonObject = new JSONObject(myEnum, names);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 3 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 3);
assertTrue("expected VAL1", MyEnum.VAL1.equals(jsonObject.query("/VAL1")));
assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonObject.query("/VAL2")));
assertTrue("expected VAL3", MyEnum.VAL3.equals(jsonObject.query("/VAL3")));
names = JSONObject.getNames(myEnumField);
jsonObject = new JSONObject(myEnumField, names);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 3 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 3);
assertTrue("expected VAL1", MyEnumField.VAL1.equals(jsonObject.query("/VAL1")));
assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonObject.query("/VAL2")));
assertTrue("expected VAL3", MyEnumField.VAL3.equals(jsonObject.query("/VAL3")));
expectedStr = "{\"myEnum\":\"VAL2\", \"myEnumField\":\"VAL2\"}";
jsonObject = new JSONObject();
jsonObject.putOpt("myEnum", myEnum);
jsonObject.putOnce("myEnumField", myEnumField);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 2 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonObject.query("/myEnum")));
assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonObject.query("/myEnumField")));
JSONArray jsonArray = new JSONArray();
jsonArray.put(myEnum);
jsonArray.put(1, myEnumField);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
assertTrue("expected 2 top level items", ((List<?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected VAL2", MyEnum.VAL2.equals(jsonArray.query("/0")));
assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonArray.query("/1")));
}
/**
* Wrap should handle enums exactly as a value type like Integer, Boolean, or String.
*/
@Test
public void wrap() {
assertTrue("simple enum has no getters", JSONObject.wrap(MyEnum.VAL2) instanceof MyEnum);
MyEnumField myEnumField = MyEnumField.VAL2;
JSONObject jsonObject = new JSONObject();
jsonObject.put("enum",myEnumField);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 1 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 1);
assertTrue("expected VAL2", MyEnumField.VAL2.equals(jsonObject.query("/enum")));
MyEnumClass myEnumClass = new MyEnumClass();
myEnumClass.setMyEnum(MyEnum.VAL1);
myEnumClass.setMyEnumField(MyEnumField.VAL3);
jsonObject = (JSONObject)JSONObject.wrap(myEnumClass);
// validate JSON content
doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 2 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 2);
assertTrue("expected VAL3", "VAL3".equals((JsonPath.read(doc, "$.myEnumField"))));
assertTrue("expected VAL1", "VAL1".equals((JsonPath.read(doc, "$.myEnum"))));
assertTrue("expecting MyEnumField.VAL3", MyEnumField.VAL3.equals(jsonObject.query("/myEnumField")));
assertTrue("expecting MyEnum.VAL1", MyEnum.VAL1.equals(jsonObject.query("/myEnum")));
}
/**
* It was determined that some API methods should be added to
* support enums:<br>
* JSONObject.getEnum(class, key)<br>
* JSONObject.optEnum(class, key)<br>
* JSONObject.optEnum(class, key, default)<br>
* JSONArray.getEnum(class, index)<br>
* JSONArray.optEnum(class, index)<br>
* JSONArray.optEnum(class, index, default)<br>
* <p>
* Exercise these enum API methods on JSONObject and JSONArray
*/
@Test
public void enumAPI() {
MyEnumClass myEnumClass = new MyEnumClass();
myEnumClass.setMyEnum(MyEnum.VAL1);
MyEnumField myEnumField = MyEnumField.VAL2;
JSONObject jsonObject = new JSONObject();
jsonObject.put("strKey", "value");
jsonObject.put("strKey2", "VAL1");
jsonObject.put("enumKey", myEnumField);
jsonObject.put("enumClassKey", myEnumClass);
// get a plain old enum
MyEnumField actualEnum = jsonObject.getEnum(MyEnumField.class, "enumKey");
assertTrue("get myEnumField", actualEnum == MyEnumField.VAL2);
// try to get the wrong value
try {
actualEnum = jsonObject.getEnum(MyEnumField.class, "strKey");
assertTrue("should throw an exception for wrong key", false);
} catch (Exception ignored) {}
// get a class that contains an enum
MyEnumClass actualEnumClass = (MyEnumClass)jsonObject.get("enumClassKey");
assertTrue("get enum", actualEnumClass.getMyEnum() == MyEnum.VAL1);
// opt a plain old enum
actualEnum = jsonObject.optEnum(MyEnumField.class, "enumKey");
assertTrue("opt myEnumField", actualEnum == MyEnumField.VAL2);
// opt the wrong value
actualEnum = jsonObject.optEnum(MyEnumField.class, "strKey");
assertTrue("opt null", actualEnum == null);
// opt a class that contains an enum
actualEnumClass = (MyEnumClass)jsonObject.opt("enumClassKey");
assertTrue("get enum", actualEnumClass.getMyEnum() == MyEnum.VAL1);
// opt with default a plain old enum
actualEnum = jsonObject.optEnum(MyEnumField.class, "enumKey", null);
assertTrue("opt myEnumField", actualEnum == MyEnumField.VAL2);
// opt with default the wrong value
actualEnum = jsonObject.optEnum(MyEnumField.class, "strKey", null);
assertNull("opt null", actualEnum);
// opt with default the string value
actualEnum = jsonObject.optEnum(MyEnumField.class, "strKey2", null);
assertEquals(MyEnumField.VAL1, actualEnum);
// opt with default an index that does not exist
actualEnum = jsonObject.optEnum(MyEnumField.class, "noKey", null);
assertNull("opt null", actualEnum);
assertNull("Expected Null when the enum class is null",
jsonObject.optEnum(null, "enumKey"));
/**
* Exercise the proposed enum API methods on JSONArray
*/
JSONArray jsonArray = new JSONArray();
jsonArray.put("value");
jsonArray.put(myEnumField);
jsonArray.put(myEnumClass);
// get a plain old enum
actualEnum = jsonArray.getEnum(MyEnumField.class, 1);
assertTrue("get myEnumField", actualEnum == MyEnumField.VAL2);
// try to get the wrong value
try {
actualEnum = jsonArray.getEnum(MyEnumField.class, 0);
assertTrue("should throw an exception for wrong index", false);
} catch (Exception ignored) {}
// get a class that contains an enum
actualEnumClass = (MyEnumClass)jsonArray.get(2);
assertTrue("get enum", actualEnumClass.getMyEnum() == MyEnum.VAL1);
// opt a plain old enum
actualEnum = jsonArray.optEnum(MyEnumField.class, 1);
assertTrue("opt myEnumField", actualEnum == MyEnumField.VAL2);
// opt the wrong value
actualEnum = jsonArray.optEnum(MyEnumField.class, 0);
assertTrue("opt null", actualEnum == null);
// opt a class that contains an enum
actualEnumClass = (MyEnumClass)jsonArray.opt(2);
assertTrue("get enum", actualEnumClass.getMyEnum() == MyEnum.VAL1);
// opt with default a plain old enum
actualEnum = jsonArray.optEnum(MyEnumField.class, 1, null);
assertTrue("opt myEnumField", actualEnum == MyEnumField.VAL2);
// opt with default the wrong value
actualEnum = jsonArray.optEnum(MyEnumField.class, 0, null);
assertTrue("opt null", actualEnum == null);
// opt with default an index that does not exist
actualEnum = jsonArray.optEnum(MyEnumField.class, 3, null);
assertTrue("opt null", actualEnum == null);
}
}

View File

@@ -0,0 +1,200 @@
package org.json.junit;
/*
Public Domain.
*/
import static org.junit.Assert.*;
import org.json.*;
import org.junit.Test;
/**
* Unit tests for JSON-Java HTTP.java. See RFC7230.
*/
public class HTTPTest {
/**
* Attempt to call HTTP.toJSONObject() with a null string
* Expects a NUllPointerException.
*/
@Test(expected=NullPointerException.class)
public void nullHTTPException() {
String httpStr = null;
HTTP.toJSONObject(httpStr);
}
/**
* Attempt to call HTTP.toJSONObject() with a string containing
* an empty object. Expects a JSONException.
*/
@Test
public void notEnoughHTTPException() {
String httpStr = "{}";
JSONObject jsonObject = new JSONObject(httpStr);
try {
HTTP.toString(jsonObject);
assertTrue("Expected to throw exception", false);
} catch (JSONException e) {
assertTrue("Expecting an exception message",
"Not enough material for an HTTP header.".equals(e.getMessage()));
}
}
/**
* Calling HTTP.toJSONObject() with an empty string will result in a
* populated JSONObject with keys but no values for Request-URI, Method,
* and HTTP-Version.
*/
@Test
public void emptyStringHTTPRequest() {
String httpStr = "";
String expectedHTTPStr = "{\"Request-URI\":\"\",\"Method\":\"\",\"HTTP-Version\":\"\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Call HTTP.toJSONObject() with a Request-URI, Method,
* and HTTP-Version.
*/
@Test
public void simpleHTTPRequest() {
String httpStr = "GET /hello.txt HTTP/1.1";
String expectedHTTPStr =
"{\"Request-URI\":\"/hello.txt\",\"Method\":\"GET\",\"HTTP-Version\":\"HTTP/1.1\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Call HTTP.toJSONObject() with a response string containing a
* HTTP-Version, Status-Code, and Reason.
*/
@Test
public void simpleHTTPResponse() {
String httpStr = "HTTP/1.1 200 OK";
String expectedHTTPStr =
"{\"HTTP-Version\":\"HTTP/1.1\",\"Status-Code\":\"200\",\"Reason-Phrase\":\"OK\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Call HTTP.toJSONObject() with a full request string including
* request headers.
*/
@Test
public void extendedHTTPRequest() {
String httpStr =
"POST /enlighten/calais.asmx HTTP/1.1\n"+
"Host: api.opencalais.com\n"+
"Content-Type: text/xml; charset=utf-8\n"+
"Content-Length: 100\n"+
"SOAPAction: \"http://clearforest.com/Enlighten\"";
String expectedHTTPStr =
"{"+
"\"Request-URI\":\"/enlighten/calais.asmx\","+
"\"Host\":\"api.opencalais.com\","+
"\"Method\":\"POST\","+
"\"HTTP-Version\":\"HTTP/1.1\","+
"\"Content-Length\":\"100\","+
"\"Content-Type\":\"text/xml; charset=utf-8\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
/**
* Not too easy for JSONObject to parse a string with embedded quotes.
* For the sake of the test, add it here.
*/
expectedJsonObject.put("SOAPAction","\"http://clearforest.com/Enlighten\"");
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Call HTTP.toJSONObject() with a full response string including
* response headers.
*/
@Test
public void extendedHTTPResponse() {
String httpStr =
"HTTP/1.1 200 OK\n"+
"Content-Type: text/xml; charset=utf-8\n"+
"Content-Length: 100\n";
String expectedHTTPStr =
"{\"HTTP-Version\":\"HTTP/1.1\","+
"\"Status-Code\":\"200\","+
"\"Content-Length\":\"100\","+
"\"Reason-Phrase\":\"OK\","+
"\"Content-Type\":\"text/xml; charset=utf-8\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
}
/**
* Call HTTP.toJSONObject() with a full POST request string including
* response headers, then convert it back into an HTTP string.
*/
@Test
public void convertHTTPRequestToString() {
String httpStr =
"POST /enlighten/calais.asmx HTTP/1.1\n"+
"Host: api.opencalais.com\n"+
"Content-Type: text/xml; charset=utf-8\n"+
"Content-Length: 100";
String expectedHTTPStr =
"{"+
"\"Request-URI\":\"/enlighten/calais.asmx\","+
"\"Host\":\"api.opencalais.com\","+
"\"Method\":\"POST\","+
"\"HTTP-Version\":\"HTTP/1.1\","+
"\"Content-Length\":\"100\","+
"\"Content-Type\":\"text/xml; charset=utf-8\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
String httpToStr = HTTP.toString(jsonObject);
/**
* JSONObject objects to crlfs and any trailing chars.
* For the sake of the test, simplify the resulting string
*/
httpToStr = httpToStr.replaceAll("("+HTTP.CRLF+HTTP.CRLF+")", "");
httpToStr = httpToStr.replaceAll(HTTP.CRLF, "\n");
JSONObject finalJsonObject = HTTP.toJSONObject(httpToStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
}
/**
* Call HTTP.toJSONObject() with a full response string including
* response headers, then convert it back into an HTTP string.
*/
@Test
public void convertHTTPResponseToString() {
String httpStr =
"HTTP/1.1 200 OK\n"+
"Content-Type: text/xml; charset=utf-8\n"+
"Content-Length: 100\n";
String expectedHTTPStr =
"{\"HTTP-Version\":\"HTTP/1.1\","+
"\"Status-Code\":\"200\","+
"\"Content-Length\":\"100\","+
"\"Reason-Phrase\":\"OK\","+
"\"Content-Type\":\"text/xml; charset=utf-8\"}";
JSONObject jsonObject = HTTP.toJSONObject(httpStr);
JSONObject expectedJsonObject = new JSONObject(expectedHTTPStr);
String httpToStr = HTTP.toString(jsonObject);
/**
* JSONObject objects to crlfs and any trailing chars.
* For the sake of the test, simplify the resulting string
*/
httpToStr = httpToStr.replaceAll("("+HTTP.CRLF+HTTP.CRLF+")", "");
httpToStr = httpToStr.replaceAll(HTTP.CRLF, "\n");
JSONObject finalJsonObject = HTTP.toJSONObject(httpToStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
Util.compareActualVsExpectedJsonObjects(finalJsonObject,expectedJsonObject);
}
}

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,836 @@
package org.json.junit;
/*
Public Domain.
*/
import static org.junit.Assert.*;
import org.json.*;
import org.junit.Test;
/**
* Tests for org.json.JSONML.java
*
* Certain inputs are expected to result in exceptions. These tests are
* executed first. JSONML provides an API to:
* Convert an XML string into a JSONArray or a JSONObject.
* Convert a JSONArray or JSONObject into an XML string.
* Both fromstring and tostring operations operations should be symmetrical
* within the limits of JSONML.
* It should be possible to perform the following operations, which should
* result in the original string being recovered, within the limits of the
* underlying classes:
* Convert a string -> JSONArray -> string -> JSONObject -> string
* Convert a string -> JSONObject -> string -> JSONArray -> string
*
*/
public class JSONMLTest {
/**
* Attempts to transform a null XML string to JSON.
* Expects a NullPointerException
*/
@Test(expected=NullPointerException.class)
public void nullXMLException() {
String xmlStr = null;
JSONML.toJSONArray(xmlStr);
}
/**
* Attempts to transform an empty string to JSON.
* Expects a JSONException
*/
@Test
public void emptyXMLException() {
String xmlStr = "";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Bad XML at 0 [character 1 line 1]",
e.getMessage());
}
}
/**
* Attempts to call JSONML.toString() with a null JSONArray.
* Expects a NullPointerException.
*/
@Test(expected=NullPointerException.class)
public void nullJSONXMLException() {
/**
* Tries to convert a null JSONArray to XML.
*/
JSONArray jsonArray= null;
JSONML.toString(jsonArray);
}
/**
* Attempts to call JSONML.toString() with a null JSONArray.
* Expects a JSONException.
*/
@Test
public void emptyJSONXMLException() {
/**
* Tries to convert an empty JSONArray to XML.
*/
JSONArray jsonArray = new JSONArray();
try {
JSONML.toString(jsonArray);
assertTrue("Expecting an exception", false);
} catch (JSONException e) {
assertTrue("Expecting an exception message",
"JSONArray[0] not found.".
equals(e.getMessage()));
}
}
/**
* Attempts to transform an non-XML string to JSON.
* Expects a JSONException
*/
@Test
public void nonXMLException() {
/**
* Attempts to transform a nonXML string to JSON
*/
String xmlStr = "{ \"this is\": \"not xml\"}";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Bad XML at 23 [character 24 line 1]",
e.getMessage());
}
}
/**
* Attempts to transform a JSON document with XML content that
* does not follow JSONML conventions (element name is not first value
* in a nested JSONArray) to a JSONArray then back to string.
* Expects a JSONException
*/
@Test
public void emptyTagException() {
/**
* jsonArrayStr is used to build a JSONArray which is then
* turned into XML. For this transformation, all arrays represent
* elements and the first array entry is the name of the element.
* In this case, one of the arrays does not have a name
*/
String jsonArrayStr =
"[\"addresses\","+
"{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
// this array has no name
"["+
"[\"name\"],"+
"[\"nocontent\"],"+
"\">\""+
"]"+
"]";
JSONArray jsonArray = new JSONArray(jsonArrayStr);
try {
JSONML.toString(jsonArray);
assertTrue("Expecting an exception", false);
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"JSONArray[0] is not a String (class org.json.JSONArray).",
e.getMessage());
}
}
/**
* Attempts to transform a JSON document with XML content that
* does not follow JSONML conventions (element tag has an embedded space)
* to a JSONArray then back to string. Expects a JSONException
*/
@Test
public void spaceInTagException() {
/**
* jsonArrayStr is used to build a JSONArray which is then
* turned into XML. For this transformation, all arrays represent
* elements and the first array entry is the name of the element.
* In this case, one of the element names has an embedded space,
* which is not allowed.
*/
String jsonArrayStr =
"[\"addresses\","+
"{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
// this array has an invalid name
"[\"addr esses\","+
"[\"name\"],"+
"[\"nocontent\"],"+
"\">\""+
"]"+
"]";
JSONArray jsonArray = new JSONArray(jsonArrayStr);
try {
JSONML.toString(jsonArray);
assertTrue("Expecting an exception", false);
} catch (JSONException e) {
assertTrue("Expecting an exception message",
"'addr esses' contains a space character.".
equals(e.getMessage()));
}
}
/**
* Attempts to transform a malformed XML document
* (element tag has a frontslash) to a JSONArray.\
* Expects a JSONException
*/
@Test
public void invalidSlashInTagException() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* In this case, the XML is invalid because the 'name' element
* contains an invalid frontslash.
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/x>\n"+
" <street>abc street</street>\n"+
" </address>\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misshaped tag at 176 [character 14 line 4]",
e.getMessage());
}
}
/**
* Malformed XML text (invalid tagname) is transformed into a JSONArray.
* Expects a JSONException.
*/
@Test
public void invalidBangInTagException() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <!>\n"+
" </address>\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misshaped meta tag at 215 [character 12 line 7]",
e.getMessage());
}
}
/**
* Malformed XML text (invalid tagname, no close bracket) is transformed\
* into a JSONArray. Expects a JSONException.
*/
@Test
public void invalidBangNoCloseInTagException() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* In this case, the XML is invalid because an element
* starts with '!' and has no closing tag
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <!\n"+
" </address>\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misshaped meta tag at 214 [character 12 line 7]",
e.getMessage());
}
}
/**
* Malformed XML text (tagname with no close bracket) is transformed\
* into a JSONArray. Expects a JSONException.
*/
@Test
public void noCloseStartTagException() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* In this case, the XML is invalid because an element
* has no closing '>'.
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <abc\n"+
" </address>\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misplaced '<' at 194 [character 5 line 6]",
e.getMessage());
}
}
/**
* Malformed XML text (endtag with no name) is transformed\
* into a JSONArray. Expects a JSONException.
*/
@Test
public void noCloseEndTagException() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* In this case, the XML is invalid because an element
* has no name after the closing tag '</'.
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name/>\n"+
" <abc/>\n"+
" </>\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
assertTrue("Expecting an exception", false);
} catch (JSONException e) {
assertTrue("Expecting an exception message",
"Expected a closing name instead of '>'.".
equals(e.getMessage()));
}
}
/**
* Malformed XML text (endtag with no close bracket) is transformed\
* into a JSONArray. Expects a JSONException.
*/
@Test
public void noCloseEndBraceException() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* In this case, the XML is invalid because an element
* has '>' after the closing tag '</' and name.
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation=\"test.xsd\">\n"+
" <address>\n"+
" <name/>\n"+
" <abc/>\n"+
" </address\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Misplaced '<' at 206 [character 1 line 7]",
e.getMessage());
}
}
/**
* Malformed XML text (incomplete CDATA string) is transformed\
* into a JSONArray. Expects a JSONException.
*/
@Test
public void invalidCDATABangInTagException() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* In this case, the XML is invalid because an element
* does not have a complete CDATA string.
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
" xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
" <address>\n"+
" <name>Joe Tester</name>\n"+
" <![[]>\n"+
" </address>\n"+
"</addresses>";
try {
JSONML.toJSONArray(xmlStr);
fail("Expecting an exception");
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"Expected 'CDATA[' at 204 [character 11 line 5]",
e.getMessage());
}
}
/**
* Convert an XML document into a JSONArray, then use JSONML.toString()
* to convert it into a string. This string is then converted back into
* a JSONArray. Both JSONArrays are compared against a control to
* confirm the contents.
*/
@Test
public void toJSONArray() {
/**
* xmlStr contains XML text which is transformed into a JSONArray.
* Each element becomes a JSONArray:
* 1st entry = elementname
* 2nd entry = attributes object (if present)
* 3rd entry = content (if present)
* 4th entry = child element JSONArrays (if present)
* The result is compared against an expected JSONArray.
* The transformed JSONArray is then transformed back into a string
* which is used to create a final JSONArray, which is also compared
* against the expected JSONArray.
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
"xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
"<address attr1=\"attrValue1\" attr2=\"attrValue2\" attr3=\"attrValue3\">\n"+
"<name nameType=\"mine\">myName</name>\n"+
"<nocontent/>>\n"+
"</address>\n"+
"</addresses>";
String expectedStr =
"[\"addresses\","+
"{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
"[\"address\","+
"{\"attr1\":\"attrValue1\",\"attr2\":\"attrValue2\",\"attr3\":\"attrValue3\"},"+
"[\"name\", {\"nameType\":\"mine\"},\"myName\"],"+
"[\"nocontent\"],"+
"\">\""+
"]"+
"]";
JSONArray jsonArray = JSONML.toJSONArray(xmlStr);
JSONArray expectedJsonArray = new JSONArray(expectedStr);
String xmlToStr = JSONML.toString(jsonArray);
JSONArray finalJsonArray = JSONML.toJSONArray(xmlToStr);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
}
/**
* Convert an XML document into a JSONObject. Use JSONML.toString() to
* convert it back into a string, and then re-convert it into a JSONObject.
* Both JSONObjects are compared against a control JSONObject to confirm
* the contents.
* <p>
* Next convert the XML document into a JSONArray. Use JSONML.toString() to
* convert it back into a string, and then re-convert it into a JSONArray.
* Both JSONArrays are compared against a control JSONArray to confirm
* the contents.
* <p>
* This test gives a comprehensive example of how the JSONML
* transformations work.
*/
@Test
public void toJSONObjectToJSONArray() {
/**
* xmlStr contains XML text which is transformed into a JSONObject,
* restored to XML, transformed into a JSONArray, and then restored
* to XML again. Both JSONObject and JSONArray should contain the same
* information and should produce the same XML, allowing for non-ordered
* attributes.
*
* Transformation to JSONObject:
* The elementName is stored as a string where key="tagName"
* Attributes are simply stored as key/value pairs
* If the element has either content or child elements, they are stored
* in a jsonArray with key="childNodes".
*
* Transformation to JSONArray:
* 1st entry = elementname
* 2nd entry = attributes object (if present)
* 3rd entry = content (if present)
* 4th entry = child element JSONArrays (if present)
*/
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\""+
"xsi:noNamespaceSchemaLocation='test.xsd'>\n"+
"<address addrType=\"my address\">\n"+
"<name nameType=\"my name\">Joe Tester</name>\n"+
"<street><![CDATA[Baker street 5]]></street>\n"+
"<NothingHere except=\"an attribute\"/>\n"+
"<TrueValue>true</TrueValue>\n"+
"<FalseValue>false</FalseValue>\n"+
"<NullValue>null</NullValue>\n"+
"<PositiveValue>42</PositiveValue>\n"+
"<NegativeValue>-23</NegativeValue>\n"+
"<DoubleValue>-23.45</DoubleValue>\n"+
"<Nan>-23x.45</Nan>\n"+
"<ArrayOfNum>\n"+
"<value>1</value>\n"+
"<value>2</value>\n"+
"<value><subValue svAttr=\"svValue\">abc</subValue></value>\n"+
"<value>3</value>\n"+
"<value>4.1</value>\n"+
"<value>5.2</value>\n"+
"</ArrayOfNum>\n"+
"</address>\n"+
"</addresses>";
String expectedJSONObjectStr =
"{"+
"\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"childNodes\":["+
"{"+
"\"childNodes\":["+
"{"+
"\"childNodes\":[\"Joe Tester\"],"+
"\"nameType\":\"my name\","+
"\"tagName\":\"name\""+
"},"+
"{"+
"\"childNodes\":[\"Baker street 5\"],"+
"\"tagName\":\"street\""+
"},"+
"{"+
"\"tagName\":\"NothingHere\","+
"\"except\":\"an attribute\""+
"},"+
"{"+
"\"childNodes\":[true],"+
"\"tagName\":\"TrueValue\""+
"},"+
"{"+
"\"childNodes\":[false],"+
"\"tagName\":\"FalseValue\""+
"},"+
"{"+
"\"childNodes\":[null],"+
"\"tagName\":\"NullValue\""+
"},"+
"{"+
"\"childNodes\":[42],"+
"\"tagName\":\"PositiveValue\""+
"},"+
"{"+
"\"childNodes\":[-23],"+
"\"tagName\":\"NegativeValue\""+
"},"+
"{"+
"\"childNodes\":[-23.45],"+
"\"tagName\":\"DoubleValue\""+
"},"+
"{"+
"\"childNodes\":[\"-23x.45\"],"+
"\"tagName\":\"Nan\""+
"},"+
"{"+
"\"childNodes\":["+
"{"+
"\"childNodes\":[1],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":[2],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":["+
"{"+
"\"childNodes\":[\"abc\"],"+
"\"svAttr\":\"svValue\","+
"\"tagName\":\"subValue\""+
"}"+
"],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":[3],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":[4.1],"+
"\"tagName\":\"value\""+
"},"+
"{"+
"\"childNodes\":[5.2],"+
"\"tagName\":\"value\""+
"}"+
"],"+
"\"tagName\":\"ArrayOfNum\""+
"}"+
"],"+
"\"addrType\":\"my address\","+
"\"tagName\":\"address\""+
"}"+
"],"+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\","+
"\"tagName\":\"addresses\""+
"}";
String expectedJSONArrayStr =
"["+
"\"addresses\","+
"{"+
"\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\""+
"},"+
"["+
"\"address\","+
"{"+
"\"addrType\":\"my address\""+
"},"+
"["+
"\"name\","+
"{"+
"\"nameType\":\"my name\""+
"},"+
"\"Joe Tester\""+
"],"+
"[\"street\",\"Baker street 5\"],"+
"["+
"\"NothingHere\","+
"{\"except\":\"an attribute\"}"+
"],"+
"[\"TrueValue\",true],"+
"[\"FalseValue\",false],"+
"[\"NullValue\",null],"+
"[\"PositiveValue\",42],"+
"[\"NegativeValue\",-23],"+
"[\"DoubleValue\",-23.45],"+
"[\"Nan\",\"-23x.45\"],"+
"["+
"\"ArrayOfNum\","+
"[\"value\",1],"+
"[\"value\",2],"+
"[\"value\","+
"["+
"\"subValue\","+
"{\"svAttr\":\"svValue\"},"+
"\"abc\""+
"],"+
"],"+
"[\"value\",3],"+
"[\"value\",4.1],"+
"[\"value\",5.2]"+
"]"+
"]"+
"]";
// make a JSONObject and make sure it looks as expected
JSONObject jsonObject = JSONML.toJSONObject(xmlStr);
JSONObject expectedJsonObject = new JSONObject(expectedJSONObjectStr);
Util.compareActualVsExpectedJsonObjects(jsonObject,expectedJsonObject);
// restore the XML, then make another JSONObject and make sure it
// looks as expected
String jsonObjectXmlToStr = JSONML.toString(jsonObject);
JSONObject finalJsonObject = JSONML.toJSONObject(jsonObjectXmlToStr);
Util.compareActualVsExpectedJsonObjects(finalJsonObject, expectedJsonObject);
// create a JSON array from the original string and make sure it
// looks as expected
JSONArray jsonArray = JSONML.toJSONArray(xmlStr);
JSONArray expectedJsonArray = new JSONArray(expectedJSONArrayStr);
Util.compareActualVsExpectedJsonArrays(jsonArray,expectedJsonArray);
// restore the XML, then make another JSONArray and make sure it
// looks as expected
String jsonArrayXmlToStr = JSONML.toString(jsonArray);
JSONArray finalJsonArray = JSONML.toJSONArray(jsonArrayXmlToStr);
Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
// lastly, confirm the restored JSONObject XML and JSONArray XML look
// reasonably similar
JSONObject jsonObjectFromObject = JSONML.toJSONObject(jsonObjectXmlToStr);
JSONObject jsonObjectFromArray = JSONML.toJSONObject(jsonArrayXmlToStr);
Util.compareActualVsExpectedJsonObjects(jsonObjectFromObject, jsonObjectFromArray);
}
/**
* Convert an XML document which contains embedded comments into
* a JSONArray. Use JSONML.toString() to turn it into a string, then
* reconvert it into a JSONArray. Compare both JSONArrays to a control
* JSONArray to confirm the contents.
* <p>
* This test shows how XML comments are handled.
*/
@Test
public void commentsInXML() {
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<!-- this is a comment -->\n"+
"<addresses>\n"+
"<address>\n"+
"<!-- <!--[CDATA[ this is -- <another> comment ]] -->\n"+
"<name>Joe Tester</name>\n"+
"<!-- this is a - multi line \n"+
"comment -->\n"+
"<street>Baker street 5</street>\n"+
"</address>\n"+
"</addresses>";
String expectedStr =
"[\"addresses\","+
"[\"address\","+
"[\"name\",\"Joe Tester\"],"+
"[\"street\",\"Baker street 5\"]"+
"]"+
"]";
JSONArray jsonArray = JSONML.toJSONArray(xmlStr);
JSONArray expectedJsonArray = new JSONArray(expectedStr);
String xmlToStr = JSONML.toString(jsonArray);
JSONArray finalJsonArray = JSONML.toJSONArray(xmlToStr);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
}
/**
* JSON string with lost leading zero and converted "True" to true. See test
* result in comment below.
*/
@Test
public void testToJSONArray_jsonOutput() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
final String expectedJsonString = "[\"root\",[\"id\",\"01\"],[\"id\",1],[\"id\",\"00\"],[\"id\",0],[\"item\",{\"id\":\"01\"}],[\"title\",true]]";
final JSONArray actualJsonOutput = JSONML.toJSONArray(originalXml, false);
assertEquals(expectedJsonString, actualJsonOutput.toString());
}
/**
* JSON string cannot be reverted to original xml when type guessing is used.
*/
@Test
public void testToJSONArray_reversibility() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
final String revertedXml = JSONML.toString(JSONML.toJSONArray(originalXml, false));
assertNotEquals(revertedXml, originalXml);
}
/**
* JSON string cannot be reverted to original xml when type guessing is used.
* When we force all the values as string, the original text comes back.
*/
@Test
public void testToJSONArray_reversibility2() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
final String expectedJsonString = "[\"root\",[\"id\",\"01\"],[\"id\",\"1\"],[\"id\",\"00\"],[\"id\",\"0\"],[\"item\",{\"id\":\"01\"}],[\"title\",\"True\"]]";
final JSONArray json = JSONML.toJSONArray(originalXml,true);
assertEquals(expectedJsonString, json.toString());
final String reverseXml = JSONML.toString(json);
assertEquals(originalXml, reverseXml);
}
/**
* JSON can be reverted to original xml.
*/
@Test
public void testToJSONArray_reversibility3() {
final String originalXml = "<readResult><errors someAttr=\"arrtValue\"><code>400</code></errors><errors><code>402</code></errors></readResult>";
final JSONArray jsonArray = JSONML.toJSONArray(originalXml, false);
final String revertedXml = JSONML.toString(jsonArray);
assertEquals(revertedXml, originalXml);
}
/**
* JSON string cannot be reverted to original xml. See test result in
* comment below.
*/
@Test
public void testToJSONObject_reversibility() {
final String originalXml = "<readResult><errors someAttr=\"arrtValue\"><code>400</code></errors><errors><code>402</code></errors></readResult>";
final JSONObject originalObject=JSONML.toJSONObject(originalXml,false);
final String originalJson = originalObject.toString();
final String xml = JSONML.toString(originalObject);
final JSONObject revertedObject = JSONML.toJSONObject(xml, false);
final String newJson = revertedObject.toString();
assertTrue("JSON Objects are not similar",originalObject.similar(revertedObject));
assertEquals("original JSON does not equal the new JSON",originalJson, newJson);
}
// these tests do not pass for the following reasons:
// 1. Our XML parser does not handle generic HTML entities, only valid XML entities. Hence &nbsp;
// or other HTML specific entities would fail on reversability
// 2. Our JSON implementation for storing the XML attributes uses the standard unordered map.
// This means that <tag attr1="v1" attr2="v2" /> can not be reversed reliably.
//
// /**
// * Test texts taken from jsonml.org. Currently our implementation FAILS this conversion but shouldn't.
// * Technically JsonML should be able to transform any valid xhtml document, but ours only supports
// * standard XML entities, not HTML entities.
// */
// @Test
// public void testAttributeConversionReversabilityHTML() {
// final String originalXml = "<table class=\"MyTable\" style=\"background-color:yellow\"><tr><td class=\"MyTD\" style=\"border:1px solid black\">#5D28D1</td><td class=\"MyTD\" style=\"background-color:red\">Example text here</td></tr><tr><td class=\"MyTD\" style=\"border:1px solid black\">#AF44EF</td><td class=\"MyTD\" style=\"background-color:green\">127310656</td></tr><tr><td class=\"MyTD\" style=\"border:1px solid black\">#AAD034</td><td class=\"MyTD\" style=\"background-color:blue\">&nbsp;<span style=\"background-color:maroon\">&copy;</span>&nbsp;</td></tr></table>";
// final String expectedJsonString = "[\"table\",{\"class\" : \"MyTable\",\"style\" : \"background-color:yellow\"},[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#550758\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:red\"},\"Example text here\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#993101\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:green\"},\"127624015\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#E33D87\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:blue\"},\"\u00A0\",[\"span\",{ \"style\" : \"background-color:maroon\" },\"\u00A9\"],\"\u00A0\"]]]";
// final JSONArray json = JSONML.toJSONArray(originalXml,true);
// final String actualJsonString = json.toString();
//
// final String reverseXml = JSONML.toString(json);
// assertNotEquals(originalXml, reverseXml);
//
// assertNotEquals(expectedJsonString, actualJsonString);
// }
//
// /**
// * Test texts taken from jsonml.org but modified to have XML entities only.
// */
// @Test
// public void testAttributeConversionReversabilityXML() {
// final String originalXml = "<table class=\"MyTable\" style=\"background-color:yellow\"><tr><td class=\"MyTD\" style=\"border:1px solid black\">#5D28D1</td><td class=\"MyTD\" style=\"background-color:red\">Example text here</td></tr><tr><td class=\"MyTD\" style=\"border:1px solid black\">#AF44EF</td><td class=\"MyTD\" style=\"background-color:green\">127310656</td></tr><tr><td class=\"MyTD\" style=\"border:1px solid black\">#AAD034</td><td class=\"MyTD\" style=\"background-color:blue\">&amp;<span style=\"background-color:maroon\">&gt;</span>&lt;</td></tr></table>";
// final String expectedJsonString = "[\"table\",{\"class\" : \"MyTable\",\"style\" : \"background-color:yellow\"},[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#550758\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:red\"},\"Example text here\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#993101\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:green\"},\"127624015\"]],[\"tr\",[\"td\",{\"class\" : \"MyTD\",\"style\" : \"border:1px solid black\"},\"#E33D87\"],[\"td\",{\"class\" : \"MyTD\",\"style\" : \"background-color:blue\"},\"&\",[\"span\",{ \"style\" : \"background-color:maroon\" },\">\"],\"<\"]]]";
// final JSONArray jsonML = JSONML.toJSONArray(originalXml,true);
// final String actualJsonString = jsonML.toString();
//
// final String reverseXml = JSONML.toString(jsonML);
// // currently not equal because the hashing of the attribute objects makes the attribute
// // order not happen the same way twice
// assertEquals(originalXml, reverseXml);
//
// assertEquals(expectedJsonString, actualJsonString);
// }
@Test (timeout = 6000)
public void testIssue484InfinteLoop1() {
try {
JSONML.toJSONObject("??*^M??|?CglR^F??`??>?w??PIlr^E??D^X^]?$?-^R?o??O?*??{OD?^FY??`2a????NM?b^Tq?:O?>S$^K?J?^FB.gUK?m^H??zE??^??!v]?^A???^[^A??^U?c??????h???s???g^Z???`?q^Dbi??:^QZl?)?}1^??k?0??:$V?$?Ovs(}J??^V????2;^QgQ?^_^A?^D?^U?Tg?K?`?h%c?hmGA?<!C*^P^Y?^X9?~?t?)??,z^XA???S}?Q??.q?j????]");
fail("Exception expected for invalid JSON.");
} catch (JSONException ex) {
assertEquals("Exception string did not match: ",
"Unterminated string at 271 [character 272 line 1]",
ex.getMessage());
}
}
@Test (timeout = 6000)
public void testIssue484InfinteLoop2() {
try {
String input = "??*\n" +
"??|?CglR??`??>?w??PIlr??D?$?-?o??O?*??{OD?Y??`2a????NM?bq?:O?>S$ ?J?B.gUK?m\b??zE???!v]???????c??????h???s???g???`?qbi??:Zl?)?}1^??k?0??:$V?$?Ovs(}J??????2;gQ????Tg?K?`?h%c?hmGA?<!C*?9?~?t?)??,zA???S}?Q??.q?j????]";
JSONML.toJSONObject(input);
fail("Exception expected for invalid JSON.");
} catch (JSONException ex) {
assertEquals("Exception string did not match: ",
"Unterminated string at 242 [character 238 line 2]",
ex.getMessage());
}
}
}

View File

@@ -0,0 +1,60 @@
package org.json.junit;
/*
Public Domain.
*/
import static org.junit.Assert.*;
import java.util.*;
import org.json.*;
import org.json.junit.data.MyLocaleBean;
import org.junit.*;
/**
* Note: This file is saved as UTF-8. Do not save as ASCII or the tests will
* fail.
*
*/
public class JSONObjectLocaleTest {
/**
* JSONObject built from a bean with locale-specific keys.
* In the Turkish alphabet, there are 2 versions of the letter "i".
* 'eh' I ı (dotless i)
* 'ee' İ i (dotted i)
* A problem can occur when parsing the public get methods for a bean.
* If the method starts with getI... then the key name will be lowercased
* to 'i' in English, and 'ı' in Turkish.
* We want the keys to be consistent regardless of locale, so JSON-Java
* lowercase operations are made to be locale-neutral by specifying
* Locale.ROOT. This causes 'I' to be universally lowercased to 'i'
* regardless of the locale currently in effect.
*/
@Test
public void jsonObjectByLocaleBean() {
MyLocaleBean myLocaleBean = new MyLocaleBean();
/**
* This is just the control case which happens when the locale.ROOT
* lowercasing behavior is the same as the current locale.
*/
Locale.setDefault(new Locale("en"));
JSONObject jsonen = new JSONObject(myLocaleBean);
assertEquals("expected size 2, found: " +jsonen.length(), 2, jsonen.length());
assertEquals("expected jsonen[i] == beanI", "beanI", jsonen.getString("i"));
assertEquals("expected jsonen[id] == beanId", "beanId", jsonen.getString("id"));
/**
* Without the JSON-Java change, these keys would be stored internally as
* starting with the letter, 'ı' (dotless i), since the lowercasing of
* the getI and getId keys would be specific to the Turkish locale.
*/
Locale.setDefault(new Locale("tr"));
JSONObject jsontr = new JSONObject(myLocaleBean);
assertEquals("expected size 2, found: " +jsontr.length(), 2, jsontr.length());
assertEquals("expected jsontr[i] == beanI", "beanI", jsontr.getString("i"));
assertEquals("expected jsontr[id] == beanId", "beanId", jsontr.getString("id"));
}
}

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,397 @@
package org.json.junit;
/*
Public Domain.
*/
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.InputStream;
import org.json.JSONArray;
import org.json.JSONObject;
import org.json.JSONPointer;
import org.json.JSONPointerException;
import org.json.JSONTokener;
import org.junit.Test;
public class JSONPointerTest {
private static final JSONObject document;
private static final String EXPECTED_COMPLETE_DOCUMENT = "{\"\":0,\" \":7,\"g|h\":4,\"c%d\":2,\"k\\\"l\":6,\"a/b\":1,\"i\\\\j\":5," +
"\"obj\":{\"\":{\"\":\"empty key of an object with an empty key\",\"subKey\":\"Some other value\"}," +
"\"other~key\":{\"another/key\":[\"val\"]},\"key\":\"value\"},\"foo\":[\"bar\",\"baz\"],\"e^f\":3," +
"\"m~n\":8}";
static {
@SuppressWarnings("resource")
InputStream resourceAsStream = JSONPointerTest.class.getClassLoader().getResourceAsStream("jsonpointer-testdoc.json");
if(resourceAsStream == null) {
throw new ExceptionInInitializerError("Unable to locate test file. Please check your development environment configuration");
}
document = new JSONObject(new JSONTokener(resourceAsStream));
}
private Object query(String pointer) {
return new JSONPointer(pointer).queryFrom(document);
}
@Test
public void emptyPointer() {
assertTrue(new JSONObject(EXPECTED_COMPLETE_DOCUMENT).similar(query("")));
}
@SuppressWarnings("unused")
@Test(expected = NullPointerException.class)
public void nullPointer() {
new JSONPointer((String) null);
}
@Test
public void objectPropertyQuery() {
assertEquals("[\"bar\",\"baz\"]", query("/foo").toString());
}
@Test
public void arrayIndexQuery() {
assertEquals("bar", query("/foo/0"));
}
@Test(expected = JSONPointerException.class)
public void stringPropOfArrayFailure() {
query("/foo/bar");
}
@Test
public void queryByEmptyKey() {
assertEquals(0, query("/"));
}
@Test
public void queryByEmptyKeySubObject() {
assertEquals( "{\"\":\"empty key of an object with an empty key\",\"subKey\":\"Some" +
" other value\"}", query("/obj/").toString());
}
@Test
public void queryByEmptyKeySubObjectSubOject() {
assertEquals("empty key of an object with an empty key", query("/obj//"));
}
@Test
public void queryByEmptyKeySubObjectValue() {
assertEquals("Some other value", query("/obj//subKey"));
}
@Test
public void slashEscaping() {
assertEquals(1, query("/a~1b"));
}
@Test
public void tildeEscaping() {
assertEquals(8, query("/m~0n"));
}
/**
* We pass backslashes as-is
*
* @see <a href="https://tools.ietf.org/html/rfc6901#section-3">rfc6901 section 3</a>
*/
@Test
public void backslashHandling() {
assertEquals(5, query("/i\\j"));
}
/**
* We pass quotations as-is
*
* @see <a href="https://tools.ietf.org/html/rfc6901#section-3">rfc6901 section 3</a>
*/
@Test
public void quotationHandling() {
assertEquals(6, query("/k\"l"));
}
@Test
public void whitespaceKey() {
assertEquals(7, query("/ "));
}
@Test
public void uriFragmentNotation() {
assertEquals("[\"bar\",\"baz\"]", query("#/foo").toString());
}
@Test
public void uriFragmentNotationRoot() {
assertTrue(new JSONObject(EXPECTED_COMPLETE_DOCUMENT).similar(query("#")));
}
@Test
public void uriFragmentPercentHandling() {
assertEquals(2, query("#/c%25d"));
assertEquals(3, query("#/e%5Ef"));
assertEquals(4, query("#/g%7Ch"));
assertEquals(8, query("#/m~0n"));
}
@SuppressWarnings("unused")
@Test(expected = IllegalArgumentException.class)
public void syntaxError() {
new JSONPointer("key");
}
@Test(expected = JSONPointerException.class)
public void arrayIndexFailure() {
query("/foo/2");
}
@Test(expected = JSONPointerException.class)
public void primitiveFailure() {
query("/obj/key/failure");
}
@Test
public void builderTest() {
JSONPointer pointer = JSONPointer.builder()
.append("obj")
.append("other~key").append("another/key")
.append(0)
.build();
assertEquals("val", pointer.queryFrom(document));
}
@Test(expected = NullPointerException.class)
public void nullToken() {
JSONPointer.builder().append(null);
}
@Test
public void toStringEscaping() {
JSONPointer pointer = JSONPointer.builder()
.append("obj")
.append("other~key").append("another/key")
.append("\"")
.append(0)
.build();
assertEquals("/obj/other~0key/another~1key/\"/0", pointer.toString());
}
@Test
public void emptyPointerToString() {
assertEquals("", new JSONPointer("").toString());
}
@Test
public void toURIFragment() {
assertEquals("#/c%25d", new JSONPointer("/c%d").toURIFragment());
assertEquals("#/e%5Ef", new JSONPointer("/e^f").toURIFragment());
assertEquals("#/g%7Ch", new JSONPointer("/g|h").toURIFragment());
assertEquals("#/m%7En", new JSONPointer("/m~n").toURIFragment());
}
@Test
public void tokenListIsCopiedInConstructor() {
JSONPointer.Builder b = JSONPointer.builder().append("key1");
JSONPointer jp1 = b.build();
b.append("key2");
JSONPointer jp2 = b.build();
if(jp1.toString().equals(jp2.toString())) {
fail("Oops, my pointers are sharing a backing array");
}
}
/**
* Coverage for JSONObject query(String)
*/
@Test
public void queryFromJSONObject() {
String str = "{"+
"\"stringKey\":\"hello world!\","+
"\"arrayKey\":[0,1,2],"+
"\"objectKey\": {"+
"\"a\":\"aVal\","+
"\"b\":\"bVal\""+
"}"+
"}";
JSONObject jsonObject = new JSONObject(str);
Object obj = jsonObject.query("/stringKey");
assertTrue("Expected 'hello world!'", "hello world!".equals(obj));
obj = jsonObject.query("/arrayKey/1");
assertTrue("Expected 1", Integer.valueOf(1).equals(obj));
obj = jsonObject.query("/objectKey/b");
assertTrue("Expected bVal", "bVal".equals(obj));
try {
obj = jsonObject.query("/a/b/c");
assertTrue("Expected JSONPointerException", false);
} catch (JSONPointerException e) {
assertTrue("Expected bad key/value exception",
"value [null] is not an array or object therefore its key b cannot be resolved".
equals(e.getMessage()));
}
}
/**
* Coverage for JSONObject query(JSONPointer)
*/
@Test
public void queryFromJSONObjectUsingPointer() {
String str = "{"+
"\"stringKey\":\"hello world!\","+
"\"arrayKey\":[0,1,2],"+
"\"objectKey\": {"+
"\"a\":\"aVal\","+
"\"b\":\"bVal\""+
"}"+
"}";
JSONObject jsonObject = new JSONObject(str);
Object obj = jsonObject.query(new JSONPointer("/stringKey"));
assertTrue("Expected 'hello world!'", "hello world!".equals(obj));
obj = jsonObject.query(new JSONPointer("/arrayKey/1"));
assertTrue("Expected 1", Integer.valueOf(1).equals(obj));
obj = jsonObject.query(new JSONPointer("/objectKey/b"));
assertTrue("Expected bVal", "bVal".equals(obj));
try {
obj = jsonObject.query(new JSONPointer("/a/b/c"));
assertTrue("Expected JSONPointerException", false);
} catch (JSONPointerException e) {
assertTrue("Expected bad key/value exception",
"value [null] is not an array or object therefore its key b cannot be resolved".
equals(e.getMessage()));
}
}
/**
* Coverage for JSONObject optQuery(JSONPointer)
*/
@Test
public void optQueryFromJSONObjectUsingPointer() {
String str = "{"+
"\"stringKey\":\"hello world!\","+
"\"arrayKey\":[0,1,2],"+
"\"objectKey\": {"+
"\"a\":\"aVal\","+
"\"b\":\"bVal\""+
"}"+
"}";
JSONObject jsonObject = new JSONObject(str);
Object obj = jsonObject.optQuery(new JSONPointer("/stringKey"));
assertTrue("Expected 'hello world!'", "hello world!".equals(obj));
obj = jsonObject.optQuery(new JSONPointer("/arrayKey/1"));
assertTrue("Expected 1", Integer.valueOf(1).equals(obj));
obj = jsonObject.optQuery(new JSONPointer("/objectKey/b"));
assertTrue("Expected bVal", "bVal".equals(obj));
obj = jsonObject.optQuery(new JSONPointer("/a/b/c"));
assertTrue("Expected null", obj == null);
}
/**
* Coverage for JSONArray query(String)
*/
@Test
public void queryFromJSONArray() {
String str = "["+
"\"hello world!\","+
"[0,1,2],"+
"{"+
"\"a\":\"aVal\","+
"\"b\":\"bVal\""+
"}"+
"]";
JSONArray jsonArray = new JSONArray(str);
Object obj = jsonArray.query("/0");
assertTrue("Expected 'hello world!'", "hello world!".equals(obj));
obj = jsonArray.query("/1/1");
assertTrue("Expected 1", Integer.valueOf(1).equals(obj));
obj = jsonArray.query("/2/b");
assertTrue("Expected bVal", "bVal".equals(obj));
try {
obj = jsonArray.query("/a/b/c");
assertTrue("Expected JSONPointerException", false);
} catch (JSONPointerException e) {
assertTrue("Expected bad index exception",
"a is not an array index".equals(e.getMessage()));
}
}
/**
* Coverage for JSONArray query(JSONPointer)
*/
@Test
public void queryFromJSONArrayUsingPointer() {
String str = "["+
"\"hello world!\","+
"[0,1,2],"+
"{"+
"\"a\":\"aVal\","+
"\"b\":\"bVal\""+
"}"+
"]";
JSONArray jsonArray = new JSONArray(str);
Object obj = jsonArray.query(new JSONPointer("/0"));
assertTrue("Expected 'hello world!'", "hello world!".equals(obj));
obj = jsonArray.query(new JSONPointer("/1/1"));
assertTrue("Expected 1", Integer.valueOf(1).equals(obj));
obj = jsonArray.query(new JSONPointer("/2/b"));
assertTrue("Expected bVal", "bVal".equals(obj));
try {
obj = jsonArray.query(new JSONPointer("/a/b/c"));
assertTrue("Expected JSONPointerException", false);
} catch (JSONPointerException e) {
assertTrue("Expected bad index exception",
"a is not an array index".equals(e.getMessage()));
}
}
/**
* Coverage for JSONArray optQuery(JSONPointer)
*/
@Test
public void optQueryFromJSONArrayUsingPointer() {
String str = "["+
"\"hello world!\","+
"[0,1,2],"+
"{"+
"\"a\":\"aVal\","+
"\"b\":\"bVal\""+
"}"+
"]";
JSONArray jsonArray = new JSONArray(str);
Object obj = jsonArray.optQuery(new JSONPointer("/0"));
assertTrue("Expected 'hello world!'", "hello world!".equals(obj));
obj = jsonArray.optQuery(new JSONPointer("/1/1"));
assertTrue("Expected 1", Integer.valueOf(1).equals(obj));
obj = jsonArray.optQuery(new JSONPointer("/2/b"));
assertTrue("Expected bVal", "bVal".equals(obj));
obj = jsonArray.optQuery(new JSONPointer("/a/b/c"));
assertTrue("Expected null", obj == null);
}
/**
* When creating a jsonObject we need to parse escaped characters "\\\\"
* --> it's the string representation of "\\", so when query'ing via the JSONPointer
* we DON'T escape them
*
*/
@Test
public void queryFromJSONObjectUsingPointer0() {
String str = "{"+
"\"string\\\\\\\\Key\":\"hello world!\","+
"\"\\\\\":\"slash test\"," +
"}"+
"}";
JSONObject jsonObject = new JSONObject(str);
//Summary of issue: When a KEY in the jsonObject is "\\\\" --> it's held
// as "\\" which means when querying, we need to use "\\"
Object twoBackslahObj = jsonObject.optQuery(new JSONPointer("/\\"));
assertEquals("slash test", twoBackslahObj);
Object fourBackslashObj = jsonObject.optQuery(new JSONPointer("/string\\\\Key"));
assertEquals("hello world!", fourBackslashObj);
}
}

View File

@@ -0,0 +1,385 @@
package org.json.junit;
/*
Public Domain.
*/
import static org.junit.Assert.*;
import java.io.StringWriter;
import java.util.*;
import org.json.*;
import org.junit.Test;
/**
* Tests for JSONString implementations, and the difference between
* {@link JSONObject#valueToString} and {@link JSONObject#writeValue}.
*/
public class JSONStringTest {
/**
* This tests the JSONObject.writeValue() method. We can't test directly
* due to it being a package-protected method. Instead, we can call
* JSONArray.write(), which delegates the writing of each entry to
* writeValue().
*/
@Test
public void writeValues() throws Exception {
JSONArray jsonArray = new JSONArray();
jsonArray.put((Object)null);
StringWriter writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[null]".equals(output));
jsonArray = new JSONArray();
jsonArray.put(JSONObject.NULL);
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[null]".equals(output));
jsonArray = new JSONArray();
jsonArray.put(new JSONObject());
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[{}]".equals(output));
jsonArray = new JSONArray();
jsonArray.put(new JSONArray());
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[[]]".equals(output));
jsonArray = new JSONArray();
Map<?,?> singleMap = Collections.singletonMap("key1", "value1");
jsonArray.put((Object)singleMap);
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[{\"key1\":\"value1\"}]".equals(output));
jsonArray = new JSONArray();
List<?> singleList = Collections.singletonList("entry1");
jsonArray.put((Object)singleList);
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[[\"entry1\"]]".equals(output));
jsonArray = new JSONArray();
int[] intArray = new int[] { 1, 2, 3 };
jsonArray.put(intArray);
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[[1,2,3]]".equals(output));
jsonArray = new JSONArray();
jsonArray.put(24);
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[24]".equals(output));
jsonArray = new JSONArray();
jsonArray.put("string value");
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[\"string value\"]".equals(output));
jsonArray = new JSONArray();
jsonArray.put(true);
} finally {
writer.close();
}
writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[true]".equals(output));
} finally {
writer.close();
}
}
/**
* This tests the JSONObject.valueToString() method. These should be
* identical to the values above, except for the enclosing [ and ].
*/
@SuppressWarnings("boxing")
@Test
public void valuesToString() throws Exception {
String output = JSONObject.valueToString(null);
assertTrue("String values should be equal", "null".equals(output));
output = JSONObject.valueToString(JSONObject.NULL);
assertTrue("String values should be equal", "null".equals(output));
output = JSONObject.valueToString(new JSONObject());
assertTrue("String values should be equal", "{}".equals(output));
output = JSONObject.valueToString(new JSONArray());
assertTrue("String values should be equal", "[]".equals(output));
Map<?,?> singleMap = Collections.singletonMap("key1", "value1");
output = JSONObject.valueToString(singleMap);
assertTrue("String values should be equal", "{\"key1\":\"value1\"}".equals(output));
List<?> singleList = Collections.singletonList("entry1");
output = JSONObject.valueToString(singleList);
assertTrue("String values should be equal", "[\"entry1\"]".equals(output));
int[] intArray = new int[] { 1, 2, 3 };
output = JSONObject.valueToString(intArray);
assertTrue("String values should be equal", "[1,2,3]".equals(output));
output = JSONObject.valueToString(24);
assertTrue("String values should be equal", "24".equals(output));
output = JSONObject.valueToString("string value");
assertTrue("String values should be equal", "\"string value\"".equals(output));
output = JSONObject.valueToString(true);
assertTrue("String values should be equal", "true".equals(output));
}
/**
* Test what happens when toJSONString() returns a well-formed JSON value.
* This is the usual case.
*/
@Test
public void testJSONStringValue() throws Exception {
JSONStringValue jsonString = new JSONStringValue();
JSONArray jsonArray = new JSONArray();
jsonArray.put(jsonString);
StringWriter writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[\"the JSON string value\"]".equals(output));
output = JSONObject.valueToString(jsonString);
assertTrue("String values should be equal", "\"the JSON string value\"".equals(output));
} finally {
writer.close();
}
}
/**
* Test what happens when toJSONString() returns null. In one case,
* use the object's toString() method. In the other, throw a JSONException.
*/
@Test
public void testJSONNullStringValue() throws Exception {
JSONNullStringValue jsonString = new JSONNullStringValue();
JSONArray jsonArray = new JSONArray();
jsonArray.put(jsonString);
StringWriter writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[\"the toString value\"]".equals(output));
// The only different between writeValue() and valueToString():
// in this case, valueToString throws a JSONException
try {
output = JSONObject.valueToString(jsonString);
fail("Expected an exception, got a String value");
} catch (Exception e) {
assertTrue("Expected JSONException", e instanceof JSONException);
assertTrue("Exception message does not match", "Bad value from toJSONString: null".equals(e.getMessage()));
}
} finally {
writer.close();
}
}
/**
* Test what happens when toJSONString() returns an exception. In both
* cases, a JSONException is thrown, with the cause and message set from
* the original exception.
*/
@Test
public void testJSONStringExceptionValue() {
JSONStringExceptionValue jsonString = new JSONStringExceptionValue();
JSONArray jsonArray = new JSONArray();
jsonArray.put(jsonString);
StringWriter writer = new StringWriter();
try {
jsonArray.write(writer).toString();
fail("Expected an exception, got a String value");
} catch (JSONException e) {
assertEquals("Unable to write JSONArray value at index: 0", e.getMessage());
} catch(Exception e) {
fail("Expected JSONException");
} finally {
try {
writer.close();
} catch (Exception e){}
}
try {
JSONObject.valueToString(jsonString);
fail("Expected an exception, got a String value");
} catch (JSONException e) {
assertTrue("Exception message does not match", "the exception value".equals(e.getMessage()));
} catch(Exception e) {
fail("Expected JSONException");
}
}
/**
* Test what happens when a Java object's toString() returns a String value.
* This is the usual case.
*/
@Test
public void testStringValue() throws Exception {
StringValue nonJsonString = new StringValue();
JSONArray jsonArray = new JSONArray();
jsonArray.put(nonJsonString);
StringWriter writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[\"the toString value for StringValue\"]".equals(output));
output = JSONObject.valueToString(nonJsonString);
assertTrue("String values should be equal", "\"the toString value for StringValue\"".equals(output));
} finally {
writer.close();
}
}
/**
* Test what happens when a Java object's toString() returns null.
* Defaults to empty string.
*/
@Test
public void testNullStringValue() throws Exception {
NullStringValue nonJsonString = new NullStringValue();
JSONArray jsonArray = new JSONArray();
jsonArray.put(nonJsonString);
StringWriter writer = new StringWriter();
try {
String output = jsonArray.write(writer).toString();
assertTrue("String values should be equal", "[\"\"]".equals(output));
output = JSONObject.valueToString(nonJsonString);
assertTrue("String values should be equal", "\"\"".equals(output));
} finally {
writer.close();
}
}
/**
* A JSONString that returns a valid JSON string value.
*/
private static final class JSONStringValue implements JSONString {
@Override
public String toJSONString() {
return "\"the JSON string value\"";
}
@Override
public String toString() {
return "the toString value for JSONStringValue";
}
}
/**
* A JSONString that returns null when calling toJSONString().
*/
private static final class JSONNullStringValue implements JSONString {
@Override
public String toJSONString() {
return null;
}
@Override
public String toString() {
return "the toString value";
}
}
/**
* A JSONString that throw an exception when calling toJSONString().
*/
private static final class JSONStringExceptionValue implements JSONString {
@Override
public String toJSONString() {
throw new IllegalStateException("the exception value");
}
@Override
public String toString() {
return "the toString value for JSONStringExceptionValue";
}
}
public static final class StringValue {
@Override
public String toString() {
return "the toString value for StringValue";
}
}
public static final class NullStringValue {
@Override
public String toString() {
return null;
}
}
}

View File

@@ -0,0 +1,357 @@
package org.json.junit;
/*
Public Domain.
*/
import static org.junit.Assert.*;
import java.math.BigDecimal;
import java.util.*;
import org.json.*;
import org.junit.Test;
import com.jayway.jsonpath.*;
/**
* Tests for JSON-Java JSONStringer and JSONWriter.
*/
public class JSONStringerTest {
/**
* Object with a null key.
* Expects a JSONException.
*/
@Test
public void nullKeyException() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.object();
try {
jsonStringer.key(null);
assertTrue("Expected an exception", false);
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Null key.".
equals(e.getMessage()));
}
}
/**
* Add a key with no object.
* Expects a JSONException.
*/
@Test
public void outOfSequenceException() {
JSONStringer jsonStringer = new JSONStringer();
try {
jsonStringer.key("hi");
assertTrue("Expected an exception", false);
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Misplaced key.".
equals(e.getMessage()));
}
}
/**
* Missplace an array.
* Expects a JSONException
*/
@Test
public void missplacedArrayException() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.object().endObject();
try {
jsonStringer.array();
assertTrue("Expected an exception", false);
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Misplaced array.".
equals(e.getMessage()));
}
}
/**
* Missplace an endErray.
* Expects a JSONException
*/
@Test
public void missplacedEndArrayException() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.object();
try {
jsonStringer.endArray();
assertTrue("Expected an exception", false);
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Misplaced endArray.".
equals(e.getMessage()));
}
}
/**
* Missplace an endObject.
* Expects a JSONException
*/
@Test
public void missplacedEndObjectException() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.array();
try {
jsonStringer.endObject();
assertTrue("Expected an exception", false);
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Misplaced endObject.".
equals(e.getMessage()));
}
}
/**
* Missplace an object.
* Expects a JSONException.
*/
@Test
public void missplacedObjectException() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.object().endObject();
try {
jsonStringer.object();
assertTrue("Expected an exception", false);
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Misplaced object.".
equals(e.getMessage()));
}
}
/**
* Exceeds implementation max nesting depth.
* Expects a JSONException
*/
@Test
public void exceedNestDepthException() {
try {
JSONStringer s = new JSONStringer();
s.object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object();
s.key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object().
key("k").object().key("k").object().key("k").object().key("k").object().key("k").object();
fail("Expected an exception message");
} catch (JSONException e) {
assertTrue("Expected an exception message",
"Nesting too deep.".
equals(e.getMessage()));
}
}
/**
* Build a JSON doc using JSONString API calls,
* then convert to JSONObject
*/
@Test
public void simpleObjectString() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.object();
jsonStringer.key("trueValue").value(true);
jsonStringer.key("falseValue").value(false);
jsonStringer.key("nullValue").value(null);
jsonStringer.key("stringValue").value("hello world!");
jsonStringer.key("complexStringValue").value("h\be\tllo w\u1234orld!");
jsonStringer.key("intValue").value(42);
jsonStringer.key("doubleValue").value(-23.45e67);
jsonStringer.endObject();
String str = jsonStringer.toString();
JSONObject jsonObject = new JSONObject(str);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 7 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 7);
assertTrue("expected true", Boolean.TRUE.equals(jsonObject.query("/trueValue")));
assertTrue("expected false", Boolean.FALSE.equals(jsonObject.query("/falseValue")));
assertTrue("expected null", JSONObject.NULL.equals(jsonObject.query("/nullValue")));
assertTrue("expected hello world!", "hello world!".equals(jsonObject.query("/stringValue")));
assertTrue("expected h\be\tllo w\u1234orld!", "h\be\tllo w\u1234orld!".equals(jsonObject.query("/complexStringValue")));
assertTrue("expected 42", Integer.valueOf(42).equals(jsonObject.query("/intValue")));
assertTrue("expected -23.45e67", BigDecimal.valueOf(-23.45e67).equals(jsonObject.query("/doubleValue")));
}
/**
* Build a JSON doc using JSONString API calls,
* then convert to JSONArray
*/
@Test
public void simpleArrayString() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.array();
jsonStringer.value(true);
jsonStringer.value(false);
jsonStringer.value(null);
jsonStringer.value("hello world!");
jsonStringer.value(42);
jsonStringer.value(-23.45e67);
jsonStringer.endArray();
String str = jsonStringer.toString();
JSONArray jsonArray = new JSONArray(str);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonArray.toString());
assertTrue("expected 6 top level items", ((List<?>)(JsonPath.read(doc, "$"))).size() == 6);
assertTrue("expected true", Boolean.TRUE.equals(jsonArray.query("/0")));
assertTrue("expected false", Boolean.FALSE.equals(jsonArray.query("/1")));
assertTrue("expected null", JSONObject.NULL.equals(jsonArray.query("/2")));
assertTrue("expected hello world!", "hello world!".equals(jsonArray.query("/3")));
assertTrue("expected 42", Integer.valueOf(42).equals(jsonArray.query("/4")));
assertTrue("expected -23.45e67", BigDecimal.valueOf(-23.45e67).equals(jsonArray.query("/5")));
}
/**
* Build a nested JSON doc using JSONString API calls, then convert to
* JSONObject. Will create a long cascade of output by reusing the
* returned values..
*/
@Test
public void complexObjectString() {
JSONStringer jsonStringer = new JSONStringer();
jsonStringer.object().
key("trueValue").value(true).
key("falseValue").value(false).
key("nullValue").value(null).
key("stringValue").value("hello world!").
key("object2").object().
key("k1").value("v1").
key("k2").value("v2").
key("k3").value("v3").
key("array1").array().
value(1).
value(2).
object().
key("k4").value("v4").
key("k5").value("v5").
key("k6").value("v6").
key("array2").array().
value(5).
value(6).
value(7).
value(8).
endArray().
endObject().
value(3).
value(4).
endArray().
endObject().
key("complexStringValue").value("h\be\tllo w\u1234orld!").
key("intValue").value(42).
key("doubleValue").value(-23.45e67).
endObject();
String str = jsonStringer.toString();
JSONObject jsonObject = new JSONObject(str);
// validate JSON content
Object doc = Configuration.defaultConfiguration().jsonProvider().parse(jsonObject.toString());
assertTrue("expected 8 top level items", ((Map<?,?>)(JsonPath.read(doc, "$"))).size() == 8);
assertTrue("expected 4 object2 items", ((Map<?,?>)(JsonPath.read(doc, "$.object2"))).size() == 4);
assertTrue("expected 5 array1 items", ((List<?>)(JsonPath.read(doc, "$.object2.array1"))).size() == 5);
assertTrue("expected 4 array[2] items", ((Map<?,?>)(JsonPath.read(doc, "$.object2.array1[2]"))).size() == 4);
assertTrue("expected 4 array1[2].array2 items", ((List<?>)(JsonPath.read(doc, "$.object2.array1[2].array2"))).size() == 4);
assertTrue("expected true", Boolean.TRUE.equals(jsonObject.query("/trueValue")));
assertTrue("expected false", Boolean.FALSE.equals(jsonObject.query("/falseValue")));
assertTrue("expected null", JSONObject.NULL.equals(jsonObject.query("/nullValue")));
assertTrue("expected hello world!", "hello world!".equals(jsonObject.query("/stringValue")));
assertTrue("expected 42", Integer.valueOf(42).equals(jsonObject.query("/intValue")));
assertTrue("expected -23.45e67", BigDecimal.valueOf(-23.45e67).equals(jsonObject.query("/doubleValue")));
assertTrue("expected h\be\tllo w\u1234orld!", "h\be\tllo w\u1234orld!".equals(jsonObject.query("/complexStringValue")));
assertTrue("expected v1", "v1".equals(jsonObject.query("/object2/k1")));
assertTrue("expected v2", "v2".equals(jsonObject.query("/object2/k2")));
assertTrue("expected v3", "v3".equals(jsonObject.query("/object2/k3")));
assertTrue("expected 1", Integer.valueOf(1).equals(jsonObject.query("/object2/array1/0")));
assertTrue("expected 2", Integer.valueOf(2).equals(jsonObject.query("/object2/array1/1")));
assertTrue("expected v4", "v4".equals(jsonObject.query("/object2/array1/2/k4")));
assertTrue("expected v5", "v5".equals(jsonObject.query("/object2/array1/2/k5")));
assertTrue("expected v6", "v6".equals(jsonObject.query("/object2/array1/2/k6")));
assertTrue("expected 5", Integer.valueOf(5).equals(jsonObject.query("/object2/array1/2/array2/0")));
assertTrue("expected 6", Integer.valueOf(6).equals(jsonObject.query("/object2/array1/2/array2/1")));
assertTrue("expected 7", Integer.valueOf(7).equals(jsonObject.query("/object2/array1/2/array2/2")));
assertTrue("expected 8", Integer.valueOf(8).equals(jsonObject.query("/object2/array1/2/array2/3")));
assertTrue("expected 3", Integer.valueOf(3).equals(jsonObject.query("/object2/array1/3")));
assertTrue("expected 4", Integer.valueOf(4).equals(jsonObject.query("/object2/array1/4")));
}
}

View File

@@ -0,0 +1,316 @@
package org.json.junit;
/*
Public Domain.
*/
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.junit.Test;
/**
* Test specific to the {@link org.json.JSONTokener} class.
* @author John Aylward
*
*/
public class JSONTokenerTest {
/**
* verify that back() fails as expected.
* @throws IOException thrown if something unexpected happens.
*/
@Test
public void verifyBackFailureZeroIndex() throws IOException {
Reader reader = new StringReader("some test string");
try {
final JSONTokener tokener = new JSONTokener(reader);
try {
// this should fail since the index is 0;
tokener.back();
fail("Expected an exception");
} catch (JSONException e) {
assertEquals("Stepping back two steps is not supported", e.getMessage());
} catch (Exception e) {
fail("Unknown Exception type " + e.getClass().getCanonicalName()+" with message "+e.getMessage());
}
} finally {
reader.close();
}
}
/**
* verify that back() fails as expected.
* @throws IOException thrown if something unexpected happens.
*/
@Test
public void verifyBackFailureDoubleBack() throws IOException {
Reader reader = new StringReader("some test string");
try {
final JSONTokener tokener = new JSONTokener(reader);
tokener.next();
tokener.back();
try {
// this should fail since the index is 0;
tokener.back();
fail("Expected an exception");
} catch (JSONException e) {
assertEquals("Stepping back two steps is not supported", e.getMessage());
} catch (Exception e) {
fail("Unknown Exception type " + e.getClass().getCanonicalName()+" with message "+e.getMessage());
}
} finally {
reader.close();
}
}
@Test
public void testValid() {
checkValid("0",Number.class);
checkValid(" 0 ",Number.class);
checkValid("23",Number.class);
checkValid("23.5",Number.class);
checkValid(" 23.5 ",Number.class);
checkValid("null",null);
checkValid(" null ",null);
checkValid("true",Boolean.class);
checkValid(" true\n",Boolean.class);
checkValid("false",Boolean.class);
checkValid("\nfalse ",Boolean.class);
checkValid("{}",JSONObject.class);
checkValid(" {} ",JSONObject.class);
checkValid("{\"a\":1}",JSONObject.class);
checkValid(" {\"a\":1} ",JSONObject.class);
checkValid("[]",JSONArray.class);
checkValid(" [] ",JSONArray.class);
checkValid("[1,2]",JSONArray.class);
checkValid("\n\n[1,2]\n\n",JSONArray.class);
checkValid("1 2", String.class);
}
@Test
public void testErrors() {
// Check that stream can detect that a value is found after
// the first one
checkError(" { \"a\":1 } 4 ");
checkError("null \"a\"");
checkError("{} true");
}
private Object checkValid(String testStr, Class<?> aClass) {
Object result = nextValue(testStr);
// Check class of object returned
if( null == aClass ) {
if(JSONObject.NULL.equals(result)) {
// OK
} else {
throw new JSONException("Unexpected class: "+result.getClass().getSimpleName());
}
} else {
if( null == result ) {
throw new JSONException("Unexpected null result");
} else if(!aClass.isAssignableFrom(result.getClass()) ) {
throw new JSONException("Unexpected class: "+result.getClass().getSimpleName());
}
}
return result;
}
private void checkError(String testStr) {
try {
nextValue(testStr);
fail("Error should be triggered: (\""+testStr+"\")");
} catch (JSONException e) {
// OK
}
}
/**
* Verifies that JSONTokener can read a stream that contains a value. After
* the reading is done, check that the stream is left in the correct state
* by reading the characters after. All valid cases should reach end of stream.
* @param testStr
* @return
* @throws Exception
*/
private Object nextValue(String testStr) throws JSONException {
StringReader sr = new StringReader(testStr);
try {
JSONTokener tokener = new JSONTokener(sr);
Object result = tokener.nextValue();
if( result == null ) {
throw new JSONException("Unable to find value token in JSON stream: ("+tokener+"): "+testStr);
}
char c = tokener.nextClean();
if( 0 != c ) {
throw new JSONException("Unexpected character found at end of JSON stream: "+c+ " ("+tokener+"): "+testStr);
}
return result;
} finally {
sr.close();
}
}
/**
* Tests the failure of the skipTo method with a buffered reader. Preferably
* we'd like this not to fail but at this time we don't have a good recovery.
*
* @throws IOException thrown if something unexpected happens.
*/
@Test
public void testSkipToFailureWithBufferedReader() throws IOException {
final byte[] superLongBuffer = new byte[1000001];
// fill our buffer
for(int i=0;i<superLongBuffer.length;i++) {
superLongBuffer[i] = 'A';
}
Reader reader = new BufferedReader(new InputStreamReader(
new ByteArrayInputStream(superLongBuffer)));
try {
final JSONTokener tokener = new JSONTokener(reader);
try {
// this should fail since the internal markAhead buffer is only 1,000,000
// but 'B' doesn't exist in our buffer that is 1,000,001 in size
tokener.skipTo('B');
fail("Expected exception");
} catch (JSONException e) {
assertEquals("Mark invalid", e.getMessage());
} catch (Exception e) {
fail("Unknown Exception type " + e.getClass().getCanonicalName()+" with message "+e.getMessage());
}
} finally {
reader.close();
}
}
/**
* Tests the success of the skipTo method with a String reader.
*
* @throws IOException thrown if something unexpected happens.
*/
@Test
public void testSkipToSuccessWithStringReader() throws IOException {
final StringBuilder superLongBuffer = new StringBuilder(1000001);
// fill our buffer
for(int i=0;i<superLongBuffer.length();i++) {
superLongBuffer.append('A');
}
Reader reader = new StringReader(superLongBuffer.toString());
try {
final JSONTokener tokener = new JSONTokener(reader);
try {
// this should not fail since the internal markAhead is ignored for StringReaders
tokener.skipTo('B');
} catch (Exception e) {
fail("Unknown Exception type " + e.getClass().getCanonicalName()+" with message "+e.getMessage());
}
} finally {
reader.close();
}
}
/**
* Verify that next and back are working properly and tracking the correct positions
* with different new line combinations.
*/
@Test
public void testNextBackComboWithNewLines() {
final String testString = "this is\nA test\r\nWith some different\rNew Lines";
// ^ ^ ^ ^
// index positions 0 8 16 36
final JSONTokener tokener = new JSONTokener(testString);
assertEquals(" at 0 [character 1 line 1]", tokener.toString());
assertEquals('t',tokener.next());
assertEquals(" at 1 [character 2 line 1]", tokener.toString());
tokener.skipTo('\n');
assertEquals("skipTo() improperly modifying indexes"," at 7 [character 8 line 1]", tokener.toString());
assertEquals('\n',tokener.next());
assertEquals(" at 8 [character 0 line 2]", tokener.toString());
assertEquals('A',tokener.next());
assertEquals(" at 9 [character 1 line 2]", tokener.toString());
tokener.back();
assertEquals(" at 8 [character 0 line 2]", tokener.toString());
tokener.skipTo('\r');
assertEquals("skipTo() improperly modifying indexes"," at 14 [character 6 line 2]", tokener.toString());
// verify \r\n combo doesn't increment the line twice
assertEquals('\r', tokener.next());
assertEquals(" at 15 [character 0 line 3]", tokener.toString());
assertEquals('\n', tokener.next());
assertEquals(" at 16 [character 0 line 3]", tokener.toString());
// verify stepping back after reading the \n of an \r\n combo doesn't increment the line incorrectly
tokener.back();
assertEquals(" at 15 [character 6 line 2]", tokener.toString());
assertEquals('\n', tokener.next());
assertEquals(" at 16 [character 0 line 3]", tokener.toString());
assertEquals('W', tokener.next());
assertEquals(" at 17 [character 1 line 3]", tokener.toString());
assertEquals('i', tokener.next());
assertEquals(" at 18 [character 2 line 3]", tokener.toString());
tokener.skipTo('\r');
assertEquals("skipTo() improperly modifying indexes"," at 35 [character 19 line 3]", tokener.toString());
assertEquals('\r', tokener.next());
assertEquals(" at 36 [character 0 line 4]", tokener.toString());
tokener.back();
assertEquals(" at 35 [character 19 line 3]", tokener.toString());
assertEquals('\r', tokener.next());
assertEquals(" at 36 [character 0 line 4]", tokener.toString());
assertEquals('N', tokener.next());
assertEquals(" at 37 [character 1 line 4]", tokener.toString());
// verify we get the same data just walking though, no calls to back
final JSONTokener t2 = new JSONTokener(testString);
for(int i=0; i<7; i++) {
assertTrue(t2.toString().startsWith(" at " + i + " "));
assertEquals(testString.charAt(i), t2.next());
}
assertEquals(" at 7 [character 8 line 1]", t2.toString());
assertEquals(testString.charAt(7), t2.next());
assertEquals(" at 8 [character 0 line 2]", t2.toString());
for(int i=8; i<14; i++) {
assertTrue(t2.toString().startsWith(" at " + i + " "));
assertEquals(testString.charAt(i), t2.next());
}
assertEquals(" at 14 [character 6 line 2]", t2.toString());
assertEquals('\r', t2.next());
assertEquals(" at 15 [character 0 line 3]", t2.toString());
assertEquals('\n', t2.next());
assertEquals(" at 16 [character 0 line 3]", t2.toString());
assertEquals('W', t2.next());
assertEquals(" at 17 [character 1 line 3]", t2.toString());
for(int i=17; i<37; i++) {
assertTrue(t2.toString().startsWith(" at " + i + " "));
assertEquals(testString.charAt(i), t2.next());
}
assertEquals(" at 37 [character 1 line 4]", t2.toString());
for(int i=37; i<testString.length(); i++) {
assertTrue(t2.toString().startsWith(" at " + i + " "));
assertEquals(testString.charAt(i), t2.next());
}
assertEquals(" at "+ testString.length() +" [character 9 line 4]", t2.toString());
// end of the input
assertEquals(0, t2.next());
assertFalse(t2.more());
}
}

View File

@@ -0,0 +1,102 @@
package org.json.junit;
/*
Public Domain.
*/
import java.util.*;
import static org.junit.Assert.*;
import org.json.*;
import org.junit.Test;
/**
* Tests for JSON-Java Property
*/
public class PropertyTest {
/**
* JSONObject from null properties object should
* result in an empty JSONObject.
*/
@Test
public void shouldHandleNullProperties() {
Properties properties = null;
JSONObject jsonObject = Property.toJSONObject(properties);
assertTrue("jsonObject should be empty", jsonObject.isEmpty());
}
/**
* JSONObject from empty properties object should
* result in an empty JSONObject.
*/
@Test
public void shouldHandleEmptyProperties() {
Properties properties = new Properties();
JSONObject jsonObject = Property.toJSONObject(properties);
assertTrue("jsonObject should be empty", jsonObject.isEmpty());
}
/**
* JSONObject from simple properties object.
*/
@Test
public void shouldHandleProperties() {
Properties properties = new Properties();
properties.put("Illinois", "Springfield");
properties.put("Missouri", "Jefferson City");
properties.put("Washington", "Olympia");
properties.put("California", "Sacramento");
properties.put("Indiana", "Indianapolis");
JSONObject jsonObject = Property.toJSONObject(properties);
assertTrue("jsonObject should contain 5 items", jsonObject.length() == 5);
assertTrue("jsonObject should contain Illinois property",
"Springfield".equals(jsonObject.get("Illinois")));
assertTrue("jsonObject should contain Missouri property",
"Jefferson City".equals(jsonObject.get("Missouri")));
assertTrue("jsonObject should contain Washington property",
"Olympia".equals(jsonObject.get("Washington")));
assertTrue("jsonObject should contain California property",
"Sacramento".equals(jsonObject.get("California")));
assertTrue("jsonObject should contain Indiana property",
"Indianapolis".equals(jsonObject.get("Indiana")));
}
/**
* Null JSONObject toProperties() should result in an empty
* Properties object.
*/
@Test
public void shouldHandleNullJSONProperty() {
JSONObject jsonObject= null;
Properties properties = Property.toProperties(jsonObject);
assertTrue("properties should be empty",
properties.size() == 0);
}
/**
* Properties should convert to JSONObject, and back to
* Properties without changing.
*/
@Test
public void shouldHandleJSONProperty() {
Properties properties = new Properties();
properties.put("Illinois", "Springfield");
properties.put("Missouri", "Jefferson City");
properties.put("Washington", "Olympia");
properties.put("California", "Sacramento");
properties.put("Indiana", "Indianapolis");
JSONObject jsonObject = Property.toJSONObject(properties);
Properties jsonProperties = Property.toProperties(jsonObject);
assertTrue("property objects should match",
properties.equals(jsonProperties));
}
}

View File

@@ -0,0 +1,201 @@
package org.json.junit;
/*
Public Domain.
*/
import static org.junit.Assert.*;
import java.util.*;
import org.json.*;
/**
* These are helpful utility methods that perform basic comparisons
* between various objects. In most cases, the comparisons are not
* order-dependent, or else the order is known.
*/
public class Util {
/**
* Compares two JSONArrays for equality.
* The arrays need not be in the same order.
* @param jsonArray created by the code to be tested
* @param expectedJsonArray created specifically for comparing
*/
public static void compareActualVsExpectedJsonArrays(JSONArray jsonArray,
JSONArray expectedJsonArray) {
assertTrue("jsonArray lengths should be equal",
jsonArray.length() == expectedJsonArray.length());
for (int i = 0; i < jsonArray.length(); ++i) {
Object value = jsonArray.get(i);
Object expectedValue = expectedJsonArray.get(i);
compareActualVsExpectedObjects(value, expectedValue);
}
}
/**
* Compares two JSONObjects for equality. The objects need not be
* in the same order
* @param jsonObject created by the code to be tested
* @param expectedJsonObject created specifically for comparing
*/
public static void compareActualVsExpectedJsonObjects(
JSONObject jsonObject, JSONObject expectedJsonObject) {
assertTrue("jsonObjects should have the same length",
jsonObject.length() == expectedJsonObject.length());
Iterator<String> keys = jsonObject.keys();
while (keys.hasNext()) {
String key = keys.next();
Object value = jsonObject.get(key);
Object expectedValue = expectedJsonObject.get(key);
compareActualVsExpectedObjects(value, expectedValue);
}
}
/**
* Compare two objects for equality. Might be JSONArray, JSONObject,
* or something else.
* @param value created by the code to be tested
* @param expectedValue created specifically for comparing
*/
private static void compareActualVsExpectedObjects(Object value,
Object expectedValue) {
if (value instanceof JSONObject && expectedValue instanceof JSONObject) {
// Compare JSONObjects
JSONObject jsonObject = (JSONObject)value;
JSONObject expectedJsonObject = (JSONObject)expectedValue;
compareActualVsExpectedJsonObjects(
jsonObject, expectedJsonObject);
} else if (value instanceof JSONArray && expectedValue instanceof JSONArray) {
// Compare JSONArrays
JSONArray jsonArray = (JSONArray)value;
JSONArray expectedJsonArray = (JSONArray)expectedValue;
compareActualVsExpectedJsonArrays(
jsonArray, expectedJsonArray);
} else {
/**
* Compare all other types using toString(). First, the types must
* also be equal, unless both are Number type. Certain helper
* classes (e.g. XML) may create Long instead of Integer for small
* int values.
*/
if (!(value instanceof Number && expectedValue instanceof Number)) {
// Non-Number and non-matching types
assertEquals("object types should be equal ",
expectedValue.getClass().toString(),
value.getClass().toString()
);
}
/**
* Same types or both Numbers, compare by toString()
*/
assertEquals("values should be equal",
expectedValue.toString(),
value.toString()
);
}
}
/**
* Asserts that all JSONObject maps are the same as the default ctor
* @param jsonObjects list of objects to be tested
*/
public static void checkJSONObjectsMaps(List<JSONObject> jsonObjects) {
if (jsonObjects == null || jsonObjects.size() == 0) {
return;
}
Class<? extends Map> mapType = new JSONObject().getMapType();
for (JSONObject jsonObject : jsonObjects) {
if (jsonObject != null) {
assertTrue(mapType == jsonObject.getMapType());
checkJSONObjectMaps(jsonObject, mapType);
}
}
}
/**
* Asserts that all JSONObject maps are the same as the default ctor
* @param jsonObject the object to be tested
*/
public static void checkJSONObjectMaps(JSONObject jsonObject) {
if (jsonObject != null) {
checkJSONObjectMaps(jsonObject, jsonObject.getMapType());
}
}
/**
* Asserts that all JSONObject maps are the same as mapType
* @param jsonObject object to be tested
* @param mapType mapType to test against
*/
public static void checkJSONObjectMaps(JSONObject jsonObject, Class<? extends Map> mapType) {
if (mapType == null) {
mapType = new JSONObject().getMapType();
}
Set<String> keys = jsonObject.keySet();
for (String key : keys) {
Object val = jsonObject.get(key);
if (val instanceof JSONObject) {
JSONObject jsonObjectVal = (JSONObject) val;
assertTrue(mapType == ((JSONObject) val).getMapType());
checkJSONObjectMaps(jsonObjectVal, mapType);
} else if (val instanceof JSONArray) {
JSONArray jsonArrayVal = (JSONArray)val;
checkJSONArrayMaps(jsonArrayVal, mapType);
}
}
}
/**
* Asserts that all JSONObject maps in the JSONArray object match the default map
* @param jsonArrays list of JSONArray objects to be tested
*/
public static void checkJSONArraysMaps(List<JSONArray> jsonArrays) {
if (jsonArrays == null || jsonArrays.size() == 0) {
return;
}
Class<? extends Map> mapType = new JSONObject().getMapType();
for (JSONArray jsonArray : jsonArrays) {
if (jsonArray != null) {
checkJSONArrayMaps(jsonArray, mapType);
}
}
}
/**
* Asserts that all JSONObject maps in the JSONArray object match mapType
* @param jsonArray object to be tested
* @param mapType map type to be tested against
*/
public static void checkJSONArrayMaps(JSONArray jsonArray, Class<? extends Map> mapType) {
if (jsonArray == null) {
return;
}
if (mapType == null) {
mapType = new JSONObject().getMapType();
}
Iterator<Object> it = jsonArray.iterator();
while (it.hasNext()) {
Object val = it.next();
if (val instanceof JSONObject) {
JSONObject jsonObjectVal = (JSONObject)val;
checkJSONObjectMaps(jsonObjectVal, mapType);
} else if (val instanceof JSONArray) {
JSONArray jsonArrayVal = (JSONArray)val;
checkJSONArrayMaps(jsonArrayVal, mapType);
}
}
}
/**
* Asserts that all JSONObject maps nested in the JSONArray match
* the default mapType
* @param jsonArray the object to be tested
*/
public static void checkJSONArrayMaps(JSONArray jsonArray) {
if (jsonArray != null) {
checkJSONArrayMaps(jsonArray, null);
}
}
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,13 @@
package org.json.junit.data;
/**
* test class for verifying write errors.
* @author John Aylward
*
*/
public class BrokenToString {
@Override
public String toString() {
throw new IllegalStateException("Something went horribly wrong!");
}
}

View File

@@ -0,0 +1,66 @@
/**
*
*/
package org.json.junit.data;
import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
/**
* Object for testing the exception handling in {@link org.json.JSONObject#populateMap}.
*
* @author John Aylward
*/
public class ExceptionalBean {
/**
* @return a closeable.
*/
public Closeable getCloseable() {
// anonymous inner class did not work...
return new MyCloseable();
}
/**
* @return Nothing really. Just can't be void.
* @throws IllegalAccessException
* always thrown
*/
public int getIllegalAccessException() throws IllegalAccessException {
throw new IllegalAccessException("Yup, it's illegal");
}
/**
* @return Nothing really. Just can't be void.
* @throws IllegalArgumentException
* always thrown
*/
public int getIllegalArgumentException() throws IllegalArgumentException {
throw new IllegalArgumentException("Yup, it's illegal");
}
/**
* @return Nothing really. Just can't be void.
* @throws InvocationTargetException
* always thrown
*/
public int getInvocationTargetException() throws InvocationTargetException {
throw new InvocationTargetException(new Exception("Yup, it's illegal"));
}
/** My closeable class. */
public static final class MyCloseable implements Closeable {
/**
* @return a string
*/
public String getString() {
return "Yup, it's closeable";
}
@Override
public void close() throws IOException {
throw new IOException("Closing is too hard!");
}
}
}

View File

@@ -0,0 +1,180 @@
package org.json.junit.data;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.math.RoundingMode;
/**
* basic fraction class, no frills.
* @author John Aylward
*
*/
public class Fraction extends Number implements Comparable<Fraction> {
/**
* serial id.
*/
private static final long serialVersionUID = 1L;
/**
* value as a big decimal.
*/
private final BigDecimal bigDecimal;
/**
* value of the denominator.
*/
private final BigInteger denominator;
/**
* value of the numerator.
*/
private final BigInteger numerator;
/**
* @param numerator
* numerator
* @param denominator
* denominator
*/
public Fraction(final BigInteger numerator, final BigInteger denominator) {
super();
if (numerator == null || denominator == null) {
throw new IllegalArgumentException("All values must be non-null");
}
if (denominator.compareTo(BigInteger.ZERO)==0) {
throw new IllegalArgumentException("Divide by zero");
}
final BigInteger n;
final BigInteger d;
// normalize fraction
if (denominator.signum()<0) {
n = numerator.negate();
d = denominator.negate();
} else {
n = numerator;
d = denominator;
}
this.numerator = n;
this.denominator = d;
if (n.compareTo(BigInteger.ZERO)==0) {
this.bigDecimal = BigDecimal.ZERO;
} else if (n.compareTo(d)==0) {// i.e. 4/4, 10/10
this.bigDecimal = BigDecimal.ONE;
} else {
this.bigDecimal = new BigDecimal(this.numerator).divide(new BigDecimal(this.denominator),
RoundingMode.HALF_EVEN);
}
}
/**
* @param numerator
* numerator
* @param denominator
* denominator
*/
public Fraction(final long numerator, final long denominator) {
this(BigInteger.valueOf(numerator),BigInteger.valueOf(denominator));
}
/**
* @return the decimal
*/
public BigDecimal bigDecimalValue() {
return this.bigDecimal;
}
@Override
public int compareTo(final Fraction o) {
// .equals call this, so no .equals compare allowed
// if they are the same reference, just return equals
if (this == o) {
return 0;
}
// if my denominators are already equal, just compare the numerators
if (this.denominator.compareTo(o.denominator)==0) {
return this.numerator.compareTo(o.numerator);
}
// get numerators of common denominators
// a x ay xb
// --- --- = ---- ----
// b y by yb
final BigInteger thisN = this.numerator.multiply(o.denominator);
final BigInteger otherN = o.numerator.multiply(this.denominator);
return thisN.compareTo(otherN);
}
@Override
public double doubleValue() {
return this.bigDecimal.doubleValue();
}
/**
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(final Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (this.getClass() != obj.getClass()) {
return false;
}
final Fraction other = (Fraction) obj;
return this.compareTo(other) == 0;
}
@Override
public float floatValue() {
return this.bigDecimal.floatValue();
}
/**
* @return the denominator
*/
public BigInteger getDenominator() {
return this.denominator;
}
/**
* @return the numerator
*/
public BigInteger getNumerator() {
return this.numerator;
}
/**
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + (this.bigDecimal == null ? 0 : this.bigDecimal.hashCode());
return result;
}
@Override
public int intValue() {
return this.bigDecimal.intValue();
}
@Override
public long longValue() {
return this.bigDecimal.longValue();
}
/**
* @see java.lang.Object#toString()
*/
@Override
public String toString() {
return this.numerator + "/" + this.denominator;
}
}

View File

@@ -0,0 +1,79 @@
package org.json.junit.data;
import java.io.StringReader;
/**
*
* @author John Aylward
*
* @param <T>
* generic number value
*/
public class GenericBean<T extends Number & Comparable<T>> implements MyBean {
/**
* @param genericValue
* value to initiate with
*/
public GenericBean(T genericValue) {
super();
this.genericValue = genericValue;
}
/** */
protected T genericValue;
/** to be used by the calling test to see how often the getter is called */
public int genericGetCounter;
/** to be used by the calling test to see how often the setter is called */
public int genericSetCounter;
/** @return the genericValue */
public T getGenericValue() {
this.genericGetCounter++;
return this.genericValue;
}
/**
* @param genericValue
* generic value to set
*/
public void setGenericValue(T genericValue) {
this.genericSetCounter++;
this.genericValue = genericValue;
}
@Override
public Integer getIntKey() {
return Integer.valueOf(42);
}
@Override
public Double getDoubleKey() {
return Double.valueOf(4.2);
}
@Override
public String getStringKey() {
return "MyString Key";
}
@Override
public String getEscapeStringKey() {
return "\"My String with \"s";
}
@Override
public Boolean isTrueKey() {
return Boolean.TRUE;
}
@Override
public Boolean isFalseKey() {
return Boolean.FALSE;
}
@Override
public StringReader getStringReaderKey() {
return new StringReader("Some String Value in a reader");
}
}

View File

@@ -0,0 +1,69 @@
/**
*
*/
package org.json.junit.data;
/**
* @author john
*
*/
public class GenericBeanInt extends GenericBean<Integer> {
/** */
final char a = 'A';
/** @return the a */
public char getA() {
return this.a;
}
/**
* Should not be beanable
*
* @return false
*/
public boolean getable() {
return false;
}
/**
* Should not be beanable
*
* @return false
*/
public boolean get() {
return false;
}
/**
* Should not be beanable
*
* @return false
*/
public boolean is() {
return false;
}
/**
* Should be beanable
*
* @return false
*/
public boolean isB() {
return this.genericValue.equals((Integer.valueOf(this.a+1)));
}
/**
* @param genericValue
* the value to initiate with.
*/
public GenericBeanInt(Integer genericValue) {
super(genericValue);
}
/** override to generate a bridge method */
@Override
public Integer getGenericValue() {
return super.getGenericValue();
}
}

View File

@@ -0,0 +1,16 @@
package org.json.junit.data;
import java.io.*;
/**
* Used in testing when Bean behavior is needed
*/
public interface MyBean {
public Integer getIntKey();
public Double getDoubleKey();
public String getStringKey();
public String getEscapeStringKey();
public Boolean isTrueKey();
public Boolean isFalseKey();
public StringReader getStringReaderKey();
}

View File

@@ -0,0 +1,20 @@
package org.json.junit.data;
import org.json.JSONPropertyName;
/**
* Test bean for the {@link JSONPropertyName} annotation.
*/
public class MyBeanCustomName implements MyBeanCustomNameInterface {
public int getSomeInt() { return 42; }
@JSONPropertyName("")
public long getSomeLong() { return 42L; }
@JSONPropertyName("myStringField")
public String getSomeString() { return "someStringValue"; }
@JSONPropertyName("Some Weird NAme that Normally Wouldn't be possible!")
public double getMyDouble() { return 0.0d; }
@Override
public float getSomeFloat() { return 2.0f; }
@Override
public int getIgnoredInt() { return 40; }
}

View File

@@ -0,0 +1,11 @@
package org.json.junit.data;
import org.json.JSONPropertyIgnore;
import org.json.JSONPropertyName;
public interface MyBeanCustomNameInterface {
@JSONPropertyName("InterfaceField")
float getSomeFloat();
@JSONPropertyIgnore
int getIgnoredInt();
}

View File

@@ -0,0 +1,32 @@
/**
*
*/
package org.json.junit.data;
import org.json.JSONPropertyIgnore;
import org.json.JSONPropertyName;
/**
* Test bean to verify that the {@link org.json.JSONPropertyName} annotation
* is inherited.
*/
public class MyBeanCustomNameSubClass extends MyBeanCustomName {
@Override
@JSONPropertyName("forcedInt")
public int getIgnoredInt() { return 42*42; }
@Override
@JSONPropertyName("newIntFieldName")
public int getSomeInt() { return 43; }
@Override
public String getSomeString() { return "subClassString"; }
@Override
@JSONPropertyName("AMoreNormalName")
public double getMyDouble() { return 1.0d; }
@Override
public float getSomeFloat() { return 3.0f; }
@JSONPropertyIgnore
@JSONPropertyName("ShouldBeIgnored")
public boolean getShouldNotBeJSON() { return true; }
@JSONPropertyName("Getable")
public boolean getable() { return true; }
}

View File

@@ -0,0 +1,11 @@
package org.json.junit.data;
import java.math.*;
/**
* Used in testing when a Bean containing big numbers is needed
*/
public interface MyBigNumberBean {
public BigInteger getBigInteger();
public BigDecimal getBigDecimal();
}

View File

@@ -0,0 +1,10 @@
package org.json.junit.data;
/**
* An enum with no methods or data
*/
public enum MyEnum {
VAL1,
VAL2,
VAL3;
}

View File

@@ -0,0 +1,22 @@
package org.json.junit.data;
/**
* this is simply a class that contains some enum instances
*/
public class MyEnumClass {
private MyEnum myEnum;
private MyEnumField myEnumField;
public MyEnum getMyEnum() {
return this.myEnum;
}
public void setMyEnum(MyEnum myEnum) {
this.myEnum = myEnum;
}
public MyEnumField getMyEnumField() {
return this.myEnumField;
}
public void setMyEnumField(MyEnumField myEnumField) {
this.myEnumField = myEnumField;
}
}

View File

@@ -0,0 +1,28 @@
package org.json.junit.data;
/**
* An enum that contains getters and some internal fields
*/
@SuppressWarnings("boxing")
public enum MyEnumField {
VAL1(1, "val 1"),
VAL2(2, "val 2"),
VAL3(3, "val 3");
private String value;
private Integer intVal;
private MyEnumField(Integer intVal, String value) {
this.value = value;
this.intVal = intVal;
}
public String getValue() {
return this.value;
}
public Integer getIntVal() {
return this.intVal;
}
@Override
public String toString(){
return this.value;
}
}

View File

@@ -0,0 +1,14 @@
package org.json.junit.data;
import org.json.*;
/**
* Used in testing when a JSONString is needed
*/
public class MyJsonString implements JSONString {
@Override
public String toJSONString() {
return "my string";
}
}

View File

@@ -0,0 +1,12 @@
package org.json.junit.data;
public class MyLocaleBean {
private final String id = "beanId";
private final String i = "beanI";
public String getId() {
return this.id;
}
public String getI() {
return this.i;
}
}

View File

@@ -0,0 +1,97 @@
package org.json.junit.data;
import java.math.BigDecimal;
/**
* Number override for testing. Number overrides should always override
* toString, hashCode, and Equals.
*
* @see <a
* href="https://docs.oracle.com/javase/tutorial/java/data/numberclasses.html">The
* Numbers Classes</a>
* @see <a
* href="https://docs.oracle.com/javase/tutorial/java/data/numberformat.html">Formatting
* Numeric Print Output</a>
*
* @author John Aylward
*/
public class MyNumber extends Number {
private Number number = BigDecimal.valueOf(42);
/**
*/
private static final long serialVersionUID = 1L;
/**
* @return number!
*/
public Number getNumber() {
return this.number;
}
@Override
public int intValue() {
return getNumber().intValue();
}
@Override
public long longValue() {
return getNumber().longValue();
}
@Override
public float floatValue() {
return getNumber().floatValue();
}
@Override
public double doubleValue() {
return getNumber().doubleValue();
}
/* (non-Javadoc)
* @see java.lang.Object#toString()
*
* Number overrides should in general always override the toString method.
*/
@Override
public String toString() {
return getNumber().toString();
}
/* (non-Javadoc)
* @see java.lang.Object#hashCode()
*/
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((this.number == null) ? 0 : this.number.hashCode());
return result;
}
/* (non-Javadoc)
* @see java.lang.Object#equals(java.lang.Object)
*/
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof MyNumber)) {
return false;
}
MyNumber other = (MyNumber) obj;
if (this.number == null) {
if (other.number != null) {
return false;
}
} else if (!this.number.equals(other.number)) {
return false;
}
return true;
}
}

View File

@@ -0,0 +1,13 @@
package org.json.junit.data;
/**
* Class that holds our MyNumber override as a property.
* @author John Aylward
*/
public class MyNumberContainer {
private MyNumber myNumber = new MyNumber();
/**
* @return a MyNumber.
*/
public Number getMyNumber() {return this.myNumber;}
}

View File

@@ -0,0 +1,10 @@
package org.json.junit.data;
/**
* Need a class with some public data members for testing
*/
@SuppressWarnings("boxing")
public class MyPublicClass {
public Integer publicInt = 42;
public String publicString = "abc";
}

View File

@@ -0,0 +1,23 @@
package org.json.junit.data;
/**
* test class for verifying if recursively defined bean can be correctly identified
* @author Zetmas
*
*/
public class RecursiveBean {
private String name;
private Object reference;
private Object reference2;
public String getName() { return name; }
public Object getRef() {return reference;}
public Object getRef2() {return reference2;}
public void setRef(Object refObj) {reference = refObj;}
public void setRef2(Object refObj) {reference2 = refObj;}
public RecursiveBean(String name) {
this.name = name;
reference = null;
reference2 = null;
}
}

View File

@@ -0,0 +1,33 @@
package org.json.junit.data;
/** test class for verifying if recursively defined bean can be correctly identified */
public class RecursiveBeanEquals {
private final String name;
private Object reference;
public RecursiveBeanEquals(String name) {
this.name = name;
}
public String getName() {
return name;
}
public Object getRef() {
return reference;
}
public void setRef(Object refObj) {
reference = refObj;
}
@Override
public boolean equals(Object other) {
return other instanceof RecursiveBeanEquals && name.equals(((RecursiveBeanEquals) other).name);
}
@Override
public int hashCode() {
return name.hashCode();
}
}

View File

@@ -0,0 +1,91 @@
package org.json.junit.data;
/**
* Sample singleton for use with bean testing.
*
* @author John Aylward
*
*/
public final class Singleton {
/** */
private int someInt;
/** */
private String someString;
/** single instance. */
private static final Singleton INSTANCE = new Singleton();
/** @return the singleton instance. */
public static final Singleton getInstance() {
return INSTANCE;
}
/** */
private Singleton() {
if (INSTANCE != null) {
throw new IllegalStateException("Already instantiated");
}
}
@Override
protected Object clone() throws CloneNotSupportedException {
return INSTANCE;
}
/** @return someInt */
public int getSomeInt() {
return this.someInt;
}
/**
* sets someInt.
*
* @param someInt
* the someInt to set
*/
public void setSomeInt(int someInt) {
this.someInt = someInt;
}
/** @return someString */
public String getSomeString() {
return this.someString;
}
/**
* sets someString.
*
* @param someString
* the someString to set
*/
public void setSomeString(String someString) {
this.someString = someString;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + this.someInt;
result = prime * result + ((this.someString == null) ? 0 : this.someString.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
Singleton other = (Singleton) obj;
if (this.someInt != other.someInt)
return false;
if (this.someString == null) {
if (other.someString != null)
return false;
} else if (!this.someString.equals(other.someString))
return false;
return true;
}
}

View File

@@ -0,0 +1,62 @@
package org.json.junit.data;
/**
* Sample singleton done as an Enum for use with bean testing.
*
* @author John Aylward
*
*/
public enum SingletonEnum {
/**
* the singleton instance.
*/
INSTANCE;
/** */
private int someInt;
/** */
private String someString;
/** single instance. */
/**
* @return the singleton instance. In a real application, I'd hope no one did
* this to an enum singleton.
*/
public static final SingletonEnum getInstance() {
return INSTANCE;
}
/** */
private SingletonEnum() {
}
/** @return someInt */
public int getSomeInt() {
return this.someInt;
}
/**
* sets someInt.
*
* @param someInt
* the someInt to set
*/
public void setSomeInt(int someInt) {
this.someInt = someInt;
}
/** @return someString */
public String getSomeString() {
return this.someString;
}
/**
* sets someString.
*
* @param someString
* the someString to set
*/
public void setSomeString(String someString) {
this.someString = someString;
}
}

View File

@@ -0,0 +1,19 @@
package org.json.junit.data;
import java.util.*;
/**
* A resource bundle class
*/
public class StringsResourceBundle extends ListResourceBundle {
@Override
public Object[][] getContents() {
return contents;
}
static final Object[][] contents = {
{"greetings.hello", "Hello, "},
{"greetings.world", "World!"},
{"farewells.later", "Later, "},
{"farewells.gator", "Alligator!"}
};
}

View File

@@ -0,0 +1,68 @@
/**
*
*/
package org.json.junit.data;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
/**
* @author John Aylward
*/
public class WeirdList {
/** */
private final List<Integer> list = new ArrayList();
/**
* @param vals
*/
public WeirdList(Integer... vals) {
this.list.addAll(Arrays.asList(vals));
}
/**
* @return a copy of the list
*/
public List<Integer> get() {
return new ArrayList(this.list);
}
/**
* @return a copy of the list
*/
public List<Integer> getALL() {
return new ArrayList(this.list);
}
/**
* get a value at an index.
*
* @param i
* index to get
* @return the value at the index
*/
public Integer get(int i) {
return this.list.get(i);
}
/**
* get a value at an index.
*
* @param i
* index to get
* @return the value at the index
*/
@SuppressWarnings("boxing")
public int getInt(int i) {
return this.list.get(i);
}
/**
* @param value
* new value to add to the end of the list
*/
public void add(Integer value) {
this.list.add(value);
}
}

View File

@@ -0,0 +1,189 @@
{
"clinical_study": {
"brief_summary": {
"textblock": "CLEAR SYNERGY is an international multi center 2x2 randomized placebo controlled trial of"
},
"brief_title": "CLEAR SYNERGY Neutrophil Substudy",
"overall_status": "Recruiting",
"eligibility": {
"study_pop": {
"textblock": "Patients who are randomized to the drug RCT portion of the CLEAR SYNERGY (OASIS 9) trial"
},
"minimum_age": "19 Years",
"sampling_method": "Non-Probability Sample",
"gender": "All",
"criteria": {
"textblock": "Inclusion Criteria:"
},
"healthy_volunteers": "No",
"maximum_age": "110 Years"
},
"number_of_groups": "2",
"source": "NYU Langone Health",
"location_countries": {
"country": "United States"
},
"study_design_info": {
"time_perspective": "Prospective",
"observational_model": "Other"
},
"last_update_submitted_qc": "September 10, 2019",
"intervention_browse": {
"mesh_term": "Colchicine"
},
"official_title": "Studies on the Effects of Colchicine on Neutrophil Biology in Acute Myocardial Infarction: A Substudy of the CLEAR SYNERGY (OASIS 9) Trial",
"primary_completion_date": {
"type": "Anticipated",
"content": "February 1, 2021"
},
"sponsors": {
"lead_sponsor": {
"agency_class": "Other",
"agency": "NYU Langone Health"
},
"collaborator": [
{
"agency_class": "Other",
"agency": "Population Health Research Institute"
},
{
"agency_class": "NIH",
"agency": "National Heart, Lung, and Blood Institute (NHLBI)"
}
]
},
"overall_official": {
"role": "Principal Investigator",
"affiliation": "NYU School of Medicine",
"last_name": "Binita Shah, MD"
},
"overall_contact_backup": {
"last_name": "Binita Shah, MD"
},
"condition_browse": {
"mesh_term": [
"Myocardial Infarction",
"ST Elevation Myocardial Infarction",
"Infarction"
]
},
"overall_contact": {
"phone": "646-501-9648",
"last_name": "Fatmira Curovic",
"email": "fatmira.curovic@nyumc.org"
},
"responsible_party": {
"responsible_party_type": "Principal Investigator",
"investigator_title": "Assistant Professor of Medicine",
"investigator_full_name": "Binita Shah",
"investigator_affiliation": "NYU Langone Health"
},
"study_first_submitted_qc": "March 12, 2019",
"start_date": {
"type": "Actual",
"content": "March 4, 2019"
},
"has_expanded_access": "No",
"study_first_posted": {
"type": "Actual",
"content": "March 14, 2019"
},
"arm_group": [
{
"arm_group_label": "Colchicine"
},
{
"arm_group_label": "Placebo"
}
],
"primary_outcome": {
"measure": "soluble L-selectin",
"time_frame": "between baseline and 3 months",
"description": "Change in soluble L-selectin between baseline and 3 mo after STEMI in the placebo vs. colchicine groups."
},
"secondary_outcome": [
{
"measure": "Other soluble markers of neutrophil activity",
"time_frame": "between baseline and 3 months",
"description": "Other markers of neutrophil activity will be evaluated at baseline and 3 months after STEMI (myeloperoxidase, matrix metalloproteinase-9, neutrophil gelatinase-associated lipocalin, neutrophil elastase, intercellular/vascular cellular adhesion molecules)"
},
{
"measure": "Markers of systemic inflammation",
"time_frame": "between baseline and 3 months",
"description": "Markers of systemic inflammation will be evaluated at baseline and 3 months after STEMI (high sensitive CRP, IL-1β)"
},
{
"measure": "Neutrophil-driven responses that may further propagate injury",
"time_frame": "between baseline and 3 months",
"description": "Neutrophil-driven responses that may further propagate injury will be evaluated at baseline and 3 months after STEMI (neutrophil extracellular traps, neutrophil-derived microparticles)"
}
],
"oversight_info": {
"is_fda_regulated_drug": "No",
"is_fda_regulated_device": "No",
"has_dmc": "No"
},
"last_update_posted": {
"type": "Actual",
"content": "September 12, 2019"
},
"id_info": {
"nct_id": "NCT03874338",
"org_study_id": "18-01323",
"secondary_id": "1R01HL146206"
},
"enrollment": {
"type": "Anticipated",
"content": "670"
},
"study_first_submitted": "March 12, 2019",
"condition": [
"Neutrophils.Hypersegmented | Bld-Ser-Plas",
"STEMI - ST Elevation Myocardial Infarction"
],
"study_type": "Observational",
"required_header": {
"download_date": "ClinicalTrials.gov processed this data on July 19, 2020",
"link_text": "Link to the current ClinicalTrials.gov record.",
"url": "https://clinicaltrials.gov/show/NCT03874338"
},
"last_update_submitted": "September 10, 2019",
"completion_date": {
"type": "Anticipated",
"content": "February 1, 2022"
},
"location": {
"contact": {
"phone": "646-501-9648",
"last_name": "Fatmira Curovic",
"email": "fatmira.curovic@nyumc.org"
},
"facility": {
"address": {
"zip": "10016",
"country": "United States",
"city": "New York",
"state": "New York"
},
"name": "NYU School of Medicine"
},
"status": "Recruiting",
"contact_backup": {
"last_name": "Binita Shah, MD"
}
},
"intervention": {
"intervention_type": "Drug",
"arm_group_label": [
"Colchicine",
"Placebo"
],
"description": "Participants in the main CLEAR SYNERGY trial are randomized to colchicine/spironolactone versus placebo in a 2x2 factorial design. The substudy is interested in the evaluation of biospecimens obtained from patients in the colchicine vs placebo group.",
"intervention_name": "Colchicine Pill"
},
"patient_data": {
"sharing_ipd": "No"
},
"verification_date": "September 2019"
}
}

View File

@@ -0,0 +1,169 @@
<?xml version="1.0" encoding="UTF-8"?>
<clinical_study>
<!-- This xml conforms to an XML Schema at:
https://clinicaltrials.gov/ct2/html/images/info/public.xsd -->
<required_header>
<download_date>ClinicalTrials.gov processed this data on July 19, 2020</download_date>
<link_text>Link to the current ClinicalTrials.gov record.</link_text>
<url>https://clinicaltrials.gov/show/NCT03874338</url>
</required_header>
<id_info>
<org_study_id>18-01323</org_study_id>
<secondary_id>1R01HL146206</secondary_id>
<nct_id>NCT03874338</nct_id>
</id_info>
<brief_title>CLEAR SYNERGY Neutrophil Substudy</brief_title>
<official_title>Studies on the Effects of Colchicine on Neutrophil Biology in Acute Myocardial Infarction: A Substudy of the CLEAR SYNERGY (OASIS 9) Trial</official_title>
<sponsors>
<lead_sponsor>
<agency>NYU Langone Health</agency>
<agency_class>Other</agency_class>
</lead_sponsor>
<collaborator>
<agency>Population Health Research Institute</agency>
<agency_class>Other</agency_class>
</collaborator>
<collaborator>
<agency>National Heart, Lung, and Blood Institute (NHLBI)</agency>
<agency_class>NIH</agency_class>
</collaborator>
</sponsors>
<source>NYU Langone Health</source>
<oversight_info>
<has_dmc>No</has_dmc>
<is_fda_regulated_drug>No</is_fda_regulated_drug>
<is_fda_regulated_device>No</is_fda_regulated_device>
</oversight_info>
<brief_summary>
<textblock>
CLEAR SYNERGY is an international multi center 2x2 randomized placebo controlled trial of
</textblock>
</brief_summary>
<overall_status>Recruiting</overall_status>
<start_date type="Actual">March 4, 2019</start_date>
<completion_date type="Anticipated">February 1, 2022</completion_date>
<primary_completion_date type="Anticipated">February 1, 2021</primary_completion_date>
<study_type>Observational</study_type>
<has_expanded_access>No</has_expanded_access>
<study_design_info>
<observational_model>Other</observational_model>
<time_perspective>Prospective</time_perspective>
</study_design_info>
<primary_outcome>
<measure>soluble L-selectin</measure>
<time_frame>between baseline and 3 months</time_frame>
<description>Change in soluble L-selectin between baseline and 3 mo after STEMI in the placebo vs. colchicine groups.</description>
</primary_outcome>
<secondary_outcome>
<measure>Other soluble markers of neutrophil activity</measure>
<time_frame>between baseline and 3 months</time_frame>
<description>Other markers of neutrophil activity will be evaluated at baseline and 3 months after STEMI (myeloperoxidase, matrix metalloproteinase-9, neutrophil gelatinase-associated lipocalin, neutrophil elastase, intercellular/vascular cellular adhesion molecules)</description>
</secondary_outcome>
<secondary_outcome>
<measure>Markers of systemic inflammation</measure>
<time_frame>between baseline and 3 months</time_frame>
<description>Markers of systemic inflammation will be evaluated at baseline and 3 months after STEMI (high sensitive CRP, IL-1β)</description>
</secondary_outcome>
<secondary_outcome>
<measure>Neutrophil-driven responses that may further propagate injury</measure>
<time_frame>between baseline and 3 months</time_frame>
<description>Neutrophil-driven responses that may further propagate injury will be evaluated at baseline and 3 months after STEMI (neutrophil extracellular traps, neutrophil-derived microparticles)</description>
</secondary_outcome>
<number_of_groups>2</number_of_groups>
<enrollment type="Anticipated">670</enrollment>
<condition>Neutrophils.Hypersegmented &#X7C; Bld-Ser-Plas</condition>
<condition>STEMI - ST Elevation Myocardial Infarction</condition>
<arm_group>
<arm_group_label>Colchicine</arm_group_label>
</arm_group>
<arm_group>
<arm_group_label>Placebo</arm_group_label>
</arm_group>
<intervention>
<intervention_type>Drug</intervention_type>
<intervention_name>Colchicine Pill</intervention_name>
<description>Participants in the main CLEAR SYNERGY trial are randomized to colchicine/spironolactone versus placebo in a 2x2 factorial design. The substudy is interested in the evaluation of biospecimens obtained from patients in the colchicine vs placebo group.</description>
<arm_group_label>Colchicine</arm_group_label>
<arm_group_label>Placebo</arm_group_label>
</intervention>
<eligibility>
<study_pop>
<textblock>
Patients who are randomized to the drug RCT portion of the CLEAR SYNERGY (OASIS 9) trial
</textblock>
</study_pop>
<sampling_method>Non-Probability Sample</sampling_method>
<criteria>
<textblock>
Inclusion Criteria:
</textblock>
</criteria>
<gender>All</gender>
<minimum_age>19 Years</minimum_age>
<maximum_age>110 Years</maximum_age>
<healthy_volunteers>No</healthy_volunteers>
</eligibility>
<overall_official>
<last_name>Binita Shah, MD</last_name>
<role>Principal Investigator</role>
<affiliation>NYU School of Medicine</affiliation>
</overall_official>
<overall_contact>
<last_name>Fatmira Curovic</last_name>
<phone>646-501-9648</phone>
<email>fatmira.curovic@nyumc.org</email>
</overall_contact>
<overall_contact_backup>
<last_name>Binita Shah, MD</last_name>
</overall_contact_backup>
<location>
<facility>
<name>NYU School of Medicine</name>
<address>
<city>New York</city>
<state>New York</state>
<zip>10016</zip>
<country>United States</country>
</address>
</facility>
<status>Recruiting</status>
<contact>
<last_name>Fatmira Curovic</last_name>
<phone>646-501-9648</phone>
<email>fatmira.curovic@nyumc.org</email>
</contact>
<contact_backup>
<last_name>Binita Shah, MD</last_name>
</contact_backup>
</location>
<location_countries>
<country>United States</country>
</location_countries>
<verification_date>September 2019</verification_date>
<study_first_submitted>March 12, 2019</study_first_submitted>
<study_first_submitted_qc>March 12, 2019</study_first_submitted_qc>
<study_first_posted type="Actual">March 14, 2019</study_first_posted>
<last_update_submitted>September 10, 2019</last_update_submitted>
<last_update_submitted_qc>September 10, 2019</last_update_submitted_qc>
<last_update_posted type="Actual">September 12, 2019</last_update_posted>
<responsible_party>
<responsible_party_type>Principal Investigator</responsible_party_type>
<investigator_affiliation>NYU Langone Health</investigator_affiliation>
<investigator_full_name>Binita Shah</investigator_full_name>
<investigator_title>Assistant Professor of Medicine</investigator_title>
</responsible_party>
<condition_browse>
<!-- CAUTION: The following MeSH terms are assigned with an imperfect algorithm -->
<mesh_term>Myocardial Infarction</mesh_term>
<mesh_term>ST Elevation Myocardial Infarction</mesh_term>
<mesh_term>Infarction</mesh_term>
</condition_browse>
<intervention_browse>
<!-- CAUTION: The following MeSH terms are assigned with an imperfect algorithm -->
<mesh_term>Colchicine</mesh_term>
</intervention_browse>
<patient_data>
<sharing_ipd>No</sharing_ipd>
</patient_data>
<!-- Results have not yet been posted for this study -->
</clinical_study>

View File

@@ -0,0 +1,822 @@
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",
["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",["a",[]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]
]]]]]]]]]]]]

View File

@@ -0,0 +1,822 @@
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":
{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{"a":{}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}
}}}}}}}}}}}}

View File

@@ -0,0 +1,28 @@
{
"foo":
[
"bar",
"baz"
],
"": 0,
"a/b": 1,
"c%d": 2,
"e^f": 3,
"g|h": 4,
"i\\j": 5,
"k\"l": 6,
" ": 7,
"m~n": 8,
"obj" : {
"key" : "value",
"other~key" : {
"another/key" : [
"val"
]
},
"" : {
"" : "empty key of an object with an empty key",
"subKey" : "Some other value"
}
}
}