Compare commits

...

446 Commits

Author SHA1 Message Date
Sean Leary
78137d389d
Merge pull request #1001 from marilynel/master
addressing sonarqube concerns in JSONObject
2025-07-31 20:54:08 -05:00
marilynel
38c3a0bb3f more sonarcube issues 2025-07-27 11:45:07 -08:00
marilynel
ebd9a17a3b addressing minor sonarqube concerns 2025-07-27 11:26:50 -08:00
Sean Leary
82432f0245
Merge pull request #1000 from marilynel/master
fixing sonarcube issues
2025-07-23 20:46:33 -05:00
marilynel
e762629bcc oops one more sonarcube issue lol 2025-07-20 12:04:51 -08:00
marilynel
7fc41a6c0e addressing cognitive complextity 2025-07-20 11:58:30 -08:00
marilynel
d5d82cdb87 fixing sonarcube issues 2025-07-20 11:31:29 -08:00
Sean Leary
0a9364e920
Merge pull request #999 from marilynel/master
fixed some strict mode issues
2025-07-16 20:12:57 -05:00
marilynel
c91b728386 oops forgot null 2025-07-13 12:52:42 -08:00
marilynel
fdaeb486ed fixed some strict mode issues 980 2025-07-13 12:41:17 -08:00
Sean Leary
f0a78aff61
Merge pull request #995 from marilynel/master
Fix regression XML parsing null with keepStrings
2025-07-09 20:18:48 -05:00
Sean Leary
a79e8a15e5
Merge pull request #994 from stleary/tech-debt-20250701
tech-debt-25250701
2025-07-08 11:04:29 -05:00
marilynel
7bb3df8ebf added test details 2025-07-06 12:41:44 -08:00
marilynel
3dce55794f fixed keeping null as string 2025-07-06 12:37:05 -08:00
Sean Leary
d7593fb808
Merge pull request #992 from surajdm123/add-tests
Added JUnit test cases for HTTPTokener
2025-07-06 08:27:59 -05:00
Sean Leary
1eed44a59e
Merge pull request #993 from surajdm123/add-tests-2
Added JUnit tests for XMLTokenerTest
2025-07-06 08:27:20 -05:00
Sean Leary
7eccadefcd
Merge pull request #991 from Simulant87/update-codeql-v3
update CodeQL to v3
2025-07-04 16:39:18 -05:00
Sean Leary
7b0d1942b4 tech-debt-25250701 add jacoco to gradle build, refactor JSONObject to restore performance 2025-07-03 20:39:13 -05:00
surajdm123
a729c2077a Added JUnit tests for XMLTokenerTest 2025-07-03 01:23:46 -07:00
surajdm123
7ac773be72 Added JUnit test cases for HTTPTokener 2025-07-03 00:58:15 -07:00
Simulant
7da120e631 update CodeQL to v3 2025-07-01 22:57:36 +02:00
Sean Leary
197afddbfb
Merge pull request #990 from Simulant87/984-refactor-cognitive-complexity-populateMap
Refactor JSONObject populateMap() per SonarQube
2025-07-01 07:13:18 -05:00
Sean Leary
1bdaacc8b0
Merge pull request #989 from AlexCai2019/master
Minor refactoring
2025-06-27 20:17:17 -05:00
Alex Cai
c882783d58
Format line 2755 in JSONObject.java 2025-06-27 01:44:27 +08:00
Simulant
5063d314a5 #984 extract method for annotation value check 2025-06-25 23:08:01 +02:00
Simulant
916fba5d39 #984 extract methods reducing cognitive complexity
for JSONObject#populateMap
2025-06-25 23:00:07 +02:00
AlexCai2019
aac376f305 Remove a redundant condition and an empty string
Remove "NULL.equals(object)" on line 2756 of JSONObject.java since line 2752 has already tested it.
Remove the empty string on line 249 of JSONPointer.java.
2025-06-23 01:31:51 +08:00
Sean Leary
32e56da786
Merge pull request #988 from stleary/remove-unused-code-jsonobject
removed unused method from jsonobject
2025-06-16 11:34:35 -05:00
Sean Leary
50330430ce remove-unused-code-jsonobject removed unused method from jsonobject 2025-06-07 16:15:43 -05:00
Sean Leary
f1935f5254
Merge pull request #987 from AlexCai2019/master
Use constant.equals()
2025-06-07 09:59:48 -05:00
AlexCai2019
e800cc349f Use constant.equals()
There are some equals() that are not constant.equals(variable), but variable.equals(constant)
2025-06-05 02:15:49 +08:00
Sean Leary
72a1a48173
Merge pull request #983 from harshith8854/master
Use JSONParserConfiguration to decide on serializing Null fields into JSONObject #982
2025-05-31 09:58:46 -05:00
hboggavarapu
a381060f81 Add testcase to assert Null fields serialization without JSONParserConfiguration 2025-05-24 21:54:12 +05:30
hboggavarapu
dadc3e59dc Use JSONParserConfiguration to decide on serializing null fields into JSONObject #982 2025-05-23 17:57:08 +05:30
Sean Leary
24fafcffeb
Merge pull request #981 from stleary/pre-release-20250517
pre-release-20250517 prep for next release
2025-05-17 07:44:38 -05:00
Sean Leary
418d5e9973 pre-release-20250517 prep for next release 2025-05-17 07:41:21 -05:00
Sean Leary
82a02d879e
Merge pull request #969 from marilynel/master
refactored large test for strict mode
2025-04-18 11:48:25 -05:00
marilynel
2184ef34d1 refactored large test for strict mode 2025-04-13 11:35:45 -07:00
Sean Leary
8e65eaa992
Merge pull request #968 from marilynel/master
Update keepStrings behavior to reflect changes in keepBooleanAsString, keepNumberAsString
2025-04-10 11:56:36 -05:00
marilynel
74439cf696 Merge branch 'master' of https://github.com/marilynel/JSON-java 2025-04-06 11:05:02 -07:00
marilynel
53da5ce2a9 adjusted keepstrings behavior to reflect changes in keepBooleanAsString & keepNumberAsString 2025-04-06 11:04:33 -07:00
Sean Leary
2e9ad6ff5a
Merge pull request #966 from marilynel/master
granular flags to control for keeping boolean or number values as strings
2025-04-04 07:40:55 -05:00
marilynel
8dbf03e76b work on issue 841 2025-03-30 12:21:44 -07:00
Sean Leary
4917e3579d
Merge pull request #962 from marilynel/master
Fix: handles edge case 'no \n at end of csv dataset + empty last column'
2025-03-26 20:24:01 -05:00
marilynel
45ec164faa Merge branch 'master' of https://github.com/marilynel/JSON-java 2025-03-23 10:27:57 -07:00
Sean Leary
d4c5136c21
Merge pull request #961 from effad/master
Option to store null value in JSONObject when parsing a map
2025-03-23 10:21:53 -05:00
Robert Lichtenberger
fd0cca3586 Fix cloning of parser configuration. 2025-03-21 10:12:20 +01:00
Robert Lichtenberger
50a5ce256b
Merge branch 'stleary:master' into master 2025-03-21 07:27:12 +01:00
Robert Lichtenberger
1afd7cd6bc Use better name for parser configuration option, fix API comment. 2025-03-21 07:25:37 +01:00
Sean Leary
7751b397bf
Merge pull request #960 from marilynel/master
Updated configuration to enable strictMode unit testing with Maven
2025-03-19 11:39:35 -05:00
Robert Lichtenberger
5d1c789490 Add test for JSONArray from Java collection. 2025-03-19 08:10:33 +01:00
Robert Lichtenberger
d1327c2da3 Allow to configure Java null handling. 2025-03-19 07:59:57 +01:00
marilynel
b2943b8fd0 fixed issue #943 Csv parsing skip last row if last line is missing newline 2025-03-16 12:50:58 -07:00
Marilyn Leary
628d8c42d9
Merge branch 'stleary:master' into master 2025-03-16 10:38:04 -07:00
marilynel
76ee4312b3 readme edit 2025-03-16 10:36:24 -07:00
marilynel
4a662316f7 edited pom.xml for mvn testing with strict mode 2025-03-16 10:33:14 -07:00
Sean Leary
6452a6f38d
Merge pull request #955 from marilynel/master
Add testWithStrictMode option to build.gradle
2025-03-05 20:30:24 -06:00
marilynel
ae4f4afcc7 dont mess with my line 2025-03-02 11:08:00 -08:00
marilynel
8a86894c63 test with strict mode enabled and fixed 2025-03-02 11:02:27 -08:00
marilynel
f30167e7c0 tests seem to be working, run with strictMode = fale then true 2025-02-23 22:00:22 -08:00
Sean Leary
75e5a3d646
Merge pull request #951 from marilynel/master
Fixing and updating unit tests for default strictMode
2025-02-21 07:37:47 -06:00
marilynel
3919abd69a optimized unit tests to respond accurately to default strictMode 2025-02-15 12:30:12 -08:00
marilynel
f112a091aa fixed failing unit tests in strict mode, issue 940 2025-02-15 12:03:03 -08:00
Sean Leary
42afb34045
Merge pull request #949 from marilynel/master
deprecated unnecessary setter method
2025-02-15 09:59:56 -06:00
Marilyn Leary
a746322e57
Merge branch 'stleary:master' into master 2025-02-09 19:36:46 -08:00
Sean Leary
c524cd17a0
Merge pull request #950 from stleary/upgrade-upload-artifact-in-pipeline
upgrade-upload-artifact-in-pipeline update from v3 to v4
2025-02-09 15:01:26 -06:00
Sean Leary
52f249c71e upgrade-upload-artifact-in-pipeline update from v3 to v4 2025-02-09 14:47:18 -06:00
marilynel
1689fc28cf deprecated unnecessary setter method 2025-02-09 11:13:22 -08:00
Sean Leary
22f8290840
Merge pull request #948 from Simulant87/947-JSONTokener-configuration-ignored
use JSONParserConfiguration of JSONTokener in JSONObject and JSONArray constructor instead of creating a new one
2025-01-19 09:09:42 -06:00
Sean Leary
8b857da467
Merge pull request #946 from Simulant87/928-javadoc-warning-JSONParserConfiguration
#928 add missing javaDoc for JSONParserConfiguration
2025-01-19 09:07:53 -06:00
Sean Leary
07b1291448
Merge pull request #942 from michael-ameri/fix-clone
add missing fields when cloning JSONParserConfiguration
2025-01-19 09:06:21 -06:00
Sean Leary
1d81e8879a
Merge pull request #938 from Simulant87/remove-references
Strict mode unit tests
2025-01-19 09:03:47 -06:00
Simulant
4c873a1db4 #947 use JSONParserConfiguration of JSONTokener in JSONObject and JSONArray constructor 2025-01-15 21:41:01 +01:00
Simulant
6631b80e8f #947 add new failing tests with JSONTokener having strict mode configuration 2025-01-15 21:38:46 +01:00
Simulant
9218f28db8 #928 add missing java dock for JSONParserConfiguration
(cherry picked from commit afd9a6fbb70cd66d440a53458c186d11377bd2ff)
2025-01-15 21:02:25 +01:00
Simulant
94341cd663 Revert "#928 add missing java dock for JSONParserConfiguration"
This reverts commit afd9a6fbb70cd66d440a53458c186d11377bd2ff.
2025-01-15 20:58:45 +01:00
Simulant
afd9a6fbb7 #928 add missing java dock for JSONParserConfiguration 2025-01-15 20:55:13 +01:00
Simulant87
54470e6b56
Merge branch 'stleary:master' into remove-references 2025-01-15 20:48:24 +01:00
Sean Leary
dde9d7eceb
Merge pull request #931 from stleary/remove-duplicate-moditect
remove-duplicate-moditect: from pom.xml
2025-01-15 07:46:37 -06:00
Sean Leary
8c427d9101
Merge pull request #937 from michael-ameri/remove-references
Update JSONParserConfiguration usage in JSONTokener, JSONArray, and JSONObject
2025-01-15 07:45:50 -06:00
Michael Ameri
4bbbe77446 add missing fields when cloning 2025-01-12 23:03:31 +01:00
Simulant
ad44a9274c add new test cases for JSONObject and JSONArray Constructors with JSONTokener and strict mode 2025-01-11 21:43:04 +01:00
Simulant
3b7ba07531 add test for invalid input on JSONTokener 2025-01-11 21:40:41 +01:00
Simulant
215f4268bf add Javadoc and rename parameters to speaking variable names 2025-01-11 21:35:36 +01:00
Michael Ameri
ca1c6830c9 remove field references to JSONTokener and JSONParserConfiguration in JSONArray
and JSONObject
2025-01-10 18:05:27 +01:00
Sean Leary
2e153737b1 remove-duplicate-moditect: from pom.xml 2025-01-08 07:33:37 -06:00
Sean Leary
391c86931b
Merge pull request #930 from stleary/pre-release-20250107
pre-release-20250107
2025-01-07 15:40:58 -06:00
Sean Leary
ed8c73964a pre-release-20250107 2025-01-07 15:30:43 -06:00
Sean Leary
324090a876
Merge pull request #929 from stleary/restore-moditect-pom.xml
restore-moditect-pom.xml restore plugin
2025-01-07 15:24:21 -06:00
Sean Leary
41c6e9e81e restore-moditect-pom.xml restore plugin 2025-01-07 07:47:46 -06:00
Sean Leary
0e60592bdb
Merge pull request #924 from stleary/pre-release-20241224
pre-release-20241224: updates for next release
2024-12-24 08:27:15 -06:00
Sean Leary
4cd70cf9d9 pre-release-20241224: updates for next release 2024-12-24 08:19:27 -06:00
Sean Leary
ac40a6faa3
Merge pull request #921 from stleary/restore-jsonparserconfiguration
Restore strict mode text parsing
2024-12-21 10:11:03 -06:00
Sean Leary
2dcef89a6f Code review action items - add comments and consistent error messages for strict mode 2024-12-21 09:50:52 -06:00
Sean Leary
d3c7eaf17e restore-jsonparserconfiguration: fix unit tests to work when strictMode default is true 2024-12-15 13:18:39 -06:00
Sean Leary
09536cd6c8 restore-jsonparserconfiguration: add jsonobject strict tests. Detect semicolon instead of colon separator in object 2024-12-15 10:38:54 -06:00
Sean Leary
1f0729cadb restore-jsonparserconfiguration: strict mode initial attempt. Still missing all JSONObject test cases and strict mode sanity check. Might be able to simplify implementation a bit more 2024-12-14 14:40:40 -06:00
Sean Leary
80b2672f77 restore-jsonparserconfiguration: clean up some whitespace 2024-12-14 10:07:26 -06:00
Sean Leary
1f308db7c4 restore-jsonparserconfiguration: Restore methods to be used for strict mode 2024-12-14 10:01:27 -06:00
Sean Leary
2ee5bf13f4
Merge pull request #907 from hexetia/fix-901
Fix a bug when calling JSONArray.addAll() with Collection as Object
2024-11-13 16:29:34 -06:00
Sean Leary
e7e52dad82
Merge pull request #894 from stleary/update-jsonpath
update-jsonpath: update jsonpath from 2.4.0 to 2.9.0
2024-11-10 17:43:33 -06:00
Sean Leary
39ee5e092f
Merge pull request #911 from stleary/revert-strict-mode-for-now
Revert strict mode
2024-11-10 17:41:11 -06:00
Sean Leary
215ec9bb9c Revert "Merge pull request #877 from rikkarth/feat/871-strictMode"
This reverts commit d02ac0f2a35f8c8ba56230bc4b67275010d4d617, reversing
changes made to cfd47615d0b9a2392945d198d7fd820bbbc17437.
2024-11-03 09:50:08 -06:00
Sean Leary
61dc2644d8 Revert "Merge pull request #886 from Simulant87/884-strictmode-javadoc"
This reverts commit 8983ca6da195bd8b7eb9e6655e97a2490d4afa2e, reversing
changes made to d02ac0f2a35f8c8ba56230bc4b67275010d4d617.
2024-11-03 09:49:50 -06:00
Sean Leary
ab1b9a3459 Revert "Merge pull request #888 from rikkarth/fix/887"
This reverts commit 14f71274f79ac50afb316845539f4195facc33ee, reversing
changes made to 054786e300d0fc38f0cf7fc0f2db4d9b39cb6443.
2024-11-03 09:49:23 -06:00
Lucas Nascimento
14e9cdc485
fix(#901): add the jsonparserConfiguration param to avoid a stackoverflow error 2024-10-05 11:43:00 -03:00
Lucas Nascimento
0d71dcf713
test(#901): call JsonArray.putAll with a casted list as object 2024-10-05 11:39:26 -03:00
Sean Leary
14f71274f7
Merge pull request #888 from rikkarth/fix/887
fix(#887): complete strictMode for JSONArray
2024-05-20 20:18:49 -05:00
rikkarth
a8ab79e3f3
chore(#887): JSONParserConfiguration strictMode true flag cleanup 2024-05-19 14:41:16 +01:00
Sean Leary
783577be19 update-jsonpath: update jsonpath from 2.4.0 to 2.9.0 2024-05-14 20:48:33 -05:00
Sean Leary
054786e300
Merge pull request #889 from kaiyaok2/fix_nio_tests
Fixed non-idempotent unit tests in `JSONObjectTest`
2024-05-03 12:15:52 -05:00
rikkarth
48dfeb84b0
fix(#887): unit tests, uncommented tests after fix 2024-04-28 23:52:53 +01:00
rikkarth
1ae43bdb90
fix(#887): regressions, unit tests
- JSONArray now evaluates EOF accordingly for empty Array inputs.
- JSONTokener fixed indentation
- externalized two JSONMLTest cases
2024-04-28 23:30:05 +01:00
Sean Leary
cf00ef3e8a fixes the broken JSONTokenerTest cases 2024-04-28 12:47:51 -05:00
Sean Leary
0180bd90f0 fixes the broken XMLTest cases 2024-04-28 12:41:58 -05:00
Sean Leary
fa2f3402d6 fixes the broken XMLConfigurationTest cases 2024-04-28 11:33:31 -05:00
Sean Leary
f4944fbf1e fixes the broken JSONMLTest cases 2024-04-28 11:28:38 -05:00
Sean Leary
1881cbe91a fixes the broken CDLTest cases 2024-04-28 11:23:01 -05:00
Sean Leary
209837357b fixes the broken JSONObjectTest cases 2024-04-28 11:03:24 -05:00
Sean Leary
d1fd901bdb fixes the JSONObjectNumberTest cases 2024-04-28 10:47:40 -05:00
Sean Leary
6529a7e536 fixes the broken JSONArrayTest cases 2024-04-28 10:45:23 -05:00
Sean Leary
4319b71934 force strict mode to expose failing tests 2024-04-28 10:37:36 -05:00
rikkarth
1e3f37be98
feat(#877): add additional validation, test case 2024-04-27 22:37:21 +01:00
rikkarth
7a8c21621c
fix(#877): adaptation for java 6 compatibility 2024-04-27 22:16:38 +01:00
rikkarth
9216a19366
feat(#877): improved JSONArray and JSONTokener logic
JSONArray construction improved to recursive validation
JSONTokener implemented smallCharMemory and array level for improved validation
Added new test cases and minor test case adaption
2024-04-27 22:14:35 +01:00
Kaiyao Ke
b6e347d7f8 fixed non-idempotent unit tests 2024-04-26 01:01:21 -05:00
rikkarth
879579d3bb
chore(#887): signature minor edit 2024-04-23 20:54:20 +01:00
rikkarth
898dd5a39d
fix(#887): allow null value strict mode 2024-04-23 20:52:02 +01:00
rikkarth
ce13ebd5fe
chore(#887): clean up parsedUnquotedText implementation 2024-04-23 20:42:11 +01:00
rikkarth
7cc19483fb
fix(#887): regression parsing array with non-string and boolean values 2024-04-23 19:06:27 +01:00
rikkarth
0bace72ced
fix(#887): small typo 2024-04-21 22:09:05 +01:00
rikkarth
03def9c7fc
Merge branch 'master' of github.com:stleary/JSON-java into fix/887 2024-04-21 22:05:56 +01:00
rikkarth
3dcd5b2fab
fix(#887): double array breaking JSONTokener.nextValue
change(#887): input validation
2024-04-21 11:03:15 +01:00
Sean Leary
8983ca6da1
Merge pull request #886 from Simulant87/884-strictmode-javadoc
add javadoc for strictmode
2024-04-15 17:00:32 -05:00
rikkarth
ce074e9f9a
fix(#887): corrected small typo 2024-04-14 23:23:06 +01:00
rikkarth
fe597d296e
fix(#887): complete strictMode for JSONArray 2024-04-14 23:11:17 +01:00
Simulant87
5bd4257c54
add javadoc for strictmode 2024-04-12 15:30:41 +02:00
Sean Leary
d02ac0f2a3
Merge pull request #877 from rikkarth/feat/871-strictMode
StrictMode Implementation for JSONArray
2024-04-10 10:27:09 -05:00
Sean Leary
cfd47615d0
Update README.md to fix the download-jar link
This got accidentally left out in the last release
2024-04-07 12:33:33 -05:00
rikkarth
3200275881
change(stleary#871-strictMode): cleanup
chore: removed PII from json sample
chore: JSONParserConfiguration.java cleanup
chore: JSONTokener.java nextValue partial rollback
2024-04-07 10:26:28 +01:00
rikkarth
d92d62afc2
Merge branch 'master' into feat/871-strictMode 2024-03-30 22:03:57 +00:00
rikkarth
46534b56ad
feat(#871-strictMode): removed allowSingleQuotes
test(#871-strictMode): adjusted related tests, add more test cases for non-compliant quotes in strict mode
2024-03-30 18:44:51 +00:00
Sean Leary
87406e4db1
Merge pull request #879 from Simulant87/add-syntax-error-details
extend syntax error information
2024-03-30 09:42:27 -05:00
rikkarth
c0918c2428
feat(#871-strictMode): add allowSingleQuote option, add enhancements and simplification 2024-03-30 11:06:30 +00:00
rikkarth
d2cb38dba7
feat(#871-strictMode): added ORIGINAL implementation to JSONParserConfiguration 2024-03-30 10:26:44 +00:00
rikkarth
4929fc99c1
test(#871-strictMode): added more test cases, improved existing ones 2024-03-30 10:15:47 +00:00
rikkarth
372f5caac4
feat(#871-strictMode): enhanced and simplified strictMode logic 2024-03-30 10:15:10 +00:00
Simulant
0fcf352848 Revert "explain position information numbers in syntax exception"
This reverts commit d69d5e284b3ee797f3950d80eb9dfc571a944284.
2024-03-27 20:36:35 +01:00
Simulant87
78cdb3d0d6
fix wrong comment update 2024-03-23 22:07:05 +01:00
Simulant87
7324cc0b26
fix wrong comment update 2024-03-23 22:06:20 +01:00
Simulant87
75a34a246f
fix wrong comment update 2024-03-23 22:05:51 +01:00
Simulant87
78151beea2
fix wrong comment update 2024-03-23 22:05:27 +01:00
Simulant87
ccb4a9b95f
fix wrong comment update 2024-03-23 22:04:53 +01:00
Simulant87
4e39d8ccf2
fix wrong comment update 2024-03-23 22:03:57 +01:00
Simulant
d69d5e284b explain position information numbers in syntax exception 2024-03-23 22:02:54 +01:00
Simulant
f1c9d0787b add test cases for extended syntax error exception messages 2024-03-23 21:49:58 +01:00
rikkarth
49de92224d
chore(#871-strictMode): fix small spacing typo 2024-03-22 18:42:49 +00:00
rikkarth
d335447ab4
test(#871-strictMode): add two more test which validate error correctness 2024-03-22 18:28:56 +00:00
Simulant
6c160b7d1a leave JSONTokener.toString unchanged 2024-03-22 12:08:06 +01:00
Simulant
30dc22790c extend syntax error information 2024-03-22 12:02:09 +01:00
rikkarth
8f66865e0a
Merge branch 'master' into feat/871-strictMode 2024-03-21 08:08:15 +00:00
Sean Leary
45dede448c
Merge pull request #867 from Simulant87/863-improve-toString-performance-StringBuilderWriter
Improve toString Performance: Use StringBuilderWriter for toString methods
2024-03-20 16:56:33 -05:00
Simulant87
6aed1cfeb6
fix typo 2024-03-18 23:07:22 +01:00
rikkarth
3672b5e158
chore(#871-strictMode): reverted unrelated changes 2024-03-17 15:20:38 +00:00
rikkarth
f3b3491f4d
chore(#871-strictMode): reverted refactor in JSONTokener 2024-03-16 01:13:52 +00:00
rikkarth
e2fe14d951
fix(#871-strictMode): replaced stream with conventional loop for 1.6 compatibility 2024-03-16 00:48:58 +00:00
rikkarth
0ff368ca07
chore(#871-strictMode): corrected small syntax typo in unit test 2024-03-15 23:13:21 +00:00
rikkarth
c51efe8b08
docs(#871-strictMode): JSONArray constructor JavaDoc update 2024-03-15 22:55:09 +00:00
rikkarth
e67abb3842
feat(#871-strictMode): improved validation, strict mode for quotes implementation 2024-03-15 22:28:31 +00:00
rikkarth
c140e91bb8 test(#871-strictMode): strict mode false initial implementation 2024-03-15 01:23:20 +00:00
rikkarth
63e8314deb feat(#871-strictMode): strictMode JSONArray initial implementation
test(#871-strictMode): initial test implementation
2024-03-15 00:45:32 +00:00
rikkarth
dcbbccc76c feat(#871-strictMode): strictMode configuration add to JSONParserConfiguration
docs(#871-strictMode): add javadoc
2024-03-15 00:19:25 +00:00
Simulant
b75da07545 #863 move instanceof Enum check back to original position 2024-03-10 23:21:47 +01:00
Simulant
6c35b08ad6 #863 make StringBuilderWriter public and move test 2024-03-10 23:20:09 +01:00
Simulant
60090a7167 add a test case for an enum implementing JSONString
(cherry picked from commit d17bbbd4174b3d84f70a6f0fdce9edc10d846a1a)
2024-03-10 21:13:54 +01:00
Simulant
0c5cf18255 Revert "#863 improve performance of JSONTokener#nextString"
This reverts commit 63625b3c622407273d2654660be7659ac5d74db7.
2024-03-10 21:12:28 +01:00
Simulant
5974fc1a38 Merge branch 'master' into 863-improve-toString-performance-StringBuilderWriter 2024-03-10 21:10:21 +01:00
Simulant
a3f15e5883 Revert "#863 replace usage of back() method in JSONObject parsing"
This reverts commit 5407423e439dfb4095e371666a65cf4f6603606d.
2024-03-10 21:08:31 +01:00
Simulant
045324ab42 Revert "#863 replace short switch statements with if-else"
This reverts commit c010033591c192a0821bdd8fe23bc61cdc6fe738.
2024-03-10 21:08:10 +01:00
Simulant
eda08415ca Revert "#863 increase compiler stack size on build pipeline"
This reverts commit 6660e4091569fc48e582ab77c6626491f8bab8db.
2024-03-10 21:05:22 +01:00
Sean Leary
48c092acfb
Merge pull request #876 from stleary/remove-jsonparserconfig-ctor
remove-jsonparserconfig-ctor - just use withOverwriteDuplicateKey()
2024-03-09 09:22:39 -06:00
Sean Leary
dab29ec1d5 remove-jsonparserconfig-ctor - just use the withOverwriteDuplicateKey() method 2024-03-09 09:15:53 -06:00
Sean Leary
712859d771
Merge pull request #857 from XIAYM-gh/master
Implemented custom duplicate key handling (#840)
2024-03-09 09:11:09 -06:00
XIAYM
05b0897f41
Merge branch 'stleary:master' into master 2024-03-09 22:19:30 +08:00
Simulant
c010033591 #863 replace short switch statements with if-else 2024-03-05 22:12:57 +01:00
Simulant
5407423e43 #863 replace usage of back() method in JSONObject parsing 2024-03-05 22:11:24 +01:00
Simulant
63625b3c62 #863 improve performance of JSONTokener#nextString
replacing a switch-case statement with few branches
by if-else cases
2024-03-05 09:43:54 +01:00
Sean Leary
f9b5587c87
Merge pull request #875 from stleary/20240303-pre-release-updates
20240303-pre-release-updates updates for release
2024-03-03 08:55:13 -06:00
Sean Leary
3d69990ab5 20240303-pre-release-updates updates for release 2024-03-03 08:47:53 -06:00
Sean Leary
ba05e1a98c
Merge pull request #874 from stleary/pipeline-updates
Deployment and Pipeline action updates
2024-03-03 08:02:03 -06:00
Sean Leary
390d442054 pipeline-updates - remove deployment.yml for now, will restore after setting up secrets 2024-03-02 10:00:13 -06:00
Sean Leary
3eb8a62af6 pipeline-updates - space after # char? 2024-03-02 09:57:40 -06:00
Sean Leary
989cdb61bc pipeline-updates - do not build in parallel 2024-03-02 09:15:32 -06:00
Sean Leary
8de0628bd1 pipeline-updates - disable deployment.yml workflow for now (it's not set up in secrets yet) 2024-03-02 08:55:24 -06:00
Sean Leary
569be9d19e Merge branch 'master' into pipeline-updates 2024-03-02 08:34:10 -06:00
Sean Leary
3f97826462
Merge pull request #869 from stleary/revert-recent-objLong-getLong-changes
Revert recent obj long get long changes
2024-02-28 09:52:04 -06:00
Sean Leary
d520210ea2 Added one more example to XMLTest clarifyCurrentBehavior() 2024-02-25 10:45:34 -06:00
Simulant
f38452a00c add a comment explaining the ordering
(cherry picked from commit df0e3e9ab73d99f1256055a17bd86c8a1a000b59)
2024-02-25 09:50:26 +01:00
Simulant
4f456d9432 #863 fix changed behaviour of changing order in writeValue with JSONString 2024-02-25 09:42:06 +01:00
Sean Leary
898288810f add unit tests to clarify current behavior for JSONObject and XML 2024-02-24 21:07:12 -06:00
Simulant
d878c38d40 #863 reorder instanceof checks by assumed frequency 2024-02-24 22:36:14 +01:00
Simulant
e2194bc190 #863 undo wrong optimisation, fixing failing test 2024-02-24 21:35:29 +01:00
Simulant
d672b44a25 #863 add StringBuilderWriter unit test 2024-02-24 21:29:28 +01:00
Simulant
06778bd2d9 #863 compute initial capacity for StringBuilderWriter 2024-02-24 21:21:06 +01:00
Sean Leary
771c82c4eb backing out recent changes to optLong, getLong. See #868 2024-02-24 13:07:51 -06:00
Simulant
6660e40915 #863 increase compiler stack size on build pipeline 2024-02-23 22:02:35 +01:00
Simulant
0ff635c456 #863 improve formatting 2024-02-23 21:56:40 +01:00
Simulant
7c7a98da71 #863 use StringBuilderWriter to toString methods
resulting in a faster toString generation.
2024-02-23 21:48:25 +01:00
Sean Leary
d36066cf82
Merge pull request #860 from jscrdev/fixed-javadocs2
Added missing Javadocs for Java 21
2024-02-22 20:18:34 -06:00
XIAYM-gh
af8cb376c2 Add tests (+ fix bugs) & missing javadoc 2024-02-19 18:58:25 +08:00
Sean Leary
c1107fa987 pipeline-updates: Java 11 intermittent fail - try separate build 2024-02-18 16:17:41 -06:00
Sean Leary
cd631d970e pipeline-updates: Java 11 intermittent fail - try an earlier release (there is no later release 2024-02-18 15:54:29 -06:00
Sean Leary
f0289413d6 pipeline-updates: Java 11 intermittent fail - try increasing stack size 2024-02-18 15:45:13 -06:00
Sean Leary
b4b39bb441 pipeline-updates: Java 11 intermittent test failures, try not running in parallel 2024-02-18 15:29:44 -06:00
XIAYM
6dc1ed0a02
Merge branch 'stleary:master' into master 2024-02-18 11:07:09 +08:00
Valentyn Kolesnikov
86253211c2 Added missing Javadocs for Java 21 2024-02-18 04:20:33 +02:00
Sean Leary
77c899d325
Merge pull request #858 from stleary/cleanup-after-commit
cleanup-after-commit for #854 and #856
2024-02-17 16:23:51 -06:00
XIAYM
b314611230
Merge branch 'stleary:master' into master 2024-02-15 09:51:56 +08:00
XIAYM-gh
cb2c8d3962 Revert some unnecessary changes (mentioned in #840) 2024-02-14 17:53:58 +08:00
Sean Leary
f164b8c597 cleanup-after-commit reverted pom.xml version 8 change and tabs in cdl. Updated JavaDocs in cdl 2024-02-13 20:08:54 -06:00
Sean Leary
6358b7f681
Merge pull request #854 from jscrdev/fixed-javadocs
Enhanced documentation for Java classes
2024-02-13 09:05:48 -06:00
XIAYM-gh
21a9fae7b0 Try making java 6 & old version javadoc generator compatible 2024-02-13 22:33:30 +08:00
Sean Leary
8550175556
Merge pull request #856 from michael-ameri/custom-delimiter
add ability for custom delimiters
2024-02-13 08:21:43 -06:00
XIAYM-gh
10514e48cb Implemented custom duplicate key handling
- Supports: throw an exception (by default), ignore, overwrite & merge into a JSONArray
 - With tests, 4/4 passed.
2024-02-13 18:56:10 +08:00
mameri
72214f1b43 add ability for custom delimiters 2024-02-09 11:52:18 +01:00
Valentyn Kolesnikov
99c84fdf3a Enhanced documentation for Java classes 2024-02-07 14:43:44 +02:00
Sean Leary
010e83b925
Update RELEASES.md for release 20240205 2024-02-05 20:44:18 -06:00
Sean Leary
9865dbbebe
Update pom.xml for release 20240205 2024-02-05 20:23:59 -06:00
Sean Leary
4548696c8d
Update README.md for release 20240205 2024-02-05 20:22:23 -06:00
Sean Leary
f0308a3475
Merge pull request #855 from stleary/Fix-stack-overflow-failures
Fixing JSONArrayTest testRecursiveDepthArrayFor1000Levels()
2024-02-05 14:18:20 -06:00
Sean Leary
19dec1bb5f Fixing JSONArrayTest testRecursiveDepthArrayFor1000Levels() 2024-02-02 13:11:37 -06:00
Sean Leary
f2d20988de
Merge pull request #832 from keatontaylor10/feature-disable-whitespace-trim
Add a config flag to disable whitespace trimming
2024-01-26 19:40:36 -06:00
Keaton
7915d8518f
Merge branch 'stleary:master' into feature-disable-whitespace-trim 2024-01-18 09:17:26 +02:00
Sean Leary
55b824d4c4
Merge pull request #846 from stleary/cleanup-and-merge-tests
Cleanup warnings and merge new unit tests
2024-01-04 08:52:02 -06:00
Sean Leary
ac7806d060
Merge pull request #845 from seppl831/fix-annotation-search-performance
improved annotation search performance
2024-01-01 11:43:15 -06:00
Sean Leary
86bb0a1a02 cleanup-and-merge-tests: pull in unit tests from #809 2023-12-30 17:00:02 -06:00
Sean Leary
5ddb8c3d35 cleanup-and-merge-tests: fix warnings, set gradlew permissions, enable unchecked warnings in maven 2023-12-30 16:30:19 -06:00
Thomas Gress
23ac2e7bca improved annotation search performance 2023-12-29 12:28:24 +01:00
Sean Leary
d7819a4fa2
Merge pull request #823 from sk02241994/issue_743
JSON parsing self reference object and array
2023-12-27 05:28:17 -06:00
sk02241994
7701f21839 Adding comments 2023-12-24 11:39:26 +05:30
sk02241994
ffd48afa42 Review comments 2023-12-23 10:53:54 +05:30
sk02241994
abea194120 Adding JSONParserConfiguration for configuring the depth of nested maps 2023-12-22 15:47:55 +05:30
sk02241994
dcac3bc18e Adding test case for nested json with depth of 999, 1000, 1001 2023-12-22 15:47:54 +05:30
sk02241994
6d811607dd Resolving issue #743
- Recursive depth issue found in JSONObject
- Recursive depth issue found in JSONArray
2023-12-22 15:47:54 +05:30
Keaton Taylor
4d6de8c00a Remove unused constructor and add comment above other constructor 2023-12-13 14:04:05 +02:00
Sean Leary
6dba7220e1
Merge pull request #835 from LaFriska/branch1
deleted redundant .toString() call in README test method Sysout
2023-12-07 08:20:34 -06:00
Sean Leary
d4521696a9
Merge pull request #831 from adityap27/refactor
Refactor NumberConversionUtil and toString() of CookieList & XML Classes.
2023-12-03 10:18:22 -06:00
Keaton Taylor
e430db40aa Update XMLParserConfiguration to not be static and add a comment about the use of shouldTrimWhiteSpace 2023-11-30 10:05:54 +02:00
LaFriska
7cbeb35498 deleted redundant .toString() call in README test method Sysout 2023-11-28 17:39:46 -05:00
Aditya Purohit
aba82d9cc4 isNumericChar() - switch comparison order 2023-11-28 02:56:10 +00:00
Keaton Taylor
9ee10fdfc8 Merge remote-tracking branch 'origin/master' into feature-disable-whitespace-trim 2023-11-27 11:15:49 +02:00
Aditya Purohit
4a468d163a
Merge branch 'stleary:master' into refactor 2023-11-26 20:16:53 -04:00
Sean Leary
92991770ca
Merge pull request #830 from HappyHacker123/upgrade_json_path
Upgrade json-path's version to 2.4.0 to avoid dependency conflict.
2023-11-25 13:51:07 -06:00
Keaton Taylor
09f35372d4 Update clone() method so that default constructor does not need to be changed 2023-11-22 11:14:50 +02:00
Keaton Taylor
30f5b2de79 Add a config flag to disable whitespace trimming 2023-11-20 17:50:22 +02:00
Aditya Purohit
7f1cb8bf62 refactor: decompose condition of digit checks by using extra method 'isNumericChar(...)' in NumberConversionUtil. 2023-11-19 09:51:44 -04:00
Aditya Purohit
75419e3f25 refactor: introduce explaining variable 'indentationSuffix' in XML.toString() 2023-11-19 09:21:05 -04:00
Aditya Purohit
097a401f3f refactor: rename variable boolean 'b' to 'isEndOfPair' in CookieList.toString() 2023-11-19 09:11:32 -04:00
Sean Leary
5c4a7a1b1f
Merge pull request #828 from harshith2000/Fix-flaky-tests
Fixed flaky tests in XMLTest.java
2023-11-17 11:51:00 -06:00
HappyHacker123
b5f9febfe9 Upgrade json-path's version to 2.4 to avoid dependency conflict. 2023-11-17 21:31:06 +08:00
Saiharshith Karuneegar Ramesh
1a61af8255 Fixed flaky tests in XMLTest.java 2023-11-13 13:25:30 -06:00
Sean Leary
11c29c366d
Merge pull request #824 from johnjaylward/fix821
Ignore tests that fail due to resource differences
2023-11-10 11:27:18 -06:00
John J. Aylward
a3742acf74 Fixes #821
add ignore annotation to tests that may fail due to differences in machine resources and can't be controlled via the tests
2023-11-06 17:54:09 -05:00
Sean Leary
783d298f99
Merge pull request #814 from rudrajyotib/issue813
Refactor duplicate code for stringToNumber() in JSONObject, JSONArray, and XML
2023-10-31 17:40:17 -05:00
Sean Leary
6c1bc0660a
Merge pull request #820 from rudrajyotib/issue748
Close XML tag explicitly for empty tags with configuration.
2023-10-31 17:38:45 -05:00
rudrajyoti biswas
8ec822c575 #748 - PR comments - follow convention of configuration builder. 2023-10-28 07:36:31 +05:30
rudrajyoti biswas
1ceb70b525 #813 - PR comments - alignments 2023-10-28 07:09:37 +05:30
rudrajyoti biswas
c05d7058ff #748 - javadoc updated for methods. 2023-10-27 17:17:20 +05:30
rudrajyoti biswas
07a358449a Merge branch 'master' into issue813 2023-10-27 17:09:01 +05:30
rudrajyoti biswas
7fe2fd95a5 Merge branch 'master' into issue748 2023-10-27 17:07:46 +05:30
Sean Leary
b5b9f636ff
Merge pull request #815 from johnjaylward/ensure_1-6_compat
Ensure java 6 compatable
2023-10-25 13:53:23 -05:00
rudrajyoti biswas
c6ec2f0e4c #748 - close XML tag explicitly for empty tags with configuration. 2023-10-25 23:23:00 +05:30
Sean Leary
1a2108efa2
Merge pull request #812 from yeikel/patch-1
docs: use syntax highlighting
2023-10-25 09:58:30 -05:00
Sean Leary
caadcba30e
Merge pull request #794 from rudrajyotib/master
XML optLong/getLong equivalent updates for string to number conversion.
2023-10-25 09:55:13 -05:00
John J. Aylward
ea842b437c remove unneeded matrix build typ for java 1.6 2023-10-23 17:13:07 -04:00
John J. Aylward
a2a8240d0d upload jar files to GitHub release 2023-10-23 17:07:10 -04:00
John J. Aylward
1ab11d0802 ensure java 6 compatable 2023-10-23 15:08:21 -04:00
rudrajyoti biswas
5539722c69 #813 - address PR review comment - brought down visibility. 2023-10-23 23:03:35 +05:30
rudrajyoti biswas
98b79ae7bf #813 - moved number conversion related common changes to utility static method. 2023-10-23 19:16:25 +05:30
Rudrajyoti Biswas
04a4c5a3ec
Merge branch 'stleary:master' into master 2023-10-21 12:29:31 +00:00
Yeikel
6007165c17
docs: use syntax highlighting
use syntax highlighting to improve the format of the readme
2023-10-21 00:10:42 -04:00
Sean Leary
411f71137b
Merge pull request #803 from yeikel/patch-2
ci: test with Java 21
2023-10-20 07:37:32 -05:00
Sean Leary
e9117dbe5c
Merge branch 'master' into patch-2 2023-10-20 07:33:03 -05:00
Sean Leary
7a85b514a9
Merge pull request #808 from theKnightsOfRohan/fix-build-messages
Fix compiler warnings
2023-10-20 07:32:07 -05:00
Sean Leary
82c8f486c5
Merge pull request #806 from johnjaylward/deploymentPipeline
Add new deployment pipeline
2023-10-20 07:31:12 -05:00
Sean Leary
006b29bda3
Merge branch 'master' into deploymentPipeline 2023-10-20 07:28:44 -05:00
Sean Leary
996d3a5fad
Merge pull request #801 from johnjaylward/updateActionsForDeploy
Updates the pipeline to validate that packaging a jar works properly
2023-10-20 07:26:41 -05:00
Yeikel
de745e9c81
ci: test with Java 21 2023-10-19 22:41:47 -04:00
rudrajyoti biswas
2374766018 #790 - Update XML with changes for string to number conversion.
For now the code remains duplicated in JSON and XML parsers.
Unit test cases updated to comply with number expectations.
2023-10-19 14:07:53 +05:30
rudrajyoti biswas
1d0775cce7 Revert changes with feature and refactor together. 2023-10-19 10:28:11 +05:30
Sean Leary
d677a99f4e
Merge pull request #798 from hofi1/bugfix/fix-XML-flacky-test
fix: flakiness in org.json.junit.XMLTest#testIndentComplicatedJsonObjectWithArrayAndWithConfig
2023-10-17 13:52:29 -05:00
Sean Leary
e6d37c469d
Merge pull request #788 from hofi1/bugfix/fix-JSON-flakiness
Fix string compare unit tests
2023-10-17 13:51:40 -05:00
theKnightsOfRohan
f074bed732 fix(ParserConfiguration): add <T> params to docs 2023-10-16 17:48:03 -07:00
John J. Aylward
e8f125fb6e update workflow to use GPG 2023-10-16 18:23:39 -04:00
John J. Aylward
ed183e6142 remove deprecated parent pom per Sonatype docs 2023-10-16 18:22:08 -04:00
John J. Aylward
a86786a5f5 Add snapshot repository 2023-10-16 18:03:39 -04:00
John J. Aylward
7c4f98c42c Add new deployment pipeline.
This should only trigger when a release is published
2023-10-16 17:30:57 -04:00
John J. Aylward
3894483560 Add build badges to README 2023-10-16 15:44:02 -04:00
John J. Aylward
be115059e9 Correct supported java versions 2023-10-16 15:44:02 -04:00
John J. Aylward
2b41cf44b5 include jar in job artifacts 2023-10-16 15:43:55 -04:00
John J. Aylward
9a9efac2af Correct moditect configuration to work on java8 2023-10-16 15:36:33 -04:00
John J. Aylward
134074aeaa Revert "Reverting #761"
This reverts commit b180dbedbc99bb177e5b277f1bff2a1b79cebda6.
2023-10-16 15:36:33 -04:00
John J. Aylward
8540bb80c0 Validate that the mvn package step completes 2023-10-16 15:36:33 -04:00
simonh5
4dfd779b1c fix: flakiness in org.json.junit.XMLTest#testIndentComplicatedJsonObjectWithArrayAndWithConfig 2023-10-14 17:21:06 -05:00
rudrajyoti biswas
7b2677ac5a #790 - Update XML with changes for string to number conversion.
Moved the code logic to a common utility to de-duplicate.
2023-10-14 10:05:36 +05:30
simonh5
29a7f4622d remove JSONAssert 2023-10-13 21:23:09 -05:00
Sean Leary
f346203cd6
Merge pull request #793 from stleary/revert-761
Reverting #761
2023-10-13 16:10:17 -05:00
Sean Leary
b180dbedbc Reverting #761 2023-10-13 16:04:14 -05:00
Sean Leary
cca6d1020f
Merge pull request #792 from stleary/pre-release-20231013
update the docs for release 20231013
2023-10-13 15:40:19 -05:00
Sean Leary
af5f780d5b update the docs for release 20231013 2023-10-13 15:30:31 -05:00
Sean Leary
495cec9037
Merge pull request #783 from rudrajyotib/master
optLong vs getLong inconsistencies
2023-10-12 22:06:11 -05:00
simonh5
e4aa7f1308 fix: change from JSONAssert to checking the similarity of JSONObjects 2023-10-12 21:09:27 -05:00
rudrajyoti biswas
56cb5f84c4 #653 - review comments updated. 2023-10-12 11:03:13 +05:30
rudrajyoti biswas
0cdc38ac24 #653 - review comments updated. 2023-10-12 00:53:36 +05:30
Rudrajyoti Biswas
d5277b126b
Merge branch 'stleary:master' into master 2023-10-11 19:17:21 +00:00
Simon Hofbauer
228598ca84
Merge pull request #6 from hofi1/bugfix/fix-flakyness-testToJSONObject_reversibility
fix: flakiness in JSONMLTest#testToJSONObject_reversibility
2023-10-10 18:20:20 -05:00
Simon Hofbauer
0a6fb1d578
Merge pull request #5 from hofi1/bugfix/fix-flakyness-org.json.junit.JSONObjectTest#valueToString
fix: flakiness in org.json.junit.JSONObjectTest#valueToString
2023-10-10 18:19:28 -05:00
Sean Leary
c4cd526c53
Merge pull request #779 from Madjosz/713_jsonobject_nonfinite
add validity check for JSONObject constructors
2023-10-08 17:08:32 -05:00
Sean Leary
776b5ccb85
Merge pull request #778 from Madjosz/fix_xml_test
Fix XMLTest.testIndentComplicatedJsonObjectWithArrayAndWithConfig() for Windows - in the test
2023-10-08 17:06:55 -05:00
Sean Leary
fb99c06bad
Merge branch 'master' into fix_xml_test 2023-10-08 17:03:35 -05:00
Sean Leary
bc09f90e90
Merge pull request #782 from mureinik/XMLTest-windows
Fix XMLTest.testIndentComplicatedJsonObjectWithArrayAndWithConfig() for Windows - in the test
2023-10-08 17:00:25 -05:00
Madjosz
c93014cb53 add validity check for JSONObject constructors
* fixes #713
* document JSONException in JavaDoc
* remove unused Comparable<T> boundary to reuse GenericBean in test
2023-10-07 09:38:54 +02:00
Madjosz
0e4a94d91d fix failing test XML test on Windows machines 2023-10-07 09:38:07 +02:00
rudrajyoti biswas
1a38879c90 #653 - optLong vs getLong inconsistencies
For exponential decimal conversion, number is not touched.
Leading zeros removed from numeric number strings before converting to number.
2023-10-06 21:34:00 +05:30
Allon Mureinik
4c8cac22a8 Use System.lineSeparator()
Use the built-in System.lineSeparator() instead of implementing it
ourselves with System.getProperty("line.separator") in order to clean
up the code and make it easier to maintain.
2023-10-05 19:47:33 +03:00
Allon Mureinik
fe45fa9cfb Fix XMLTest on Windows
XMLTest.testIndentComplicatedJsonObjectWithArrayAndWithConfig fails
when run on Windows due to mismatching linebreaks (that aren't
important for the test's functionality) between the actual and
expected strings.

For the actual strings, linebreaks are canonized to the platform's
native linebreak using `replaceAll("\\n|\\r\\n",
System.getProperty("line.separator")`. However, the expected result is
read from a file, and is left with the linebreaks that were originally
used to create it.

The solution is to perform the same canonization on both strings.

Closes #781
2023-10-05 15:36:07 +03:00
Sean Leary
79af389f7a
Merge pull request #774 from mccartney/removing-synchronized
Removing excessive synchronization
2023-10-04 07:40:10 -05:00
Sean Leary
1726b6cf55
Merge pull request #776 from mccartney/junit-4-13-2
JUnit 4.13.2
2023-10-04 07:39:26 -05:00
Sean Leary
beb2fb5706
Merge pull request #772 from eamonnmcmanus/complexkey
Disallow nested objects and arrays as keys in objects.
2023-10-01 11:04:40 -05:00
Grzegorz Olędzki
ff921db783 Junit 4.13.2 2023-09-30 21:53:36 +02:00
Grzegorz Olędzki
61bb60e752 Removing excessive synchronization 2023-09-30 21:36:11 +02:00
Sean Leary
ef68cdf810
Merge pull request #773 from eedijs/master
Add optJSONArray method to JSONObject with a default value
2023-09-30 11:47:01 -05:00
Éamonn McManus
eaa5611ba3
Merge branch 'stleary:master' into complexkey 2023-09-28 11:33:08 -07:00
Éamonn McManus
dbb113176b Add more test cases for unquoted text in objects and arrays. 2023-09-28 11:05:50 -07:00
Éamonn McManus
16967f322e Simplify the check for object keys that are themselves objects.
For object keys, we can just skip the part of `nextValue()` that parses values
that are objects or arrays. Then the existing logic for unquoted values will
already stop at `{` or `[`, and that will produce a `Missing value` exception.
2023-09-27 12:42:04 -07:00
Edijs
284a316838 Add optJSONArray and optJSONObject methods to JSONArray with a default value 2023-09-27 19:30:45 +03:00
Sean Leary
4e8231c512
Merge pull request #770 from eamonnmcmanus/testfixes
Small test fixes.
2023-09-25 20:37:44 -05:00
Edijs
db0fde2a56 Add optJSONArray method to JSONObject with a default value 2023-09-25 20:31:58 +03:00
Éamonn McManus
661114c50d Generalize the logic to disallow nested objects and arrays as keys in objects.
Fixes #771.
2023-09-20 10:50:48 -07:00
simonh5
ca88454f1c fix: flakiness in org.json.junit.JSONObjectTest#valueToString 2023-09-19 14:28:06 -05:00
Éamonn McManus
3e688afc66 Small test fixes.
One test method was missing `@Test` so it was never run.

One test method used another test class as the base for finding a test
resource. While this works in practice with Maven, it is not strictly
right.
2023-09-19 07:38:13 -07:00
simonh5
becc1631e6 fix: flakiness in JSONMLTest#testToJSONObject_reversibility 2023-09-18 20:20:13 -05:00
Sean Leary
01727fd0ed
Merge pull request #769 from jscrdev/fixed-warnings
Addressed Java 17 compile warnings
2023-09-16 08:30:44 -05:00
Valentyn Kolesnikov
74cd73f97c Addressed compile warnings 2023-09-08 07:34:00 +03:00
Sean Leary
c29d4881e0
Merge pull request #741 from jscrdev/setup-java-11
Configure Java 8 as the minimum required version
2023-09-03 17:17:04 -05:00
Sean Leary
7c1b6531e7
Update CONTRIBUTING.md
Updated for Hacktoberfest 2023
2023-09-03 11:35:15 -05:00
Valentyn Kolesnikov
db122e5d3a
Merge branch 'master' into setup-java-11 2023-09-03 18:40:40 +03:00
Sean Leary
a309931d20
Merge pull request #761 from bowbahdoe/master
Add module-info
2023-09-03 10:35:21 -05:00
Valentyn Kolesnikov
e27da22e05
Update build.gradle 2023-08-29 05:00:13 +03:00
Valentyn Kolesnikov
af6d07cecb Resolved Gradle build dependency 2023-08-29 03:22:20 +03:00
Sean Leary
64093366b3
Merge pull request #764 from johnjaylward/CodeQl_Pipeline_Update
Update CodeQL action version
2023-08-28 19:20:36 -05:00
John J. Aylward
9b69ec49ad update CodeQL action version 2023-08-28 12:51:52 -04:00
Valentyn Kolesnikov
2c674be1b6 Update pipeline.yml 2023-08-28 19:06:27 +03:00
Valentyn Kolesnikov
be33deb7d5 Update README.md 2023-08-28 19:04:30 +03:00
Valentyn Kolesnikov
48089a4da7 Update pipeline.yml 2023-08-28 19:04:30 +03:00
Valentyn Kolesnikov
a4e152f4f0 Update pipeline.yml 2023-08-28 19:03:43 +03:00
dburbrid
3dd8f2ecd5 Correction of bug when compiling/testing on Windows: Issue537 file must be read as UTF-8 (Issue 745) 2023-08-28 19:03:40 +03:00
Valentyn Kolesnikov
bae0b0dac9 Updated mockito 2023-08-28 19:01:47 +03:00
Valentyn Kolesnikov
e563dbcaaa Setup java 8 as minimum version 2023-08-28 19:00:00 +03:00
Ethan McCue
50dfcc59b3 Remove automatic module name 2023-08-16 11:25:15 -04:00
Ethan McCue
b2943eb395 Add module-info to maven build 2023-08-16 11:24:57 -04:00
Sean Leary
60662e2f83
Merge pull request #759 from eamonnmcmanus/eofnull
JSON parsing should detect embedded `\0` values
2023-08-05 08:33:26 -05:00
Éamonn McManus
2a4bc3420a Apply simplification suggested by @johnjaylward. 2023-08-01 14:38:45 -07:00
Éamonn McManus
b6ff0db984 Fix indentation in test. 2023-08-01 13:49:59 -07:00
Éamonn McManus
c8a9e15a57 Don't skip past \0 when parsing JSON objects.
A better solution might be to use -1 instead 0 to represent EOF everywhere,
which of course means changing `char` variables to `int`. The solution here is
enough to solve the immediate problem, though.

Fixes #758.
2023-08-01 13:11:25 -07:00
Sean Leary
402db6ad84
Merge pull request #753 from davejbur/add-object-methods-and-test
Updated new object methods
2023-07-14 20:03:13 -05:00
dburbrid
4951ec48c8 Renamed object methods from ...Obj to ...Object.
Added object method for optDoubleObject (returns Double vice double).
Added similar methods in JSONArray.
Added test methods.
2023-06-29 09:39:34 +01:00
Sean Leary
8ce0019a5d
Merge pull request #752 from davejbur/issue-745-compile-error
Correction of bug when compiling/testing on Windows
2023-06-28 20:45:05 -05:00
dburbrid
3d524349a1 Correction of bug when compiling/testing on Windows: Issue537 file must be read as UTF-8 (Issue 745) 2023-06-26 09:33:03 +01:00
Sean Leary
a963115ac2
Update pom.xml for maven deploy
Deploy failed on the mac pro with: gpg: signing failed: Inappropriate ioctl for device

Somehow I had a different gpg version installed. This change fixed it.
2023-06-18 12:58:32 -05:00
Sean Leary
f959baa3cb
Merge pull request #749 from stleary/pre-release-20230618
Prep for release 20230618
2023-06-18 12:24:27 -05:00
Sean Leary
c048b36516
Update pom.xml for 20230618 2023-06-18 12:18:36 -05:00
Sean Leary
f6e5bfa2db
Update RELEASES.md for 20230618 2023-06-18 12:17:56 -05:00
Sean Leary
084b24cbe7
Update README.md for 20230618 2023-06-18 12:16:14 -05:00
Sean Leary
22ccf1b8e5
Merge pull request #740 from michael-o/proper-encoding
JSONTokener(InputStream) violates rfc8259#section-8.1 (#739)
2023-05-28 14:11:41 -05:00
Michael Osipov
133c0cc75f JSONTokener(InputStream) violates rfc8259#section-8.1 (#739)
Always use UTF-8 when an InputStream is passed.

This fixes #739.
2023-05-24 11:45:25 +02:00
Sean Leary
0578285036
Merge pull request #734 from superMaaax/fix_flaky
Fixed Flaky Tests Caused by JSON permutations
2023-03-27 16:25:57 -05:00
superMaaax
48fb5261fe Fixed Flaky Tests Caused by JSON permutations
###Description
Flaky Tests found using NonDex by running the commands -
mvn -pl . edu.illinois:nondex-maven-plugin:2.1.1:nondex -Dtest=org.json.junit.XMLTest#testIndentComplicatedJsonObject

mvn -pl . edu.illinois:nondex-maven-plugin:2.1.1:nondex -Dtest=org.json.junit.XMLTest#testIndentSimpleJsonArray

mvn -pl . edu.illinois:nondex-maven-plugin:2.1.1:nondex -Dtest=org.json.junit.XMLTest#testIndentSimpleJsonObject

The logged failure was-

[ERROR] Failures:
[ERROR] XMLTest.testIndentSimpleJsonObject:1193 expected:<...>
<employee>
<[married>true</married>
<name>sonoo</name>
<salary>56000</salary]>
</employee>
</Te...> but was:<...>
<employee>
<[name>sonoo</name>
<salary>56000</salary>
<married>true</married]>
</employee>
</Te...>

The issue is the same for all three tests, so here I only show the failure message for the third test (to reduce the length of the error message).

### Investigation

The tests fail with a comparison error while comparing an expected JSON String and the result from the value returned from XML.toString(). The toString function of XML makes no guarantees as to the iteration order of the attributes in the object. This makes the test outcome non-deterministic, and the test fails whenever the function returns a mismatch in order of the elements in the JSON String. To fix this, the expected and actual keys should be checked in a more deterministic way so that the assertions do not fail.

### Fix

Expected and Actual values can be converted into JSONObject and the similar function can be used to compare these objects. As this function compares the values inside the JSONObjects without needing order, the test becomes deterministic and ensures that the flakiness from the test is removed.

The PR does not introduce a breaking change.
2023-03-21 20:58:32 -05:00
Sean Leary
8353b9c3f0
Merge pull request #731 from JoaoGFarias/patch-1
Removing commented out code in JSONObject optDouble()
2023-03-11 19:28:01 -06:00
Sean Leary
fe22b242b5
Merge pull request #733 from haribabu-dev/jsontokener_closable
JSONTokener implemented java.io.Closeable
2023-03-11 19:26:55 -06:00
HariBabu t
7eca507d13 Removed overriding closable interface. 2023-03-07 13:58:30 +08:00
HariBabu t
e1eabc9c27 JSONTokener implemented java.io.Closeable 2023-03-04 23:08:32 +08:00
JoĂŁo Farias
0d436d92e2
Removing commented out code 2023-03-02 16:39:11 +01:00
Sean Leary
45bcba518f
Merge pull request #729 from TamasPergerDWP/f-parserconfig
Refactor ParserConfiguration class hierarchy
2023-02-28 12:49:42 -06:00
Sean Leary
47fb49b6a8
Update for release 20230227 2023-02-27 07:21:11 -06:00
Sean Leary
0df034c9fd
Update for release 20230227 2023-02-27 07:20:10 -06:00
Sean Leary
f0a05e6911
Update README.md 2023-02-27 07:17:51 -06:00
Tamas Perger
24093491a8 refactor: introduce ParserConfiguration class hierarchy 2023-02-21 19:13:07 +00:00
Sean Leary
1275f6809d
Merge pull request #723 from TamasPergerDWP/master
JSONML should be protected from stack overflow exceptions caused by recursion, resolving #722
2023-02-17 13:47:36 -06:00
Tamas Perger
9234eab00a refactor: make JSONMLParserConfiguration all-args constructor private, enforcing the builder pattern. 2023-02-13 01:09:29 +00:00
Tamas Perger
72f4c3e646 refactor: rename XMLtoJSONMLParserConfiguration to JSONMLParserConfiguration 2023-02-12 01:32:34 +00:00
Tamas Perger
df2d6f8363 fix: introduce optional XMLtoJSONMLParserConfiguration parameter for JSONML.toJSONArray(...) functions, to facilitate max nesting depth override. 2023-02-11 01:52:13 +00:00
Tamas Perger
a6e412bded fix: limit the nesting depth in JSONML
Limit the XML nesting depth for CVE-2022-45688 when using the JsonML transform.
2023-02-10 01:46:44 +00:00
Tamas Perger
2391d248cc fix: amend XMLParserConfiguration.clone() to include the new maxNestingDepth param.
Amend Javadoc for XML and XMLParserConfiguration classes.
2023-02-10 01:45:34 +00:00
Sean Leary
401495ae86
Merge pull request #720 from cleydyr/issue-708
Limit the XML nesting depth for CVE-2022-45688
2023-02-05 19:30:04 -06:00
Cleydyr de Albuquerque
448e204186 docs: remove wrong description of parse method 2023-02-02 20:16:16 +01:00
Cleydyr de Albuquerque
eb56704e68 fix: set default maximum nesting depth as 512 2023-02-02 18:15:03 +01:00
Cleydyr de Albuquerque
651511f500 tests: add new test to verify that an XML having the permitted nesting depth can be converted 2023-02-01 20:22:47 +01:00
Cleydyr de Albuquerque
a14cb12c85 refactor: keep consistence with other tests and tidy up constant 2023-02-01 20:22:32 +01:00
Cleydyr de Albuquerque
f566a1d9ee fix: limit the nesting depth 2023-02-01 16:26:58 +01:00
Sean Leary
5920eca2d7
Merge pull request #711 from 6d64/revert-pull-707-interviewbit-spam
Revert pull 707 - interviewbit spam
2022-11-30 20:20:39 -06:00
6d64
3b097d051a Revert pull 707 - interviewbit spam
Reverted commit that was added by a bot adding interviewbit spam to
repos on github
2022-12-01 03:21:26 +11:00
Sean Leary
4e630e58a4
Merge pull request #707 from ASAlishaa/patch-1
Added new resource to the repos
2022-11-17 19:14:11 -06:00
ASAlisha
b732188e4e
Added new resource to this repos.
Added resource in the correct format.
2022-11-15 16:31:05 +05:30
ASAlisha
5369442671
Added new resource to the repos
Added new useful JSON resource.
2022-11-14 03:26:18 +05:30
Sean Leary
bb1138762a
Merge pull request #703 from TomerPacific/feature/update-release-for-JSONMap-Change
Update Releases.md for JSONObject(Map): Throws NPE if key is null
2022-11-05 17:39:13 -05:00
Sean Leary
6a732ec99d
Merge pull request #704 from niranjanib/fix-javadoc-not-visible-in-website
move javadoc comments above the interface definition to make it visible
2022-11-05 17:38:15 -05:00
Niranjani
c798c76ddd move javadoc comments above the interface definition to make it visible
Fix #670
2022-10-30 22:10:38 +05:30
unknown
23d5e52a53 feature/update-release-for-JSONMap-Change adding breaking change for JSONMap to corresponding release 2022-10-28 08:45:54 +03:00
Sean Leary
98df35449a
Merge pull request #696 from bmk15897/fix-flaky-test
Update JSONPointerTest for NonDex compatibility
2022-10-15 08:24:01 -05:00
Sean Leary
1be6ee31a7
Merge pull request #694 from DeaneOC/Pretty-Print-XML-Functionality
Pretty print XML
2022-10-13 21:46:26 -05:00
Bharati Kulkarni
a2d3d3c9b5 Fix Flaky Test 2022-10-11 14:33:43 -05:00
Dean
bf9219386a
Merge branch 'master' of https://github.com/stleary/JSON-java into Pretty-Print-XML-Functionality 2022-10-10 11:12:49 +01:00
Dean
85495facbd
Corrected test 2022-10-10 11:12:35 +01:00
Dean
7aba3ac941
System line seperator now being used in JUnit test 2022-10-10 11:09:42 +01:00
Sean Leary
d51250f6b0
Merge pull request #692 from InACommandBlock/patch-1
Example.md syntax highlight and indentation
2022-10-09 22:28:36 -05:00
Dean
9cb8e153bf
Added JavaDocs 2022-10-07 17:57:07 +01:00
Dean
80c1479ad8
Merge branch 'master' of https://github.com/stleary/JSON-java into Pretty-Print-XML-Functionality 2022-10-07 17:56:54 +01:00
Sean Leary
444335d12a
Merge pull request #691 from hendrixjoseph/issue-657-unit-tests-should-check-various-number-formats
create unit tests for various number formats
2022-10-07 11:18:41 -05:00
Dean
a2c0562e04
Removed unused import 2022-10-07 15:04:09 +01:00
Dean
153972afdf
Adding resources 2022-10-07 10:35:14 +01:00
Dean
4a8ff28fd8
Reduced Test code length by using resources 2022-10-07 10:35:06 +01:00
Dean
fa457a4113
Test cases for XML toString indentation 2022-10-06 12:01:26 +01:00
Dean
b7f708b222
Altered XML toString to allow indentation param 2022-10-06 12:01:13 +01:00
TheCommandBlock
12411b7981
Update Examples.md
Co-authored-by: JAYSE <104235500+JayseMayne@users.noreply.github.com>
2022-10-06 03:18:03 +02:00
TheCommandBlock
61801c623e
Minor Adjustments Example.md
Added syntax highlighting, standardised indentation
2022-10-06 00:48:34 +02:00
hendrixjoseph
1915aab7c4 create unit tests for various number formats 2022-10-04 14:32:41 -04:00
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
65 changed files with 12111 additions and 2246 deletions

View File

@ -25,11 +25,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v2
uses: actions/checkout@v3
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
uses: github/codeql-action/init@v3
with:
languages: ${{ matrix.language }}
# If you wish to specify custom queries, you can do so here or in a config file.
@ -40,4 +40,4 @@ jobs:
- 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
uses: github/codeql-action/analyze@v3

View File

@ -1,5 +1,5 @@
# 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
# For more information see: https://docs.github.com/en/actions/learn-github-actions or https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions
name: Java CI with Maven
@ -12,63 +12,217 @@ on:
jobs:
# old-school build and jar method. No tests run or compiled.
build-1_6:
name: Java 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
- uses: actions/checkout@v4
- name: Setup java
uses: actions/setup-java@v1
with:
java-version: ${{ matrix.java }}
- name: Compile Java ${{ matrix.java }}
java-version: 1.6
- name: Compile Java 1.6
run: |
mkdir -p target/classes
javac -d target/classes/ src/main/java/org/json/*.java
- name: Create java ${{ matrix.java }} JAR
javac -version
javac -source 1.6 -target 1.6 -d target/classes/ src/main/java/org/json/*.java
- name: Create java 1.6 JAR
run: |
jar cvf target/org.json.jar -C target/classes .
- name: Upload Java ${{ matrix.java }} JAR
uses: actions/upload-artifact@v1
- name: Upload JAR 1.6
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: Java ${{ matrix.java }} JAR
path: target/org.json.jar
build:
name: Create java 1.6 JAR
path: target/*.jar
build-8:
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 1
matrix:
# build against supported Java LTS versions:
java: [ 1.7, 8, 11 ]
java: [ 8 ]
name: Java ${{ matrix.java }}
steps:
- uses: actions/checkout@v2
- name: Setup java
uses: actions/setup-java@v1
- uses: actions/checkout@v3
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
cache: 'maven'
- 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
run: mvn clean compile -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }} -D maven.test.skip=true -D maven.site.skip=true -D maven.javadoc.skip=true
- name: Run Tests ${{ matrix.java }}
run: |
mvn test -Dmaven.compiler.source=${{ matrix.java }} -Dmaven.compiler.target=${{ matrix.java }}
mvn test -D maven.compiler.source=${{ matrix.java }} -D maven.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 }}
mvn surefire-report:report-only -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }}
mvn site -D generateReports=false -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }}
- name: Upload Test Results ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v4
with:
name: Test Results ${{ matrix.java }}
path: target/surefire-reports/
- name: Upload Test Report ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v1
uses: actions/upload-artifact@v4
with:
name: Test Report ${{ matrix.java }}
path: target/site/
- name: Package Jar ${{ matrix.java }}
run: mvn clean package -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }} -D maven.test.skip=true -D maven.site.skip=true
- name: Upload Package Results ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: Package Jar ${{ matrix.java }}
path: target/*.jar
build-11:
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 1
matrix:
# build against supported Java LTS versions:
java: [ 11 ]
name: Java ${{ matrix.java }}
steps:
- uses: actions/checkout@v3
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
cache: 'maven'
- name: Compile Java ${{ matrix.java }}
run: mvn clean compile -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }} -D maven.test.skip=true -D maven.site.skip=true -D maven.javadoc.skip=true
- name: Run Tests ${{ matrix.java }}
run: |
mvn test -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }}
- name: Build Test Report ${{ matrix.java }}
if: ${{ always() }}
run: |
mvn surefire-report:report-only -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }}
mvn site -D generateReports=false -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }}
- name: Upload Test Results ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: Test Results ${{ matrix.java }}
path: target/surefire-reports/
- name: Upload Test Report ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: Test Report ${{ matrix.java }}
path: target/site/
- name: Package Jar ${{ matrix.java }}
run: mvn clean package -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }} -D maven.test.skip=true -D maven.site.skip=true
- name: Upload Package Results ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: Package Jar ${{ matrix.java }}
path: target/*.jar
build-17:
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 1
matrix:
# build against supported Java LTS versions:
java: [ 17 ]
name: Java ${{ matrix.java }}
steps:
- uses: actions/checkout@v3
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
cache: 'maven'
- name: Compile Java ${{ matrix.java }}
run: mvn clean compile -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }} -D maven.test.skip=true -D maven.site.skip=true -D maven.javadoc.skip=true
- name: Run Tests ${{ matrix.java }}
run: |
mvn test -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }}
- name: Build Test Report ${{ matrix.java }}
if: ${{ always() }}
run: |
mvn surefire-report:report-only -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }}
mvn site -D generateReports=false -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }}
- name: Upload Test Results ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: Test Results ${{ matrix.java }}
path: target/surefire-reports/
- name: Upload Test Report ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: Test Report ${{ matrix.java }}
path: target/site/
- name: Package Jar ${{ matrix.java }}
run: mvn clean package -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }} -D maven.test.skip=true -D maven.site.skip=true
- name: Upload Package Results ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: Package Jar ${{ matrix.java }}
path: target/*.jar
build-21:
runs-on: ubuntu-latest
strategy:
fail-fast: false
max-parallel: 1
matrix:
# build against supported Java LTS versions:
java: [ 21 ]
name: Java ${{ matrix.java }}
steps:
- uses: actions/checkout@v3
- name: Set up JDK ${{ matrix.java }}
uses: actions/setup-java@v3
with:
distribution: 'temurin'
java-version: ${{ matrix.java }}
cache: 'maven'
- name: Compile Java ${{ matrix.java }}
run: mvn clean compile -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }} -D maven.test.skip=true -D maven.site.skip=true -D maven.javadoc.skip=true
- name: Run Tests ${{ matrix.java }}
run: |
mvn test -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }}
- name: Build Test Report ${{ matrix.java }}
if: ${{ always() }}
run: |
mvn surefire-report:report-only -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }}
mvn site -D generateReports=false -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }}
- name: Upload Test Results ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: Test Results ${{ matrix.java }}
path: target/surefire-reports/
- name: Upload Test Report ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: Test Report ${{ matrix.java }}
path: target/site/
- name: Package Jar ${{ matrix.java }}
run: mvn clean package -D maven.compiler.source=${{ matrix.java }} -D maven.compiler.target=${{ matrix.java }} -D maven.test.skip=true -D maven.site.skip=true
- name: Upload Package Results ${{ matrix.java }}
if: ${{ always() }}
uses: actions/upload-artifact@v4
with:
name: Package Jar ${{ matrix.java }}
path: target/*.jar

2
.gitignore vendored
View File

@ -1,6 +1,8 @@
# ignore eclipse project files
.project
.classpath
# ignore vscode files
.vscode
# ignore Intellij Idea project files
.idea
*.iml

View File

@ -1,8 +1,8 @@
# Contribution Guidelines
Feel free to work on any issue with a #hacktoberfest label.
Feel free to work on any open issue, you don't need to ask permission first. This year, the hacktoberfest label will be added to any PR and associated issue during the month of October.
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.
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, it will be available to work on (if not, it will be closed after review).
# Who is allowed to submit pull requests for this project?

View File

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

23
LICENSE
View File

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

View File

@ -7,8 +7,10 @@ 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)
[![Java CI with Maven](https://github.com/stleary/JSON-java/actions/workflows/pipeline.yml/badge.svg)](https://github.com/stleary/JSON-java/actions/workflows/pipeline.yml)
[![CodeQL](https://github.com/stleary/JSON-java/actions/workflows/codeql-analysis.yml/badge.svg)](https://github.com/stleary/JSON-java/actions/workflows/codeql-analysis.yml)
**[Click here if you just want the latest release jar file.](https://search.maven.org/remotecontent?filepath=org/json/json/20220320/json-20220320.jar)**
**[Click here if you just want the latest release jar file.](https://search.maven.org/remotecontent?filepath=org/json/json/20250517/json-20250517.jar)**
# Overview
@ -24,12 +26,11 @@ Project goals include:
* No external dependencies
* Fast execution and low memory footprint
* Maintain backward compatibility
* Designed and tested to use on Java versions 1.6 - 1.11
* Designed and tested to use on Java versions 1.6 - 21
The files in this package implement JSON encoders and decoders. The package can also convert between JSON and XML, HTTP headers, Cookies, and CDL.
The license includes this restriction: ["The software shall be used for good, not evil."](https://en.wikipedia.org/wiki/Douglas_Crockford#%22Good,_not_Evil%22) If your conscience cannot live with that, then choose a different package.
# If you would like to contribute to this project
For more information on contributions, please see [CONTRIBUTING.md](https://github.com/stleary/JSON-java/blob/master/docs/CONTRIBUTING.md)
@ -43,59 +44,71 @@ The org.json package can be built from the command line, Maven, and Gradle. The
**Building from the command line**
*Build the class files from the package root directory src/main/java*
````
```shell
javac org/json/*.java
````
```
*Create the jar file in the current directory*
````
```shell
jar cf json-java.jar org/json/*.class
````
```
*Compile a program that uses the jar (see example code below)*
````
```shell
javac -cp .;json-java.jar Test.java (Windows)
javac -cp .:json-java.jar Test.java (Unix Systems)
````
```
*Test file contents*
````
```java
import org.json.JSONObject;
public class Test {
public static void main(String args[]){
JSONObject jo = new JSONObject("{ \"abc\" : \"def\" }");
System.out.println(jo.toString());
System.out.println(jo);
}
}
````
```
*Execute the Test file*
````
```shell
java -cp .;json-java.jar Test (Windows)
java -cp .:json-java.jar Test (Unix Systems)
````
```
*Expected output*
````
```json
{"abc":"def"}
````
```
**Tools to build the package and execute the unit tests**
Execute the test suite with Maven:
```
```shell
mvn clean test
```
Execute the test suite with Gradlew:
```
```shell
gradlew clean build test
```
*Optional* Execute the test suite in strict mode with Gradlew:
```shell
gradlew testWithStrictMode
```
*Optional* Execute the test suite in strict mode with Maven:
```shell
mvn test -P test-strict-mode
```
# Notes
For more information, please see [NOTES.md](https://github.com/stleary/JSON-java/blob/master/docs/NOTES.md)

View File

@ -3,9 +3,10 @@
*/
apply plugin: 'java'
apply plugin: 'eclipse'
// apply plugin: 'jacoco'
apply plugin: 'jacoco'
apply plugin: 'maven-publish'
// for now, publishing to maven is still a manual process
//plugins {
// id 'java'
//id 'maven-publish'
@ -19,10 +20,21 @@ repositories {
}
}
// To view the report open build/reports/jacoco/test/html/index.html
jacocoTestReport {
reports {
html.required = true
}
}
test {
finalizedBy jacocoTestReport
}
dependencies {
testImplementation 'junit:junit:4.13.1'
testImplementation 'com.jayway.jsonpath:json-path:2.1.0'
testImplementation 'org.mockito:mockito-core:1.9.5'
testImplementation 'junit:junit:4.13.2'
testImplementation 'com.jayway.jsonpath:json-path:2.9.0'
testImplementation 'org.mockito:mockito-core:4.2.0'
}
subprojects {
@ -30,9 +42,9 @@ subprojects {
}
group = 'org.json'
version = 'v20211205-SNAPSHOT'
version = 'v20250517-SNAPSHOT'
description = 'JSON in Java'
sourceCompatibility = '1.7'
sourceCompatibility = '1.8'
configurations.all {
}
@ -53,3 +65,75 @@ publishing {
tasks.withType(JavaCompile) {
options.encoding = 'UTF-8'
}
// Add these imports at the top of your build.gradle file
import java.nio.file.Files
import java.nio.file.Path
import java.nio.file.Paths
import java.nio.file.StandardCopyOption
// Your existing build configurations...
// Add a new task to modify the file
task modifyStrictMode {
doLast {
println "Modifying JSONParserConfiguration.java to enable strictMode..."
def filePath = project.file('src/main/java/org/json/JSONParserConfiguration.java')
if (!filePath.exists()) {
throw new GradleException("Could not find file: ${filePath.absolutePath}")
}
// Create a backup of the original file
def backupFile = new File(filePath.absolutePath + '.bak')
Files.copy(filePath.toPath(), backupFile.toPath(), StandardCopyOption.REPLACE_EXISTING)
// Read and modify the file content
def content = filePath.text
def modifiedContent = content.replace('// this.strictMode = true;', 'this.strictMode = true;')
// Write the modified content back to the file
filePath.text = modifiedContent
println "File modified successfully at: ${filePath.absolutePath}"
}
}
// Add a task to restore the original file
task restoreStrictMode {
doLast {
println "Restoring original JSONParserConfiguration.java..."
def filePath = project.file('src/main/java/org/json/JSONParserConfiguration.java')
def backupFile = new File(filePath.absolutePath + '.bak')
if (backupFile.exists()) {
Files.copy(backupFile.toPath(), filePath.toPath(), StandardCopyOption.REPLACE_EXISTING)
backupFile.delete()
println "Original file restored successfully at: ${filePath.absolutePath}"
} else {
println "Backup file not found at: ${backupFile.absolutePath}. No restoration performed."
}
}
}
// Create a task to run the workflow
task testWithStrictMode {
dependsOn modifyStrictMode
finalizedBy restoreStrictMode
doLast {
// This will trigger a clean build and run tests with strictMode enabled
if (org.gradle.internal.os.OperatingSystem.current().isWindows()) {
exec {
executable 'cmd'
args '/c', 'gradlew.bat', 'clean', 'build'
}
} else {
exec {
executable './gradlew'
args 'clean', 'build'
}
}
}
}

View File

@ -5,7 +5,26 @@ 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)
~~~
20220320 Recent commits
20250517 Strict mode hardening and recent commits
20250107 Restore moditect in pom.xml
20241224 Strict mode opt-in feature, and recent commits. This release does not contain module-info.class.
It is not recommended if you need this feature.
20240303 Revert optLong/getLong changes, and recent commits.
20240205 Recent commits.
20231013 First release with minimum Java version 1.8. Recent commits, including fixes for CVE-2023-5072.
20230618 Final release with Java 1.6 compatibility. Future releases will require Java 1.8 or greater.
20230227 Fix for CVE-2022-45688 and recent commits
20220924 New License - public domain, and some minor updates
20220320 Wrap StackOverflow with JSONException
20211205 Recent commits and some bug fixes for similar()
@ -18,6 +37,7 @@ and artifactId "json". For example:
20190722 Recent commits
20180813 POM change to include Automatic-Module-Name (#431)
JSONObject(Map) now throws an exception if any of a map keys are null (#405)
20180130 Recent commits

0
gradlew vendored Normal file → Executable file
View File

163
pom.xml
View File

@ -3,7 +3,7 @@
<groupId>org.json</groupId>
<artifactId>json</artifactId>
<version>20220320</version>
<version>20250517</version>
<packaging>bundle</packaging>
<name>JSON in Java</name>
@ -15,22 +15,12 @@
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
This is a reference implementation. There are 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.
</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>
@ -39,28 +29,9 @@
<licenses>
<license>
<name>The JSON License</name>
<url>http://json.org/license.html</url>
<name>Public Domain</name>
<url>https://github.com/stleary/JSON-java/blob/master/LICENSE</url>
<distribution>repo</distribution>
<comments>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.
</comments>
</license>
</licenses>
@ -76,23 +47,36 @@
</properties>
<distributionManagement>
<repository>
<id>ossrh</id>
<name>Central Repository OSSRH</name>
<url>https://oss.sonatype.org/service/local/staging/deploy/maven2/</url>
</repository>
<snapshotRepository>
<id>ossrh</id>
<url>https://oss.sonatype.org/content/repositories/snapshots</url>
</snapshotRepository>
</distributionManagement>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.13.1</version>
<version>4.13.2</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.jayway.jsonpath</groupId>
<artifactId>json-path</artifactId>
<version>2.1.0</version>
<version>2.9.0</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>1.9.5</version>
<version>4.2.0</version>
<scope>test</scope>
</dependency>
</dependencies>
@ -102,7 +86,7 @@
<plugin>
<groupId>org.apache.felix</groupId>
<artifactId>maven-bundle-plugin</artifactId>
<version>3.0.1</version>
<version>5.1.9</version>
<extensions>true</extensions>
<configuration>
<instructions>
@ -116,16 +100,19 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>2.3.2</version>
<version>3.11.0</version>
<configuration>
<source>1.6</source>
<target>1.6</target>
<source>1.8</source>
<target>1.8</target>
<compilerArgs>
<arg>-Xlint:unchecked</arg>
</compilerArgs>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>2.1.2</version>
<version>3.3.0</version>
<executions>
<execution>
<id>attach-sources</id>
@ -138,7 +125,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-javadoc-plugin</artifactId>
<version>2.7</version>
<version>3.5.0</version>
<executions>
<execution>
<id>attach-javadocs</id>
@ -154,7 +141,7 @@
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-gpg-plugin</artifactId>
<version>1.5</version>
<version>1.6</version>
<executions>
<execution>
<id>sign-artifacts</id>
@ -162,6 +149,12 @@
<goals>
<goal>sign</goal>
</goals>
<configuration>
<gpgArguments>
<arg>--pinentry-mode</arg>
<arg>loopback</arg>
</gpgArguments>
</configuration>
</execution>
</executions>
</plugin>
@ -176,18 +169,86 @@
<autoReleaseAfterClose>false</autoReleaseAfterClose>
</configuration>
</plugin>
<plugin>
<groupId>org.moditect</groupId>
<artifactId>moditect-maven-plugin</artifactId>
<version>1.0.0.Final</version>
<executions>
<execution>
<id>add-module-infos</id>
<phase>package</phase>
<goals>
<goal>add-module-info</goal>
</goals>
<configuration>
<jvmVersion>9</jvmVersion>
<module>
<moduleInfoSource>
module org.json {
exports org.json;
}
</moduleInfoSource>
</module>
</configuration>
</execution>
</executions>
</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>
<version>3.3.0</version>
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>test-strict-mode</id>
<build>
<plugins>
<plugin>
<groupId>com.google.code.maven-replacer-plugin</groupId>
<artifactId>replacer</artifactId>
<version>1.5.3</version>
<executions>
<!-- Enable strict mode -->
<execution>
<id>enable-strict-mode</id>
<phase>process-sources</phase>
<goals>
<goal>replace</goal>
</goals>
<configuration>
<file>src/main/java/org/json/JSONParserConfiguration.java</file>
<replacements>
<replacement>
<token>// this.strictMode = true;</token>
<value>this.strictMode = true;</value>
</replacement>
</replacements>
</configuration>
</execution>
<!-- Restore original code after tests -->
<execution>
<id>restore-original</id>
<phase>test</phase>
<goals>
<goal>replace</goal>
</goals>
<configuration>
<file>src/main/java/org/json/JSONParserConfiguration.java</file>
<replacements>
<replacement>
<token>this.strictMode = true;</token>
<value>// this.strictMode = true;</value>
</replacement>
</replacements>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@ -1,39 +1,19 @@
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.
*/
/**
* This provides static methods to convert comma delimited text into a
* JSONArray, and to convert a JSONArray into comma delimited text. Comma
* This provides static methods to convert comma (or otherwise) delimited text into a
* JSONArray, and to convert a JSONArray into comma (or otherwise) delimited text. Comma
* delimited text is a very popular format for data interchange. It is
* understood by most database, spreadsheet, and organizer programs.
* <p>
* Each row of text represents a row in a table or a data record. Each row
* ends with a NEWLINE character. Each row contains one or more values.
* Values are separated by commas. A value can contain any character except
* for comma, unless is is wrapped in single quotes or double quotes.
* for comma, unless it is wrapped in single quotes or double quotes.
* <p>
* The first row usually contains the names of the columns.
* <p>
@ -45,25 +25,30 @@ SOFTWARE.
*/
public class CDL {
/**
* Constructs a new CDL object.
*/
public CDL() {
}
/**
* Get the next value. The value can be wrapped in quotes. The value can
* be empty.
* @param x A JSONTokener of the source text.
* @param delimiter used in the file
* @return The value string, or null if empty.
* @throws JSONException if the quoted string is badly formed.
*/
private static String getValue(JSONTokener x) throws JSONException {
private static String getValue(JSONTokener x, char delimiter) throws JSONException {
char c;
char q;
StringBuilder sb;
do {
c = x.next();
} while (c == ' ' || c == '\t');
switch (c) {
case 0:
if (c == 0) {
return null;
case '"':
case '\'':
} else if (c == '"' || c == '\'') {
q = c;
sb = new StringBuilder();
for (;;) {
@ -71,9 +56,9 @@ public class CDL {
if (c == q) {
//Handle escaped double-quote
char nextC = x.next();
if(nextC != '\"') {
if (nextC != '\"') {
// if our quote was the end of the file, don't step
if(nextC > 0) {
if (nextC > 0) {
x.back();
}
break;
@ -85,13 +70,12 @@ public class CDL {
sb.append(c);
}
return sb.toString();
case ',':
} else if (c == delimiter) {
x.back();
return "";
default:
x.back();
return x.nextTo(',');
}
x.back();
return x.nextTo(delimiter);
}
/**
@ -101,17 +85,32 @@ public class CDL {
* @throws JSONException if a called function fails
*/
public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException {
return rowToJSONArray(x, ',');
}
/**
* Produce a JSONArray of strings from a row of comma delimited values.
* @param x A JSONTokener of the source text.
* @param delimiter custom delimiter char
* @return A JSONArray of strings.
* @throws JSONException if a called function fails
*/
public static JSONArray rowToJSONArray(JSONTokener x, char delimiter) throws JSONException {
JSONArray ja = new JSONArray();
for (;;) {
String value = getValue(x);
String value = getValue(x,delimiter);
char c = x.next();
if (value == null ||
(ja.length() == 0 && value.length() == 0 && c != ',')) {
if (value != null) {
ja.put(value);
} else if (ja.length() == 0 && c != delimiter) {
return null;
} else {
// This line accounts for CSV ending with no newline
ja.put("");
}
ja.put(value);
for (;;) {
if (c == ',') {
if (c == delimiter) {
break;
}
if (c != ' ') {
@ -136,9 +135,23 @@ public class CDL {
* @return A JSONObject combining the names and values.
* @throws JSONException if a called function fails
*/
public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x)
throws JSONException {
JSONArray ja = rowToJSONArray(x);
public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x) throws JSONException {
return rowToJSONObject(names, x, ',');
}
/**
* Produce a JSONObject from a row of comma delimited text, using a
* parallel JSONArray of strings to provides the names of the elements.
* @param names A JSONArray of names. This is commonly obtained from the
* first row of a comma delimited text file using the rowToJSONArray
* method.
* @param x A JSONTokener of the source text.
* @param delimiter custom delimiter char
* @return A JSONObject combining the names and values.
* @throws JSONException if a called function fails
*/
public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x, char delimiter) throws JSONException {
JSONArray ja = rowToJSONArray(x, delimiter);
return ja != null ? ja.toJSONObject(names) : null;
}
@ -150,15 +163,27 @@ public class CDL {
* @return A string ending in NEWLINE.
*/
public static String rowToString(JSONArray ja) {
return rowToString(ja, ',');
}
/**
* Produce a comma delimited text row from a JSONArray. Values containing
* the comma character will be quoted. Troublesome characters may be
* removed.
* @param ja A JSONArray of strings.
* @param delimiter custom delimiter char
* @return A string ending in NEWLINE.
*/
public static String rowToString(JSONArray ja, char delimiter) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < ja.length(); i += 1) {
if (i > 0) {
sb.append(',');
sb.append(delimiter);
}
Object object = ja.opt(i);
if (object != null) {
String string = object.toString();
if (string.length() > 0 && (string.indexOf(',') >= 0 ||
if (string.length() > 0 && (string.indexOf(delimiter) >= 0 ||
string.indexOf('\n') >= 0 || string.indexOf('\r') >= 0 ||
string.indexOf(0) >= 0 || string.charAt(0) == '"')) {
sb.append('"');
@ -187,7 +212,19 @@ public class CDL {
* @throws JSONException if a called function fails
*/
public static JSONArray toJSONArray(String string) throws JSONException {
return toJSONArray(new JSONTokener(string));
return toJSONArray(string, ',');
}
/**
* Produce a JSONArray of JSONObjects from a comma delimited text string,
* using the first row as a source of names.
* @param string The comma delimited text.
* @param delimiter custom delimiter char
* @return A JSONArray of JSONObjects.
* @throws JSONException if a called function fails
*/
public static JSONArray toJSONArray(String string, char delimiter) throws JSONException {
return toJSONArray(new JSONTokener(string), delimiter);
}
/**
@ -198,7 +235,19 @@ public class CDL {
* @throws JSONException if a called function fails
*/
public static JSONArray toJSONArray(JSONTokener x) throws JSONException {
return toJSONArray(rowToJSONArray(x), x);
return toJSONArray(x, ',');
}
/**
* Produce a JSONArray of JSONObjects from a comma delimited text string,
* using the first row as a source of names.
* @param x The JSONTokener containing the comma delimited text.
* @param delimiter custom delimiter char
* @return A JSONArray of JSONObjects.
* @throws JSONException if a called function fails
*/
public static JSONArray toJSONArray(JSONTokener x, char delimiter) throws JSONException {
return toJSONArray(rowToJSONArray(x, delimiter), x, delimiter);
}
/**
@ -209,9 +258,21 @@ public class CDL {
* @return A JSONArray of JSONObjects.
* @throws JSONException if a called function fails
*/
public static JSONArray toJSONArray(JSONArray names, String string)
throws JSONException {
return toJSONArray(names, new JSONTokener(string));
public static JSONArray toJSONArray(JSONArray names, String string) throws JSONException {
return toJSONArray(names, string, ',');
}
/**
* Produce a JSONArray of JSONObjects from a comma delimited text string
* using a supplied JSONArray as the source of element names.
* @param names A JSONArray of strings.
* @param string The comma delimited text.
* @param delimiter custom delimiter char
* @return A JSONArray of JSONObjects.
* @throws JSONException if a called function fails
*/
public static JSONArray toJSONArray(JSONArray names, String string, char delimiter) throws JSONException {
return toJSONArray(names, new JSONTokener(string), delimiter);
}
/**
@ -222,14 +283,26 @@ public class CDL {
* @return A JSONArray of JSONObjects.
* @throws JSONException if a called function fails
*/
public static JSONArray toJSONArray(JSONArray names, JSONTokener x)
throws JSONException {
public static JSONArray toJSONArray(JSONArray names, JSONTokener x) throws JSONException {
return toJSONArray(names, x, ',');
}
/**
* Produce a JSONArray of JSONObjects from a comma delimited text string
* using a supplied JSONArray as the source of element names.
* @param names A JSONArray of strings.
* @param x A JSONTokener of the source text.
* @param delimiter custom delimiter char
* @return A JSONArray of JSONObjects.
* @throws JSONException if a called function fails
*/
public static JSONArray toJSONArray(JSONArray names, JSONTokener x, char delimiter) throws JSONException {
if (names == null || names.length() == 0) {
return null;
}
JSONArray ja = new JSONArray();
for (;;) {
JSONObject jo = rowToJSONObject(names, x);
JSONObject jo = rowToJSONObject(names, x, delimiter);
if (jo == null) {
break;
}
@ -238,6 +311,17 @@ public class CDL {
if (ja.length() == 0) {
return null;
}
// The following block accounts for empty datasets (no keys or vals)
if (ja.length() == 1) {
JSONObject j = ja.getJSONObject(0);
if (j.length() == 1) {
String key = j.keys().next();
if ("".equals(key) && "".equals(j.get(key))) {
return null;
}
}
}
return ja;
}
@ -251,11 +335,24 @@ public class CDL {
* @throws JSONException if a called function fails
*/
public static String toString(JSONArray ja) throws JSONException {
return toString(ja, ',');
}
/**
* Produce a comma delimited text from a JSONArray of JSONObjects. The
* first row will be a list of names obtained by inspecting the first
* JSONObject.
* @param ja A JSONArray of JSONObjects.
* @param delimiter custom delimiter char
* @return A comma delimited text.
* @throws JSONException if a called function fails
*/
public static String toString(JSONArray ja, char delimiter) throws JSONException {
JSONObject jo = ja.optJSONObject(0);
if (jo != null) {
JSONArray names = jo.names();
if (names != null) {
return rowToString(names) + toString(names, ja);
return rowToString(names, delimiter) + toString(names, ja, delimiter);
}
}
return null;
@ -270,8 +367,21 @@ public class CDL {
* @return A comma delimited text.
* @throws JSONException if a called function fails
*/
public static String toString(JSONArray names, JSONArray ja)
throws JSONException {
public static String toString(JSONArray names, JSONArray ja) throws JSONException {
return toString(names, ja, ',');
}
/**
* Produce a comma delimited text from a JSONArray of JSONObjects using
* a provided list of names. The list of names is not included in the
* output.
* @param names A JSONArray of strings.
* @param ja A JSONArray of JSONObjects.
* @param delimiter custom delimiter char
* @return A comma delimited text.
* @throws JSONException if a called function fails
*/
public static String toString(JSONArray names, JSONArray ja, char delimiter) throws JSONException {
if (names == null || names.length() == 0) {
return null;
}
@ -279,7 +389,7 @@ public class CDL {
for (int i = 0; i < ja.length(); i += 1) {
JSONObject jo = ja.optJSONObject(i);
if (jo != null) {
sb.append(rowToString(jo.toJSONArray(names)));
sb.append(rowToString(jo.toJSONArray(names), delimiter));
}
}
return sb.toString();

View File

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

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.
*/
/**
@ -31,6 +11,12 @@ SOFTWARE.
*/
public class CookieList {
/**
* Constructs a new CookieList object.
*/
public CookieList() {
}
/**
* Convert a cookie list into a JSONObject. A cookie list is a sequence
* of name/value pairs. The names are separated from the values by '='.
@ -66,19 +52,19 @@ public class CookieList {
* @throws JSONException if a called function fails
*/
public static String toString(JSONObject jo) throws JSONException {
boolean b = false;
boolean isEndOfPair = false;
final StringBuilder sb = new StringBuilder();
// Don't use the new entrySet API to maintain Android support
for (final String key : jo.keySet()) {
final Object value = jo.opt(key);
if (!JSONObject.NULL.equals(value)) {
if (b) {
if (isEndOfPair) {
sb.append(';');
}
sb.append(Cookie.escape(key));
sb.append("=");
sb.append(Cookie.escape(value.toString()));
b = true;
isEndOfPair = true;
}
}
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.
*/
import java.util.Locale;
@ -33,6 +13,12 @@ import java.util.Locale;
*/
public class HTTP {
/**
* Constructs a new HTTP object.
*/
public HTTP() {
}
/** Carriage return/line feed. */
public static final String CRLF = "\r\n";

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,31 +1,10 @@
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;
import java.io.StringWriter;
import java.io.Writer;
import java.lang.reflect.Array;
import java.math.BigDecimal;
@ -104,11 +83,24 @@ public class JSONArray implements Iterable<Object> {
* If there is a syntax error.
*/
public JSONArray(JSONTokener x) throws JSONException {
this(x, x.getJsonParserConfiguration());
}
/**
* Constructs a JSONArray from a JSONTokener and a JSONParserConfiguration.
*
* @param x A JSONTokener instance from which the JSONArray is constructed.
* @param jsonParserConfiguration A JSONParserConfiguration instance that controls the behavior of the parser.
* @throws JSONException If a syntax error occurs during the construction of the JSONArray.
*/
public JSONArray(JSONTokener x, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
this();
boolean isInitial = x.getPrevious() == 0;
if (x.nextClean() != '[') {
throw x.syntaxError("A JSONArray text must start with '['");
}
char nextChar = x.nextClean();
if (nextChar == 0) {
// array is unclosed. No ']' found, instead EOF
@ -135,16 +127,35 @@ public class JSONArray implements Iterable<Object> {
throw x.syntaxError("Expected a ',' or ']'");
}
if (nextChar == ']') {
// trailing commas are not allowed in strict mode
if (jsonParserConfiguration.isStrictMode()) {
throw x.syntaxError("Strict mode error: Expected another array element");
}
return;
}
if (nextChar == ',') {
// consecutive commas are not allowed in strict mode
if (jsonParserConfiguration.isStrictMode()) {
throw x.syntaxError("Strict mode error: Expected a valid array element");
}
return;
}
x.back();
break;
case ']':
if (isInitial && jsonParserConfiguration.isStrictMode() &&
x.nextClean() != 0) {
throw x.syntaxError("Strict mode error: Unparsed characters found at end of input text");
}
return;
default:
throw x.syntaxError("Expected a ',' or ']'");
}
}
} else {
if (isInitial && jsonParserConfiguration.isStrictMode() && x.nextClean() != 0) {
throw x.syntaxError("Strict mode error: Unparsed characters found at end of input text");
}
}
}
@ -159,7 +170,22 @@ public class JSONArray implements Iterable<Object> {
* If there is a syntax error.
*/
public JSONArray(String source) throws JSONException {
this(new JSONTokener(source));
this(source, new JSONParserConfiguration());
}
/**
* Construct a JSONArray from a source JSON text.
*
* @param source
* A string that begins with <code>[</code>&nbsp;<small>(left
* bracket)</small> and ends with <code>]</code>
* &nbsp;<small>(right bracket)</small>.
* @param jsonParserConfiguration the parser config object
* @throws JSONException
* If there is a syntax error.
*/
public JSONArray(String source, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
this(new JSONTokener(source, jsonParserConfiguration), jsonParserConfiguration);
}
/**
@ -169,11 +195,40 @@ public class JSONArray implements Iterable<Object> {
* A Collection.
*/
public JSONArray(Collection<?> collection) {
this(collection, 0, new JSONParserConfiguration());
}
/**
* Construct a JSONArray from a Collection.
*
* @param collection
* A Collection.
* @param jsonParserConfiguration
* Configuration object for the JSON parser
*/
public JSONArray(Collection<?> collection, JSONParserConfiguration jsonParserConfiguration) {
this(collection, 0, jsonParserConfiguration);
}
/**
* Construct a JSONArray from a collection with recursion depth.
*
* @param collection
* A Collection.
* @param recursionDepth
* Variable for tracking the count of nested object creations.
* @param jsonParserConfiguration
* Configuration object for the JSON parser
*/
JSONArray(Collection<?> collection, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
if (recursionDepth > jsonParserConfiguration.getMaxNestingDepth()) {
throw new JSONException("JSONArray has reached recursion depth limit of " + jsonParserConfiguration.getMaxNestingDepth());
}
if (collection == null) {
this.myArrayList = new ArrayList<Object>();
} else {
this.myArrayList = new ArrayList<Object>(collection.size());
this.addAll(collection, true);
this.addAll(collection, true, recursionDepth, jsonParserConfiguration);
}
}
@ -225,7 +280,7 @@ public class JSONArray implements Iterable<Object> {
throw new JSONException(
"JSONArray initial value should be a string or collection or array.");
}
this.addAll(array, true);
this.addAll(array, true, 0);
}
/**
@ -279,16 +334,14 @@ public class JSONArray implements Iterable<Object> {
*/
public boolean getBoolean(int index) throws JSONException {
Object object = this.get(index);
if (object.equals(Boolean.FALSE)
|| (object instanceof String && ((String) object)
.equalsIgnoreCase("false"))) {
if (Boolean.FALSE.equals(object)
|| (object instanceof String && "false".equalsIgnoreCase((String) object))) {
return false;
} else if (object.equals(Boolean.TRUE)
|| (object instanceof String && ((String) object)
.equalsIgnoreCase("true"))) {
} else if (Boolean.TRUE.equals(object)
|| (object instanceof String && "true".equalsIgnoreCase((String) object))) {
return true;
}
throw wrongValueFormatException(index, "boolean", null);
throw wrongValueFormatException(index, "boolean", object, null);
}
/**
@ -309,7 +362,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);
}
}
@ -331,7 +384,7 @@ public class JSONArray implements Iterable<Object> {
try {
return Float.parseFloat(object.toString());
} catch (Exception e) {
throw wrongValueFormatException(index, "float", e);
throw wrongValueFormatException(index, "float", object, e);
}
}
@ -353,7 +406,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);
}
}
@ -378,7 +431,7 @@ 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;
}
@ -441,7 +494,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);
}
}
@ -460,7 +513,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);
}
/**
@ -478,7 +531,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);
}
/**
@ -499,7 +552,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);
}
}
@ -517,7 +570,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);
}
/**
@ -619,6 +672,38 @@ public class JSONArray implements Iterable<Object> {
}
}
/**
* Get the optional Boolean object associated with an index. It returns false
* if there is no value at that index, or if the value is not Boolean.TRUE
* or the String "true".
*
* @param index
* The index must be between 0 and length() - 1.
* @return The truth.
*/
public Boolean optBooleanObject(int index) {
return this.optBooleanObject(index, false);
}
/**
* Get the optional Boolean object associated with an index. It returns the
* defaultValue if there is no value at that index or if it is not a Boolean
* or the String "true" or "false" (case insensitive).
*
* @param index
* The index must be between 0 and length() - 1.
* @param defaultValue
* A boolean default.
* @return The truth.
*/
public Boolean optBooleanObject(int index, Boolean defaultValue) {
try {
return this.getBoolean(index);
} catch (Exception e) {
return defaultValue;
}
}
/**
* Get the optional double value associated with an index. NaN is returned
* if there is no value for the index, or if the value is not a number and
@ -655,6 +740,42 @@ public class JSONArray implements Iterable<Object> {
return doubleValue;
}
/**
* Get the optional Double object associated with an index. NaN 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.
*
* @param index
* The index must be between 0 and length() - 1.
* @return The object.
*/
public Double optDoubleObject(int index) {
return this.optDoubleObject(index, Double.NaN);
}
/**
* Get the optional double 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.
*
* @param index
* subscript
* @param defaultValue
* The default object.
* @return The object.
*/
public Double optDoubleObject(int index, Double defaultValue) {
final Number val = this.optNumber(index, null);
if (val == null) {
return defaultValue;
}
final Double doubleValue = val.doubleValue();
// if (Double.isNaN(doubleValue) || Double.isInfinite(doubleValue)) {
// return defaultValue;
// }
return doubleValue;
}
/**
* Get the optional float value associated with an index. NaN is returned
* if there is no value for the index, or if the value is not a number and
@ -691,6 +812,42 @@ public class JSONArray implements Iterable<Object> {
return floatValue;
}
/**
* Get the optional Float object associated with an index. NaN 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.
*
* @param index
* The index must be between 0 and length() - 1.
* @return The object.
*/
public Float optFloatObject(int index) {
return this.optFloatObject(index, Float.NaN);
}
/**
* Get the optional Float object 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.
*
* @param index
* subscript
* @param defaultValue
* The default object.
* @return The object.
*/
public Float optFloatObject(int index, Float defaultValue) {
final Number val = this.optNumber(index, null);
if (val == null) {
return defaultValue;
}
final Float floatValue = val.floatValue();
// if (Float.isNaN(floatValue) || Float.isInfinite(floatValue)) {
// return floatValue;
// }
return floatValue;
}
/**
* Get the optional int value associated with an index. Zero is returned if
* there is no value for the index, or if the value is not a number and
@ -723,6 +880,38 @@ public class JSONArray implements Iterable<Object> {
return val.intValue();
}
/**
* Get the optional Integer object associated with an index. Zero 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.
*
* @param index
* The index must be between 0 and length() - 1.
* @return The object.
*/
public Integer optIntegerObject(int index) {
return this.optIntegerObject(index, 0);
}
/**
* Get the optional Integer object 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.
*
* @param index
* The index must be between 0 and length() - 1.
* @param defaultValue
* The default object.
* @return The object.
*/
public Integer optIntegerObject(int index, Integer defaultValue) {
final Number val = this.optNumber(index, null);
if (val == null) {
return defaultValue;
}
return val.intValue();
}
/**
* Get the enum value associated with a key.
*
@ -808,30 +997,57 @@ public class JSONArray implements Iterable<Object> {
}
/**
* Get the optional JSONArray associated with an index.
* Get the optional JSONArray associated with an index. Null is returned if
* there is no value at that index or if the value is not a JSONArray.
*
* @param index
* subscript
* @return A JSONArray value, or null if the index has no value, or if the
* value is not a JSONArray.
* The index must be between 0 and length() - 1.
* @return A JSONArray value.
*/
public JSONArray optJSONArray(int index) {
Object o = this.opt(index);
return o instanceof JSONArray ? (JSONArray) o : null;
return this.optJSONArray(index, null);
}
/**
* Get the optional JSONArray associated with an index. The defaultValue is returned if
* there is no value at that index or if the value is not a JSONArray.
*
* @param index
* The index must be between 0 and length() - 1.
* @param defaultValue
* The default.
* @return A JSONArray value.
*/
public JSONArray optJSONArray(int index, JSONArray defaultValue) {
Object object = this.opt(index);
return object instanceof JSONArray ? (JSONArray) object : defaultValue;
}
/**
* Get the optional JSONObject associated with an index. Null is returned if
* the key is not found, or null if the index has no value, or if the value
* is not a JSONObject.
* there is no value at that index or if the value is not a JSONObject.
*
* @param index
* The index must be between 0 and length() - 1.
* @return A JSONObject value.
*/
public JSONObject optJSONObject(int index) {
Object o = this.opt(index);
return o instanceof JSONObject ? (JSONObject) o : null;
return this.optJSONObject(index, null);
}
/**
* Get the optional JSONObject associated with an index. The defaultValue is returned if
* there is no value at that index or if the value is not a JSONObject.
*
* @param index
* The index must be between 0 and length() - 1.
* @param defaultValue
* The default.
* @return A JSONObject value.
*/
public JSONObject optJSONObject(int index, JSONObject defaultValue) {
Object object = this.opt(index);
return object instanceof JSONObject ? (JSONObject) object : defaultValue;
}
/**
@ -866,6 +1082,38 @@ public class JSONArray implements Iterable<Object> {
return val.longValue();
}
/**
* Get the optional Long object associated with an index. Zero 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.
*
* @param index
* The index must be between 0 and length() - 1.
* @return The object.
*/
public Long optLongObject(int index) {
return this.optLongObject(index, 0L);
}
/**
* Get the optional Long object 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.
*
* @param index
* The index must be between 0 and length() - 1.
* @param defaultValue
* The default object.
* @return The object.
*/
public Long optLongObject(int index, Long defaultValue) {
final Number val = this.optNumber(index, null);
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,
@ -1155,7 +1403,8 @@ public class JSONArray implements Iterable<Object> {
* The subscript.
* @param value
* The Map value.
* @return this.
* @return
* reference to self
* @throws JSONException
* If the index is negative or if the value is an invalid
* number.
@ -1163,7 +1412,27 @@ public class JSONArray implements Iterable<Object> {
* If a key in the map is <code>null</code>
*/
public JSONArray put(int index, Map<?, ?> value) throws JSONException {
this.put(index, new JSONObject(value));
this.put(index, new JSONObject(value, new JSONParserConfiguration()));
return this;
}
/**
* Put a value in the JSONArray, where the value will be a JSONObject that
* is produced from a Map.
*
* @param index
* The subscript
* @param value
* The Map value.
* @param jsonParserConfiguration
* Configuration object for the JSON parser
* @return reference to self
* @throws JSONException
* If the index is negative or if the value is an invalid
* number.
*/
public JSONArray put(int index, Map<?, ?> value, JSONParserConfiguration jsonParserConfiguration) throws JSONException {
this.put(index, new JSONObject(value, jsonParserConfiguration));
return this;
}
@ -1386,6 +1655,10 @@ public class JSONArray implements Iterable<Object> {
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;
}
@ -1464,11 +1737,13 @@ public class JSONArray implements Iterable<Object> {
* &nbsp;<small>(right bracket)</small>.
* @throws JSONException if a called function fails
*/
@SuppressWarnings("resource")
public String toString(int indentFactor) throws JSONException {
StringWriter sw = new StringWriter();
synchronized (sw.getBuffer()) {
return this.write(sw, indentFactor, 0).toString();
}
// each value requires a comma, so multiply the count by 2
// We don't want to oversize the initial capacity
int initialSize = myArrayList.size() * 2;
Writer sw = new StringBuilderWriter(Math.max(initialSize, 16));
return this.write(sw, indentFactor, 0).toString();
}
/**
@ -1513,6 +1788,7 @@ public class JSONArray implements Iterable<Object> {
* @return The writer.
* @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 {
@ -1600,13 +1876,14 @@ public class JSONArray implements Iterable<Object> {
* @param wrap
* {@code true} to call {@link JSONObject#wrap(Object)} for each item,
* {@code false} to add the items directly
*
* @param recursionDepth
* Variable for tracking the count of nested object creations.
*/
private void addAll(Collection<?> collection, boolean wrap) {
private void addAll(Collection<?> collection, boolean wrap, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) {
this.myArrayList.ensureCapacity(this.myArrayList.size() + collection.size());
if (wrap) {
for (Object o: collection){
this.put(JSONObject.wrap(o));
this.put(JSONObject.wrap(o, recursionDepth + 1, jsonParserConfiguration));
}
} else {
for (Object o: collection){
@ -1635,7 +1912,24 @@ public class JSONArray implements Iterable<Object> {
}
}
}
/**
* 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.
*/
private void addAll(Object array, boolean wrap) throws JSONException {
this.addAll(array, wrap, 0);
}
/**
* Add an array's elements to the JSONArray.
*
@ -1644,21 +1938,40 @@ public class JSONArray implements Iterable<Object> {
* 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
* @param recursionDepth
* Variable for tracking the count of nested object creations.
*/
private void addAll(Object array, boolean wrap, int recursionDepth) {
addAll(array, wrap, recursionDepth, new JSONParserConfiguration());
}
/**
* 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
*
* @param recursionDepth
* Variable for tracking the count of nested object creations.
* @param jsonParserConfiguration
* Variable to pass parser custom configuration for json parsing.
* @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 void addAll(Object array, boolean wrap) throws JSONException {
private void addAll(Object array, boolean wrap, int recursionDepth, JSONParserConfiguration jsonParserConfiguration) 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)));
this.put(JSONObject.wrap(Array.get(array, i), recursionDepth + 1, jsonParserConfiguration));
}
} else {
for (int i = 0; i < length; i += 1) {
@ -1671,7 +1984,7 @@ public class JSONArray implements Iterable<Object> {
// JSONArray
this.myArrayList.addAll(((JSONArray)array).myArrayList);
} else if (array instanceof Collection) {
this.addAll((Collection<?>)array, wrap);
this.addAll((Collection<?>)array, wrap, recursionDepth, jsonParserConfiguration);
} else if (array instanceof Iterable) {
this.addAll((Iterable<?>)array, wrap);
} else {
@ -1680,22 +1993,6 @@ public class JSONArray implements Iterable<Object> {
}
}
/**
* 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.
*/
private static JSONException wrongValueFormatException(
int idx,
String valueType,
Throwable cause) {
return new JSONException(
"JSONArray[" + idx + "] is not a " + valueType + "."
, cause);
}
/**
* Create a new JSONException in a common format for incorrect conversions.
* @param idx index of the item
@ -1708,8 +2005,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.
*/
/**
@ -33,6 +13,13 @@ SOFTWARE.
* @version 2016-01-30
*/
public class JSONML {
/**
* Constructs a new JSONML object.
*/
public JSONML() {
}
/**
* Parse XML values and store them in a JSONArray.
* @param x The XMLTokener containing the source string.
@ -47,7 +34,32 @@ public class JSONML {
XMLTokener x,
boolean arrayForm,
JSONArray ja,
boolean keepStrings
boolean keepStrings,
int currentNestingDepth
) throws JSONException {
return parse(x,arrayForm, ja,
keepStrings ? JSONMLParserConfiguration.KEEP_STRINGS : JSONMLParserConfiguration.ORIGINAL,
currentNestingDepth);
}
/**
* Parse XML values and store them in a JSONArray.
* @param x The XMLTokener containing the source string.
* @param arrayForm true if array form, false if object form.
* @param ja The JSONArray that is containing the current tag or null
* if we are at the outermost level.
* @param config The parser configuration:
* JSONMLParserConfiguration.ORIGINAL is the default behaviour;
* JSONMLParserConfiguration.KEEP_STRINGS means Don't type-convert text nodes and attribute values.
* @return A JSONArray if the value is the outermost tag, otherwise null.
* @throws JSONException if a parsing error occurs
*/
private static Object parse(
XMLTokener x,
boolean arrayForm,
JSONArray ja,
JSONMLParserConfiguration config,
int currentNestingDepth
) throws JSONException {
String attribute;
char c;
@ -99,7 +111,7 @@ public class JSONML {
}
} else if (c == '[') {
token = x.nextToken();
if (token.equals("CDATA") && x.next() == '[') {
if ("CDATA".equals(token) && x.next() == '[') {
if (ja != null) {
ja.put(x.nextCDATA());
}
@ -172,7 +184,7 @@ public class JSONML {
if (!(token instanceof String)) {
throw x.syntaxError("Missing value");
}
newjo.accumulate(attribute, keepStrings ? ((String)token) :XML.stringToValue((String)token));
newjo.accumulate(attribute, config.isKeepStrings() ? ((String)token) :XML.stringToValue((String)token));
token = null;
} else {
newjo.accumulate(attribute, "");
@ -201,7 +213,12 @@ public class JSONML {
if (token != XML.GT) {
throw x.syntaxError("Misshaped tag");
}
closeTag = (String)parse(x, arrayForm, newja, keepStrings);
if (currentNestingDepth == config.getMaxNestingDepth()) {
throw x.syntaxError("Maximum nesting depth of " + config.getMaxNestingDepth() + " reached");
}
closeTag = (String)parse(x, arrayForm, newja, config, currentNestingDepth + 1);
if (closeTag != null) {
if (!closeTag.equals(tagName)) {
throw x.syntaxError("Mismatched '" + tagName +
@ -223,7 +240,7 @@ public class JSONML {
} else {
if (ja != null) {
ja.put(token instanceof String
? keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token)
? (config.isKeepStrings() ? XML.unescape((String)token) : XML.stringToValue((String)token))
: token);
}
}
@ -244,7 +261,7 @@ public class JSONML {
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(String string) throws JSONException {
return (JSONArray)parse(new XMLTokener(string), true, null, false);
return (JSONArray)parse(new XMLTokener(string), true, null, JSONMLParserConfiguration.ORIGINAL, 0);
}
@ -255,8 +272,8 @@ 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.
* As opposed to toJSONArray this method does not attempt to convert
* any text node or attribute value to any type
* 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 <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param string The source string.
@ -266,7 +283,32 @@ public class JSONML {
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException {
return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings);
return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings, 0);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONArray using the JsonML transform. Each XML tag is represented as
* a JSONArray in which the first element is the tag name. If the tag has
* 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.
* 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 <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param string The source string.
* @param config The parser configuration:
* JSONMLParserConfiguration.ORIGINAL is the default behaviour;
* JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
* or numeric values and will instead be left as strings
* @return A JSONArray containing the structured data from the XML string.
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(String string, JSONMLParserConfiguration config) throws JSONException {
return (JSONArray)parse(new XMLTokener(string), true, null, config, 0);
}
@ -277,8 +319,32 @@ 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.
* As opposed to toJSONArray this method does not attempt to convert
* any text node or attribute value to any type
* 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 <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param x An XMLTokener.
* @param config The parser configuration:
* JSONMLParserConfiguration.ORIGINAL is the default behaviour;
* JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
* or numeric values and will instead be left as strings
* @return A JSONArray containing the structured data from the XML string.
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(XMLTokener x, JSONMLParserConfiguration config) throws JSONException {
return (JSONArray)parse(x, true, null, config, 0);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONArray using the JsonML transform. Each XML tag is represented as
* a JSONArray in which the first element is the tag name. If the tag has
* 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.
* 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 <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param x An XMLTokener.
@ -288,7 +354,7 @@ public class JSONML {
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException {
return (JSONArray)parse(x, true, null, keepStrings);
return (JSONArray)parse(x, true, null, keepStrings, 0);
}
@ -305,7 +371,7 @@ public class JSONML {
* @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
return (JSONArray)parse(x, true, null, false);
return (JSONArray)parse(x, true, null, false, 0);
}
@ -323,10 +389,10 @@ public class JSONML {
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(String string) throws JSONException {
return (JSONObject)parse(new XMLTokener(string), false, null, false);
return (JSONObject)parse(new XMLTokener(string), false, null, false, 0);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONObject using the JsonML transform. Each XML tag is represented as
@ -343,10 +409,32 @@ public class JSONML {
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings);
return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings, 0);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONObject using the JsonML transform. Each XML tag is represented as
* a JSONObject with a "tagName" property. If the tag has attributes, then
* the attributes will be in the JSONObject as properties. If the tag
* contains children, the object will have a "childNodes" property which
* will be an array of strings and JsonML JSONObjects.
* Comments, prologs, DTDs, and <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param string The XML source text.
* @param config The parser configuration:
* JSONMLParserConfiguration.ORIGINAL is the default behaviour;
* JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
* or numeric values and will instead be left as strings
* @return A JSONObject containing the structured data from the XML string.
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(String string, JSONMLParserConfiguration config) throws JSONException {
return (JSONObject)parse(new XMLTokener(string), false, null, config, 0);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONObject using the JsonML transform. Each XML tag is represented as
@ -361,7 +449,7 @@ public class JSONML {
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
return (JSONObject)parse(x, false, null, false);
return (JSONObject)parse(x, false, null, false, 0);
}
@ -381,7 +469,29 @@ public class JSONML {
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) throws JSONException {
return (JSONObject)parse(x, false, null, keepStrings);
return (JSONObject)parse(x, false, null, keepStrings, 0);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONObject using the JsonML transform. Each XML tag is represented as
* a JSONObject with a "tagName" property. If the tag has attributes, then
* the attributes will be in the JSONObject as properties. If the tag
* contains children, the object will have a "childNodes" property which
* will be an array of strings and JsonML JSONObjects.
* Comments, prologs, DTDs, and <pre>{@code &lt;[ [ ]]>}</pre> are ignored.
* @param x An XMLTokener of the XML source text.
* @param config The parser configuration:
* JSONMLParserConfiguration.ORIGINAL is the default behaviour;
* JSONMLParserConfiguration.KEEP_STRINGS means values will not be coerced into boolean
* or numeric values and will instead be left as strings
* @return A JSONObject containing the structured data from the XML string.
* @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(XMLTokener x, JSONMLParserConfiguration config) throws JSONException {
return (JSONObject)parse(x, false, null, config, 0);
}
@ -462,6 +572,7 @@ public class JSONML {
return sb.toString();
}
/**
* Reverse the JSONML transformation, making an XML text from a JSONObject.
* The JSONObject must contain a "tagName" property. If it has children,

View File

@ -0,0 +1,69 @@
package org.json;
/*
Public Domain.
*/
/**
* Configuration object for the XML to JSONML parser. The configuration is immutable.
*/
@SuppressWarnings({""})
public class JSONMLParserConfiguration extends ParserConfiguration {
/**
* We can override the default maximum nesting depth if needed.
*/
public static final int DEFAULT_MAXIMUM_NESTING_DEPTH = ParserConfiguration.DEFAULT_MAXIMUM_NESTING_DEPTH;
/** Original Configuration of the XML to JSONML Parser. */
public static final JSONMLParserConfiguration ORIGINAL
= new JSONMLParserConfiguration();
/** Original configuration of the XML to JSONML Parser except that values are kept as strings. */
public static final JSONMLParserConfiguration KEEP_STRINGS
= new JSONMLParserConfiguration().withKeepStrings(true);
/**
* Default parser configuration. Does not keep strings (tries to implicitly convert values).
*/
public JSONMLParserConfiguration() {
super();
this.maxNestingDepth = DEFAULT_MAXIMUM_NESTING_DEPTH;
}
/**
* 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.
* @param maxNestingDepth <code>int</code> to limit the nesting depth
*/
protected JSONMLParserConfiguration(final boolean keepStrings, final int maxNestingDepth) {
super(keepStrings, maxNestingDepth);
}
/**
* Provides a new instance of the same configuration.
*/
@Override
protected JSONMLParserConfiguration 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 JSONMLParserConfiguration(
this.keepStrings,
this.maxNestingDepth
);
}
@SuppressWarnings("unchecked")
@Override
public JSONMLParserConfiguration withKeepStrings(final boolean newVal) {
return super.withKeepStrings(newVal);
}
@SuppressWarnings("unchecked")
@Override
public JSONMLParserConfiguration withMaxNestingDepth(int maxNestingDepth) {
return super.withMaxNestingDepth(maxNestingDepth);
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,152 @@
package org.json;
/**
* Configuration object for the JSON parser. The configuration is immutable.
*/
public class JSONParserConfiguration extends ParserConfiguration {
/**
* Used to indicate whether to overwrite duplicate key or not.
*/
private boolean overwriteDuplicateKey;
/**
* Used to indicate whether to convert java null values to JSONObject.NULL or ignoring the entry when converting java maps.
*/
private boolean useNativeNulls;
/**
* Configuration with the default values.
*/
public JSONParserConfiguration() {
super();
this.overwriteDuplicateKey = false;
// DO NOT DELETE THE FOLLOWING LINE -- it is used for strictMode testing
// this.strictMode = true;
}
/**
* This flag, when set to true, instructs the parser to enforce strict mode when parsing JSON text.
* Garbage chars at the end of the doc, unquoted string, and single-quoted strings are all disallowed.
*/
private boolean strictMode;
@Override
protected JSONParserConfiguration clone() {
JSONParserConfiguration clone = new JSONParserConfiguration();
clone.overwriteDuplicateKey = overwriteDuplicateKey;
clone.strictMode = strictMode;
clone.maxNestingDepth = maxNestingDepth;
clone.keepStrings = keepStrings;
clone.useNativeNulls = useNativeNulls;
return clone;
}
/**
* Defines the maximum nesting depth that the parser will descend before throwing an exception
* when parsing a map into JSONObject or parsing a {@link java.util.Collection} instance into
* JSONArray. The default max nesting depth is 512, which means the parser will throw a JsonException
* if the maximum depth is reached.
*
* @param maxNestingDepth the maximum nesting depth allowed to the JSON parser
* @return The existing configuration will not be modified. A new configuration is returned.
*/
@SuppressWarnings("unchecked")
@Override
public JSONParserConfiguration withMaxNestingDepth(final int maxNestingDepth) {
JSONParserConfiguration clone = this.clone();
clone.maxNestingDepth = maxNestingDepth;
return clone;
}
/**
* Controls the parser's behavior when meeting duplicate keys.
* If set to false, the parser will throw a JSONException when meeting a duplicate key.
* Or the duplicate key's value will be overwritten.
*
* @param overwriteDuplicateKey defines should the parser overwrite duplicate keys.
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public JSONParserConfiguration withOverwriteDuplicateKey(final boolean overwriteDuplicateKey) {
JSONParserConfiguration clone = this.clone();
clone.overwriteDuplicateKey = overwriteDuplicateKey;
return clone;
}
/**
* Controls the parser's behavior when meeting Java null values while converting maps.
* If set to true, the parser will put a JSONObject.NULL into the resulting JSONObject.
* Or the map entry will be ignored.
*
* @param useNativeNulls defines if the parser should convert null values in Java maps
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public JSONParserConfiguration withUseNativeNulls(final boolean useNativeNulls) {
JSONParserConfiguration clone = this.clone();
clone.useNativeNulls = useNativeNulls;
return clone;
}
/**
* Sets the strict mode configuration for the JSON parser with default true value
* <p>
* When strict mode is enabled, the parser will throw a JSONException if it encounters an invalid character
* immediately following the final ']' character in the input. This is useful for ensuring strict adherence to the
* JSON syntax, as any characters after the final closing bracket of a JSON array are considered invalid.
* @return a new JSONParserConfiguration instance with the updated strict mode setting
*/
public JSONParserConfiguration withStrictMode() {
return withStrictMode(true);
}
/**
* Sets the strict mode configuration for the JSON parser.
* <p>
* When strict mode is enabled, the parser will throw a JSONException if it encounters an invalid character
* immediately following the final ']' character in the input. This is useful for ensuring strict adherence to the
* JSON syntax, as any characters after the final closing bracket of a JSON array are considered invalid.
*
* @param mode a boolean value indicating whether strict mode should be enabled or not
* @return a new JSONParserConfiguration instance with the updated strict mode setting
*/
public JSONParserConfiguration withStrictMode(final boolean mode) {
JSONParserConfiguration clone = this.clone();
clone.strictMode = mode;
return clone;
}
/**
* The parser's behavior when meeting duplicate keys, controls whether the parser should
* overwrite duplicate keys or not.
*
* @return The <code>overwriteDuplicateKey</code> configuration value.
*/
public boolean isOverwriteDuplicateKey() {
return this.overwriteDuplicateKey;
}
/**
* The parser's behavior when meeting a null value in a java map, controls whether the parser should
* write a JSON entry with a null value (<code>isUseNativeNulls() == true</code>)
* or ignore that map entry (<code>isUseNativeNulls() == false</code>).
*
* @return The <code>useNativeNulls</code> configuration value.
*/
public boolean isUseNativeNulls() {
return this.useNativeNulls;
}
/**
* The parser throws an Exception when strict mode is true and tries to parse invalid JSON characters.
* Otherwise, the parser is more relaxed and might tolerate some invalid characters.
*
* @return the current strict mode setting.
*/
public boolean isStrictMode() {
return this.strictMode;
}
}

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.
*/
/**
@ -62,6 +42,12 @@ public class JSONPointer {
*/
public static class Builder {
/**
* Constructs a new Builder object.
*/
public Builder() {
}
// Segments for the eventual JSONPointer string
private final List<String> refTokens = new ArrayList<String>();
@ -141,7 +127,7 @@ public class JSONPointer {
if (pointer == null) {
throw new NullPointerException("pointer cannot be null");
}
if (pointer.isEmpty() || pointer.equals("#")) {
if (pointer.isEmpty() || "#".equals(pointer)) {
this.refTokens = Collections.emptyList();
return;
}
@ -183,6 +169,12 @@ public class JSONPointer {
//}
}
/**
* Constructs a new JSONPointer instance with the provided list of reference tokens.
*
* @param refTokens A list of strings representing the reference tokens for the JSON Pointer.
* Each token identifies a step in the path to the targeted value.
*/
public JSONPointer(List<String> refTokens) {
this.refTokens = new ArrayList<String>(refTokens);
}
@ -254,7 +246,7 @@ public class JSONPointer {
*/
@Override
public String toString() {
StringBuilder rval = new StringBuilder("");
StringBuilder rval = new StringBuilder();
for (String token: this.refTokens) {
rval.append('/').append(escape(token));
}

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.
*/
/**
@ -34,10 +14,21 @@ SOFTWARE.
public class JSONPointerException extends JSONException {
private static final long serialVersionUID = 8872944667561856751L;
/**
* Constructs a new JSONPointerException with the specified error message.
*
* @param message The detail message describing the reason for the exception.
*/
public JSONPointerException(String message) {
super(message);
}
/**
* Constructs a new JSONPointerException with the specified error message and cause.
*
* @param message The detail message describing the reason for the exception.
* @param cause The cause of the exception.
*/
public JSONPointerException(String message, Throwable cause) {
super(message, cause);
}

View File

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

View File

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

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

View File

@ -1,34 +1,10 @@
package org.json;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.io.*;
import java.nio.charset.Charset;
/*
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.
*/
/**
@ -56,13 +32,27 @@ public class JSONTokener {
/** the number of characters read in the previous line. */
private long characterPreviousLine;
// access to this object is required for strict mode checking
private JSONParserConfiguration jsonParserConfiguration;
/**
* Construct a JSONTokener from a Reader. The caller must close the Reader.
*
* @param reader A reader.
* @param reader the source.
*/
public JSONTokener(Reader reader) {
this(reader, new JSONParserConfiguration());
}
/**
* Construct a JSONTokener from a Reader with a given JSONParserConfiguration. The caller must close the Reader.
*
* @param reader the source.
* @param jsonParserConfiguration A JSONParserConfiguration instance that controls the behavior of the parser.
*
*/
public JSONTokener(Reader reader, JSONParserConfiguration jsonParserConfiguration) {
this.jsonParserConfiguration = jsonParserConfiguration;
this.reader = reader.markSupported()
? reader
: new BufferedReader(reader);
@ -75,25 +65,60 @@ public class JSONTokener {
this.line = 1;
}
/**
* Construct a JSONTokener from an InputStream. The caller must close the input stream.
* @param inputStream The source.
*/
public JSONTokener(InputStream inputStream) {
this(new InputStreamReader(inputStream));
this(inputStream, new JSONParserConfiguration());
}
/**
* Construct a JSONTokener from an InputStream. The caller must close the input stream.
* @param inputStream The source.
* @param jsonParserConfiguration A JSONParserConfiguration instance that controls the behavior of the parser.
*/
public JSONTokener(InputStream inputStream, JSONParserConfiguration jsonParserConfiguration) {
this(new InputStreamReader(inputStream, Charset.forName("UTF-8")), jsonParserConfiguration);
}
/**
* Construct a JSONTokener from a string.
*
* @param s A source string.
* @param source A source string.
*/
public JSONTokener(String s) {
this(new StringReader(s));
public JSONTokener(String source) {
this(new StringReader(source));
}
/**
* Construct a JSONTokener from an InputStream. The caller must close the input stream.
* @param source The source.
* @param jsonParserConfiguration A JSONParserConfiguration instance that controls the behavior of the parser.
*/
public JSONTokener(String source, JSONParserConfiguration jsonParserConfiguration) {
this(new StringReader(source), jsonParserConfiguration);
}
/**
* Getter
* @return jsonParserConfiguration
*/
public JSONParserConfiguration getJsonParserConfiguration() {
return jsonParserConfiguration;
}
/**
* Setter
* @param jsonParserConfiguration new value for jsonParserConfiguration
*
* @deprecated method should not be used
*/
@Deprecated
public void setJsonParserConfiguration(JSONParserConfiguration jsonParserConfiguration) {
this.jsonParserConfiguration = jsonParserConfiguration;
}
/**
* Back up one character. This provides a sort of lookahead capability,
@ -145,7 +170,7 @@ public class JSONTokener {
/**
* Checks if the end of the input has been reached.
*
*
* @return true if at the end of the file and we didn't step back
*/
public boolean end() {
@ -209,7 +234,7 @@ 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.
@ -323,7 +348,8 @@ public class JSONTokener {
case 0:
case '\n':
case '\r':
throw this.syntaxError("Unterminated string");
throw this.syntaxError("Unterminated string. " +
"Character with int code " + (int) c + " is not allowed within a quoted string.");
case '\\':
c = this.next();
switch (c) {
@ -343,10 +369,12 @@ public class JSONTokener {
sb.append('\r');
break;
case 'u':
String next = this.next(4);
try {
sb.append((char)Integer.parseInt(this.next(4), 16));
sb.append((char)Integer.parseInt(next, 16));
} catch (NumberFormatException e) {
throw this.syntaxError("Illegal escape.", e);
throw this.syntaxError("Illegal escape. " +
"\\u must be followed by a 4 digit hexadecimal number. \\" + next + " is not valid.", e);
}
break;
case '"':
@ -356,7 +384,7 @@ public class JSONTokener {
sb.append(c);
break;
default:
throw this.syntaxError("Illegal escape.");
throw this.syntaxError("Illegal escape. Escape sequence \\" + c + " is not valid.");
}
break;
default:
@ -426,27 +454,39 @@ public class JSONTokener {
*/
public Object nextValue() throws JSONException {
char c = this.nextClean();
String string;
switch (c) {
case '"':
case '\'':
return this.nextString(c);
case '{':
this.back();
try {
return new JSONObject(this);
return new JSONObject(this, jsonParserConfiguration);
} catch (StackOverflowError e) {
throw new JSONException("JSON Array or Object depth too large to process.", e);
}
case '[':
this.back();
try {
return new JSONArray(this);
return new JSONArray(this, jsonParserConfiguration);
} catch (StackOverflowError e) {
throw new JSONException("JSON Array or Object depth too large to process.", e);
}
}
return nextSimpleValue(c);
}
Object nextSimpleValue(char c) {
String string;
// Strict mode only allows strings with explicit double quotes
if (jsonParserConfiguration != null &&
jsonParserConfiguration.isStrictMode() &&
c == '\'') {
throw this.syntaxError("Strict mode error: Single quoted strings are not allowed");
}
switch (c) {
case '"':
case '\'':
return this.nextString(c);
}
/*
* Handle unquoted text. This could be the values true, false, or
@ -470,7 +510,24 @@ public class JSONTokener {
if ("".equals(string)) {
throw this.syntaxError("Missing value");
}
return JSONObject.stringToValue(string);
Object obj = JSONObject.stringToValue(string);
// if obj is a boolean, look at string
if (jsonParserConfiguration != null &&
jsonParserConfiguration.isStrictMode()) {
if (obj instanceof Boolean && !"true".equals(string) && !"false".equals(string)) {
// Strict mode only allows lowercase true or false
throw this.syntaxError(String.format("Strict mode error: Value '%s' is not lowercase boolean", obj));
}
else if (obj == JSONObject.NULL && !"null".equals(string)) {
// Strint mode only allows lowercase null
throw this.syntaxError(String.format("Strict mode error: Value '%s' is not lowercase null", obj));
}
else if (obj instanceof String) {
// Strict mode only allows strings with explicit double quotes
throw this.syntaxError(String.format("Strict mode error: Value '%s' is not surrounded by quotes", obj));
}
}
return obj;
}
@ -542,4 +599,15 @@ public class JSONTokener {
return " at " + this.index + " [character " + this.character + " line " +
this.line + "]";
}
/**
* Closes the underlying reader, releasing any resources associated with it.
*
* @throws IOException If an I/O error occurs while closing the reader.
*/
public void close() throws IOException {
if(reader!=null){
reader.close();
}
}
}

View File

@ -5,27 +5,7 @@ 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.
Public Domain.
*/
/**

View File

@ -0,0 +1,126 @@
package org.json;
/*
Public Domain.
*/
/**
* Configuration base object for parsers. The configuration is immutable.
*/
@SuppressWarnings({""})
public class ParserConfiguration {
/**
* Used to indicate there's no defined limit to the maximum nesting depth when parsing a document.
*/
public static final int UNDEFINED_MAXIMUM_NESTING_DEPTH = -1;
/**
* The default maximum nesting depth when parsing a document.
*/
public static final int DEFAULT_MAXIMUM_NESTING_DEPTH = 512;
/**
* 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).
*/
protected boolean keepStrings;
/**
* The maximum nesting depth when parsing an object.
*/
protected int maxNestingDepth;
/**
* Constructs a new ParserConfiguration with default settings.
*/
public ParserConfiguration() {
this.keepStrings = false;
this.maxNestingDepth = DEFAULT_MAXIMUM_NESTING_DEPTH;
}
/**
* Constructs a new ParserConfiguration with the specified settings.
*
* @param keepStrings A boolean indicating whether to preserve strings during parsing.
* @param maxNestingDepth An integer representing the maximum allowed nesting depth.
*/
protected ParserConfiguration(final boolean keepStrings, final int maxNestingDepth) {
this.keepStrings = keepStrings;
this.maxNestingDepth = maxNestingDepth;
}
/**
* Provides a new instance of the same configuration.
*/
@Override
protected ParserConfiguration 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 ParserConfiguration(
this.keepStrings,
this.maxNestingDepth
);
}
/**
* When parsing the XML into JSONML, 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 JSONML, 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.
* @param <T> the type of the configuration object
* @return The existing configuration will not be modified. A new configuration is returned.
*/
@SuppressWarnings("unchecked")
public <T extends ParserConfiguration> T withKeepStrings(final boolean newVal) {
T newConfig = (T) this.clone();
newConfig.keepStrings = newVal;
return newConfig;
}
/**
* The maximum nesting depth that the parser will descend before throwing an exception
* when parsing an object (e.g. Map, Collection) into JSON-related objects.
*
* @return the maximum nesting depth set for this configuration
*/
public int getMaxNestingDepth() {
return maxNestingDepth;
}
/**
* Defines the maximum nesting depth that the parser will descend before throwing an exception
* when parsing an object (e.g. Map, Collection) into JSON-related objects.
* The default max nesting depth is 512, which means the parser will throw a JsonException if
* the maximum depth is reached.
* Using any negative value as a parameter is equivalent to setting no limit to the nesting depth,
* which means the parses will go as deep as the maximum call stack size allows.
*
* @param maxNestingDepth the maximum nesting depth allowed to the XML parser
* @param <T> the type of the configuration object
* @return The existing configuration will not be modified. A new configuration is returned.
*/
@SuppressWarnings("unchecked")
public <T extends ParserConfiguration> T withMaxNestingDepth(int maxNestingDepth) {
T newConfig = (T) this.clone();
if (maxNestingDepth > UNDEFINED_MAXIMUM_NESTING_DEPTH) {
newConfig.maxNestingDepth = maxNestingDepth;
} else {
newConfig.maxNestingDepth = UNDEFINED_MAXIMUM_NESTING_DEPTH;
}
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.util.Enumeration;
@ -33,6 +13,13 @@ import java.util.Properties;
* @version 2015-05-05
*/
public class Property {
/**
* Constructs a new Property object.
*/
public 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

View File

@ -0,0 +1,92 @@
package org.json;
import java.io.IOException;
import java.io.Writer;
/**
* Performance optimised alternative for {@link java.io.StringWriter}
* using internally a {@link StringBuilder} instead of a {@link StringBuffer}.
*/
public class StringBuilderWriter extends Writer {
private final StringBuilder builder;
/**
* Create a new string builder writer using the default initial string-builder buffer size.
*/
public StringBuilderWriter() {
builder = new StringBuilder();
lock = builder;
}
/**
* Create a new string builder writer using the specified initial string-builder buffer size.
*
* @param initialSize The number of {@code char} values that will fit into this buffer
* before it is automatically expanded
*
* @throws IllegalArgumentException If {@code initialSize} is negative
*/
public StringBuilderWriter(int initialSize) {
builder = new StringBuilder(initialSize);
lock = builder;
}
@Override
public void write(int c) {
builder.append((char) c);
}
@Override
public void write(char[] cbuf, int offset, int length) {
if ((offset < 0) || (offset > cbuf.length) || (length < 0) ||
((offset + length) > cbuf.length) || ((offset + length) < 0)) {
throw new IndexOutOfBoundsException();
} else if (length == 0) {
return;
}
builder.append(cbuf, offset, length);
}
@Override
public void write(String str) {
builder.append(str);
}
@Override
public void write(String str, int offset, int length) {
builder.append(str, offset, offset + length);
}
@Override
public StringBuilderWriter append(CharSequence csq) {
write(String.valueOf(csq));
return this;
}
@Override
public StringBuilderWriter append(CharSequence csq, int start, int end) {
if (csq == null) {
csq = "null";
}
return append(csq.subSequence(start, end));
}
@Override
public StringBuilderWriter append(char c) {
write(c);
return this;
}
@Override
public String toString() {
return builder.toString();
}
@Override
public void flush() {
}
@Override
public void close() throws IOException {
}
}

View File

@ -1,37 +1,15 @@
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.lang.reflect.Method;
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.
@ -42,6 +20,12 @@ import java.util.Iterator;
@SuppressWarnings("boxing")
public class XML {
/**
* Constructs a new XML object.
*/
public XML() {
}
/** The Character '&amp;'. */
public static final Character AMP = '&';
@ -74,6 +58,9 @@ public class XML {
*/
public static final String NULL_ATTR = "xsi:nil";
/**
* Represents the XML attribute name for specifying type information.
*/
public static final String TYPE_ATTR = "xsi:type";
/**
@ -119,7 +106,7 @@ public class XML {
/**
* Replace special characters with XML escapes:
*
* <pre>{@code
* <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;
@ -250,10 +237,14 @@ public class XML {
* The JSONObject that will include the new material.
* @param name
* The tag name.
* @param config
* The XML parser configuration.
* @param currentNestingDepth
* The current nesting depth.
* @return true if the close tag is processed.
* @throws JSONException
* @throws JSONException Thrown if any parsing error occurs.
*/
private static boolean parse(XMLTokener x, JSONObject context, String name, XMLParserConfiguration config)
private static boolean parse(XMLTokener x, JSONObject context, String name, XMLParserConfiguration config, int currentNestingDepth)
throws JSONException {
char c;
int i;
@ -364,10 +355,20 @@ public class XML {
&& TYPE_ATTR.equals(string)) {
xmlXsiTypeConverter = config.getXsiTypeMap().get(token);
} else if (!nilAttributeFound) {
jsonObject.accumulate(string,
config.isKeepStrings()
? ((String) token)
: stringToValue((String) token));
Object obj = stringToValue((String) token);
if (obj instanceof Boolean) {
jsonObject.accumulate(string,
config.isKeepBooleanAsString()
? ((String) token)
: obj);
} else if (obj instanceof Number) {
jsonObject.accumulate(string,
config.isKeepNumberAsString()
? ((String) token)
: obj);
} else {
jsonObject.accumulate(string, stringToValue((String) token));
}
}
token = null;
} else {
@ -416,14 +417,33 @@ public class XML {
jsonObject.accumulate(config.getcDataTagName(),
stringToValue(string, xmlXsiTypeConverter));
} else {
jsonObject.accumulate(config.getcDataTagName(),
config.isKeepStrings() ? string : stringToValue(string));
Object obj = stringToValue((String) token);
if (obj instanceof Boolean) {
jsonObject.accumulate(config.getcDataTagName(),
config.isKeepBooleanAsString()
? ((String) token)
: obj);
} else if (obj instanceof Number) {
jsonObject.accumulate(config.getcDataTagName(),
config.isKeepNumberAsString()
? ((String) token)
: obj);
} else if (obj == JSONObject.NULL) {
jsonObject.accumulate(config.getcDataTagName(),
config.isKeepStrings() ? ((String) token) : obj);
} else {
jsonObject.accumulate(config.getcDataTagName(), stringToValue((String) token));
}
}
}
} else if (token == LT) {
// Nested element
if (parse(x, jsonObject, tagName, config)) {
if (currentNestingDepth == config.getMaxNestingDepth()) {
throw x.syntaxError("Maximum nesting depth of " + config.getMaxNestingDepth() + " reached");
}
if (parse(x, jsonObject, tagName, config, currentNestingDepth + 1)) {
if (config.getForceList().contains(tagName)) {
// Force the value to be an array
if (jsonObject.length() == 0) {
@ -441,10 +461,13 @@ public class XML {
&& jsonObject.opt(config.getcDataTagName()) != null) {
context.accumulate(tagName, jsonObject.opt(config.getcDataTagName()));
} else {
if (!config.shouldTrimWhiteSpace()) {
removeEmpty(jsonObject, config);
}
context.accumulate(tagName, jsonObject);
}
}
return false;
}
}
@ -455,6 +478,118 @@ public class XML {
}
}
}
/**
* This method removes any JSON entry which has the key set by XMLParserConfiguration.cDataTagName
* and contains whitespace as this is caused by whitespace between tags. See test XMLTest.testNestedWithWhitespaceTrimmingDisabled.
* @param jsonObject JSONObject which may require deletion
* @param config The XMLParserConfiguration which includes the cDataTagName
*/
private static void removeEmpty(final JSONObject jsonObject, final XMLParserConfiguration config) {
if (jsonObject.has(config.getcDataTagName())) {
final Object s = jsonObject.get(config.getcDataTagName());
if (s instanceof String) {
if (isStringAllWhiteSpace(s.toString())) {
jsonObject.remove(config.getcDataTagName());
}
}
else if (s instanceof JSONArray) {
final JSONArray sArray = (JSONArray) s;
for (int k = sArray.length()-1; k >= 0; k--){
final Object eachString = sArray.get(k);
if (eachString instanceof String) {
String s1 = (String) eachString;
if (isStringAllWhiteSpace(s1)) {
sArray.remove(k);
}
}
}
if (sArray.isEmpty()) {
jsonObject.remove(config.getcDataTagName());
}
}
}
}
private static boolean isStringAllWhiteSpace(final String s) {
for (int k = 0; k<s.length(); k++){
final char eachChar = s.charAt(k);
if (!Character.isWhitespace(eachChar)) {
return false;
}
}
return true;
}
/**
* 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);
}
/**
* This method tries to convert the given string value to the target object
@ -508,78 +643,6 @@ public class XML {
}
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
@ -589,7 +652,7 @@ 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 <pre>{@code
* "content" member. Comments, prologs, DTDs, and <pre>{@code
* &lt;[ [ ]]>}</pre>
* are ignored.
*
@ -610,7 +673,7 @@ 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 <pre>{@code
* "content" member. Comments, prologs, DTDs, and <pre>{@code
* &lt;[ [ ]]>}</pre>
* are ignored.
*
@ -650,6 +713,44 @@ public class XML {
return toJSONObject(reader, XMLParserConfiguration.ORIGINAL);
}
/**
* Convert a well-formed (but not necessarily valid) XML into a
* JSONObject. Some information may be lost in this transformation because
* JSON is a data format and XML is a document format. XML uses elements,
* attributes, and content text, while JSON uses unordered collections of
* name/value pairs and arrays of values. JSON does not does not like to
* distinguish between elements and attributes. Sequences of similar
* elements are represented as JSONArrays. Content text may be placed in a
* "content" member. Comments, prologs, DTDs, and <pre>{@code
* &lt;[ [ ]]>}</pre>
* are ignored.
*
* All numbers are converted as strings, for 1, 01, 29.0 will not be coerced to
* numbers but will instead be the exact value as seen in the XML document depending
* on how flag is set.
* All booleans are converted as strings, for true, false will not be coerced to
* booleans but will instead be the exact value as seen in the XML document depending
* on how flag is set.
*
* @param reader The XML source reader.
* @param keepNumberAsString If true, then numeric values will not be coerced into
* numeric values and will instead be left as strings
* @param keepBooleanAsString If true, then boolean values will not be coerced into
* * numeric values and will instead be left as strings
* @return A JSONObject containing the structured data from the XML string.
* @throws JSONException Thrown if there is an errors while parsing the string
*/
public static JSONObject toJSONObject(Reader reader, boolean keepNumberAsString, boolean keepBooleanAsString) throws JSONException {
XMLParserConfiguration xmlParserConfiguration = new XMLParserConfiguration();
if(keepNumberAsString) {
xmlParserConfiguration = xmlParserConfiguration.withKeepNumberAsString(keepNumberAsString);
}
if(keepBooleanAsString) {
xmlParserConfiguration = xmlParserConfiguration.withKeepBooleanAsString(keepBooleanAsString);
}
return toJSONObject(reader, xmlParserConfiguration);
}
/**
* Convert a well-formed (but not necessarily valid) XML into a
* JSONObject. Some information may be lost in this transformation because
@ -672,11 +773,11 @@ public class XML {
*/
public static JSONObject toJSONObject(Reader reader, XMLParserConfiguration config) throws JSONException {
JSONObject jo = new JSONObject();
XMLTokener x = new XMLTokener(reader);
XMLTokener x = new XMLTokener(reader, config);
while (x.more()) {
x.skipPast("<");
if(x.more()) {
parse(x, jo, null, config);
parse(x, jo, null, config, 0);
}
}
return jo;
@ -690,7 +791,7 @@ 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 <pre>{@code
* "content" member. Comments, prologs, DTDs, and <pre>{@code
* &lt;[ [ ]]>}</pre>
* are ignored.
*
@ -716,7 +817,39 @@ 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 <pre>{@code
* "content" member. Comments, prologs, DTDs, and <pre>{@code
* &lt;[ [ ]]>}</pre>
* are ignored.
*
* All numbers are converted as strings, for 1, 01, 29.0 will not be coerced to
* numbers but will instead be the exact value as seen in the XML document depending
* on how flag is set.
* All booleans are converted as strings, for true, false will not be coerced to
* booleans but will instead be the exact value as seen in the XML document depending
* on how flag is set.
*
* @param string
* The source string.
* @param keepNumberAsString If true, then numeric values will not be coerced into
* numeric values and will instead be left as strings
* @param keepBooleanAsString If true, then boolean values will not be coerced into
* numeric values and will instead be left as strings
* @return A JSONObject containing the structured data from the XML string.
* @throws JSONException Thrown if there is an errors while parsing the string
*/
public static JSONObject toJSONObject(String string, boolean keepNumberAsString, boolean keepBooleanAsString) throws JSONException {
return toJSONObject(new StringReader(string), keepNumberAsString, keepBooleanAsString);
}
/**
* Convert a well-formed (but not necessarily valid) XML string into a
* JSONObject. Some information may be lost in this transformation because
* JSON is a data format and XML is a document format. XML uses elements,
* attributes, and content text, while JSON uses unordered collections of
* name/value pairs and arrays of values. JSON does not does not like to
* distinguish between elements and attributes. Sequences of similar
* elements are represented as JSONArrays. Content text may be placed in a
* "content" member. Comments, prologs, DTDs, and <pre>{@code
* &lt;[ [ ]]>}</pre>
* are ignored.
*
@ -773,6 +906,28 @@ public class XML {
*/
public static String toString(final Object object, final String tagName, final XMLParserConfiguration config)
throws JSONException {
return toString(object, tagName, config, 0, 0);
}
/**
* Convert a JSONObject into a well-formed, element-normal XML string,
* either pretty print or single-lined depending on indent factor.
*
* @param object
* A JSONObject.
* @param tagName
* The optional name of the enclosing tag.
* @param config
* Configuration that can control output to XML.
* @param indentFactor
* The number of spaces to add to each level of indentation.
* @param indent
* The current ident level in spaces.
* @return
* @throws JSONException
*/
private static String toString(final Object object, final String tagName, final XMLParserConfiguration config, int indentFactor, int indent)
throws JSONException {
StringBuilder sb = new StringBuilder();
JSONArray ja;
JSONObject jo;
@ -782,9 +937,14 @@ public class XML {
// Emit <tagName>
if (tagName != null) {
sb.append(indent(indent));
sb.append('<');
sb.append(tagName);
sb.append('>');
if(indentFactor > 0){
sb.append("\n");
indent += indentFactor;
}
}
// Loop thru the keys.
@ -827,31 +987,52 @@ public class XML {
sb.append('<');
sb.append(key);
sb.append('>');
sb.append(toString(val, null, config));
sb.append(toString(val, null, config, indentFactor, indent));
sb.append("</");
sb.append(key);
sb.append('>');
} else {
sb.append(toString(val, key, config));
sb.append(toString(val, key, config, indentFactor, indent));
}
}
} else if ("".equals(value)) {
sb.append('<');
sb.append(key);
sb.append("/>");
if (config.isCloseEmptyTag()){
sb.append(indent(indent));
sb.append('<');
sb.append(key);
sb.append(">");
sb.append("</");
sb.append(key);
sb.append(">");
if (indentFactor > 0) {
sb.append("\n");
}
}else {
sb.append(indent(indent));
sb.append('<');
sb.append(key);
sb.append("/>");
if (indentFactor > 0) {
sb.append("\n");
}
}
// Emit a new tag <k>
} else {
sb.append(toString(value, key, config));
sb.append(toString(value, key, config, indentFactor, indent));
}
}
if (tagName != null) {
// Emit the </tagName> close tag
sb.append(indent(indent - indentFactor));
sb.append("</");
sb.append(tagName);
sb.append('>');
if(indentFactor > 0){
sb.append("\n");
}
}
return sb.toString();
@ -870,15 +1051,85 @@ public class XML {
// XML does not have good support for arrays. If an array
// appears in a place where XML is lacking, synthesize an
// <array> element.
sb.append(toString(val, tagName == null ? "array" : tagName, config));
sb.append(toString(val, tagName == null ? "array" : tagName, config, indentFactor, indent));
}
return sb.toString();
}
string = (object == null) ? "null" : escape(object.toString());
return (tagName == null) ? "\"" + string + "\""
: (string.length() == 0) ? "<" + tagName + "/>" : "<" + tagName
+ ">" + string + "</" + tagName + ">";
string = (object == null) ? "null" : escape(object.toString());
String indentationSuffix = (indentFactor > 0) ? "\n" : "";
if(tagName == null){
return indent(indent) + "\"" + string + "\"" + indentationSuffix;
} else if(string.length() == 0){
return indent(indent) + "<" + tagName + "/>" + indentationSuffix;
} else {
return indent(indent) + "<" + tagName
+ ">" + string + "</" + tagName + ">" + indentationSuffix;
}
}
/**
* Convert a JSONObject into a well-formed, pretty printed element-normal XML string.
*
* @param object
* A JSONObject.
* @param indentFactor
* The number of spaces to add to each level of indentation.
* @return A string.
* @throws JSONException Thrown if there is an error parsing the string
*/
public static String toString(Object object, int indentFactor){
return toString(object, null, XMLParserConfiguration.ORIGINAL, indentFactor);
}
/**
* Convert a JSONObject into a well-formed, pretty printed element-normal XML string.
*
* @param object
* A JSONObject.
* @param tagName
* The optional name of the enclosing tag.
* @param indentFactor
* The number of spaces to add to each level of indentation.
* @return A string.
* @throws JSONException Thrown if there is an error parsing the string
*/
public static String toString(final Object object, final String tagName, int indentFactor) {
return toString(object, tagName, XMLParserConfiguration.ORIGINAL, indentFactor);
}
/**
* Convert a JSONObject into a well-formed, pretty printed element-normal XML string.
*
* @param object
* A JSONObject.
* @param tagName
* The optional name of the enclosing tag.
* @param config
* Configuration that can control output to XML.
* @param indentFactor
* The number of spaces to add to each level of indentation.
* @return A string.
* @throws JSONException Thrown if there is an error parsing the string
*/
public static String toString(final Object object, final String tagName, final XMLParserConfiguration config, int indentFactor)
throws JSONException {
return toString(object, tagName, config, indentFactor, 0);
}
/**
* Return a String consisting of a number of space characters specified by indent
*
* @param indent
* The number of spaces to be appended to the String.
* @return
*/
private static final String indent(int indent) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < indent; i++) {
sb.append(' ');
}
return sb.toString();
}
}

View File

@ -1,26 +1,6 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import java.util.Collections;
@ -35,7 +15,23 @@ import java.util.Set;
* @author AylwardJ
*/
@SuppressWarnings({""})
public class XMLParserConfiguration {
public class XMLParserConfiguration extends ParserConfiguration {
/**
* The default maximum nesting depth when parsing a XML document to JSON.
*/
// public static final int DEFAULT_MAXIMUM_NESTING_DEPTH = 512; // We could override
/**
* Allow user to control how numbers are parsed
*/
private boolean keepNumberAsString;
/**
* Allow user to control how booleans are parsed
*/
private boolean keepBooleanAsString;
/** Original Configuration of the XML Parser. */
public static final XMLParserConfiguration ORIGINAL
= new XMLParserConfiguration();
@ -43,19 +39,13 @@ public class XMLParserConfiguration {
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
@ -63,6 +53,13 @@ public class XMLParserConfiguration {
*/
private boolean convertNilAttributeToNull;
/**
* When creating an XML from JSON Object, an empty tag by default will self-close.
* If it has to be closed explicitly, with empty content between start and end tag,
* this flag is to be turned on.
*/
private boolean closeEmptyTag;
/**
* This will allow type conversion for values in XML if xsi:type attribute is defined
*/
@ -74,16 +71,26 @@ public class XMLParserConfiguration {
*/
private Set<String> forceList;
/**
* Flag to indicate whether white space should be trimmed when parsing XML.
* The default behaviour is to trim white space. When this is set to false, inputting XML
* with tags that are the same as the value of cDataTagName is unsupported. It is recommended to set cDataTagName
* to a distinct value in this case.
*/
private boolean shouldTrimWhiteSpace;
/**
* Default parser configuration. Does not keep strings (tries to implicitly convert
* values), and the CDATA Tag Name is "content".
* values), and the CDATA Tag Name is "content". Trims whitespace.
*/
public XMLParserConfiguration () {
this.keepStrings = false;
super();
this.cDataTagName = "content";
this.convertNilAttributeToNull = false;
this.xsiTypeMap = Collections.emptyMap();
this.forceList = Collections.emptySet();
this.shouldTrimWhiteSpace = true;
}
/**
@ -126,7 +133,7 @@ public class XMLParserConfiguration {
*/
@Deprecated
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName) {
this.keepStrings = keepStrings;
super(keepStrings, DEFAULT_MAXIMUM_NESTING_DEPTH);
this.cDataTagName = cDataTagName;
this.convertNilAttributeToNull = false;
}
@ -145,7 +152,9 @@ public class XMLParserConfiguration {
*/
@Deprecated
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName, final boolean convertNilAttributeToNull) {
this.keepStrings = keepStrings;
super(false, DEFAULT_MAXIMUM_NESTING_DEPTH);
this.keepNumberAsString = keepStrings;
this.keepBooleanAsString = keepStrings;
this.cDataTagName = cDataTagName;
this.convertNilAttributeToNull = convertNilAttributeToNull;
}
@ -160,15 +169,21 @@ public class XMLParserConfiguration {
* <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
* @param forceList <code>new HashSet<String>()</code> to parse the provided tags' values as arrays
* @param maxNestingDepth <code>int</code> to limit the nesting depth
* @param closeEmptyTag <code>boolean</code> to turn on explicit end tag for tag with empty value
*/
private XMLParserConfiguration (final boolean keepStrings, final String cDataTagName,
final boolean convertNilAttributeToNull, final Map<String, XMLXsiTypeConverter<?>> xsiTypeMap, final Set<String> forceList ) {
this.keepStrings = keepStrings;
final boolean convertNilAttributeToNull, final Map<String, XMLXsiTypeConverter<?>> xsiTypeMap, final Set<String> forceList,
final int maxNestingDepth, final boolean closeEmptyTag, final boolean keepNumberAsString, final boolean keepBooleanAsString) {
super(false, maxNestingDepth);
this.keepNumberAsString = keepNumberAsString;
this.keepBooleanAsString = keepBooleanAsString;
this.cDataTagName = cDataTagName;
this.convertNilAttributeToNull = convertNilAttributeToNull;
this.xsiTypeMap = Collections.unmodifiableMap(xsiTypeMap);
this.forceList = Collections.unmodifiableSet(forceList);
this.closeEmptyTag = closeEmptyTag;
}
/**
@ -181,37 +196,69 @@ public class XMLParserConfiguration {
// 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(
final XMLParserConfiguration config = new XMLParserConfiguration(
this.keepStrings,
this.cDataTagName,
this.convertNilAttributeToNull,
this.xsiTypeMap,
this.forceList
this.forceList,
this.maxNestingDepth,
this.closeEmptyTag,
this.keepNumberAsString,
this.keepBooleanAsString
);
}
/**
* 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;
config.shouldTrimWhiteSpace = this.shouldTrimWhiteSpace;
return config;
}
/**
* 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.
*/
@SuppressWarnings("unchecked")
@Override
public XMLParserConfiguration withKeepStrings(final boolean newVal) {
XMLParserConfiguration newConfig = this.clone();
newConfig.keepStrings = newVal;
newConfig.keepNumberAsString = newVal;
newConfig.keepBooleanAsString = newVal;
return newConfig;
}
/**
* When parsing the XML into JSON, specifies if numbers should be kept as strings (<code>1</code>), or if
* they should try to be guessed into JSON values (numeric, boolean, string)
*
* @param newVal
* new value to use for the <code>keepNumberAsString</code> configuration option.
*
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public XMLParserConfiguration withKeepNumberAsString(final boolean newVal) {
XMLParserConfiguration newConfig = this.clone();
newConfig.keepNumberAsString = newVal;
newConfig.keepStrings = newConfig.keepBooleanAsString && newConfig.keepNumberAsString;
return newConfig;
}
/**
* When parsing the XML into JSON, specifies if booleans 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>withKeepBooleanAsString</code> configuration option.
*
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public XMLParserConfiguration withKeepBooleanAsString(final boolean newVal) {
XMLParserConfiguration newConfig = this.clone();
newConfig.keepBooleanAsString = newVal;
newConfig.keepStrings = newConfig.keepBooleanAsString && newConfig.keepNumberAsString;
return newConfig;
}
@ -219,21 +266,41 @@ public class XMLParserConfiguration {
* 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;
}
/**
* When parsing the XML into JSONML, specifies if numbers 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 isKeepNumberAsString() {
return this.keepNumberAsString;
}
/**
* When parsing the XML into JSONML, specifies if booleans 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 isKeepBooleanAsString() {
return this.keepBooleanAsString;
}
/**
* 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) {
@ -246,7 +313,7 @@ public class XMLParserConfiguration {
* 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() {
@ -257,10 +324,10 @@ public class XMLParserConfiguration {
* 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) {
@ -298,7 +365,7 @@ public class XMLParserConfiguration {
/**
* 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
* 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() {
@ -307,8 +374,8 @@ public class XMLParserConfiguration {
/**
* 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
* 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) {
@ -317,4 +384,61 @@ public class XMLParserConfiguration {
newConfig.forceList = Collections.unmodifiableSet(cloneForceList);
return newConfig;
}
/**
* Defines the maximum nesting depth that the parser will descend before throwing an exception
* when parsing the XML into JSON. The default max nesting depth is 512, which means the parser
* will throw a JsonException if the maximum depth is reached.
* Using any negative value as a parameter is equivalent to setting no limit to the nesting depth,
* which means the parses will go as deep as the maximum call stack size allows.
* @param maxNestingDepth the maximum nesting depth allowed to the XML parser
* @return The existing configuration will not be modified. A new configuration is returned.
*/
@SuppressWarnings("unchecked")
@Override
public XMLParserConfiguration withMaxNestingDepth(int maxNestingDepth) {
return super.withMaxNestingDepth(maxNestingDepth);
}
/**
* To enable explicit end tag with empty value.
* @param closeEmptyTag new value for the closeEmptyTag property
* @return same instance of configuration with empty tag config updated
*/
public XMLParserConfiguration withCloseEmptyTag(boolean closeEmptyTag){
XMLParserConfiguration clonedConfiguration = this.clone();
clonedConfiguration.closeEmptyTag = closeEmptyTag;
return clonedConfiguration;
}
/**
* Sets whether whitespace should be trimmed inside of tags. *NOTE* Do not use this if
* you expect your XML tags to have names that are the same as cDataTagName as this is unsupported.
* cDataTagName should be set to a distinct value in these cases.
* @param shouldTrimWhiteSpace boolean to set trimming on or off. Off is default.
* @return same instance of configuration with empty tag config updated
*/
public XMLParserConfiguration withShouldTrimWhitespace(boolean shouldTrimWhiteSpace){
XMLParserConfiguration clonedConfiguration = this.clone();
clonedConfiguration.shouldTrimWhiteSpace = shouldTrimWhiteSpace;
return clonedConfiguration;
}
/**
* Checks if the parser should automatically close empty XML tags.
*
* @return {@code true} if empty XML tags should be automatically closed, {@code false} otherwise.
*/
public boolean isCloseEmptyTag() {
return this.closeEmptyTag;
}
/**
* Checks if the parser should trim white spaces from XML content.
*
* @return {@code true} if white spaces should be trimmed, {@code false} otherwise.
*/
public boolean shouldTrimWhiteSpace() {
return this.shouldTrimWhiteSpace;
}
}

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;
@ -40,6 +20,8 @@ public class XMLTokener extends JSONTokener {
*/
public static final java.util.HashMap<String, Character> entity;
private XMLParserConfiguration configuration = XMLParserConfiguration.ORIGINAL;
static {
entity = new java.util.HashMap<String, Character>(8);
entity.put("amp", XML.AMP);
@ -65,6 +47,16 @@ public class XMLTokener extends JSONTokener {
super(s);
}
/**
* Construct an XMLTokener from a Reader and an XMLParserConfiguration.
* @param r A source reader.
* @param configuration the configuration that can be used to set certain flags
*/
public XMLTokener(Reader r, XMLParserConfiguration configuration) {
super(r);
this.configuration = configuration;
}
/**
* Get the text in the CDATA block.
* @return The string up to the <code>]]&gt;</code>.
@ -103,7 +95,7 @@ public class XMLTokener extends JSONTokener {
StringBuilder sb;
do {
c = next();
} while (Character.isWhitespace(c));
} while (Character.isWhitespace(c) && configuration.shouldTrimWhiteSpace());
if (c == 0) {
return null;
}
@ -117,7 +109,9 @@ public class XMLTokener extends JSONTokener {
}
if (c == '<') {
back();
return sb.toString().trim();
if (configuration.shouldTrimWhiteSpace()) {
return sb.toString().trim();
} else return sb.toString();
}
if (c == '&') {
sb.append(nextEntity(c));

View File

@ -1,26 +1,6 @@
package org.json;
/*
Copyright (c) 2002 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
/**
@ -62,5 +42,12 @@ SOFTWARE.
* @param <T> return type of convert method
*/
public interface XMLXsiTypeConverter<T> {
/**
* Converts an XML xsi:type attribute value to the specified type {@code T}.
*
* @param value The string representation of the XML xsi:type attribute value to be converted.
* @return An object of type {@code T} representing the converted value.
*/
T convert(String value);
}

View File

@ -1,27 +1,7 @@
package org.json.junit;
/*
Copyright (c) 2020 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import static org.junit.Assert.*;
@ -44,14 +24,13 @@ 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"
);
private static final String LINES = "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
@ -59,12 +38,54 @@ public class CDLTest {
* 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}]");
private static final String EXPECTED_LINES =
"[ " +
"{" +
"\"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.
@ -147,6 +168,33 @@ public class CDLTest {
}
}
/**
* Csv parsing skip last row if last field of this row is empty #943
*/
@Test
public void csvParsingCatchesLastRow(){
String data = "Field 1,Field 2,Field 3\n" +
"value11,value12,\n" +
"value21,value22,";
JSONArray jsonArray = CDL.toJSONArray(data);
JSONArray expectedJsonArray = new JSONArray();
JSONObject jsonObject = new JSONObject();
jsonObject.put("Field 1", "value11");
jsonObject.put("Field 2", "value12");
jsonObject.put("Field 3", "");
expectedJsonArray.put(jsonObject);
jsonObject = new JSONObject();
jsonObject.put("Field 1", "value21");
jsonObject.put("Field 2", "value22");
jsonObject.put("Field 3", "");
expectedJsonArray.put(jsonObject);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
}
/**
* Assert that there is no error for a single escaped quote within a properly embedded quote.
*/
@ -214,8 +262,7 @@ public class CDLTest {
public void emptyString() {
String emptyStr = "";
JSONArray jsonArray = CDL.toJSONArray(emptyStr);
assertTrue("CDL should return null when the input string is empty",
jsonArray == null);
assertNull("CDL should return null when the input string is empty", jsonArray);
}
/**
@ -274,7 +321,7 @@ public class CDLTest {
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);
assertEquals("expected length should be 1", 1, jsonArray.length());
String cdlStr = CDL.toString(jsonArray);
jsonObject = jsonArray.getJSONObject(0);
assertTrue(cdlStr.contains("\"Col 1\""));
@ -288,8 +335,15 @@ public class CDLTest {
*/
@Test
public void textToJSONArray() {
JSONArray jsonArray = CDL.toJSONArray(this.lines);
JSONArray expectedJsonArray = new JSONArray(this.expectedLines);
JSONArray jsonArray = CDL.toJSONArray(LINES);
JSONArray expectedJsonArray = new JSONArray(EXPECTED_LINES);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
}
@Test
public void textToJSONArrayPipeDelimited() {
char delimiter = '|';
JSONArray jsonArray = CDL.toJSONArray(LINES.replaceAll(",", String.valueOf(delimiter)), delimiter);
JSONArray expectedJsonArray = new JSONArray(EXPECTED_LINES);
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
}
@ -299,11 +353,11 @@ public class CDLTest {
*/
@Test
public void jsonArrayToJSONArray() {
String nameArrayStr = "[Col1, Col2]";
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}]");
JSONArray expectedJsonArray = new JSONArray("[{\"Col1\":\"V1\",\"Col2\":\"V2\"}]");
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
}
@ -313,10 +367,24 @@ public class CDLTest {
*/
@Test
public void textToJSONArrayAndBackToString() {
JSONArray jsonArray = CDL.toJSONArray(this.lines);
JSONArray jsonArray = CDL.toJSONArray(LINES);
String jsonStr = CDL.toString(jsonArray);
JSONArray finalJsonArray = CDL.toJSONArray(jsonStr);
JSONArray expectedJsonArray = new JSONArray(this.expectedLines);
JSONArray expectedJsonArray = new JSONArray(EXPECTED_LINES);
Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
}
/**
* Create a JSONArray from a string of lines,
* then convert to string and then back to JSONArray
* with a custom delimiter
*/
@Test
public void textToJSONArrayAndBackToStringCustomDelimiter() {
JSONArray jsonArray = CDL.toJSONArray(LINES, ',');
String jsonStr = CDL.toString(jsonArray, ';');
JSONArray finalJsonArray = CDL.toJSONArray(jsonStr, ';');
JSONArray expectedJsonArray = new JSONArray(EXPECTED_LINES);
Util.compareActualVsExpectedJsonArrays(finalJsonArray, expectedJsonArray);
}

View File

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

View File

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

View File

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

View File

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

View File

@ -0,0 +1,107 @@
package org.json.junit;
import org.json.HTTPTokener;
import org.json.JSONException;
import org.junit.Test;
import static org.junit.Assert.*;
/**
* Tests for JSON-Java HTTPTokener.java
*/
public class HTTPTokenerTest {
/**
* Test parsing a simple unquoted token.
*/
@Test
public void parseSimpleToken() {
HTTPTokener tokener = new HTTPTokener("Content-Type");
String token = tokener.nextToken();
assertEquals("Content-Type", token);
}
/**
* Test parsing multiple tokens separated by whitespace.
*/
@Test
public void parseMultipleTokens() {
HTTPTokener tokener = new HTTPTokener("Content-Type application/json");
String token1 = tokener.nextToken();
String token2 = tokener.nextToken();
assertEquals("Content-Type", token1);
assertEquals("application/json", token2);
}
/**
* Test parsing a double-quoted token.
*/
@Test
public void parseDoubleQuotedToken() {
HTTPTokener tokener = new HTTPTokener("\"application/json\"");
String token = tokener.nextToken();
assertEquals("application/json", token);
}
/**
* Test parsing a single-quoted token.
*/
@Test
public void parseSingleQuotedToken() {
HTTPTokener tokener = new HTTPTokener("'application/json'");
String token = tokener.nextToken();
assertEquals("application/json", token);
}
/**
* Test parsing a quoted token that includes spaces and semicolons.
*/
@Test
public void parseQuotedTokenWithSpaces() {
HTTPTokener tokener = new HTTPTokener("\"text/html; charset=UTF-8\"");
String token = tokener.nextToken();
assertEquals("text/html; charset=UTF-8", token);
}
/**
* Test that unterminated quoted strings throw a JSONException.
*/
@Test
public void throwExceptionOnUnterminatedString() {
HTTPTokener tokener = new HTTPTokener("\"incomplete");
JSONException exception = assertThrows(JSONException.class, tokener::nextToken);
assertTrue(exception.getMessage().contains("Unterminated string"));
}
/**
* Test behavior with empty input string.
*/
@Test
public void parseEmptyInput() {
HTTPTokener tokener = new HTTPTokener("");
String token = tokener.nextToken();
assertEquals("", token);
}
/**
* Test behavior with input consisting only of whitespace.
*/
@Test
public void parseWhitespaceOnly() {
HTTPTokener tokener = new HTTPTokener(" \t \n ");
String token = tokener.nextToken();
assertEquals("", token);
}
/**
* Test parsing tokens separated by multiple whitespace characters.
*/
@Test
public void parseTokensWithMultipleWhitespace() {
HTTPTokener tokener = new HTTPTokener("GET /index.html");
String method = tokener.nextToken();
String path = tokener.nextToken();
assertEquals("GET", method);
assertEquals("/index.html", path);
}
}

View File

@ -1,33 +1,14 @@
package org.json.junit;
/*
Copyright (c) 2020 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
@ -48,8 +29,13 @@ import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONParserConfiguration;
import org.json.JSONPointerException;
import org.json.JSONString;
import org.json.JSONTokener;
import org.json.ParserConfiguration;
import org.json.junit.data.MyJsonString;
import org.junit.Ignore;
import org.junit.Test;
import com.jayway.jsonpath.Configuration;
@ -136,7 +122,7 @@ public class JSONArrayTest {
* Expects a JSONException.
*/
@Test
public void emptStr() {
public void emptyStr() {
String str = "";
try {
assertNull("Should throw an exception", new JSONArray(str));
@ -237,6 +223,23 @@ public class JSONArrayTest {
assertTrue(
"The RAW Collection should give me the same as the Typed Collection",
expected.similar(jaObj));
Util.checkJSONArrayMaps(expected);
Util.checkJSONArrayMaps(jaObj);
Util.checkJSONArrayMaps(jaRaw);
Util.checkJSONArrayMaps(jaInt);
}
@Test
public void jsonArrayByListWithNestedNullValue() {
List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
Map<String, Object> sub = new HashMap<String, Object>();
sub.put("nullKey", null);
list.add(sub);
JSONParserConfiguration parserConfiguration = new JSONParserConfiguration().withUseNativeNulls(true);
JSONArray jsonArray = new JSONArray(list, parserConfiguration);
JSONObject subObject = jsonArray.getJSONObject(0);
assertTrue(subObject.has("nullKey"));
assertEquals(JSONObject.NULL, subObject.get("nullKey"));
}
/**
@ -270,11 +273,17 @@ public class JSONArrayTest {
jsonArray.length(),
len);
// collection as object
@SuppressWarnings("RedundantCast")
Object myListAsObject = (Object) myList;
jsonArray.putAll(myListAsObject);
for (int i = 0; i < myList.size(); i++) {
assertEquals("collection elements should be equal",
myList.get(i),
jsonArray.getString(myInts.length + i));
}
Util.checkJSONArrayMaps(jsonArray);
}
/**
@ -308,6 +317,9 @@ public class JSONArrayTest {
assertTrue(
"The RAW Collection should give me the same as the Typed Collection",
expected.similar(jaInt));
Util.checkJSONArraysMaps(new ArrayList<JSONArray>(Arrays.asList(
jaRaw, jaObj, jaInt
)));
}
@ -351,6 +363,9 @@ public class JSONArrayTest {
assertTrue(
"The RAW Collection should give me the same as the Typed Collection",
expected.similar(jaObjObj));
Util.checkJSONArraysMaps(new ArrayList<JSONArray>(Arrays.asList(
expected, jaRaw, jaStrObj, jaStrInt, jaObjObj
)));
}
/**
@ -375,16 +390,16 @@ public class JSONArrayTest {
"hello".equals(jsonArray.getString(4)));
// doubles
assertTrue("Array double",
new Double(23.45e-4).equals(jsonArray.getDouble(5)));
Double.valueOf(23.45e-4).equals(jsonArray.getDouble(5)));
assertTrue("Array string double",
new Double(23.45).equals(jsonArray.getDouble(6)));
Double.valueOf(23.45).equals(jsonArray.getDouble(6)));
assertTrue("Array double can be float",
new Float(23.45e-4f).equals(jsonArray.getFloat(5)));
Float.valueOf(23.45e-4f).equals(jsonArray.getFloat(5)));
// ints
assertTrue("Array value int",
new Integer(42).equals(jsonArray.getInt(7)));
Integer.valueOf(42).equals(jsonArray.getInt(7)));
assertTrue("Array value string int",
new Integer(43).equals(jsonArray.getInt(8)));
Integer.valueOf(43).equals(jsonArray.getInt(8)));
// nested objects
JSONArray nestedJsonArray = jsonArray.getJSONArray(9);
assertTrue("Array value JSONArray", nestedJsonArray != null);
@ -392,11 +407,12 @@ public class JSONArrayTest {
assertTrue("Array value JSONObject", nestedJsonObject != null);
// longs
assertTrue("Array value long",
new Long(0).equals(jsonArray.getLong(11)));
Long.valueOf(0).equals(jsonArray.getLong(11)));
assertTrue("Array value string long",
new Long(-1).equals(jsonArray.getLong(12)));
Long.valueOf(-1).equals(jsonArray.getLong(12)));
assertTrue("Array value null", jsonArray.isNull(-1));
Util.checkJSONArrayMaps(jsonArray);
}
/**
@ -412,7 +428,7 @@ public class JSONArrayTest {
assertTrue("expected getBoolean to fail", false);
} catch (JSONException e) {
assertEquals("Expected an exception message",
"JSONArray[4] is not a boolean.",e.getMessage());
"JSONArray[4] is not a boolean (class java.lang.String : hello).",e.getMessage());
}
try {
jsonArray.get(-1);
@ -426,42 +442,67 @@ public class JSONArrayTest {
assertTrue("expected getDouble to fail", false);
} catch (JSONException e) {
assertEquals("Expected an exception message",
"JSONArray[4] is not a double.",e.getMessage());
"JSONArray[4] is not a double (class java.lang.String : hello).",e.getMessage());
}
try {
jsonArray.getInt(4);
assertTrue("expected getInt to fail", false);
} catch (JSONException e) {
assertEquals("Expected an exception message",
"JSONArray[4] is not a int.",e.getMessage());
"JSONArray[4] is not a int (class java.lang.String : hello).",e.getMessage());
}
try {
jsonArray.getJSONArray(4);
assertTrue("expected getJSONArray to fail", false);
} catch (JSONException e) {
assertEquals("Expected an exception message",
"JSONArray[4] is not a JSONArray.",e.getMessage());
"JSONArray[4] is not a JSONArray (class java.lang.String : hello).",e.getMessage());
}
try {
jsonArray.getJSONObject(4);
assertTrue("expected getJSONObject to fail", false);
} catch (JSONException e) {
assertEquals("Expected an exception message",
"JSONArray[4] is not a JSONObject.",e.getMessage());
"JSONArray[4] is not a JSONObject (class java.lang.String : hello).",e.getMessage());
}
try {
jsonArray.getLong(4);
assertTrue("expected getLong to fail", false);
} catch (JSONException e) {
assertEquals("Expected an exception message",
"JSONArray[4] is not a long.",e.getMessage());
"JSONArray[4] is not a long (class java.lang.String : hello).",e.getMessage());
}
try {
jsonArray.getString(5);
assertTrue("expected getString to fail", false);
} catch (JSONException e) {
assertEquals("Expected an exception message",
"JSONArray[5] is not a String.",e.getMessage());
"JSONArray[5] is not a String (class java.math.BigDecimal : 0.002345).",e.getMessage());
}
Util.checkJSONArrayMaps(jsonArray);
}
/**
* The JSON parser is permissive of unambiguous unquoted keys and values.
* Such JSON text should be allowed, even if it does not strictly conform
* to the spec. However, after being parsed, toString() should emit strictly
* conforming JSON text.
*/
@Test
public void unquotedText() {
String str = "[value1, something!, (parens), foo@bar.com, 23, 23+45]";
List<Object> expected = Arrays.asList("value1", "something!", "(parens)", "foo@bar.com", 23, "23+45");
// Test should fail if default strictMode is true, pass if false
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration();
if (jsonParserConfiguration.isStrictMode()) {
try {
JSONArray jsonArray = new JSONArray(str);
assertEquals("Expected to throw exception due to invalid string", true, false);
} catch (JSONException e) { }
} else {
JSONArray jsonArray = new JSONArray(str);
assertEquals(expected, jsonArray.toList());
}
}
@ -499,6 +540,7 @@ public class JSONArrayTest {
assertTrue("expected value4", "value4".equals(jsonArray.query("/10/key4")));
assertTrue("expected 0", Integer.valueOf(0).equals(jsonArray.query("/11")));
assertTrue("expected \"-1\"", "-1".equals(jsonArray.query("/12")));
Util.checkJSONArrayMaps(jsonArray);
}
/**
@ -512,6 +554,9 @@ public class JSONArrayTest {
assertTrue("expected JSONArray length 13. instead found "+jsonArray.length(), jsonArray.length() == 13);
JSONArray nestedJsonArray = jsonArray.getJSONArray(9);
assertTrue("expected JSONArray length 1", nestedJsonArray.length() == 1);
Util.checkJSONArraysMaps(new ArrayList<JSONArray>(Arrays.asList(
jsonArray, nestedJsonArray
)));
}
/**
@ -538,43 +583,75 @@ public class JSONArrayTest {
assertTrue("Array opt boolean implicit default",
Boolean.FALSE == jsonArray.optBoolean(-1));
assertTrue("Array opt boolean object",
Boolean.TRUE.equals(jsonArray.optBooleanObject(0)));
assertTrue("Array opt boolean object default",
Boolean.FALSE.equals(jsonArray.optBooleanObject(-1, Boolean.FALSE)));
assertTrue("Array opt boolean object implicit default",
Boolean.FALSE.equals(jsonArray.optBooleanObject(-1)));
assertTrue("Array opt double",
new Double(23.45e-4).equals(jsonArray.optDouble(5)));
Double.valueOf(23.45e-4).equals(jsonArray.optDouble(5)));
assertTrue("Array opt double default",
new Double(1).equals(jsonArray.optDouble(0, 1)));
Double.valueOf(1).equals(jsonArray.optDouble(0, 1)));
assertTrue("Array opt double default implicit",
new Double(jsonArray.optDouble(99)).isNaN());
Double.valueOf(jsonArray.optDouble(99)).isNaN());
assertTrue("Array opt double object",
Double.valueOf(23.45e-4).equals(jsonArray.optDoubleObject(5)));
assertTrue("Array opt double object default",
Double.valueOf(1).equals(jsonArray.optDoubleObject(0, 1D)));
assertTrue("Array opt double object default implicit",
jsonArray.optDoubleObject(99).isNaN());
assertTrue("Array opt float",
new Float(23.45e-4).equals(jsonArray.optFloat(5)));
Float.valueOf(Double.valueOf(23.45e-4).floatValue()).equals(jsonArray.optFloat(5)));
assertTrue("Array opt float default",
new Float(1).equals(jsonArray.optFloat(0, 1)));
Float.valueOf(1).equals(jsonArray.optFloat(0, 1)));
assertTrue("Array opt float default implicit",
new Float(jsonArray.optFloat(99)).isNaN());
Float.valueOf(jsonArray.optFloat(99)).isNaN());
assertTrue("Array opt float object",
Float.valueOf(23.45e-4F).equals(jsonArray.optFloatObject(5)));
assertTrue("Array opt float object default",
Float.valueOf(1).equals(jsonArray.optFloatObject(0, 1F)));
assertTrue("Array opt float object default implicit",
jsonArray.optFloatObject(99).isNaN());
assertTrue("Array opt Number",
BigDecimal.valueOf(23.45e-4).equals(jsonArray.optNumber(5)));
assertTrue("Array opt Number default",
new Double(1).equals(jsonArray.optNumber(0, 1d)));
Double.valueOf(1).equals(jsonArray.optNumber(0, 1d)));
assertTrue("Array opt Number default implicit",
new Double(jsonArray.optNumber(99,Double.NaN).doubleValue()).isNaN());
Double.valueOf(jsonArray.optNumber(99,Double.NaN).doubleValue()).isNaN());
assertTrue("Array opt int",
new Integer(42).equals(jsonArray.optInt(7)));
Integer.valueOf(42).equals(jsonArray.optInt(7)));
assertTrue("Array opt int default",
new Integer(-1).equals(jsonArray.optInt(0, -1)));
Integer.valueOf(-1).equals(jsonArray.optInt(0, -1)));
assertTrue("Array opt int default implicit",
0 == jsonArray.optInt(0));
assertTrue("Array opt int object",
Integer.valueOf(42).equals(jsonArray.optIntegerObject(7)));
assertTrue("Array opt int object default",
Integer.valueOf(-1).equals(jsonArray.optIntegerObject(0, -1)));
assertTrue("Array opt int object default implicit",
Integer.valueOf(0).equals(jsonArray.optIntegerObject(0)));
JSONArray nestedJsonArray = jsonArray.optJSONArray(9);
assertTrue("Array opt JSONArray", nestedJsonArray != null);
assertTrue("Array opt JSONArray default",
assertTrue("Array opt JSONArray null",
null == jsonArray.optJSONArray(99));
assertTrue("Array opt JSONArray default",
"value".equals(jsonArray.optJSONArray(99, new JSONArray("[\"value\"]")).getString(0)));
JSONObject nestedJsonObject = jsonArray.optJSONObject(10);
assertTrue("Array opt JSONObject", nestedJsonObject != null);
assertTrue("Array opt JSONObject default",
assertTrue("Array opt JSONObject null",
null == jsonArray.optJSONObject(99));
assertTrue("Array opt JSONObject default",
"value".equals(jsonArray.optJSONObject(99, new JSONObject("{\"key\":\"value\"}")).getString("key")));
assertTrue("Array opt long",
0 == jsonArray.optLong(11));
@ -583,10 +660,21 @@ public class JSONArrayTest {
assertTrue("Array opt long default implicit",
0 == jsonArray.optLong(-1));
assertTrue("Array opt long object",
Long.valueOf(0).equals(jsonArray.optLongObject(11)));
assertTrue("Array opt long object default",
Long.valueOf(-2).equals(jsonArray.optLongObject(-1, -2L)));
assertTrue("Array opt long object default implicit",
Long.valueOf(0).equals(jsonArray.optLongObject(-1)));
assertTrue("Array opt string",
"hello".equals(jsonArray.optString(4)));
assertTrue("Array opt string default implicit",
"".equals(jsonArray.optString(-1)));
Util.checkJSONArraysMaps(new ArrayList<JSONArray>(Arrays.asList(
jsonArray, nestedJsonArray
)));
Util.checkJSONObjectMaps(nestedJsonObject);
}
/**
@ -596,12 +684,19 @@ public class JSONArrayTest {
public void optStringConversion(){
JSONArray ja = new JSONArray("[\"123\",\"true\",\"false\"]");
assertTrue("unexpected optBoolean value",ja.optBoolean(1,false)==true);
assertTrue("unexpected optBooleanObject value",Boolean.valueOf(true).equals(ja.optBooleanObject(1,false)));
assertTrue("unexpected optBoolean value",ja.optBoolean(2,true)==false);
assertTrue("unexpected optBooleanObject value",Boolean.valueOf(false).equals(ja.optBooleanObject(2,true)));
assertTrue("unexpected optInt value",ja.optInt(0,0)==123);
assertTrue("unexpected optIntegerObject value",Integer.valueOf(123).equals(ja.optIntegerObject(0,0)));
assertTrue("unexpected optLong value",ja.optLong(0,0)==123);
assertTrue("unexpected optLongObject value",Long.valueOf(123).equals(ja.optLongObject(0,0L)));
assertTrue("unexpected optDouble value",ja.optDouble(0,0.0)==123.0);
assertTrue("unexpected optDoubleObject value",Double.valueOf(123.0).equals(ja.optDoubleObject(0,0.0)));
assertTrue("unexpected optBigInteger value",ja.optBigInteger(0,BigInteger.ZERO).compareTo(new BigInteger("123"))==0);
assertTrue("unexpected optBigDecimal value",ja.optBigDecimal(0,BigDecimal.ZERO).compareTo(new BigDecimal("123"))==0); }
assertTrue("unexpected optBigDecimal value",ja.optBigDecimal(0,BigDecimal.ZERO).compareTo(new BigDecimal("123"))==0);
Util.checkJSONArrayMaps(ja);
}
/**
* Exercise the JSONArray.put(value) method with various parameters
@ -619,8 +714,8 @@ public class JSONArrayTest {
String jsonArrayStr =
"["+
"hello,"+
"world"+
"\"hello\","+
"\"world\""+
"]";
// 2
jsonArray.put(new JSONArray(jsonArrayStr));
@ -677,6 +772,8 @@ public class JSONArrayTest {
assertTrue("expected 2 items in [9]", ((List<?>)(JsonPath.read(doc, "$[9]"))).size() == 2);
assertTrue("expected 1", Integer.valueOf(1).equals(jsonArray.query("/9/0")));
assertTrue("expected 2", Integer.valueOf(2).equals(jsonArray.query("/9/1")));
Util.checkJSONArrayMaps(jsonArray);
Util.checkJSONObjectMaps(jsonObject);
}
/**
@ -695,8 +792,8 @@ public class JSONArrayTest {
String jsonArrayStr =
"["+
"hello,"+
"world"+
"\"hello\","+
"\"world\""+
"]";
// 2
jsonArray.put(2, new JSONArray(jsonArrayStr));
@ -756,6 +853,8 @@ public class JSONArrayTest {
assertTrue("expected 2", Integer.valueOf(2).equals(jsonArray.query("/9/1")));
assertTrue("expected 1 item in [10]", ((Map<?,?>)(JsonPath.read(doc, "$[10]"))).size() == 1);
assertTrue("expected v1", "v1".equals(jsonArray.query("/10/k1")));
Util.checkJSONObjectMaps(jsonObject);
Util.checkJSONArrayMaps(jsonArray);
}
/**
@ -772,6 +871,7 @@ public class JSONArrayTest {
jsonArray.remove(0);
assertTrue("array should be empty", null == jsonArray.remove(5));
assertTrue("jsonArray should be empty", jsonArray.isEmpty());
Util.checkJSONArrayMaps(jsonArray);
}
/**
@ -811,6 +911,12 @@ public class JSONArrayTest {
otherJsonArray.put("world");
assertTrue("arrays values differ",
!jsonArray.similar(otherJsonArray));
Util.checkJSONArraysMaps(new ArrayList<JSONArray>(Arrays.asList(
jsonArray, otherJsonArray
)));
Util.checkJSONObjectsMaps(new ArrayList<JSONObject>(Arrays.asList(
jsonObject, otherJsonObject
)));
}
/**
@ -894,6 +1000,7 @@ public class JSONArrayTest {
for (String s : jsonArray4Strs) {
list.contains(s);
}
Util.checkJSONArrayMaps(jsonArray);
}
/**
@ -905,6 +1012,9 @@ public class JSONArrayTest {
JSONArray jsonArray = new JSONArray();
assertTrue("toJSONObject should return null",
null == jsonArray.toJSONObject(names));
Util.checkJSONArraysMaps(new ArrayList<JSONArray>(Arrays.asList(
names, jsonArray
)));
}
/**
@ -926,6 +1036,7 @@ public class JSONArrayTest {
assertTrue("expected 5", Integer.valueOf(5).equals(jsonArray.query("/4")));
assertTrue("expected 6", Integer.valueOf(6).equals(jsonArray.query("/5")));
assertTrue("expected 7", Integer.valueOf(7).equals(jsonArray.query("/6")));
Util.checkJSONArrayMaps(jsonArray);
}
/**
@ -950,12 +1061,12 @@ public class JSONArrayTest {
assertTrue("Array double [23.45e-4]",
new BigDecimal("0.002345").equals(it.next()));
assertTrue("Array string double",
new Double(23.45).equals(Double.parseDouble((String)it.next())));
Double.valueOf(23.45).equals(Double.parseDouble((String)it.next())));
assertTrue("Array value int",
new Integer(42).equals(it.next()));
Integer.valueOf(42).equals(it.next()));
assertTrue("Array value string int",
new Integer(43).equals(Integer.parseInt((String)it.next())));
Integer.valueOf(43).equals(Integer.parseInt((String)it.next())));
JSONArray nestedJsonArray = (JSONArray)it.next();
assertTrue("Array value JSONArray", nestedJsonArray != null);
@ -964,10 +1075,14 @@ public class JSONArrayTest {
assertTrue("Array value JSONObject", nestedJsonObject != null);
assertTrue("Array value long",
new Long(0).equals(((Number) it.next()).longValue()));
Long.valueOf(0).equals(((Number) it.next()).longValue()));
assertTrue("Array value string long",
new Long(-1).equals(Long.parseLong((String) it.next())));
Long.valueOf(-1).equals(Long.parseLong((String) it.next())));
assertTrue("should be at end of array", !it.hasNext());
Util.checkJSONArraysMaps(new ArrayList<JSONArray>(Arrays.asList(
jsonArray, nestedJsonArray
)));
Util.checkJSONObjectMaps(nestedJsonObject);
}
@Test(expected = JSONPointerException.class)
@ -1010,6 +1125,7 @@ public class JSONArrayTest {
} finally {
stringWriter.close();
}
Util.checkJSONArrayMaps(jsonArray);
}
/**
@ -1069,9 +1185,11 @@ public class JSONArrayTest {
&& actualStr.contains("\"key2\": false")
&& actualStr.contains("\"key3\": 3.14")
);
Util.checkJSONArrayMaps(finalArray);
} finally {
stringWriter.close();
}
Util.checkJSONArrayMaps(jsonArray);
}
/**
@ -1182,6 +1300,7 @@ public class JSONArrayTest {
// assert that the new list is mutable
assertTrue("Removing an entry should succeed", list.remove(2) != null);
assertTrue("List should have 2 elements", list.size() == 2);
Util.checkJSONArrayMaps(jsonArray);
}
/**
@ -1190,13 +1309,13 @@ public class JSONArrayTest {
*/
@Test
public void testJSONArrayInt() {
assertNotNull(new JSONArray(0));
assertNotNull(new JSONArray(5));
// Check Size -> Even though the capacity of the JSONArray can be specified using a positive
// integer but the length of JSONArray always reflects upon the items added into it.
assertEquals(0l, new JSONArray(10).length());
assertNotNull(new JSONArray(0));
assertNotNull(new JSONArray(5));
// Check Size -> Even though the capacity of the JSONArray can be specified using a positive
// integer but the length of JSONArray always reflects upon the items added into it.
// assertEquals(0l, new JSONArray(10).length());
try {
assertNotNull("Should throw an exception", new JSONArray(-1));
assertNotNull("Should throw an exception", new JSONArray(-1));
} catch (JSONException e) {
assertEquals("Expected an exception message",
"JSONArray initial capacity cannot be negative.",
@ -1223,8 +1342,8 @@ public class JSONArrayTest {
((Collection<Object>)o).add("test");
((Collection<Object>)o).add(false);
try {
a = new JSONArray(o);
assertNull("Should error", a);
JSONArray a0 = new JSONArray(o);
assertNull("Should error", a0);
} catch (JSONException ex) {
}
@ -1232,10 +1351,11 @@ public class JSONArrayTest {
// this is required for backwards compatibility
o = a;
try {
a = new JSONArray(o);
assertNull("Should error", a);
JSONArray a1 = new JSONArray(o);
assertNull("Should error", a1);
} catch (JSONException ex) {
}
Util.checkJSONArrayMaps(a);
}
/**
@ -1252,6 +1372,9 @@ public class JSONArrayTest {
for(int i = 0; i < a1.length(); i++) {
assertEquals("index " + i + " are equal", a1.get(i), a2.get(i));
}
Util.checkJSONArraysMaps(new ArrayList<JSONArray>(Arrays.asList(
a1, a2
)));
}
/**
@ -1269,6 +1392,9 @@ public class JSONArrayTest {
for(int i = 0; i < a1.length(); i++) {
assertEquals("index " + i + " are equal", a1.get(i), a2.get(i));
}
Util.checkJSONArraysMaps(new ArrayList<JSONArray>(Arrays.asList(
a1, a2
)));
}
/**
@ -1284,18 +1410,138 @@ public class JSONArrayTest {
jsonArray.clear(); //Clears the JSONArray
assertTrue("expected jsonArray.length() == 0", jsonArray.length() == 0); //Check if its length is 0
jsonArray.getInt(0); //Should throws org.json.JSONException: JSONArray[0] not found
Util.checkJSONArrayMaps(jsonArray);
}
/**
* Tests for stack overflow. See https://github.com/stleary/JSON-java/issues/654
*/
@Ignore("This test relies on system constraints and may not always pass. See: https://github.com/stleary/JSON-java/issues/821")
@Test(expected = JSONException.class)
public void issue654StackOverflowInputWellFormed() {
//String input = new String(java.util.Base64.getDecoder().decode(base64Bytes));
final InputStream resourceAsStream = JSONObjectTest.class.getClassLoader().getResourceAsStream("Issue654WellFormedArray.json");
final InputStream resourceAsStream = JSONArrayTest.class.getClassLoader().getResourceAsStream("Issue654WellFormedArray.json");
JSONTokener tokener = new JSONTokener(resourceAsStream);
JSONArray json_input = new JSONArray(tokener);
assertNotNull(json_input);
fail("Excepected Exception.");
fail("Excepected Exception due to stack overflow.");
Util.checkJSONArrayMaps(json_input);
}
@Test
public void testIssue682SimilarityOfJSONString() {
JSONArray ja1 = new JSONArray()
.put(new MyJsonString())
.put(2);
JSONArray ja2 = new JSONArray()
.put(new MyJsonString())
.put(2);
assertTrue(ja1.similar(ja2));
JSONArray ja3 = new JSONArray()
.put(new JSONString() {
@Override
public String toJSONString() {
return "\"different value\"";
}
})
.put(2);
assertFalse(ja1.similar(ja3));
}
@Test(expected = JSONException.class)
public void testRecursiveDepth() {
HashMap<String, Object> map = new HashMap<>();
map.put("t", map);
new JSONArray().put(map);
}
@Test(expected = JSONException.class)
public void testRecursiveDepthAtPosition() {
HashMap<String, Object> map = new HashMap<>();
map.put("t", map);
new JSONArray().put(0, map);
}
@Test(expected = JSONException.class)
public void testRecursiveDepthArray() {
ArrayList<Object> array = new ArrayList<>();
array.add(array);
new JSONArray(array);
}
@Test
public void testRecursiveDepthAtPositionDefaultObject() {
HashMap<String, Object> map = JSONObjectTest.buildNestedMap(ParserConfiguration.DEFAULT_MAXIMUM_NESTING_DEPTH);
new JSONArray().put(0, map);
}
@Test
public void testRecursiveDepthAtPosition1000Object() {
HashMap<String, Object> map = JSONObjectTest.buildNestedMap(1000);
new JSONArray().put(0, map, new JSONParserConfiguration().withMaxNestingDepth(1000));
}
@Test(expected = JSONException.class)
public void testRecursiveDepthAtPosition1001Object() {
HashMap<String, Object> map = JSONObjectTest.buildNestedMap(1001);
new JSONArray().put(0, map);
}
@Test(expected = JSONException.class)
public void testRecursiveDepthArrayLimitedMaps() {
ArrayList<Object> array = new ArrayList<>();
array.add(array);
new JSONArray(array);
}
@Test
public void testRecursiveDepthArrayForDefaultLevels() {
ArrayList<Object> array = buildNestedArray(ParserConfiguration.DEFAULT_MAXIMUM_NESTING_DEPTH);
new JSONArray(array, new JSONParserConfiguration());
}
@Test
public void testRecursiveDepthArrayFor1000Levels() {
try {
ArrayList<Object> array = buildNestedArray(1000);
JSONParserConfiguration parserConfiguration = new JSONParserConfiguration().withMaxNestingDepth(1000);
new JSONArray(array, parserConfiguration);
} catch (StackOverflowError e) {
String javaVersion = System.getProperty("java.version");
if (javaVersion.startsWith("11.")) {
System.out.println(
"testRecursiveDepthArrayFor1000Levels() allowing intermittent stackoverflow, Java Version: "
+ javaVersion);
} else {
String errorStr = "testRecursiveDepthArrayFor1000Levels() unexpected stackoverflow, Java Version: "
+ javaVersion;
System.out.println(errorStr);
throw new RuntimeException(errorStr);
}
}
}
@Test(expected = JSONException.class)
public void testRecursiveDepthArrayFor1001Levels() {
ArrayList<Object> array = buildNestedArray(1001);
new JSONArray(array);
}
@Test
public void testStrictModeJSONTokener_expectException(){
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration().withStrictMode();
JSONTokener tokener = new JSONTokener("[\"value\"]invalidCharacters", jsonParserConfiguration);
assertThrows(JSONException.class, () -> { new JSONArray(tokener); });
}
public static ArrayList<Object> buildNestedArray(int maxDepth) {
if (maxDepth <= 0) {
return new ArrayList<>();
}
ArrayList<Object> nestedArray = new ArrayList<>();
nestedArray.add(buildNestedArray(maxDepth - 1));
return nestedArray;
}
}

View File

@ -1,27 +1,7 @@
package org.json.junit;
/*
Copyright (c) 2020 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import static org.junit.Assert.*;
@ -31,19 +11,19 @@ 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 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.
* 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 {
@ -76,7 +56,7 @@ public class JSONMLTest {
/**
* Attempts to call JSONML.toString() with a null JSONArray.
* Expects a NullPointerException.
* Expects a NullPointerException.
*/
@Test(expected=NullPointerException.class)
public void nullJSONXMLException() {
@ -89,7 +69,7 @@ public class JSONMLTest {
/**
* Attempts to call JSONML.toString() with a null JSONArray.
* Expects a JSONException.
* Expects a JSONException.
*/
@Test
public void emptyJSONXMLException() {
@ -145,7 +125,7 @@ public class JSONMLTest {
"[\"addresses\","+
"{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
// this array has no name
// this array has no name
"["+
"[\"name\"],"+
"[\"nocontent\"],"+
@ -158,7 +138,7 @@ public class JSONMLTest {
assertTrue("Expecting an exception", false);
} catch (JSONException e) {
assertEquals("Expecting an exception message",
"JSONArray[0] is not a String.",
"JSONArray[0] is not a String (class org.json.JSONArray).",
e.getMessage());
}
}
@ -200,7 +180,7 @@ public class JSONMLTest {
}
/**
* Attempts to transform a malformed XML document
* Attempts to transform a malformed XML document
* (element tag has a frontslash) to a JSONArray.\
* Expects a JSONException
*/
@ -211,7 +191,7 @@ public class JSONMLTest {
* In this case, the XML is invalid because the 'name' element
* contains an invalid frontslash.
*/
String xmlStr =
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"+
@ -236,7 +216,7 @@ public class JSONMLTest {
*/
@Test
public void invalidBangInTagException() {
String xmlStr =
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"+
@ -266,7 +246,7 @@ public class JSONMLTest {
* In this case, the XML is invalid because an element
* starts with '!' and has no closing tag
*/
String xmlStr =
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"+
@ -296,7 +276,7 @@ public class JSONMLTest {
* In this case, the XML is invalid because an element
* has no closing '>'.
*/
String xmlStr =
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"+
@ -326,7 +306,7 @@ public class JSONMLTest {
* In this case, the XML is invalid because an element
* has no name after the closing tag '</'.
*/
String xmlStr =
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"+
@ -356,7 +336,7 @@ public class JSONMLTest {
* In this case, the XML is invalid because an element
* has '>' after the closing tag '</' and name.
*/
String xmlStr =
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"+
@ -384,9 +364,9 @@ public class JSONMLTest {
/**
* 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.
* does not have a complete CDATA string.
*/
String xmlStr =
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"+
@ -408,7 +388,7 @@ public class JSONMLTest {
/**
* 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
* a JSONArray. Both JSONArrays are compared against a control to
* confirm the contents.
*/
@Test
@ -425,7 +405,7 @@ public class JSONMLTest {
* which is used to create a final JSONArray, which is also compared
* against the expected JSONArray.
*/
String xmlStr =
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"+
@ -434,7 +414,7 @@ public class JSONMLTest {
"<nocontent/>>\n"+
"</address>\n"+
"</addresses>";
String expectedStr =
String expectedStr =
"[\"addresses\","+
"{\"xsi:noNamespaceSchemaLocation\":\"test.xsd\","+
"\"xmlns:xsi\":\"http://www.w3.org/2001/XMLSchema-instance\"},"+
@ -454,12 +434,12 @@ public class JSONMLTest {
}
/**
* Convert an XML document into a JSONObject. Use JSONML.toString() to
* 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
* 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.
@ -472,23 +452,23 @@ public class JSONMLTest {
/**
* 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
* 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 =
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"+
@ -605,7 +585,7 @@ public class JSONMLTest {
"\"tagName\":\"addresses\""+
"}";
String expectedJSONArrayStr =
String expectedJSONArrayStr =
"["+
"\"addresses\","+
"{"+
@ -645,7 +625,7 @@ public class JSONMLTest {
"\"subValue\","+
"{\"svAttr\":\"svValue\"},"+
"\"abc\""+
"],"+
"]"+
"],"+
"[\"value\",3],"+
"[\"value\",4.1],"+
@ -665,12 +645,12 @@ public class JSONMLTest {
JSONObject finalJsonObject = JSONML.toJSONObject(jsonObjectXmlToStr);
Util.compareActualVsExpectedJsonObjects(finalJsonObject, expectedJsonObject);
// create a JSON array from the original string and make sure it
// 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);
@ -688,14 +668,14 @@ public class JSONMLTest {
* 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.
* JSONArray to confirm the contents.
* <p>
* This test shows how XML comments are handled.
*/
@Test
public void commentsInXML() {
String xmlStr =
String xmlStr =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<!-- this is a comment -->\n"+
"<addresses>\n"+
@ -754,7 +734,7 @@ public class JSONMLTest {
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);
}
@ -769,7 +749,7 @@ public class JSONMLTest {
final String revertedXml = JSONML.toString(jsonArray);
assertEquals(revertedXml, originalXml);
}
/**
* JSON string cannot be reverted to original xml. See test result in
* comment below.
@ -782,15 +762,15 @@ public class JSONMLTest {
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);
assertTrue("JSON Objects are not similar", originalObject.similar(revertedObject));
assertTrue("JSON Strings are not similar", new JSONObject(originalJson).similar(new JSONObject(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.
// 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.
@ -803,13 +783,13 @@ public class JSONMLTest {
// 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.
// */
@ -819,15 +799,15 @@ public class JSONMLTest {
// 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
// // order not happen the same way twice
// assertEquals(originalXml, reverseXml);
//
// assertEquals(expectedJsonString, actualJsonString);
// }
@Test (timeout = 6000)
public void testIssue484InfinteLoop1() {
try {
@ -839,11 +819,11 @@ public class JSONMLTest {
ex.getMessage());
}
}
@Test (timeout = 6000)
public void testIssue484InfinteLoop2() {
try {
String input = "??*\n" +
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.");
@ -853,4 +833,157 @@ public class JSONMLTest {
ex.getMessage());
}
}
@Test
public void testToJSONArrayMaxNestingDepthOf42IsRespected() {
final String wayTooLongMalformedXML = new String(new char[6000]).replace("\0", "<a>");
final int maxNestingDepth = 42;
try {
JSONML.toJSONArray(wayTooLongMalformedXML, JSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
fail("Expecting a JSONException");
} catch (JSONException e) {
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
}
}
@Test
public void testToJSONArrayMaxNestingDepthIsRespectedWithValidXML() {
final String perfectlyFineXML = "<Test>\n" +
" <employee>\n" +
" <name>sonoo</name>\n" +
" <salary>56000</salary>\n" +
" <married>true</married>\n" +
" </employee>\n" +
"</Test>\n";
final int maxNestingDepth = 1;
try {
JSONML.toJSONArray(perfectlyFineXML, JSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
fail("Expecting a JSONException");
} catch (JSONException e) {
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
}
}
@Test
public void testToJSONArrayMaxNestingDepthWithValidFittingXML() {
final String perfectlyFineXML = "<Test>\n" +
" <employee>\n" +
" <name>sonoo</name>\n" +
" <salary>56000</salary>\n" +
" <married>true</married>\n" +
" </employee>\n" +
"</Test>\n";
final int maxNestingDepth = 3;
try {
JSONML.toJSONArray(perfectlyFineXML, JSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
} catch (JSONException e) {
e.printStackTrace();
fail("XML document should be parsed as its maximum depth fits the maxNestingDepth " +
"parameter of the JSONMLParserConfiguration used");
}
}
@Test
public void testToJSONObjectMaxDefaultNestingDepthIsRespected() {
final String wayTooLongMalformedXML = new String(new char[6000]).replace("\0", "<a>");
try {
JSONML.toJSONObject(wayTooLongMalformedXML, JSONMLParserConfiguration.ORIGINAL);
fail("Expecting a JSONException");
} catch (JSONException e) {
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
e.getMessage().startsWith("Maximum nesting depth of " + JSONMLParserConfiguration.DEFAULT_MAXIMUM_NESTING_DEPTH));
}
}
@Test
public void testToJSONObjectUnlimitedNestingDepthIsPossible() {
int actualDepth = JSONMLParserConfiguration.DEFAULT_MAXIMUM_NESTING_DEPTH +10;
final String deeperThanDefaultMax = new String(new char[actualDepth]).replace("\0", "<a>") +
"value" +
new String(new char[actualDepth]).replace("\0", "</a>");
try {
JSONML.toJSONObject(deeperThanDefaultMax, JSONMLParserConfiguration.ORIGINAL
.withMaxNestingDepth(JSONMLParserConfiguration.UNDEFINED_MAXIMUM_NESTING_DEPTH));
} catch (JSONException e) {
e.printStackTrace();
fail("XML document should be parsed beyond the default maximum depth if maxNestingDepth " +
"parameter is set to -1 in JSONMLParserConfiguration");
}
}
@Test
public void testToJSONObjectMaxNestingDepthOf42IsRespected() {
final String wayTooLongMalformedXML = new String(new char[6000]).replace("\0", "<a>");
final int maxNestingDepth = 42;
try {
JSONML.toJSONObject(wayTooLongMalformedXML, JSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
fail("Expecting a JSONException");
} catch (JSONException e) {
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
}
}
@Test
public void testToJSONObjectMaxNestingDepthIsRespectedWithValidXML() {
final String perfectlyFineXML = "<Test>\n" +
" <employee>\n" +
" <name>sonoo</name>\n" +
" <salary>56000</salary>\n" +
" <married>true</married>\n" +
" </employee>\n" +
"</Test>\n";
final int maxNestingDepth = 1;
try {
JSONML.toJSONObject(perfectlyFineXML, JSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
fail("Expecting a JSONException");
} catch (JSONException e) {
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
}
}
@Test
public void testToJSONObjectMaxNestingDepthWithValidFittingXML() {
final String perfectlyFineXML = "<Test>\n" +
" <employee>\n" +
" <name>sonoo</name>\n" +
" <salary>56000</salary>\n" +
" <married>true</married>\n" +
" </employee>\n" +
"</Test>\n";
final int maxNestingDepth = 3;
try {
JSONML.toJSONObject(perfectlyFineXML, JSONMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
} catch (JSONException e) {
e.printStackTrace();
fail("XML document should be parsed as its maximum depth fits the maxNestingDepth " +
"parameter of the JSONMLParserConfiguration used");
}
}
}

View File

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

View File

@ -0,0 +1,146 @@
package org.json.junit;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.Arrays;
import java.util.Collection;
import org.json.JSONObject;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameters;
@RunWith(value = Parameterized.class)
public class JSONObjectNumberTest {
private final String objectString;
private Integer value = 50;
@Parameters(name = "{index}: {0}")
public static Collection<Object[]> data() {
return Arrays.asList(new Object[][]{
{"{\"value\":50}", 1},
{"{\"value\":50.0}", 1},
{"{\"value\":5e1}", 1},
{"{\"value\":5E1}", 1},
{"{\"value\":5e1}", 1},
{"{\"value\":\"50\"}", 1},
{"{\"value\":-50}", -1},
{"{\"value\":-50.0}", -1},
{"{\"value\":-5e1}", -1},
{"{\"value\":-5E1}", -1},
{"{\"value\":-5e1}", -1},
{"{\"value\":\"-50\"}", -1}
// JSON does not support octal or hex numbers;
// see https://stackoverflow.com/a/52671839/6323312
// "{value:062}", // octal 50
// "{value:0x32}" // hex 50
});
}
public JSONObjectNumberTest(String objectString, int resultIsNegative) {
this.objectString = objectString;
this.value *= resultIsNegative;
}
private JSONObject object;
@Before
public void setJsonObject() {
object = new JSONObject(objectString);
}
@Test
public void testGetNumber() {
assertEquals(value.intValue(), object.getNumber("value").intValue());
}
@Test
public void testGetBigDecimal() {
assertTrue(BigDecimal.valueOf(value).compareTo(object.getBigDecimal("value")) == 0);
}
@Test
public void testGetBigInteger() {
assertEquals(BigInteger.valueOf(value), object.getBigInteger("value"));
}
@Test
public void testGetFloat() {
assertEquals(value.floatValue(), object.getFloat("value"), 0.0f);
}
@Test
public void testGetDouble() {
assertEquals(value.doubleValue(), object.getDouble("value"), 0.0d);
}
@Test
public void testGetInt() {
assertEquals(value.intValue(), object.getInt("value"));
}
@Test
public void testGetLong() {
assertEquals(value.longValue(), object.getLong("value"));
}
@Test
public void testOptNumber() {
assertEquals(value.intValue(), object.optNumber("value").intValue());
}
@Test
public void testOptBigDecimal() {
assertTrue(BigDecimal.valueOf(value).compareTo(object.optBigDecimal("value", null)) == 0);
}
@Test
public void testOptBigInteger() {
assertEquals(BigInteger.valueOf(value), object.optBigInteger("value", null));
}
@Test
public void testOptFloat() {
assertEquals(value.floatValue(), object.optFloat("value"), 0.0f);
}
@Test
public void testOptFloatObject() {
assertEquals((Float) value.floatValue(), object.optFloatObject("value"), 0.0f);
}
@Test
public void testOptDouble() {
assertEquals(value.doubleValue(), object.optDouble("value"), 0.0d);
}
@Test
public void testOptDoubleObject() {
assertEquals((Double) value.doubleValue(), object.optDoubleObject("value"), 0.0d);
}
@Test
public void testOptInt() {
assertEquals(value.intValue(), object.optInt("value"));
}
@Test
public void testOptIntegerObject() {
assertEquals((Integer) value.intValue(), object.optIntegerObject("value"));
}
@Test
public void testOptLong() {
assertEquals(value.longValue(), object.optLong("value"));
}
@Test
public void testOptLongObject() {
assertEquals((Long) value.longValue(), object.optLongObject("value"));
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,624 @@
package org.json.junit;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONParserConfiguration;
import org.json.JSONTokener;
import org.junit.Test;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertThrows;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
public class JSONParserConfigurationTest {
private static final String TEST_SOURCE = "{\"key\": \"value1\", \"key\": \"value2\"}";
@Test(expected = JSONException.class)
public void testThrowException() {
new JSONObject(TEST_SOURCE);
}
@Test
public void testOverwrite() {
JSONObject jsonObject = new JSONObject(TEST_SOURCE,
new JSONParserConfiguration().withOverwriteDuplicateKey(true));
assertEquals("duplicate key should be overwritten", "value2", jsonObject.getString("key"));
}
@Test
public void strictModeIsCloned(){
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true)
.withMaxNestingDepth(12);
assertTrue(jsonParserConfiguration.isStrictMode());
}
@Test
public void maxNestingDepthIsCloned(){
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.<JSONParserConfiguration>withKeepStrings(true)
.withStrictMode(true);
assertTrue(jsonParserConfiguration.isKeepStrings());
}
@Test
public void useNativeNullsIsCloned() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withUseNativeNulls(true)
.withStrictMode(true);
assertTrue(jsonParserConfiguration.isUseNativeNulls());
}
@Test
public void verifyDuplicateKeyThenMaxDepth() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withOverwriteDuplicateKey(true)
.withMaxNestingDepth(42);
assertEquals(42, jsonParserConfiguration.getMaxNestingDepth());
assertTrue(jsonParserConfiguration.isOverwriteDuplicateKey());
}
@Test
public void verifyMaxDepthThenDuplicateKey() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withMaxNestingDepth(42)
.withOverwriteDuplicateKey(true);
assertTrue(jsonParserConfiguration.isOverwriteDuplicateKey());
assertEquals(42, jsonParserConfiguration.getMaxNestingDepth());
}
@Test
public void givenInvalidInput_testStrictModeTrue_shouldThrowJsonException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
List<String> strictModeInputTestCases = getNonCompliantJSONArrayList();
// this is a lot easier to debug when things stop working
for (int i = 0; i < strictModeInputTestCases.size(); ++i) {
String testCase = strictModeInputTestCases.get(i);
try {
JSONArray jsonArray = new JSONArray(testCase, jsonParserConfiguration);
String s = jsonArray.toString();
String msg = "Expected an exception, but got: " + s + " Noncompliant Array index: " + i;
fail(msg);
} catch (Exception e) {
// its all good
}
}
}
@Test
public void givenInvalidInputObjects_testStrictModeTrue_shouldThrowJsonException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
List<String> strictModeInputTestCases = getNonCompliantJSONObjectList();
// this is a lot easier to debug when things stop working
for (int i = 0; i < strictModeInputTestCases.size(); ++i) {
String testCase = strictModeInputTestCases.get(i);
try {
JSONObject jsonObject = new JSONObject(testCase, jsonParserConfiguration);
String s = jsonObject.toString();
String msg = "Expected an exception, but got: " + s + " Noncompliant Array index: " + i;
fail(msg);
} catch (Exception e) {
// its all good
}
}
}
@Test
public void givenEmptyArray_testStrictModeTrue_shouldNotThrowJsonException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "[]";
JSONArray jsonArray = new JSONArray(testCase, jsonParserConfiguration);
assertEquals(testCase, jsonArray.toString());
}
@Test
public void givenEmptyObject_testStrictModeTrue_shouldNotThrowJsonException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "{}";
JSONObject jsonObject = new JSONObject(testCase, jsonParserConfiguration);
assertEquals(testCase, jsonObject.toString());
}
@Test
public void givenValidNestedArray_testStrictModeTrue_shouldNotThrowJsonException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "[[\"c\"], [10.2], [true, false, true]]";
JSONArray jsonArray = new JSONArray(testCase, jsonParserConfiguration);
JSONArray arrayShouldContainStringAt0 = jsonArray.getJSONArray(0);
JSONArray arrayShouldContainNumberAt0 = jsonArray.getJSONArray(1);
JSONArray arrayShouldContainBooleanAt0 = jsonArray.getJSONArray(2);
assertTrue(arrayShouldContainStringAt0.get(0) instanceof String);
assertTrue(arrayShouldContainNumberAt0.get(0) instanceof Number);
assertTrue(arrayShouldContainBooleanAt0.get(0) instanceof Boolean);
}
@Test
public void givenValidNestedObject_testStrictModeTrue_shouldNotThrowJsonException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "{\"a0\":[\"c\"], \"a1\":[10.2], \"a2\":[true, false, true]}";
JSONObject jsonObject = new JSONObject(testCase, jsonParserConfiguration);
JSONArray arrayShouldContainStringAt0 = jsonObject.getJSONArray("a0");
JSONArray arrayShouldContainNumberAt0 = jsonObject.getJSONArray("a1");
JSONArray arrayShouldContainBooleanAt0 = jsonObject.getJSONArray("a2");
assertTrue(arrayShouldContainStringAt0.get(0) instanceof String);
assertTrue(arrayShouldContainNumberAt0.get(0) instanceof Number);
assertTrue(arrayShouldContainBooleanAt0.get(0) instanceof Boolean);
}
@Test
public void givenValidEmptyArrayInsideArray_testStrictModeTrue_shouldNotThrowJsonException(){
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "[[]]";
JSONArray jsonArray = new JSONArray(testCase, jsonParserConfiguration);
assertEquals(testCase, jsonArray.toString());
}
@Test
public void givenValidEmptyArrayInsideObject_testStrictModeTrue_shouldNotThrowJsonException(){
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "{\"a0\":[]}";
JSONObject jsonObject = new JSONObject(testCase, jsonParserConfiguration);
assertEquals(testCase, jsonObject.toString());
}
@Test
public void givenValidEmptyArrayInsideArray_testStrictModeFalse_shouldNotThrowJsonException(){
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(false);
String testCase = "[[]]";
JSONArray jsonArray = new JSONArray(testCase, jsonParserConfiguration);
assertEquals(testCase, jsonArray.toString());
}
@Test
public void givenValidEmptyArrayInsideObject_testStrictModeFalse_shouldNotThrowJsonException(){
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(false);
String testCase = "{\"a0\":[]}";
JSONObject jsonObject = new JSONObject(testCase, jsonParserConfiguration);
assertEquals(testCase, jsonObject.toString());
}
@Test
public void givenInvalidStringArray_testStrictModeTrue_shouldThrowJsonException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "[badString]";
JSONException je = assertThrows(JSONException.class, () -> new JSONArray(testCase, jsonParserConfiguration));
assertEquals("Strict mode error: Value 'badString' is not surrounded by quotes at 10 [character 11 line 1]",
je.getMessage());
}
@Test
public void givenInvalidStringObject_testStrictModeTrue_shouldThrowJsonException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "{\"a0\":badString}";
JSONException je = assertThrows(JSONException.class, () -> new JSONObject(testCase, jsonParserConfiguration));
assertEquals("Strict mode error: Value 'badString' is not surrounded by quotes at 15 [character 16 line 1]",
je.getMessage());
}
@Test
public void allowNullArrayInStrictMode() {
String expected = "[null]";
JSONArray jsonArray = new JSONArray(expected, new JSONParserConfiguration().withStrictMode(true));
assertEquals(expected, jsonArray.toString());
}
@Test
public void allowNullObjectInStrictMode() {
String expected = "{\"a0\":null}";
JSONObject jsonObject = new JSONObject(expected, new JSONParserConfiguration().withStrictMode(true));
assertEquals(expected, jsonObject.toString());
}
@Test
public void shouldHandleNumericArray() {
String expected = "[10]";
JSONArray jsonArray = new JSONArray(expected, new JSONParserConfiguration().withStrictMode(true));
assertEquals(expected, jsonArray.toString());
}
@Test
public void shouldHandleNumericObject() {
String expected = "{\"a0\":10}";
JSONObject jsonObject = new JSONObject(expected, new JSONParserConfiguration().withStrictMode(true));
assertEquals(expected, jsonObject.toString());
}
@Test
public void givenCompliantJSONArrayFile_testStrictModeTrue_shouldNotThrowAnyException() throws IOException {
try (Stream<String> lines = Files.lines(Paths.get("src/test/resources/compliantJsonArray.json"))) {
String compliantJsonArrayAsString = lines.collect(Collectors.joining());
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
new JSONArray(compliantJsonArrayAsString, jsonParserConfiguration);
}
}
@Test
public void givenCompliantJSONObjectFile_testStrictModeTrue_shouldNotThrowAnyException() throws IOException {
try (Stream<String> lines = Files.lines(Paths.get("src/test/resources/compliantJsonObject.json"))) {
String compliantJsonObjectAsString = lines.collect(Collectors.joining());
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
new JSONObject(compliantJsonObjectAsString, jsonParserConfiguration);
}
}
@Test
public void givenInvalidInputArrays_testStrictModeFalse_shouldNotThrowAnyException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(false);
List<String> strictModeInputTestCases = getNonCompliantJSONArrayList();
// this is a lot easier to debug when things stop working
for (int i = 0; i < strictModeInputTestCases.size(); ++i) {
String testCase = strictModeInputTestCases.get(i);
try {
JSONArray jsonArray = new JSONArray(testCase, jsonParserConfiguration);
} catch (Exception e) {
System.out.println("Unexpected exception: " + e.getMessage() + " Noncompliant Array index: " + i);
fail(String.format("Noncompliant array index: %d", i));
}
}
}
@Test
public void givenInvalidInputObjects_testStrictModeFalse_shouldNotThrowAnyException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(false);
List<String> strictModeInputTestCases = getNonCompliantJSONObjectList();
// this is a lot easier to debug when things stop working
for (int i = 0; i < strictModeInputTestCases.size(); ++i) {
String testCase = strictModeInputTestCases.get(i);
try {
JSONObject jsonObject = new JSONObject(testCase, jsonParserConfiguration);
} catch (Exception e) {
System.out.println("Unexpected exception: " + e.getMessage() + " Noncompliant Array index: " + i);
fail(String.format("Noncompliant array index: %d", i));
}
}
}
@Test
public void givenInvalidInputArray_testStrictModeTrue_shouldThrowInvalidCharacterErrorMessage() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "[1,2];[3,4]";
JSONException je = assertThrows("expected non-compliant array but got instead: " + testCase,
JSONException.class, () -> new JSONArray(testCase, jsonParserConfiguration));
assertEquals("Strict mode error: Unparsed characters found at end of input text at 6 [character 7 line 1]",
je.getMessage());
}
@Test
public void givenInvalidInputObject_testStrictModeTrue_shouldThrowInvalidCharacterErrorMessage() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "{\"a0\":[1,2];\"a1\":[3,4]}";
JSONException je = assertThrows("expected non-compliant array but got instead: " + testCase,
JSONException.class, () -> new JSONObject(testCase, jsonParserConfiguration));
assertEquals("Strict mode error: Invalid character ';' found at 12 [character 13 line 1]", je.getMessage());
}
@Test
public void givenInvalidInputArrayWithNumericStrings_testStrictModeTrue_shouldThrowInvalidCharacterErrorMessage() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "[\"1\",\"2\"];[3,4]";
JSONException je = assertThrows("expected non-compliant array but got instead: " + testCase,
JSONException.class, () -> new JSONArray(testCase, jsonParserConfiguration));
assertEquals("Strict mode error: Unparsed characters found at end of input text at 10 [character 11 line 1]",
je.getMessage());
}
@Test
public void givenInvalidInputObjectWithNumericStrings_testStrictModeTrue_shouldThrowInvalidCharacterErrorMessage() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "{\"a0\":[\"1\",\"2\"];\"a1\":[3,4]}";
JSONException je = assertThrows("expected non-compliant array but got instead: " + testCase,
JSONException.class, () -> new JSONObject(testCase, jsonParserConfiguration));
assertEquals("Strict mode error: Invalid character ';' found at 16 [character 17 line 1]", je.getMessage());
}
@Test
public void givenInvalidInputArray_testStrictModeTrue_shouldThrowValueNotSurroundedByQuotesErrorMessage() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "[{\"test\": implied}]";
JSONException je = assertThrows("expected non-compliant array but got instead: " + testCase,
JSONException.class, () -> new JSONArray(testCase, jsonParserConfiguration));
assertEquals("Strict mode error: Value 'implied' is not surrounded by quotes at 17 [character 18 line 1]",
je.getMessage());
}
@Test
public void givenInvalidInputObject_testStrictModeTrue_shouldThrowValueNotSurroundedByQuotesErrorMessage() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "{\"a0\":{\"test\": implied}]}";
JSONException je = assertThrows("expected non-compliant array but got instead: " + testCase,
JSONException.class, () -> new JSONObject(testCase, jsonParserConfiguration));
assertEquals("Strict mode error: Value 'implied' is not surrounded by quotes at 22 [character 23 line 1]",
je.getMessage());
}
@Test
public void givenInvalidInputArray_testStrictModeFalse_shouldNotThrowAnyException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(false);
String testCase = "[{\"test\": implied}]";
new JSONArray(testCase, jsonParserConfiguration);
}
@Test
public void givenInvalidInputObject_testStrictModeFalse_shouldNotThrowAnyException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(false);
String testCase = "{\"a0\":{\"test\": implied}}";
new JSONObject(testCase, jsonParserConfiguration);
}
@Test
public void givenNonCompliantQuotesArray_testStrictModeTrue_shouldThrowJsonExceptionWithConcreteErrorDescription() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCaseOne = "[\"abc', \"test\"]";
String testCaseTwo = "['abc\", \"test\"]";
String testCaseThree = "['abc']";
String testCaseFour = "[{'testField': \"testValue\"}]";
JSONException jeOne = assertThrows(JSONException.class,
() -> new JSONArray(testCaseOne, jsonParserConfiguration));
JSONException jeTwo = assertThrows(JSONException.class,
() -> new JSONArray(testCaseTwo, jsonParserConfiguration));
JSONException jeThree = assertThrows(JSONException.class,
() -> new JSONArray(testCaseThree, jsonParserConfiguration));
JSONException jeFour = assertThrows(JSONException.class,
() -> new JSONArray(testCaseFour, jsonParserConfiguration));
assertEquals(
"Expected a ',' or ']' at 10 [character 11 line 1]",
jeOne.getMessage());
assertEquals(
"Strict mode error: Single quoted strings are not allowed at 2 [character 3 line 1]",
jeTwo.getMessage());
assertEquals(
"Strict mode error: Single quoted strings are not allowed at 2 [character 3 line 1]",
jeThree.getMessage());
assertEquals(
"Strict mode error: Single quoted strings are not allowed at 3 [character 4 line 1]",
jeFour.getMessage());
}
@Test
public void givenNonCompliantQuotesObject_testStrictModeTrue_shouldThrowJsonExceptionWithConcreteErrorDescription() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCaseOne = "{\"abc': \"test\"}";
String testCaseTwo = "{'abc\": \"test\"}";
String testCaseThree = "{\"a\":'abc'}";
String testCaseFour = "{'testField': \"testValue\"}";
JSONException jeOne = assertThrows(JSONException.class,
() -> new JSONObject(testCaseOne, jsonParserConfiguration));
JSONException jeTwo = assertThrows(JSONException.class,
() -> new JSONObject(testCaseTwo, jsonParserConfiguration));
JSONException jeThree = assertThrows(JSONException.class,
() -> new JSONObject(testCaseThree, jsonParserConfiguration));
JSONException jeFour = assertThrows(JSONException.class,
() -> new JSONObject(testCaseFour, jsonParserConfiguration));
assertEquals(
"Expected a ':' after a key at 10 [character 11 line 1]",
jeOne.getMessage());
assertEquals(
"Strict mode error: Single quoted strings are not allowed at 2 [character 3 line 1]",
jeTwo.getMessage());
assertEquals(
"Strict mode error: Single quoted strings are not allowed at 6 [character 7 line 1]",
jeThree.getMessage());
assertEquals(
"Strict mode error: Single quoted strings are not allowed at 2 [character 3 line 1]",
jeFour.getMessage());
}
@Test
public void givenUnbalancedQuotesArray_testStrictModeFalse_shouldThrowJsonException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(false);
String testCaseOne = "[\"abc', \"test\"]";
String testCaseTwo = "['abc\", \"test\"]";
JSONException jeOne = assertThrows(JSONException.class,
() -> new JSONArray(testCaseOne, jsonParserConfiguration));
JSONException jeTwo = assertThrows(JSONException.class,
() -> new JSONArray(testCaseTwo, jsonParserConfiguration));
assertEquals("Expected a ',' or ']' at 10 [character 11 line 1]", jeOne.getMessage());
assertEquals("Unterminated string. Character with int code 0 is not allowed within a quoted string. at 15 [character 16 line 1]", jeTwo.getMessage());
}
@Test
public void givenUnbalancedQuotesObject_testStrictModeFalse_shouldThrowJsonException() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(false);
String testCaseOne = "{\"abc': \"test\"}";
String testCaseTwo = "{'abc\": \"test\"}";
JSONException jeOne = assertThrows(JSONException.class,
() -> new JSONObject(testCaseOne, jsonParserConfiguration));
JSONException jeTwo = assertThrows(JSONException.class,
() -> new JSONObject(testCaseTwo, jsonParserConfiguration));
assertEquals("Expected a ':' after a key at 10 [character 11 line 1]", jeOne.getMessage());
assertEquals("Unterminated string. Character with int code 0 is not allowed within a quoted string. at 15 [character 16 line 1]", jeTwo.getMessage());
}
@Test
public void givenInvalidInputArray_testStrictModeTrue_shouldThrowKeyNotSurroundedByQuotesErrorMessage() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "[{test: implied}]";
JSONException je = assertThrows("expected non-compliant array but got instead: " + testCase,
JSONException.class, () -> new JSONArray(testCase, jsonParserConfiguration));
assertEquals("Strict mode error: Value 'test' is not surrounded by quotes at 6 [character 7 line 1]",
je.getMessage());
}
@Test
public void givenInvalidInputObject_testStrictModeTrue_shouldThrowKeyNotSurroundedByQuotesErrorMessage() {
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration()
.withStrictMode(true);
String testCase = "{test: implied}";
JSONException je = assertThrows("expected non-compliant json but got instead: " + testCase,
JSONException.class, () -> new JSONObject(testCase, jsonParserConfiguration));
assertEquals("Strict mode error: Value 'test' is not surrounded by quotes at 5 [character 6 line 1]",
je.getMessage());
}
@Test
public void givenInvalidInputObject_testStrictModeTrue_JSONObjectUsingJSONTokener_shouldThrowJSONException() {
JSONException exception = assertThrows(JSONException.class, () -> {
new JSONObject(new JSONTokener("{\"key\":\"value\"} invalid trailing text"), new JSONParserConfiguration().withStrictMode(true));
});
assertEquals("Strict mode error: Unparsed characters found at end of input text at 17 [character 18 line 1]", exception.getMessage());
}
@Test
public void givenInvalidInputObject_testStrictModeTrue_JSONObjectUsingString_shouldThrowJSONException() {
JSONException exception = assertThrows(JSONException.class, () -> {
new JSONObject("{\"key\":\"value\"} invalid trailing text", new JSONParserConfiguration().withStrictMode(true));
});
assertEquals("Strict mode error: Unparsed characters found at end of input text at 17 [character 18 line 1]", exception.getMessage());
}
@Test
public void givenInvalidInputObject_testStrictModeTrue_JSONArrayUsingJSONTokener_shouldThrowJSONException() {
JSONException exception = assertThrows(JSONException.class, () -> {
new JSONArray(new JSONTokener("[\"value\"] invalid trailing text"), new JSONParserConfiguration().withStrictMode(true));
});
assertEquals("Strict mode error: Unparsed characters found at end of input text at 11 [character 12 line 1]", exception.getMessage());
}
@Test
public void givenInvalidInputObject_testStrictModeTrue_JSONArrayUsingString_shouldThrowJSONException() {
JSONException exception = assertThrows(JSONException.class, () -> {
new JSONArray("[\"value\"] invalid trailing text", new JSONParserConfiguration().withStrictMode(true));
});
assertEquals("Strict mode error: Unparsed characters found at end of input text at 11 [character 12 line 1]", exception.getMessage());
}
/**
* This method contains short but focused use-case samples and is exclusively used to test strictMode unit tests in
* this class.
*
* @return List with JSON strings.
*/
private List<String> getNonCompliantJSONArrayList() {
return Arrays.asList(
"[1],",
"[1,]",
"[,]",
"[,,]",
"[[1],\"sa\",[2]]a",
"[1],\"dsa\": \"test\"",
"[[a]]",
"[]asdf",
"[]]",
"[]}",
"[][",
"[]{",
"[],",
"[]:",
"[],[",
"[],{",
"[1,2];[3,4]",
"[test]",
"[{'testSingleQuote': 'testSingleQuote'}]",
"[1, 2,3]:[4,5]",
"[{test: implied}]",
"[{\"test\": implied}]",
"[{\"number\":\"7990154836330\",\"color\":'c'},{\"number\":8784148854580,\"color\":RosyBrown},{\"number\":\"5875770107113\",\"color\":\"DarkSeaGreen\"}]",
"[{test: \"implied\"}]");
}
/**
* This method contains short but focused use-case samples and is exclusively used to test strictMode unit tests in
* this class.
*
* @return List with JSON strings.
*/
private List<String> getNonCompliantJSONObjectList() {
return Arrays.asList(
"{\"a\":1},",
"{\"a\":1,}",
"{\"a0\":[1],\"a1\":\"sa\",\"a2\":[2]}a",
"{\"a\":1},\"dsa\": \"test\"",
"{\"a\":[a]}",
"{}asdf",
"{}}",
"{}]",
"{}{",
"{}[",
"{},",
"{}:",
"{},{",
"{},[",
"{\"a0\":[1,2];\"a1\":[3,4]}",
"{\"a\":test}",
"{a:{'testSingleQuote': 'testSingleQuote'}}",
"{\"a0\":1, \"a1\":2,\"a2\":3}:{\"a3\":4,\"a4\":5}",
"{\"a\":{test: implied}}",
"{a:{\"test\": implied}}",
"{a:[{\"number\":\"7990154836330\",\"color\":'c'},{\"number\":8784148854580,\"color\":RosyBrown},{\"number\":\"5875770107113\",\"color\":\"DarkSeaGreen\"}]}",
"{a:{test: \"implied\"}}"
);
}
}

View File

@ -1,27 +1,7 @@
package org.json.junit;
/*
Copyright (c) 2020 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import static org.junit.Assert.assertEquals;
@ -92,8 +72,10 @@ public class JSONPointerTest {
@Test
public void queryByEmptyKeySubObject() {
assertEquals( "{\"\":\"empty key of an object with an empty key\",\"subKey\":\"Some" +
" other value\"}", query("/obj/").toString());
JSONObject json = new JSONObject("{\"\":\"empty key of an object with an empty key\",\"subKey\":\"Some" +
" other value\"}");
JSONObject obj = (JSONObject) query("/obj/");
assertTrue(json.similar(obj));
}
@Test
@ -402,8 +384,7 @@ public class JSONPointerTest {
String str = "{"+
"\"string\\\\\\\\Key\":\"hello world!\","+
"\"\\\\\":\"slash test\"," +
"}"+
"\"\\\\\":\"slash test\"" +
"}";
JSONObject jsonObject = new JSONObject(str);
//Summary of issue: When a KEY in the jsonObject is "\\\\" --> it's held

View File

@ -1,27 +1,7 @@
package org.json.junit;
/*
Copyright (c) 2020 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import static org.junit.Assert.*;
@ -339,6 +319,22 @@ public class JSONStringTest {
}
}
@Test
public void testEnumJSONString() {
JSONObject jsonObject = new JSONObject();
jsonObject.put("key", MyEnum.MY_ENUM);
assertEquals("{\"key\":\"myJsonString\"}", jsonObject.toString());
}
private enum MyEnum implements JSONString {
MY_ENUM;
@Override
public String toJSONString() {
return "\"myJsonString\"";
}
}
/**
* A JSONString that returns a valid JSON string value.
*/

View File

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

View File

@ -1,27 +1,7 @@
package org.json.junit;
/*
Copyright (c) 2020 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import static org.junit.Assert.assertEquals;
@ -36,10 +16,7 @@ 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.json.*;
import org.junit.Test;
/**
@ -118,7 +95,17 @@ public class JSONTokenerTest {
checkValid(" [] ",JSONArray.class);
checkValid("[1,2]",JSONArray.class);
checkValid("\n\n[1,2]\n\n",JSONArray.class);
checkValid("1 2", String.class);
// Test should fail if default strictMode is true, pass if false
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration();
if (jsonParserConfiguration.isStrictMode()) {
try {
checkValid("1 2", String.class);
assertEquals("Expected to throw exception due to invalid string", true, false);
} catch (JSONException e) { }
} else {
checkValid("1 2", String.class);
}
}
@Test
@ -333,4 +320,54 @@ public class JSONTokenerTest {
assertEquals(0, t2.next());
assertFalse(t2.more());
}
@Test
public void testAutoClose(){
Reader reader = new StringReader("some test string");
try {
JSONTokener tokener = new JSONTokener(reader);
tokener.close();
tokener.next();
} catch (Exception exception){
assertEquals("Stream closed", exception.getMessage());
}
}
@Test
public void testInvalidInput_JSONObject_withoutStrictModel_shouldParseInput() {
String input = "{\"invalidInput\": [],}";
JSONTokener tokener = new JSONTokener(input);
// Test should fail if default strictMode is true, pass if false
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration();
if (jsonParserConfiguration.isStrictMode()) {
try {
Object value = tokener.nextValue();
assertEquals(new JSONObject(input).toString(), value.toString());
assertEquals("Expected to throw exception due to invalid string", true, false);
} catch (JSONException e) { }
} else {
Object value = tokener.nextValue();
assertEquals(new JSONObject(input).toString(), value.toString());
}
}
@Test
public void testInvalidInput_JSONArray_withoutStrictModel_shouldParseInput() {
String input = "[\"invalidInput\",]";
JSONTokener tokener = new JSONTokener(input);
// Test should fail if default strictMode is true, pass if false
JSONParserConfiguration jsonParserConfiguration = new JSONParserConfiguration();
if (jsonParserConfiguration.isStrictMode()) {
try {
Object value = tokener.nextValue();
assertEquals(new JSONArray(input).toString(), value.toString());
assertEquals("Expected to throw exception due to invalid string", true, false);
} catch (JSONException e) { }
} else {
Object value = tokener.nextValue();
assertEquals(new JSONArray(input).toString(), value.toString());
}
}
}

View File

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

View File

@ -0,0 +1,60 @@
package org.json.junit;
import static org.junit.Assert.assertEquals;
import org.json.StringBuilderWriter;
import org.junit.Before;
import org.junit.Test;
public class StringBuilderWriterTest {
private StringBuilderWriter writer;
@Before
public void setUp() {
writer = new StringBuilderWriter();
}
@Test
public void testWriteChar() {
writer.write('a');
assertEquals("a", writer.toString());
}
@Test
public void testWriteCharArray() {
char[] chars = {'a', 'b', 'c'};
writer.write(chars, 0, 3);
assertEquals("abc", writer.toString());
}
@Test
public void testWriteString() {
writer.write("hello");
assertEquals("hello", writer.toString());
}
@Test
public void testWriteStringWithOffsetAndLength() {
writer.write("hello world", 6, 5);
assertEquals("world", writer.toString());
}
@Test
public void testAppendCharSequence() {
writer.append("hello");
assertEquals("hello", writer.toString());
}
@Test
public void testAppendCharSequenceWithStartAndEnd() {
CharSequence csq = "hello world";
writer.append(csq, 6, 11);
assertEquals("world", writer.toString());
}
@Test
public void testAppendChar() {
writer.append('a');
assertEquals("a", writer.toString());
}
}

View File

@ -1,27 +1,7 @@
package org.json.junit;
/*
Copyright (c) 2020 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import static org.junit.Assert.*;
@ -78,7 +58,6 @@ public class Util {
* or something else.
* @param value created by the code to be tested
* @param expectedValue created specifically for comparing
* @param key key to the jsonObject entry to be compared
*/
private static void compareActualVsExpectedObjects(Object value,
Object expectedValue) {
@ -117,4 +96,106 @@ public class Util {
);
}
}
/**
* 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);
}
}
}

View File

@ -1,34 +1,9 @@
package org.json.junit;
/*
Copyright (c) 2020 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
@ -47,6 +22,8 @@ import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import static org.junit.Assert.*;
/**
* Tests for JSON-Java XML.java with XMLParserConfiguration.java
@ -293,9 +270,9 @@ public class XMLConfigurationTest {
String expectedStr =
"{\"addresses\":{\"address\":{\"street\":\"[CDATA[Baker street 5]\","+
"\"name\":\"Joe Tester\",\"NothingHere\":\"\",TrueValue:true,\n"+
"\"name\":\"Joe Tester\",\"NothingHere\":\"\",\"TrueValue\":true,\n"+
"\"FalseValue\":false,\"NullValue\":null,\"PositiveValue\":42,\n"+
"\"NegativeValue\":-23,\"DoubleValue\":-23.45,\"Nan\":-23x.45,\n"+
"\"NegativeValue\":-23,\"DoubleValue\":-23.45,\"Nan\":\"-23x.45\",\n"+
"\"ArrayOfNum\":\"1, 2, 3, 4.1, 5.2\"\n"+
"},\"xsi:noNamespaceSchemaLocation\":"+
"\"test.xsd\",\"xmlns:xsi\":\"http://www.w3.org/2001/"+
@ -577,6 +554,40 @@ public class XMLConfigurationTest {
assertEquals(actualXML, resultXML);
}
@Test
public void shouldHandleEmptyNodeValue()
{
JSONObject inputJSON = new JSONObject();
inputJSON.put("Emptyness", "");
String expectedXmlWithoutExplicitEndTag = "<Emptyness/>";
String expectedXmlWithExplicitEndTag = "<Emptyness></Emptyness>";
assertEquals(expectedXmlWithoutExplicitEndTag, XML.toString(inputJSON, null,
new XMLParserConfiguration().withCloseEmptyTag(false)));
assertEquals(expectedXmlWithExplicitEndTag, XML.toString(inputJSON, null,
new XMLParserConfiguration().withCloseEmptyTag(true)));
}
@Test
public void shouldKeepConfigurationIntactAndUpdateCloseEmptyTagChoice()
{
XMLParserConfiguration keepStrings = XMLParserConfiguration.KEEP_STRINGS;
XMLParserConfiguration keepStringsAndCloseEmptyTag = keepStrings.withCloseEmptyTag(true);
XMLParserConfiguration keepDigits = keepStringsAndCloseEmptyTag.withKeepStrings(false);
XMLParserConfiguration keepDigitsAndNoCloseEmptyTag = keepDigits.withCloseEmptyTag(false);
assertTrue(keepStrings.isKeepNumberAsString());
assertTrue(keepStrings.isKeepBooleanAsString());
assertFalse(keepStrings.isCloseEmptyTag());
assertTrue(keepStringsAndCloseEmptyTag.isKeepNumberAsString());
assertTrue(keepStringsAndCloseEmptyTag.isKeepBooleanAsString());
assertTrue(keepStringsAndCloseEmptyTag.isCloseEmptyTag());
assertFalse(keepDigits.isKeepNumberAsString());
assertFalse(keepDigits.isKeepBooleanAsString());
assertTrue(keepDigits.isCloseEmptyTag());
assertFalse(keepDigitsAndNoCloseEmptyTag.isKeepNumberAsString());
assertFalse(keepDigitsAndNoCloseEmptyTag.isKeepBooleanAsString());
assertFalse(keepDigitsAndNoCloseEmptyTag.isCloseEmptyTag());
}
/**
* Investigate exactly how the "content" keyword works
*/
@ -759,6 +770,67 @@ public class XMLConfigurationTest {
Util.compareActualVsExpectedJsonObjects(actualJsonOutput,expected);
}
/**
* JSON string lost leading zero and converted "True" to true.
*/
@Test
public void testToJSONArray_jsonOutput_withKeepNumberAsString() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><id>null</id><item id=\"01\"/><title>True</title></root>";
final JSONObject expected = new JSONObject("{\"root\":{\"item\":{\"id\":\"01\"},\"id\":[\"01\",\"1\",\"00\",\"0\",null],\"title\":true}}");
final JSONObject actualJsonOutput = XML.toJSONObject(originalXml,
new XMLParserConfiguration().withKeepNumberAsString(true));
Util.compareActualVsExpectedJsonObjects(actualJsonOutput,expected);
}
/**
* JSON string lost leading zero and converted "True" to true.
*/
@Test
public void testToJSONArray_jsonOutput_withKeepBooleanAsString() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><id>null</id><item id=\"01\"/><title>True</title></root>";
final JSONObject expected = new JSONObject("{\"root\":{\"item\":{\"id\":\"01\"},\"id\":[\"01\",1,\"00\",0,null],\"title\":\"True\"}}");
final JSONObject actualJsonOutput = XML.toJSONObject(originalXml,
new XMLParserConfiguration().withKeepBooleanAsString(true));
Util.compareActualVsExpectedJsonObjects(actualJsonOutput,expected);
}
/**
* null is "null" when keepStrings == true
*/
@Test
public void testToJSONArray_jsonOutput_null_withKeepString() {
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>null</title></root>";
final JSONObject expected = new JSONObject("{\"root\":{\"item\":{\"id\":\"01\"},\"id\":[\"01\",\"1\",\"00\",\"0\"],\"title\":\"null\"}}");
final JSONObject actualJsonOutput = XML.toJSONObject(originalXml,
new XMLParserConfiguration().withKeepStrings(true));
Util.compareActualVsExpectedJsonObjects(actualJsonOutput,expected);
}
/**
* Test keepStrings behavior when setting keepBooleanAsString, keepNumberAsString
*/
@Test
public void test_keepStringBehavior() {
XMLParserConfiguration xpc = new XMLParserConfiguration().withKeepStrings(true);
assertEquals(xpc.isKeepStrings(), true);
xpc = xpc.withKeepBooleanAsString(true);
xpc = xpc.withKeepNumberAsString(false);
assertEquals(xpc.isKeepStrings(), false);
xpc = xpc.withKeepBooleanAsString(false);
xpc = xpc.withKeepNumberAsString(true);
assertEquals(xpc.isKeepStrings(), false);
xpc = xpc.withKeepBooleanAsString(true);
xpc = xpc.withKeepNumberAsString(true);
assertEquals(xpc.isKeepStrings(), true);
xpc = xpc.withKeepBooleanAsString(false);
xpc = xpc.withKeepNumberAsString(false);
assertEquals(xpc.isKeepStrings(), false);
}
/**
* JSON string cannot be reverted to original xml.
*/
@ -1071,6 +1143,29 @@ public class XMLConfigurationTest {
Util.compareActualVsExpectedJsonObjects(jsonObject, expetedJsonObject);
}
@Test
public void testMaxNestingDepthIsSet() {
XMLParserConfiguration xmlParserConfiguration = XMLParserConfiguration.ORIGINAL;
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), XMLParserConfiguration.DEFAULT_MAXIMUM_NESTING_DEPTH);
xmlParserConfiguration = xmlParserConfiguration.withMaxNestingDepth(42);
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), 42);
xmlParserConfiguration = xmlParserConfiguration.withMaxNestingDepth(0);
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), 0);
xmlParserConfiguration = xmlParserConfiguration.withMaxNestingDepth(-31415926);
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), XMLParserConfiguration.UNDEFINED_MAXIMUM_NESTING_DEPTH);
xmlParserConfiguration = xmlParserConfiguration.withMaxNestingDepth(Integer.MIN_VALUE);
assertEquals(xmlParserConfiguration.getMaxNestingDepth(), XMLParserConfiguration.UNDEFINED_MAXIMUM_NESTING_DEPTH);
}
/**
* Convenience method, given an input string and expected result,
@ -1150,4 +1245,4 @@ public class XMLConfigurationTest {
assertTrue("Error: " +e.getMessage(), false);
}
}
}
}

View File

@ -1,27 +1,7 @@
package org.json.junit;
/*
Copyright (c) 2020 JSON.org
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
The Software shall be used for Good, not Evil.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.
Public Domain.
*/
import static org.junit.Assert.assertEquals;
@ -38,16 +18,11 @@ import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.StringReader;
import java.nio.charset.Charset;
import java.util.HashMap;
import java.util.Map;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import org.json.JSONTokener;
import org.json.XML;
import org.json.XMLParserConfiguration;
import org.json.XMLXsiTypeConverter;
import org.json.*;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
@ -292,9 +267,9 @@ public class XMLTest {
String expectedStr =
"{\"addresses\":{\"address\":{\"street\":\"[CDATA[Baker street 5]\","+
"\"name\":\"Joe Tester\",\"NothingHere\":\"\",TrueValue:true,\n"+
"\"name\":\"Joe Tester\",\"NothingHere\":\"\",\"TrueValue\":true,\n"+
"\"FalseValue\":false,\"NullValue\":null,\"PositiveValue\":42,\n"+
"\"NegativeValue\":-23,\"DoubleValue\":-23.45,\"Nan\":-23x.45,\n"+
"\"NegativeValue\":-23,\"DoubleValue\":-23.45,\"Nan\":\"-23x.45\",\n"+
"\"ArrayOfNum\":\"1, 2, 3, 4.1, 5.2\"\n"+
"},\"xsi:noNamespaceSchemaLocation\":"+
"\"test.xsd\",\"xmlns:xsi\":\"http://www.w3.org/2001/"+
@ -941,7 +916,7 @@ public class XMLTest {
InputStream xmlStream = null;
try {
xmlStream = XMLTest.class.getClassLoader().getResourceAsStream("Issue537.xml");
Reader xmlReader = new InputStreamReader(xmlStream);
Reader xmlReader = new InputStreamReader(xmlStream, Charset.forName("UTF-8"));
JSONObject actual = XML.toJSONObject(xmlReader, true);
InputStream jsonStream = null;
try {
@ -1069,4 +1044,389 @@ public class XMLTest {
fail("Expected to be unable to modify the config");
} catch (Exception ignored) { }
}
@Test
public void testIndentComplicatedJsonObject(){
String str = "{\n" +
" \"success\": true,\n" +
" \"error\": null,\n" +
" \"response\": [\n" +
" {\n" +
" \"timestamp\": 1664917200,\n" +
" \"dateTimeISO\": \"2022-10-05T00:00:00+03:00\",\n" +
" \"loc\": {\n" +
" \"lat\": 39.91987,\n" +
" \"long\": 32.85427\n" +
" },\n" +
" \"place\": {\n" +
" \"name\": \"ankara\",\n" +
" \"state\": \"an\",\n" +
" \"country\": \"tr\"\n" +
" },\n" +
" \"profile\": {\n" +
" \"tz\": \"Europe/Istanbul\"\n" +
" },\n" +
" \"sun\": {\n" +
" \"rise\": 1664941721,\n" +
" \"riseISO\": \"2022-10-05T06:48:41+03:00\",\n" +
" \"set\": 1664983521,\n" +
" \"setISO\": \"2022-10-05T18:25:21+03:00\",\n" +
" \"transit\": 1664962621,\n" +
" \"transitISO\": \"2022-10-05T12:37:01+03:00\",\n" +
" \"midnightSun\": false,\n" +
" \"polarNight\": false,\n" +
" \"twilight\": {\n" +
" \"civilBegin\": 1664940106,\n" +
" \"civilBeginISO\": \"2022-10-05T06:21:46+03:00\",\n" +
" \"civilEnd\": 1664985136,\n" +
" \"civilEndISO\": \"2022-10-05T18:52:16+03:00\",\n" +
" \"nauticalBegin\": 1664938227,\n" +
" \"nauticalBeginISO\": \"2022-10-05T05:50:27+03:00\",\n" +
" \"nauticalEnd\": 1664987015,\n" +
" \"nauticalEndISO\": \"2022-10-05T19:23:35+03:00\",\n" +
" \"astronomicalBegin\": 1664936337,\n" +
" \"astronomicalBeginISO\": \"2022-10-05T05:18:57+03:00\",\n" +
" \"astronomicalEnd\": 1664988905,\n" +
" \"astronomicalEndISO\": \"2022-10-05T19:55:05+03:00\"\n" +
" }\n" +
" },\n" +
" \"moon\": {\n" +
" \"rise\": 1664976480,\n" +
" \"riseISO\": \"2022-10-05T16:28:00+03:00\",\n" +
" \"set\": 1664921520,\n" +
" \"setISO\": \"2022-10-05T01:12:00+03:00\",\n" +
" \"transit\": 1664994240,\n" +
" \"transitISO\": \"2022-10-05T21:24:00+03:00\",\n" +
" \"underfoot\": 1664949360,\n" +
" \"underfootISO\": \"2022-10-05T08:56:00+03:00\",\n" +
" \"phase\": {\n" +
" \"phase\": 0.3186,\n" +
" \"name\": \"waxing gibbous\",\n" +
" \"illum\": 71,\n" +
" \"age\": 9.41,\n" +
" \"angle\": 0.55\n" +
" }\n" +
" }\n" +
" }\n" +
" ]\n" +
"}" ;
JSONObject jsonObject = new JSONObject(str);
String actualIndentedXmlString = XML.toString(jsonObject, 1);
JSONObject actualJsonObject = XML.toJSONObject(actualIndentedXmlString);
String expected = "<success>true</success>\n" +
"<response>\n" +
" <dateTimeISO>2022-10-05T00:00:00+03:00</dateTimeISO>\n" +
" <loc>\n" +
" <lat>39.91987</lat>\n" +
" <long>32.85427</long>\n" +
" </loc>\n" +
" <moon>\n" +
" <phase>\n" +
" <phase>0.3186</phase>\n" +
" <name>waxing gibbous</name>\n" +
" <angle>0.55</angle>\n" +
" <illum>71</illum>\n" +
" <age>9.41</age>\n" +
" </phase>\n" +
" <setISO>2022-10-05T01:12:00+03:00</setISO>\n" +
" <underfoot>1664949360</underfoot>\n" +
" <set>1664921520</set>\n" +
" <transit>1664994240</transit>\n" +
" <transitISO>2022-10-05T21:24:00+03:00</transitISO>\n" +
" <riseISO>2022-10-05T16:28:00+03:00</riseISO>\n" +
" <rise>1664976480</rise>\n" +
" <underfootISO>2022-10-05T08:56:00+03:00</underfootISO>\n" +
" </moon>\n" +
" <profile>\n" +
" <tz>Europe/Istanbul</tz>\n" +
" </profile>\n" +
" <place>\n" +
" <country>tr</country>\n" +
" <name>ankara</name>\n" +
" <state>an</state>\n" +
" </place>\n" +
" <sun>\n" +
" <setISO>2022-10-05T18:25:21+03:00</setISO>\n" +
" <midnightSun>false</midnightSun>\n" +
" <set>1664983521</set>\n" +
" <transit>1664962621</transit>\n" +
" <polarNight>false</polarNight>\n" +
" <transitISO>2022-10-05T12:37:01+03:00</transitISO>\n" +
" <riseISO>2022-10-05T06:48:41+03:00</riseISO>\n" +
" <rise>1664941721</rise>\n" +
" <twilight>\n" +
" <civilEnd>1664985136</civilEnd>\n" +
" <astronomicalBegin>1664936337</astronomicalBegin>\n" +
" <astronomicalEnd>1664988905</astronomicalEnd>\n" +
" <astronomicalBeginISO>2022-10-05T05:18:57+03:00</astronomicalBeginISO>\n" +
" <civilBegin>1664940106</civilBegin>\n" +
" <nauticalEndISO>2022-10-05T19:23:35+03:00</nauticalEndISO>\n" +
" <astronomicalEndISO>2022-10-05T19:55:05+03:00</astronomicalEndISO>\n" +
" <nauticalBegin>1664938227</nauticalBegin>\n" +
" <nauticalEnd>1664987015</nauticalEnd>\n" +
" <nauticalBeginISO>2022-10-05T05:50:27+03:00</nauticalBeginISO>\n" +
" <civilBeginISO>2022-10-05T06:21:46+03:00</civilBeginISO>\n" +
" <civilEndISO>2022-10-05T18:52:16+03:00</civilEndISO>\n" +
" </twilight>\n" +
" </sun>\n" +
" <timestamp>1664917200</timestamp>\n" +
"</response>\n" +
"<error>null</error>\n";
JSONObject expectedJsonObject = XML.toJSONObject(expected);
assertTrue(expectedJsonObject.similar(actualJsonObject));
}
@Test
public void shouldCreateExplicitEndTagWithEmptyValueWhenConfigured(){
String jsonString = "{\"outer\":{\"innerOne\":\"\", \"innerTwo\":\"two\"}}";
JSONObject jsonObject = new JSONObject(jsonString);
String expectedXmlString = "<encloser><outer><innerOne></innerOne><innerTwo>two</innerTwo></outer></encloser>";
String xmlForm = XML.toString(jsonObject,"encloser", new XMLParserConfiguration().withCloseEmptyTag(true));
JSONObject actualJsonObject = XML.toJSONObject(xmlForm);
JSONObject expectedJsonObject = XML.toJSONObject(expectedXmlString);
assertTrue(expectedJsonObject.similar(actualJsonObject));
}
@Test
public void shouldNotCreateExplicitEndTagWithEmptyValueWhenNotConfigured(){
String jsonString = "{\"outer\":{\"innerOne\":\"\", \"innerTwo\":\"two\"}}";
JSONObject jsonObject = new JSONObject(jsonString);
String expectedXmlString = "<encloser><outer><innerOne/><innerTwo>two</innerTwo></outer></encloser>";
String xmlForm = XML.toString(jsonObject,"encloser", new XMLParserConfiguration().withCloseEmptyTag(false));
JSONObject actualJsonObject = XML.toJSONObject(xmlForm);
JSONObject expectedJsonObject = XML.toJSONObject(expectedXmlString);
assertTrue(expectedJsonObject.similar(actualJsonObject));
}
@Test
public void testIndentSimpleJsonObject(){
String str = "{ \"employee\": { \n" +
" \"name\": \"sonoo\", \n" +
" \"salary\": 56000, \n" +
" \"married\": true \n" +
" }}";
JSONObject jsonObject = new JSONObject(str);
String actual = XML.toString(jsonObject, "Test", 2);
JSONObject actualJsonObject = XML.toJSONObject(actual);
String expected = "<Test>\n" +
" <employee>\n" +
" <name>sonoo</name>\n" +
" <salary>56000</salary>\n" +
" <married>true</married>\n" +
" </employee>\n" +
"</Test>\n";
JSONObject expectedJsonObject = XML.toJSONObject(expected);
assertTrue(expectedJsonObject.similar(actualJsonObject));
}
@Test
public void testIndentSimpleJsonArray(){
String str = "[ \n" +
" {\"name\":\"Ram\", \"email\":\"Ram@gmail.com\"}, \n" +
" {\"name\":\"Bob\", \"email\":\"bob32@gmail.com\"} \n" +
"] ";
JSONArray jsonObject = new JSONArray(str);
String actual = XML.toString(jsonObject, 2);
JSONObject actualJsonObject = XML.toJSONObject(actual);
String expected = "<array>\n" +
" <name>Ram</name>\n" +
" <email>Ram@gmail.com</email>\n" +
"</array>\n" +
"<array>\n" +
" <name>Bob</name>\n" +
" <email>bob32@gmail.com</email>\n" +
"</array>\n";
JSONObject expectedJsonObject = XML.toJSONObject(expected);
assertTrue(expectedJsonObject.similar(actualJsonObject));
}
@Test
public void testIndentComplicatedJsonObjectWithArrayAndWithConfig(){
try (InputStream jsonStream = XMLTest.class.getClassLoader().getResourceAsStream("Issue593.json")) {
final JSONObject object = new JSONObject(new JSONTokener(jsonStream));
String actualString = XML.toString(object, null, XMLParserConfiguration.KEEP_STRINGS, 2);
try (InputStream xmlStream = XMLTest.class.getClassLoader().getResourceAsStream("Issue593.xml")) {
int bufferSize = 1024;
char[] buffer = new char[bufferSize];
StringBuilder expected = new StringBuilder();
Reader in = new InputStreamReader(xmlStream, "UTF-8");
for (int numRead; (numRead = in.read(buffer, 0, buffer.length)) > 0; ) {
expected.append(buffer, 0, numRead);
}
assertTrue(XML.toJSONObject(expected.toString()).similar(XML.toJSONObject(actualString)));
}
} catch (IOException e) {
fail("file writer error: " +e.getMessage());
}
}
@Test
public void testMaxNestingDepthOf42IsRespected() {
final String wayTooLongMalformedXML = new String(new char[6000]).replace("\0", "<a>");
final int maxNestingDepth = 42;
try {
XML.toJSONObject(wayTooLongMalformedXML, XMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
fail("Expecting a JSONException");
} catch (JSONException e) {
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
}
}
@Test
public void testMaxNestingDepthIsRespectedWithValidXML() {
final String perfectlyFineXML = "<Test>\n" +
" <employee>\n" +
" <name>sonoo</name>\n" +
" <salary>56000</salary>\n" +
" <married>true</married>\n" +
" </employee>\n" +
"</Test>\n";
final int maxNestingDepth = 1;
try {
XML.toJSONObject(perfectlyFineXML, XMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
fail("Expecting a JSONException");
} catch (JSONException e) {
assertTrue("Wrong throwable thrown: not expecting message <" + e.getMessage() + ">",
e.getMessage().startsWith("Maximum nesting depth of " + maxNestingDepth));
}
}
@Test
public void testMaxNestingDepthWithValidFittingXML() {
final String perfectlyFineXML = "<Test>\n" +
" <employee>\n" +
" <name>sonoo</name>\n" +
" <salary>56000</salary>\n" +
" <married>true</married>\n" +
" </employee>\n" +
"</Test>\n";
final int maxNestingDepth = 3;
try {
XML.toJSONObject(perfectlyFineXML, XMLParserConfiguration.ORIGINAL.withMaxNestingDepth(maxNestingDepth));
} catch (JSONException e) {
e.printStackTrace();
fail("XML document should be parsed as its maximum depth fits the maxNestingDepth " +
"parameter of the XMLParserConfiguration used");
}
}
@Test
public void testWithWhitespaceTrimmingDisabled() {
String originalXml = "<testXml> Test Whitespace String \t </testXml>";
JSONObject actualJson = XML.toJSONObject(originalXml, new XMLParserConfiguration().withShouldTrimWhitespace(false));
String expectedJsonString = "{\"testXml\":\" Test Whitespace String \t \"}";
JSONObject expectedJson = new JSONObject(expectedJsonString);
Util.compareActualVsExpectedJsonObjects(actualJson,expectedJson);
}
@Test
public void testNestedWithWhitespaceTrimmingDisabled() {
String originalXml =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses>\n"+
" <address>\n"+
" <name> Sherlock Holmes </name>\n"+
" </address>\n"+
"</addresses>";
JSONObject actualJson = XML.toJSONObject(originalXml, new XMLParserConfiguration().withShouldTrimWhitespace(false));
String expectedJsonString = "{\"addresses\":{\"address\":{\"name\":\" Sherlock Holmes \"}}}";
JSONObject expectedJson = new JSONObject(expectedJsonString);
Util.compareActualVsExpectedJsonObjects(actualJson,expectedJson);
}
@Test
public void shouldTrimWhitespaceDoesNotSupportTagsEqualingCDataTagName() {
// When using withShouldTrimWhitespace = true, input containing tags with same name as cDataTagName is unsupported and should not be used in conjunction
String originalXml =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses>\n"+
" <address>\n"+
" <content> Sherlock Holmes </content>\n"+
" </address>\n"+
"</addresses>";
JSONObject actualJson = XML.toJSONObject(originalXml, new XMLParserConfiguration().withShouldTrimWhitespace(false).withcDataTagName("content"));
String expectedJsonString = "{\"addresses\":{\"address\":[[\"\\n \",\" Sherlock Holmes \",\"\\n \"]]}}";
JSONObject expectedJson = new JSONObject(expectedJsonString);
Util.compareActualVsExpectedJsonObjects(actualJson,expectedJson);
}
@Test
public void shouldTrimWhitespaceEnabledDropsTagsEqualingCDataTagNameButValueRemains() {
String originalXml =
"<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n"+
"<addresses>\n"+
" <address>\n"+
" <content> Sherlock Holmes </content>\n"+
" </address>\n"+
"</addresses>";
JSONObject actualJson = XML.toJSONObject(originalXml, new XMLParserConfiguration().withShouldTrimWhitespace(true).withcDataTagName("content"));
String expectedJsonString = "{\"addresses\":{\"address\":\"Sherlock Holmes\"}}";
JSONObject expectedJson = new JSONObject(expectedJsonString);
Util.compareActualVsExpectedJsonObjects(actualJson,expectedJson);
}
@Test
public void testWithWhitespaceTrimmingEnabled() {
String originalXml = "<testXml> Test Whitespace String \t </testXml>";
JSONObject actualJson = XML.toJSONObject(originalXml, new XMLParserConfiguration().withShouldTrimWhitespace(true));
String expectedJsonString = "{\"testXml\":\"Test Whitespace String\"}";
JSONObject expectedJson = new JSONObject(expectedJsonString);
Util.compareActualVsExpectedJsonObjects(actualJson,expectedJson);
}
@Test
public void testWithWhitespaceTrimmingEnabledByDefault() {
String originalXml = "<testXml> Test Whitespace String \t </testXml>";
JSONObject actualJson = XML.toJSONObject(originalXml, new XMLParserConfiguration());
String expectedJsonString = "{\"testXml\":\"Test Whitespace String\"}";
JSONObject expectedJson = new JSONObject(expectedJsonString);
Util.compareActualVsExpectedJsonObjects(actualJson,expectedJson);
}
@Test
public void clarifyCurrentBehavior() {
// Behavior documented in #826
// After reverting the code, amount is stored as numeric, and phone is stored as string
String str1 =
" <datatypes>\n" +
" <telephone>0123456789</telephone>\n" +
" <amount>0.1230</amount>\n" +
" <boolean>true</boolean>\n" +
" </datatypes>";
JSONObject jsonObject1 = XML.toJSONObject(str1,
new XMLParserConfiguration().withKeepStrings(false));
assertEquals(jsonObject1.getJSONObject("datatypes").getFloat("amount"), 0.123, .1);
assertEquals(jsonObject1.getJSONObject("datatypes").getString("telephone"), "0123456789");
// Behavior documented in #852
// After reverting the code, value is still stored as a number. This is due to how XML.isDecimalNotation() works
// and is probably a bug. JSONObject has a similar problem.
String str2 = "<color> <color_type>primary</color_type> <value>008E97</value> </color>";
JSONObject jsonObject2 = XML.toJSONObject(str2);
assertEquals(jsonObject2.getJSONObject("color").getLong("value"), 0e897, .1);
// Workaround for now is to use keepStrings
JSONObject jsonObject3 = XML.toJSONObject(str2, new XMLParserConfiguration().withKeepStrings(true));
assertEquals(jsonObject3.getJSONObject("color").getString("value"), "008E97");
}
}

View File

@ -0,0 +1,81 @@
package org.json.junit;
import org.json.XMLTokener;
import org.junit.Test;
import java.io.StringReader;
import static org.junit.Assert.*;
/**
* Tests for JSON-Java XMLTokener.java
*/
public class XMLTokenerTest {
/**
* Tests that nextCDATA() correctly extracts content from within a CDATA section.
*/
@Test
public void testNextCDATA() {
String xml = "This is <![CDATA[ some <CDATA> content ]]> after";
XMLTokener tokener = new XMLTokener(new StringReader(xml));
tokener.skipPast("<![CDATA[");
String cdata = tokener.nextCDATA();
assertEquals(" some <CDATA> content ", cdata);
}
/**
* Tests that nextContent() returns plain text content before a tag.
*/
@Test
public void testNextContentWithText() {
String xml = "Some content<nextTag>";
XMLTokener tokener = new XMLTokener(xml);
Object content = tokener.nextContent();
assertEquals("Some content", content);
}
/**
* Tests that nextContent() returns '<' character when starting with a tag.
*/
@Test
public void testNextContentWithTag() {
String xml = "<tag>";
XMLTokener tokener = new XMLTokener(xml);
Object content = tokener.nextContent();
assertEquals('<', content);
}
/**
* Tests that nextEntity() resolves a known entity like &amp; correctly.
*/
@Test
public void testNextEntityKnown() {
XMLTokener tokener = new XMLTokener("amp;");
Object result = tokener.nextEntity('&');
assertEquals("&", result);
}
/**
* Tests that nextEntity() preserves unknown entities by returning them unchanged.
*/
@Test
public void testNextEntityUnknown() {
XMLTokener tokener = new XMLTokener("unknown;");
tokener.next(); // skip 'u'
Object result = tokener.nextEntity('&');
assertEquals("&nknown;", result); // malformed start to simulate unknown
}
/**
* Tests skipPast() to ensure the cursor moves past the specified string.
*/
@Test
public void testSkipPast() {
String xml = "Ignore this... endHere more text";
XMLTokener tokener = new XMLTokener(xml);
tokener.skipPast("endHere");
assertEquals(' ', tokener.next()); // should be the space after "endHere"
}
}

View File

@ -9,7 +9,7 @@ import java.io.StringReader;
* @param <T>
* generic number value
*/
public class GenericBean<T extends Number & Comparable<T>> implements MyBean {
public class GenericBean<T extends Number> implements MyBean {
/**
* @param genericValue
* value to initiate with

View File

@ -12,7 +12,7 @@ import java.util.List;
*/
public class WeirdList {
/** */
private final List<Integer> list = new ArrayList();
private final List<Integer> list = new ArrayList<>();
/**
* @param vals
@ -25,14 +25,14 @@ public class WeirdList {
* @return a copy of the list
*/
public List<Integer> get() {
return new ArrayList(this.list);
return new ArrayList<>(this.list);
}
/**
* @return a copy of the list
*/
public List<Integer> getALL() {
return new ArrayList(this.list);
return new ArrayList<>(this.list);
}
/**

View File

@ -0,0 +1,704 @@
{
"success": true,
"error": null,
"response": [
{
"loc": {
"long": 31.25,
"lat": 30.063
},
"interval": "day",
"place": {
"name": "cairo",
"state": "qh",
"country": "eg"
},
"periods": [
{
"timestamp": 1665032400,
"validTime": "2022-10-06T07:00:00+02:00",
"dateTimeISO": "2022-10-06T07:00:00+02:00",
"maxTempC": 32,
"maxTempF": 90,
"minTempC": 19,
"minTempF": 66,
"avgTempC": 25,
"avgTempF": 78,
"tempC": null,
"tempF": null,
"maxFeelslikeC": 32,
"maxFeelslikeF": 89,
"minFeelslikeC": 21,
"minFeelslikeF": 70,
"avgFeelslikeC": 26,
"avgFeelslikeF": 80,
"feelslikeC": 21,
"feelslikeF": 70,
"maxDewpointC": 17,
"maxDewpointF": 63,
"minDewpointC": 11,
"minDewpointF": 52,
"avgDewpointC": 14,
"avgDewpointF": 58,
"dewpointC": 17,
"dewpointF": 63,
"maxHumidity": 77,
"minHumidity": 29,
"humidity": 77,
"pop": 0,
"precipMM": 0,
"precipIN": 0,
"iceaccum": null,
"iceaccumMM": null,
"iceaccumIN": null,
"snowCM": 0,
"snowIN": 0,
"pressureMB": 1015,
"pressureIN": 29.97,
"windDir": "N",
"windDirDEG": 353,
"windSpeedKTS": 5,
"windSpeedKPH": 9,
"windSpeedMPH": 6,
"windGustKTS": 21,
"windGustKPH": 40,
"windGustMPH": 25,
"windDirMax": "NNW",
"windDirMaxDEG": 342,
"windSpeedMaxKTS": 9,
"windSpeedMaxKPH": 16,
"windSpeedMaxMPH": 10,
"windDirMin": "N",
"windDirMinDEG": 353,
"windSpeedMinKTS": 1,
"windSpeedMinKPH": 2,
"windSpeedMinMPH": 1,
"windDir80m": "N",
"windDir80mDEG": 11,
"windSpeed80mKTS": 12,
"windSpeed80mKPH": 22,
"windSpeed80mMPH": 13,
"windGust80mKTS": 22,
"windGust80mKPH": 41,
"windGust80mMPH": 25,
"windDirMax80m": "NNW",
"windDirMax80mDEG": 343,
"windSpeedMax80mKTS": 22,
"windSpeedMax80mKPH": 41,
"windSpeedMax80mMPH": 25,
"windDirMin80m": "E",
"windDirMin80mDEG": 95,
"windSpeedMin80mKTS": 8,
"windSpeedMin80mKPH": 15,
"windSpeedMin80mMPH": 10,
"sky": 22,
"cloudsCoded": "FW",
"weather": "Mostly Sunny",
"weatherCoded": [],
"weatherPrimary": "Mostly Sunny",
"weatherPrimaryCoded": "::FW",
"icon": "fair.png",
"visibilityKM": 24.135,
"visibilityMI": 15,
"uvi": 6,
"solradWM2": 5608,
"solradMinWM2": 0,
"solradMaxWM2": 778,
"isDay": true,
"maxCoverage": "",
"sunrise": 1665028274,
"sunset": 1665070502,
"sunriseISO": "2022-10-06T05:51:14+02:00",
"sunsetISO": "2022-10-06T17:35:02+02:00"
},
{
"timestamp": 1665118800,
"validTime": "2022-10-07T07:00:00+02:00",
"dateTimeISO": "2022-10-07T07:00:00+02:00",
"maxTempC": 30,
"maxTempF": 86,
"minTempC": 19,
"minTempF": 66,
"avgTempC": 24,
"avgTempF": 76,
"tempC": null,
"tempF": null,
"maxFeelslikeC": 29,
"maxFeelslikeF": 85,
"minFeelslikeC": 19,
"minFeelslikeF": 67,
"avgFeelslikeC": 24,
"avgFeelslikeF": 76,
"feelslikeC": 19,
"feelslikeF": 67,
"maxDewpointC": 15,
"maxDewpointF": 60,
"minDewpointC": 10,
"minDewpointF": 50,
"avgDewpointC": 12,
"avgDewpointF": 54,
"dewpointC": 15,
"dewpointF": 60,
"maxHumidity": 77,
"minHumidity": 30,
"humidity": 77,
"pop": 0,
"precipMM": 0,
"precipIN": 0,
"iceaccum": null,
"iceaccumMM": null,
"iceaccumIN": null,
"snowCM": 0,
"snowIN": 0,
"pressureMB": 1014,
"pressureIN": 29.95,
"windDir": "NW",
"windDirDEG": 325,
"windSpeedKTS": 1,
"windSpeedKPH": 2,
"windSpeedMPH": 1,
"windGustKTS": 16,
"windGustKPH": 29,
"windGustMPH": 18,
"windDirMax": "WNW",
"windDirMaxDEG": 298,
"windSpeedMaxKTS": 7,
"windSpeedMaxKPH": 13,
"windSpeedMaxMPH": 8,
"windDirMin": "NW",
"windDirMinDEG": 325,
"windSpeedMinKTS": 1,
"windSpeedMinKPH": 2,
"windSpeedMinMPH": 1,
"windDir80m": "NNW",
"windDir80mDEG": 347,
"windSpeed80mKTS": 6,
"windSpeed80mKPH": 10,
"windSpeed80mMPH": 6,
"windGust80mKTS": 20,
"windGust80mKPH": 37,
"windGust80mMPH": 23,
"windDirMax80m": "NW",
"windDirMax80mDEG": 316,
"windSpeedMax80mKTS": 20,
"windSpeedMax80mKPH": 37,
"windSpeedMax80mMPH": 23,
"windDirMin80m": "NNW",
"windDirMin80mDEG": 347,
"windSpeedMin80mKTS": 6,
"windSpeedMin80mKPH": 10,
"windSpeedMin80mMPH": 6,
"sky": 30,
"cloudsCoded": "FW",
"weather": "Mostly Sunny",
"weatherCoded": [],
"weatherPrimary": "Mostly Sunny",
"weatherPrimaryCoded": "::FW",
"icon": "fair.png",
"visibilityKM": 24.135,
"visibilityMI": 15,
"uvi": 6,
"solradWM2": 5486,
"solradMinWM2": 0,
"solradMaxWM2": 742,
"isDay": true,
"maxCoverage": "",
"sunrise": 1665114710,
"sunset": 1665156831,
"sunriseISO": "2022-10-07T05:51:50+02:00",
"sunsetISO": "2022-10-07T17:33:51+02:00"
},
{
"timestamp": 1665205200,
"validTime": "2022-10-08T07:00:00+02:00",
"dateTimeISO": "2022-10-08T07:00:00+02:00",
"maxTempC": 30,
"maxTempF": 87,
"minTempC": 19,
"minTempF": 66,
"avgTempC": 25,
"avgTempF": 76,
"tempC": null,
"tempF": null,
"maxFeelslikeC": 30,
"maxFeelslikeF": 86,
"minFeelslikeC": 19,
"minFeelslikeF": 67,
"avgFeelslikeC": 25,
"avgFeelslikeF": 76,
"feelslikeC": 19,
"feelslikeF": 67,
"maxDewpointC": 15,
"maxDewpointF": 59,
"minDewpointC": 11,
"minDewpointF": 52,
"avgDewpointC": 13,
"avgDewpointF": 56,
"dewpointC": 15,
"dewpointF": 59,
"maxHumidity": 76,
"minHumidity": 32,
"humidity": 76,
"pop": 0,
"precipMM": 0,
"precipIN": 0,
"iceaccum": null,
"iceaccumMM": null,
"iceaccumIN": null,
"snowCM": 0,
"snowIN": 0,
"pressureMB": 1014,
"pressureIN": 29.94,
"windDir": "NNE",
"windDirDEG": 21,
"windSpeedKTS": 1,
"windSpeedKPH": 2,
"windSpeedMPH": 1,
"windGustKTS": 17,
"windGustKPH": 32,
"windGustMPH": 20,
"windDirMax": "WNW",
"windDirMaxDEG": 301,
"windSpeedMaxKTS": 7,
"windSpeedMaxKPH": 13,
"windSpeedMaxMPH": 8,
"windDirMin": "NNE",
"windDirMinDEG": 21,
"windSpeedMinKTS": 1,
"windSpeedMinKPH": 2,
"windSpeedMinMPH": 1,
"windDir80m": "NW",
"windDir80mDEG": 309,
"windSpeed80mKTS": 5,
"windSpeed80mKPH": 9,
"windSpeed80mMPH": 5,
"windGust80mKTS": 17,
"windGust80mKPH": 31,
"windGust80mMPH": 19,
"windDirMax80m": "NW",
"windDirMax80mDEG": 322,
"windSpeedMax80mKTS": 17,
"windSpeedMax80mKPH": 31,
"windSpeedMax80mMPH": 19,
"windDirMin80m": "NW",
"windDirMin80mDEG": 309,
"windSpeedMin80mKTS": 5,
"windSpeedMin80mKPH": 9,
"windSpeedMin80mMPH": 5,
"sky": 47,
"cloudsCoded": "SC",
"weather": "Partly Cloudy",
"weatherCoded": [],
"weatherPrimary": "Partly Cloudy",
"weatherPrimaryCoded": "::SC",
"icon": "pcloudy.png",
"visibilityKM": 24.135,
"visibilityMI": 15,
"uvi": 7,
"solradWM2": 4785,
"solradMinWM2": 0,
"solradMaxWM2": 682,
"isDay": true,
"maxCoverage": "",
"sunrise": 1665201146,
"sunset": 1665243161,
"sunriseISO": "2022-10-08T05:52:26+02:00",
"sunsetISO": "2022-10-08T17:32:41+02:00"
},
{
"timestamp": 1665291600,
"validTime": "2022-10-09T07:00:00+02:00",
"dateTimeISO": "2022-10-09T07:00:00+02:00",
"maxTempC": 31,
"maxTempF": 87,
"minTempC": 19,
"minTempF": 67,
"avgTempC": 25,
"avgTempF": 77,
"tempC": null,
"tempF": null,
"maxFeelslikeC": 30,
"maxFeelslikeF": 86,
"minFeelslikeC": 20,
"minFeelslikeF": 67,
"avgFeelslikeC": 25,
"avgFeelslikeF": 77,
"feelslikeC": 20,
"feelslikeF": 67,
"maxDewpointC": 17,
"maxDewpointF": 63,
"minDewpointC": 11,
"minDewpointF": 52,
"avgDewpointC": 14,
"avgDewpointF": 57,
"dewpointC": 17,
"dewpointF": 63,
"maxHumidity": 86,
"minHumidity": 31,
"humidity": 86,
"pop": 0,
"precipMM": 0,
"precipIN": 0,
"iceaccum": null,
"iceaccumMM": null,
"iceaccumIN": null,
"snowCM": 0,
"snowIN": 0,
"pressureMB": 1016,
"pressureIN": 29.99,
"windDir": "N",
"windDirDEG": 356,
"windSpeedKTS": 2,
"windSpeedKPH": 4,
"windSpeedMPH": 2,
"windGustKTS": 19,
"windGustKPH": 36,
"windGustMPH": 22,
"windDirMax": "NNW",
"windDirMaxDEG": 343,
"windSpeedMaxKTS": 8,
"windSpeedMaxKPH": 14,
"windSpeedMaxMPH": 9,
"windDirMin": "N",
"windDirMinDEG": 356,
"windSpeedMinKTS": 2,
"windSpeedMinKPH": 4,
"windSpeedMinMPH": 2,
"windDir80m": "NW",
"windDir80mDEG": 316,
"windSpeed80mKTS": 5,
"windSpeed80mKPH": 9,
"windSpeed80mMPH": 6,
"windGust80mKTS": 20,
"windGust80mKPH": 36,
"windGust80mMPH": 23,
"windDirMax80m": "N",
"windDirMax80mDEG": 354,
"windSpeedMax80mKTS": 20,
"windSpeedMax80mKPH": 36,
"windSpeedMax80mMPH": 23,
"windDirMin80m": "NW",
"windDirMin80mDEG": 316,
"windSpeedMin80mKTS": 5,
"windSpeedMin80mKPH": 9,
"windSpeedMin80mMPH": 6,
"sky": 47,
"cloudsCoded": "SC",
"weather": "Partly Cloudy",
"weatherCoded": [],
"weatherPrimary": "Partly Cloudy",
"weatherPrimaryCoded": "::SC",
"icon": "pcloudy.png",
"visibilityKM": 24.135,
"visibilityMI": 15,
"uvi": 7,
"solradWM2": 4768,
"solradMinWM2": 0,
"solradMaxWM2": 726,
"isDay": true,
"maxCoverage": "",
"sunrise": 1665287583,
"sunset": 1665329491,
"sunriseISO": "2022-10-09T05:53:03+02:00",
"sunsetISO": "2022-10-09T17:31:31+02:00"
},
{
"timestamp": 1665378000,
"validTime": "2022-10-10T07:00:00+02:00",
"dateTimeISO": "2022-10-10T07:00:00+02:00",
"maxTempC": 31,
"maxTempF": 87,
"minTempC": 21,
"minTempF": 70,
"avgTempC": 26,
"avgTempF": 78,
"tempC": null,
"tempF": null,
"maxFeelslikeC": 30,
"maxFeelslikeF": 86,
"minFeelslikeC": 21,
"minFeelslikeF": 69,
"avgFeelslikeC": 25,
"avgFeelslikeF": 78,
"feelslikeC": 21,
"feelslikeF": 69,
"maxDewpointC": 16,
"maxDewpointF": 61,
"minDewpointC": 13,
"minDewpointF": 55,
"avgDewpointC": 14,
"avgDewpointF": 58,
"dewpointC": 16,
"dewpointF": 61,
"maxHumidity": 75,
"minHumidity": 35,
"humidity": 75,
"pop": 0,
"precipMM": 0,
"precipIN": 0,
"iceaccum": null,
"iceaccumMM": null,
"iceaccumIN": null,
"snowCM": 0,
"snowIN": 0,
"pressureMB": 1017,
"pressureIN": 30.03,
"windDir": "N",
"windDirDEG": 358,
"windSpeedKTS": 2,
"windSpeedKPH": 4,
"windSpeedMPH": 2,
"windGustKTS": 16,
"windGustKPH": 30,
"windGustMPH": 19,
"windDirMax": "N",
"windDirMaxDEG": 10,
"windSpeedMaxKTS": 8,
"windSpeedMaxKPH": 15,
"windSpeedMaxMPH": 9,
"windDirMin": "N",
"windDirMinDEG": 358,
"windSpeedMinKTS": 2,
"windSpeedMinKPH": 4,
"windSpeedMinMPH": 2,
"windDir80m": "N",
"windDir80mDEG": 8,
"windSpeed80mKTS": 7,
"windSpeed80mKPH": 13,
"windSpeed80mMPH": 8,
"windGust80mKTS": 19,
"windGust80mKPH": 36,
"windGust80mMPH": 22,
"windDirMax80m": "N",
"windDirMax80mDEG": 10,
"windSpeedMax80mKTS": 19,
"windSpeedMax80mKPH": 36,
"windSpeedMax80mMPH": 22,
"windDirMin80m": "E",
"windDirMin80mDEG": 91,
"windSpeedMin80mKTS": 7,
"windSpeedMin80mKPH": 13,
"windSpeedMin80mMPH": 8,
"sky": 64,
"cloudsCoded": "SC",
"weather": "Partly Cloudy",
"weatherCoded": [],
"weatherPrimary": "Partly Cloudy",
"weatherPrimaryCoded": "::SC",
"icon": "pcloudy.png",
"visibilityKM": 24.135,
"visibilityMI": 15,
"uvi": 6,
"solradWM2": 4494,
"solradMinWM2": 0,
"solradMaxWM2": 597,
"isDay": true,
"maxCoverage": "",
"sunrise": 1665374020,
"sunset": 1665415821,
"sunriseISO": "2022-10-10T05:53:40+02:00",
"sunsetISO": "2022-10-10T17:30:21+02:00"
},
{
"timestamp": 1665464400,
"validTime": "2022-10-11T07:00:00+02:00",
"dateTimeISO": "2022-10-11T07:00:00+02:00",
"maxTempC": 31,
"maxTempF": 87,
"minTempC": 21,
"minTempF": 70,
"avgTempC": 26,
"avgTempF": 78,
"tempC": null,
"tempF": null,
"maxFeelslikeC": 31,
"maxFeelslikeF": 87,
"minFeelslikeC": 22,
"minFeelslikeF": 72,
"avgFeelslikeC": 26,
"avgFeelslikeF": 79,
"feelslikeC": 22,
"feelslikeF": 72,
"maxDewpointC": 17,
"maxDewpointF": 62,
"minDewpointC": 11,
"minDewpointF": 51,
"avgDewpointC": 13,
"avgDewpointF": 55,
"dewpointC": 17,
"dewpointF": 62,
"maxHumidity": 71,
"minHumidity": 30,
"humidity": 71,
"pop": 0,
"precipMM": 0,
"precipIN": 0,
"iceaccum": null,
"iceaccumMM": null,
"iceaccumIN": null,
"snowCM": 0,
"snowIN": 0,
"pressureMB": 1015,
"pressureIN": 29.98,
"windDir": "NNE",
"windDirDEG": 13,
"windSpeedKTS": 8,
"windSpeedKPH": 15,
"windSpeedMPH": 9,
"windGustKTS": 15,
"windGustKPH": 28,
"windGustMPH": 17,
"windDirMax": "NNE",
"windDirMaxDEG": 28,
"windSpeedMaxKTS": 15,
"windSpeedMaxKPH": 28,
"windSpeedMaxMPH": 18,
"windDirMin": "NNE",
"windDirMinDEG": 14,
"windSpeedMinKTS": 7,
"windSpeedMinKPH": 14,
"windSpeedMinMPH": 8,
"windDir80m": "NNE",
"windDir80mDEG": 16,
"windSpeed80mKTS": 10,
"windSpeed80mKPH": 19,
"windSpeed80mMPH": 12,
"windGust80mKTS": 17,
"windGust80mKPH": 31,
"windGust80mMPH": 19,
"windDirMax80m": "NNE",
"windDirMax80mDEG": 28,
"windSpeedMax80mKTS": 17,
"windSpeedMax80mKPH": 31,
"windSpeedMax80mMPH": 19,
"windDirMin80m": "NNE",
"windDirMin80mDEG": 13,
"windSpeedMin80mKTS": 9,
"windSpeedMin80mKPH": 18,
"windSpeedMin80mMPH": 11,
"sky": 0,
"cloudsCoded": "CL",
"weather": "Sunny",
"weatherCoded": [],
"weatherPrimary": "Sunny",
"weatherPrimaryCoded": "::CL",
"icon": "sunny.png",
"visibilityKM": 24.135,
"visibilityMI": 15,
"uvi": null,
"solradWM2": 5450,
"solradMinWM2": 0,
"solradMaxWM2": 758,
"isDay": true,
"maxCoverage": "",
"sunrise": 1665460458,
"sunset": 1665502153,
"sunriseISO": "2022-10-11T05:54:18+02:00",
"sunsetISO": "2022-10-11T17:29:13+02:00"
},
{
"timestamp": 1665550800,
"validTime": "2022-10-12T07:00:00+02:00",
"dateTimeISO": "2022-10-12T07:00:00+02:00",
"maxTempC": 31,
"maxTempF": 88,
"minTempC": 21,
"minTempF": 69,
"avgTempC": 26,
"avgTempF": 79,
"tempC": null,
"tempF": null,
"maxFeelslikeC": 31,
"maxFeelslikeF": 88,
"minFeelslikeC": 22,
"minFeelslikeF": 72,
"avgFeelslikeC": 26,
"avgFeelslikeF": 80,
"feelslikeC": 22,
"feelslikeF": 72,
"maxDewpointC": 16,
"maxDewpointF": 60,
"minDewpointC": 11,
"minDewpointF": 51,
"avgDewpointC": 13,
"avgDewpointF": 55,
"dewpointC": 16,
"dewpointF": 60,
"maxHumidity": 68,
"minHumidity": 29,
"humidity": 68,
"pop": 0,
"precipMM": 0,
"precipIN": 0,
"iceaccum": null,
"iceaccumMM": null,
"iceaccumIN": null,
"snowCM": 0,
"snowIN": 0,
"pressureMB": 1014,
"pressureIN": 29.95,
"windDir": "NNE",
"windDirDEG": 12,
"windSpeedKTS": 8,
"windSpeedKPH": 15,
"windSpeedMPH": 9,
"windGustKTS": 15,
"windGustKPH": 28,
"windGustMPH": 17,
"windDirMax": "E",
"windDirMaxDEG": 96,
"windSpeedMaxKTS": 14,
"windSpeedMaxKPH": 26,
"windSpeedMaxMPH": 16,
"windDirMin": "NNE",
"windDirMinDEG": 12,
"windSpeedMinKTS": 7,
"windSpeedMinKPH": 13,
"windSpeedMinMPH": 8,
"windDir80m": "NNE",
"windDir80mDEG": 15,
"windSpeed80mKTS": 10,
"windSpeed80mKPH": 19,
"windSpeed80mMPH": 12,
"windGust80mKTS": 18,
"windGust80mKPH": 33,
"windGust80mMPH": 21,
"windDirMax80m": "E",
"windDirMax80mDEG": 96,
"windSpeedMax80mKTS": 18,
"windSpeedMax80mKPH": 33,
"windSpeedMax80mMPH": 21,
"windDirMin80m": "NNE",
"windDirMin80mDEG": 15,
"windSpeedMin80mKTS": 10,
"windSpeedMin80mKPH": 18,
"windSpeedMin80mMPH": 11,
"sky": 27,
"cloudsCoded": "FW",
"weather": "Mostly Sunny",
"weatherCoded": [],
"weatherPrimary": "Mostly Sunny",
"weatherPrimaryCoded": "::FW",
"icon": "fair.png",
"visibilityKM": 24.135,
"visibilityMI": 15,
"uvi": null,
"solradWM2": 4740,
"solradMinWM2": 0,
"solradMaxWM2": 743,
"isDay": true,
"maxCoverage": "",
"sunrise": 1665546895,
"sunset": 1665588484,
"sunriseISO": "2022-10-12T05:54:55+02:00",
"sunsetISO": "2022-10-12T17:28:04+02:00"
}
],
"profile": {
"tz": "Africa/Cairo",
"elevM": 23,
"elevFT": 75
}
}
]
}

View File

@ -0,0 +1,691 @@
<success>true</success>
<response>
<loc>
<long>31.25</long>
<lat>30.063</lat>
</loc>
<profile>
<elevM>23</elevM>
<tz>Africa/Cairo</tz>
<elevFT>75</elevFT>
</profile>
<periods>
<dateTimeISO>2022-10-06T07:00:00+02:00</dateTimeISO>
<windDirMin80m>E</windDirMin80m>
<windDirMin80mDEG>95</windDirMin80mDEG>
<feelslikeC>21</feelslikeC>
<visibilityMI>15</visibilityMI>
<windSpeedMaxMPH>10</windSpeedMaxMPH>
<windDirDEG>353</windDirDEG>
<windDir>N</windDir>
<sunriseISO>2022-10-06T05:51:14+02:00</sunriseISO>
<iceaccumMM>null</iceaccumMM>
<windSpeedMaxKTS>9</windSpeedMaxKTS>
<iceaccumIN>null</iceaccumIN>
<minTempF>66</minTempF>
<snowIN>0</snowIN>
<weather>Mostly Sunny</weather>
<sunsetISO>2022-10-06T17:35:02+02:00</sunsetISO>
<maxFeelslikeC>32</maxFeelslikeC>
<humidity>77</humidity>
<windDir80m>N</windDir80m>
<maxFeelslikeF>89</maxFeelslikeF>
<precipMM>0</precipMM>
<sky>22</sky>
<windGust80mMPH>25</windGust80mMPH>
<windSpeedMax80mMPH>25</windSpeedMax80mMPH>
<weatherPrimary>Mostly Sunny</weatherPrimary>
<windGust80mKPH>41</windGust80mKPH>
<avgDewpointF>58</avgDewpointF>
<windSpeedMax80mKPH>41</windSpeedMax80mKPH>
<windGust80mKTS>22</windGust80mKTS>
<avgDewpointC>14</avgDewpointC>
<precipIN>0</precipIN>
<windSpeedMax80mKTS>22</windSpeedMax80mKTS>
<windDirMinDEG>353</windDirMinDEG>
<windSpeedMaxKPH>16</windSpeedMaxKPH>
<windSpeedMin80mKTS>8</windSpeedMin80mKTS>
<feelslikeF>70</feelslikeF>
<validTime>2022-10-06T07:00:00+02:00</validTime>
<windSpeedMin80mMPH>10</windSpeedMin80mMPH>
<solradMaxWM2>778</solradMaxWM2>
<avgTempC>25</avgTempC>
<windSpeedMin80mKPH>15</windSpeedMin80mKPH>
<weatherPrimaryCoded>::FW</weatherPrimaryCoded>
<sunrise>1665028274</sunrise>
<avgTempF>78</avgTempF>
<windDirMin>N</windDirMin>
<maxCoverage/>
<icon>fair.png</icon>
<minFeelslikeC>21</minFeelslikeC>
<dewpointC>17</dewpointC>
<cloudsCoded>FW</cloudsCoded>
<minFeelslikeF>70</minFeelslikeF>
<minHumidity>29</minHumidity>
<dewpointF>63</dewpointF>
<windSpeed80mKTS>12</windSpeed80mKTS>
<pop>0</pop>
<snowCM>0</snowCM>
<windDirMax>NNW</windDirMax>
<windSpeed80mMPH>13</windSpeed80mMPH>
<windSpeed80mKPH>22</windSpeed80mKPH>
<windDir80mDEG>11</windDir80mDEG>
<maxTempC>32</maxTempC>
<pressureMB>1015</pressureMB>
<visibilityKM>24.135</visibilityKM>
<timestamp>1665032400</timestamp>
<maxTempF>90</maxTempF>
<tempF>null</tempF>
<minDewpointC>11</minDewpointC>
<solradMinWM2>0</solradMinWM2>
<windSpeedMinKTS>1</windSpeedMinKTS>
<windDirMax80mDEG>343</windDirMax80mDEG>
<windGustKTS>21</windGustKTS>
<windSpeedMinKPH>2</windSpeedMinKPH>
<maxDewpointF>63</maxDewpointF>
<windSpeedMinMPH>1</windSpeedMinMPH>
<avgFeelslikeC>26</avgFeelslikeC>
<uvi>6</uvi>
<windDirMax80m>NNW</windDirMax80m>
<maxDewpointC>17</maxDewpointC>
<pressureIN>29.97</pressureIN>
<avgFeelslikeF>80</avgFeelslikeF>
<iceaccum>null</iceaccum>
<isDay>true</isDay>
<minTempC>19</minTempC>
<minDewpointF>52</minDewpointF>
<windSpeedKTS>5</windSpeedKTS>
<sunset>1665070502</sunset>
<solradWM2>5608</solradWM2>
<windSpeedKPH>9</windSpeedKPH>
<windGustMPH>25</windGustMPH>
<maxHumidity>77</maxHumidity>
<windSpeedMPH>6</windSpeedMPH>
<windGustKPH>40</windGustKPH>
<windDirMaxDEG>342</windDirMaxDEG>
<tempC>null</tempC>
</periods>
<periods>
<dateTimeISO>2022-10-07T07:00:00+02:00</dateTimeISO>
<windDirMin80m>NNW</windDirMin80m>
<windDirMin80mDEG>347</windDirMin80mDEG>
<feelslikeC>19</feelslikeC>
<visibilityMI>15</visibilityMI>
<windSpeedMaxMPH>8</windSpeedMaxMPH>
<windDirDEG>325</windDirDEG>
<windDir>NW</windDir>
<sunriseISO>2022-10-07T05:51:50+02:00</sunriseISO>
<iceaccumMM>null</iceaccumMM>
<windSpeedMaxKTS>7</windSpeedMaxKTS>
<iceaccumIN>null</iceaccumIN>
<minTempF>66</minTempF>
<snowIN>0</snowIN>
<weather>Mostly Sunny</weather>
<sunsetISO>2022-10-07T17:33:51+02:00</sunsetISO>
<maxFeelslikeC>29</maxFeelslikeC>
<humidity>77</humidity>
<windDir80m>NNW</windDir80m>
<maxFeelslikeF>85</maxFeelslikeF>
<precipMM>0</precipMM>
<sky>30</sky>
<windGust80mMPH>23</windGust80mMPH>
<windSpeedMax80mMPH>23</windSpeedMax80mMPH>
<weatherPrimary>Mostly Sunny</weatherPrimary>
<windGust80mKPH>37</windGust80mKPH>
<avgDewpointF>54</avgDewpointF>
<windSpeedMax80mKPH>37</windSpeedMax80mKPH>
<windGust80mKTS>20</windGust80mKTS>
<avgDewpointC>12</avgDewpointC>
<precipIN>0</precipIN>
<windSpeedMax80mKTS>20</windSpeedMax80mKTS>
<windDirMinDEG>325</windDirMinDEG>
<windSpeedMaxKPH>13</windSpeedMaxKPH>
<windSpeedMin80mKTS>6</windSpeedMin80mKTS>
<feelslikeF>67</feelslikeF>
<validTime>2022-10-07T07:00:00+02:00</validTime>
<windSpeedMin80mMPH>6</windSpeedMin80mMPH>
<solradMaxWM2>742</solradMaxWM2>
<avgTempC>24</avgTempC>
<windSpeedMin80mKPH>10</windSpeedMin80mKPH>
<weatherPrimaryCoded>::FW</weatherPrimaryCoded>
<sunrise>1665114710</sunrise>
<avgTempF>76</avgTempF>
<windDirMin>NW</windDirMin>
<maxCoverage/>
<icon>fair.png</icon>
<minFeelslikeC>19</minFeelslikeC>
<dewpointC>15</dewpointC>
<cloudsCoded>FW</cloudsCoded>
<minFeelslikeF>67</minFeelslikeF>
<minHumidity>30</minHumidity>
<dewpointF>60</dewpointF>
<windSpeed80mKTS>6</windSpeed80mKTS>
<pop>0</pop>
<snowCM>0</snowCM>
<windDirMax>WNW</windDirMax>
<windSpeed80mMPH>6</windSpeed80mMPH>
<windSpeed80mKPH>10</windSpeed80mKPH>
<windDir80mDEG>347</windDir80mDEG>
<maxTempC>30</maxTempC>
<pressureMB>1014</pressureMB>
<visibilityKM>24.135</visibilityKM>
<timestamp>1665118800</timestamp>
<maxTempF>86</maxTempF>
<tempF>null</tempF>
<minDewpointC>10</minDewpointC>
<solradMinWM2>0</solradMinWM2>
<windSpeedMinKTS>1</windSpeedMinKTS>
<windDirMax80mDEG>316</windDirMax80mDEG>
<windGustKTS>16</windGustKTS>
<windSpeedMinKPH>2</windSpeedMinKPH>
<maxDewpointF>60</maxDewpointF>
<windSpeedMinMPH>1</windSpeedMinMPH>
<avgFeelslikeC>24</avgFeelslikeC>
<uvi>6</uvi>
<windDirMax80m>NW</windDirMax80m>
<maxDewpointC>15</maxDewpointC>
<pressureIN>29.95</pressureIN>
<avgFeelslikeF>76</avgFeelslikeF>
<iceaccum>null</iceaccum>
<isDay>true</isDay>
<minTempC>19</minTempC>
<minDewpointF>50</minDewpointF>
<windSpeedKTS>1</windSpeedKTS>
<sunset>1665156831</sunset>
<solradWM2>5486</solradWM2>
<windSpeedKPH>2</windSpeedKPH>
<windGustMPH>18</windGustMPH>
<maxHumidity>77</maxHumidity>
<windSpeedMPH>1</windSpeedMPH>
<windGustKPH>29</windGustKPH>
<windDirMaxDEG>298</windDirMaxDEG>
<tempC>null</tempC>
</periods>
<periods>
<dateTimeISO>2022-10-08T07:00:00+02:00</dateTimeISO>
<windDirMin80m>NW</windDirMin80m>
<windDirMin80mDEG>309</windDirMin80mDEG>
<feelslikeC>19</feelslikeC>
<visibilityMI>15</visibilityMI>
<windSpeedMaxMPH>8</windSpeedMaxMPH>
<windDirDEG>21</windDirDEG>
<windDir>NNE</windDir>
<sunriseISO>2022-10-08T05:52:26+02:00</sunriseISO>
<iceaccumMM>null</iceaccumMM>
<windSpeedMaxKTS>7</windSpeedMaxKTS>
<iceaccumIN>null</iceaccumIN>
<minTempF>66</minTempF>
<snowIN>0</snowIN>
<weather>Partly Cloudy</weather>
<sunsetISO>2022-10-08T17:32:41+02:00</sunsetISO>
<maxFeelslikeC>30</maxFeelslikeC>
<humidity>76</humidity>
<windDir80m>NW</windDir80m>
<maxFeelslikeF>86</maxFeelslikeF>
<precipMM>0</precipMM>
<sky>47</sky>
<windGust80mMPH>19</windGust80mMPH>
<windSpeedMax80mMPH>19</windSpeedMax80mMPH>
<weatherPrimary>Partly Cloudy</weatherPrimary>
<windGust80mKPH>31</windGust80mKPH>
<avgDewpointF>56</avgDewpointF>
<windSpeedMax80mKPH>31</windSpeedMax80mKPH>
<windGust80mKTS>17</windGust80mKTS>
<avgDewpointC>13</avgDewpointC>
<precipIN>0</precipIN>
<windSpeedMax80mKTS>17</windSpeedMax80mKTS>
<windDirMinDEG>21</windDirMinDEG>
<windSpeedMaxKPH>13</windSpeedMaxKPH>
<windSpeedMin80mKTS>5</windSpeedMin80mKTS>
<feelslikeF>67</feelslikeF>
<validTime>2022-10-08T07:00:00+02:00</validTime>
<windSpeedMin80mMPH>5</windSpeedMin80mMPH>
<solradMaxWM2>682</solradMaxWM2>
<avgTempC>25</avgTempC>
<windSpeedMin80mKPH>9</windSpeedMin80mKPH>
<weatherPrimaryCoded>::SC</weatherPrimaryCoded>
<sunrise>1665201146</sunrise>
<avgTempF>76</avgTempF>
<windDirMin>NNE</windDirMin>
<maxCoverage/>
<icon>pcloudy.png</icon>
<minFeelslikeC>19</minFeelslikeC>
<dewpointC>15</dewpointC>
<cloudsCoded>SC</cloudsCoded>
<minFeelslikeF>67</minFeelslikeF>
<minHumidity>32</minHumidity>
<dewpointF>59</dewpointF>
<windSpeed80mKTS>5</windSpeed80mKTS>
<pop>0</pop>
<snowCM>0</snowCM>
<windDirMax>WNW</windDirMax>
<windSpeed80mMPH>5</windSpeed80mMPH>
<windSpeed80mKPH>9</windSpeed80mKPH>
<windDir80mDEG>309</windDir80mDEG>
<maxTempC>30</maxTempC>
<pressureMB>1014</pressureMB>
<visibilityKM>24.135</visibilityKM>
<timestamp>1665205200</timestamp>
<maxTempF>87</maxTempF>
<tempF>null</tempF>
<minDewpointC>11</minDewpointC>
<solradMinWM2>0</solradMinWM2>
<windSpeedMinKTS>1</windSpeedMinKTS>
<windDirMax80mDEG>322</windDirMax80mDEG>
<windGustKTS>17</windGustKTS>
<windSpeedMinKPH>2</windSpeedMinKPH>
<maxDewpointF>59</maxDewpointF>
<windSpeedMinMPH>1</windSpeedMinMPH>
<avgFeelslikeC>25</avgFeelslikeC>
<uvi>7</uvi>
<windDirMax80m>NW</windDirMax80m>
<maxDewpointC>15</maxDewpointC>
<pressureIN>29.94</pressureIN>
<avgFeelslikeF>76</avgFeelslikeF>
<iceaccum>null</iceaccum>
<isDay>true</isDay>
<minTempC>19</minTempC>
<minDewpointF>52</minDewpointF>
<windSpeedKTS>1</windSpeedKTS>
<sunset>1665243161</sunset>
<solradWM2>4785</solradWM2>
<windSpeedKPH>2</windSpeedKPH>
<windGustMPH>20</windGustMPH>
<maxHumidity>76</maxHumidity>
<windSpeedMPH>1</windSpeedMPH>
<windGustKPH>32</windGustKPH>
<windDirMaxDEG>301</windDirMaxDEG>
<tempC>null</tempC>
</periods>
<periods>
<dateTimeISO>2022-10-09T07:00:00+02:00</dateTimeISO>
<windDirMin80m>NW</windDirMin80m>
<windDirMin80mDEG>316</windDirMin80mDEG>
<feelslikeC>20</feelslikeC>
<visibilityMI>15</visibilityMI>
<windSpeedMaxMPH>9</windSpeedMaxMPH>
<windDirDEG>356</windDirDEG>
<windDir>N</windDir>
<sunriseISO>2022-10-09T05:53:03+02:00</sunriseISO>
<iceaccumMM>null</iceaccumMM>
<windSpeedMaxKTS>8</windSpeedMaxKTS>
<iceaccumIN>null</iceaccumIN>
<minTempF>67</minTempF>
<snowIN>0</snowIN>
<weather>Partly Cloudy</weather>
<sunsetISO>2022-10-09T17:31:31+02:00</sunsetISO>
<maxFeelslikeC>30</maxFeelslikeC>
<humidity>86</humidity>
<windDir80m>NW</windDir80m>
<maxFeelslikeF>86</maxFeelslikeF>
<precipMM>0</precipMM>
<sky>47</sky>
<windGust80mMPH>23</windGust80mMPH>
<windSpeedMax80mMPH>23</windSpeedMax80mMPH>
<weatherPrimary>Partly Cloudy</weatherPrimary>
<windGust80mKPH>36</windGust80mKPH>
<avgDewpointF>57</avgDewpointF>
<windSpeedMax80mKPH>36</windSpeedMax80mKPH>
<windGust80mKTS>20</windGust80mKTS>
<avgDewpointC>14</avgDewpointC>
<precipIN>0</precipIN>
<windSpeedMax80mKTS>20</windSpeedMax80mKTS>
<windDirMinDEG>356</windDirMinDEG>
<windSpeedMaxKPH>14</windSpeedMaxKPH>
<windSpeedMin80mKTS>5</windSpeedMin80mKTS>
<feelslikeF>67</feelslikeF>
<validTime>2022-10-09T07:00:00+02:00</validTime>
<windSpeedMin80mMPH>6</windSpeedMin80mMPH>
<solradMaxWM2>726</solradMaxWM2>
<avgTempC>25</avgTempC>
<windSpeedMin80mKPH>9</windSpeedMin80mKPH>
<weatherPrimaryCoded>::SC</weatherPrimaryCoded>
<sunrise>1665287583</sunrise>
<avgTempF>77</avgTempF>
<windDirMin>N</windDirMin>
<maxCoverage/>
<icon>pcloudy.png</icon>
<minFeelslikeC>20</minFeelslikeC>
<dewpointC>17</dewpointC>
<cloudsCoded>SC</cloudsCoded>
<minFeelslikeF>67</minFeelslikeF>
<minHumidity>31</minHumidity>
<dewpointF>63</dewpointF>
<windSpeed80mKTS>5</windSpeed80mKTS>
<pop>0</pop>
<snowCM>0</snowCM>
<windDirMax>NNW</windDirMax>
<windSpeed80mMPH>6</windSpeed80mMPH>
<windSpeed80mKPH>9</windSpeed80mKPH>
<windDir80mDEG>316</windDir80mDEG>
<maxTempC>31</maxTempC>
<pressureMB>1016</pressureMB>
<visibilityKM>24.135</visibilityKM>
<timestamp>1665291600</timestamp>
<maxTempF>87</maxTempF>
<tempF>null</tempF>
<minDewpointC>11</minDewpointC>
<solradMinWM2>0</solradMinWM2>
<windSpeedMinKTS>2</windSpeedMinKTS>
<windDirMax80mDEG>354</windDirMax80mDEG>
<windGustKTS>19</windGustKTS>
<windSpeedMinKPH>4</windSpeedMinKPH>
<maxDewpointF>63</maxDewpointF>
<windSpeedMinMPH>2</windSpeedMinMPH>
<avgFeelslikeC>25</avgFeelslikeC>
<uvi>7</uvi>
<windDirMax80m>N</windDirMax80m>
<maxDewpointC>17</maxDewpointC>
<pressureIN>29.99</pressureIN>
<avgFeelslikeF>77</avgFeelslikeF>
<iceaccum>null</iceaccum>
<isDay>true</isDay>
<minTempC>19</minTempC>
<minDewpointF>52</minDewpointF>
<windSpeedKTS>2</windSpeedKTS>
<sunset>1665329491</sunset>
<solradWM2>4768</solradWM2>
<windSpeedKPH>4</windSpeedKPH>
<windGustMPH>22</windGustMPH>
<maxHumidity>86</maxHumidity>
<windSpeedMPH>2</windSpeedMPH>
<windGustKPH>36</windGustKPH>
<windDirMaxDEG>343</windDirMaxDEG>
<tempC>null</tempC>
</periods>
<periods>
<dateTimeISO>2022-10-10T07:00:00+02:00</dateTimeISO>
<windDirMin80m>E</windDirMin80m>
<windDirMin80mDEG>91</windDirMin80mDEG>
<feelslikeC>21</feelslikeC>
<visibilityMI>15</visibilityMI>
<windSpeedMaxMPH>9</windSpeedMaxMPH>
<windDirDEG>358</windDirDEG>
<windDir>N</windDir>
<sunriseISO>2022-10-10T05:53:40+02:00</sunriseISO>
<iceaccumMM>null</iceaccumMM>
<windSpeedMaxKTS>8</windSpeedMaxKTS>
<iceaccumIN>null</iceaccumIN>
<minTempF>70</minTempF>
<snowIN>0</snowIN>
<weather>Partly Cloudy</weather>
<sunsetISO>2022-10-10T17:30:21+02:00</sunsetISO>
<maxFeelslikeC>30</maxFeelslikeC>
<humidity>75</humidity>
<windDir80m>N</windDir80m>
<maxFeelslikeF>86</maxFeelslikeF>
<precipMM>0</precipMM>
<sky>64</sky>
<windGust80mMPH>22</windGust80mMPH>
<windSpeedMax80mMPH>22</windSpeedMax80mMPH>
<weatherPrimary>Partly Cloudy</weatherPrimary>
<windGust80mKPH>36</windGust80mKPH>
<avgDewpointF>58</avgDewpointF>
<windSpeedMax80mKPH>36</windSpeedMax80mKPH>
<windGust80mKTS>19</windGust80mKTS>
<avgDewpointC>14</avgDewpointC>
<precipIN>0</precipIN>
<windSpeedMax80mKTS>19</windSpeedMax80mKTS>
<windDirMinDEG>358</windDirMinDEG>
<windSpeedMaxKPH>15</windSpeedMaxKPH>
<windSpeedMin80mKTS>7</windSpeedMin80mKTS>
<feelslikeF>69</feelslikeF>
<validTime>2022-10-10T07:00:00+02:00</validTime>
<windSpeedMin80mMPH>8</windSpeedMin80mMPH>
<solradMaxWM2>597</solradMaxWM2>
<avgTempC>26</avgTempC>
<windSpeedMin80mKPH>13</windSpeedMin80mKPH>
<weatherPrimaryCoded>::SC</weatherPrimaryCoded>
<sunrise>1665374020</sunrise>
<avgTempF>78</avgTempF>
<windDirMin>N</windDirMin>
<maxCoverage/>
<icon>pcloudy.png</icon>
<minFeelslikeC>21</minFeelslikeC>
<dewpointC>16</dewpointC>
<cloudsCoded>SC</cloudsCoded>
<minFeelslikeF>69</minFeelslikeF>
<minHumidity>35</minHumidity>
<dewpointF>61</dewpointF>
<windSpeed80mKTS>7</windSpeed80mKTS>
<pop>0</pop>
<snowCM>0</snowCM>
<windDirMax>N</windDirMax>
<windSpeed80mMPH>8</windSpeed80mMPH>
<windSpeed80mKPH>13</windSpeed80mKPH>
<windDir80mDEG>8</windDir80mDEG>
<maxTempC>31</maxTempC>
<pressureMB>1017</pressureMB>
<visibilityKM>24.135</visibilityKM>
<timestamp>1665378000</timestamp>
<maxTempF>87</maxTempF>
<tempF>null</tempF>
<minDewpointC>13</minDewpointC>
<solradMinWM2>0</solradMinWM2>
<windSpeedMinKTS>2</windSpeedMinKTS>
<windDirMax80mDEG>10</windDirMax80mDEG>
<windGustKTS>16</windGustKTS>
<windSpeedMinKPH>4</windSpeedMinKPH>
<maxDewpointF>61</maxDewpointF>
<windSpeedMinMPH>2</windSpeedMinMPH>
<avgFeelslikeC>25</avgFeelslikeC>
<uvi>6</uvi>
<windDirMax80m>N</windDirMax80m>
<maxDewpointC>16</maxDewpointC>
<pressureIN>30.03</pressureIN>
<avgFeelslikeF>78</avgFeelslikeF>
<iceaccum>null</iceaccum>
<isDay>true</isDay>
<minTempC>21</minTempC>
<minDewpointF>55</minDewpointF>
<windSpeedKTS>2</windSpeedKTS>
<sunset>1665415821</sunset>
<solradWM2>4494</solradWM2>
<windSpeedKPH>4</windSpeedKPH>
<windGustMPH>19</windGustMPH>
<maxHumidity>75</maxHumidity>
<windSpeedMPH>2</windSpeedMPH>
<windGustKPH>30</windGustKPH>
<windDirMaxDEG>10</windDirMaxDEG>
<tempC>null</tempC>
</periods>
<periods>
<dateTimeISO>2022-10-11T07:00:00+02:00</dateTimeISO>
<windDirMin80m>NNE</windDirMin80m>
<windDirMin80mDEG>13</windDirMin80mDEG>
<feelslikeC>22</feelslikeC>
<visibilityMI>15</visibilityMI>
<windSpeedMaxMPH>18</windSpeedMaxMPH>
<windDirDEG>13</windDirDEG>
<windDir>NNE</windDir>
<sunriseISO>2022-10-11T05:54:18+02:00</sunriseISO>
<iceaccumMM>null</iceaccumMM>
<windSpeedMaxKTS>15</windSpeedMaxKTS>
<iceaccumIN>null</iceaccumIN>
<minTempF>70</minTempF>
<snowIN>0</snowIN>
<weather>Sunny</weather>
<sunsetISO>2022-10-11T17:29:13+02:00</sunsetISO>
<maxFeelslikeC>31</maxFeelslikeC>
<humidity>71</humidity>
<windDir80m>NNE</windDir80m>
<maxFeelslikeF>87</maxFeelslikeF>
<precipMM>0</precipMM>
<sky>0</sky>
<windGust80mMPH>19</windGust80mMPH>
<windSpeedMax80mMPH>19</windSpeedMax80mMPH>
<weatherPrimary>Sunny</weatherPrimary>
<windGust80mKPH>31</windGust80mKPH>
<avgDewpointF>55</avgDewpointF>
<windSpeedMax80mKPH>31</windSpeedMax80mKPH>
<windGust80mKTS>17</windGust80mKTS>
<avgDewpointC>13</avgDewpointC>
<precipIN>0</precipIN>
<windSpeedMax80mKTS>17</windSpeedMax80mKTS>
<windDirMinDEG>14</windDirMinDEG>
<windSpeedMaxKPH>28</windSpeedMaxKPH>
<windSpeedMin80mKTS>9</windSpeedMin80mKTS>
<feelslikeF>72</feelslikeF>
<validTime>2022-10-11T07:00:00+02:00</validTime>
<windSpeedMin80mMPH>11</windSpeedMin80mMPH>
<solradMaxWM2>758</solradMaxWM2>
<avgTempC>26</avgTempC>
<windSpeedMin80mKPH>18</windSpeedMin80mKPH>
<weatherPrimaryCoded>::CL</weatherPrimaryCoded>
<sunrise>1665460458</sunrise>
<avgTempF>78</avgTempF>
<windDirMin>NNE</windDirMin>
<maxCoverage/>
<icon>sunny.png</icon>
<minFeelslikeC>22</minFeelslikeC>
<dewpointC>17</dewpointC>
<cloudsCoded>CL</cloudsCoded>
<minFeelslikeF>72</minFeelslikeF>
<minHumidity>30</minHumidity>
<dewpointF>62</dewpointF>
<windSpeed80mKTS>10</windSpeed80mKTS>
<pop>0</pop>
<snowCM>0</snowCM>
<windDirMax>NNE</windDirMax>
<windSpeed80mMPH>12</windSpeed80mMPH>
<windSpeed80mKPH>19</windSpeed80mKPH>
<windDir80mDEG>16</windDir80mDEG>
<maxTempC>31</maxTempC>
<pressureMB>1015</pressureMB>
<visibilityKM>24.135</visibilityKM>
<timestamp>1665464400</timestamp>
<maxTempF>87</maxTempF>
<tempF>null</tempF>
<minDewpointC>11</minDewpointC>
<solradMinWM2>0</solradMinWM2>
<windSpeedMinKTS>7</windSpeedMinKTS>
<windDirMax80mDEG>28</windDirMax80mDEG>
<windGustKTS>15</windGustKTS>
<windSpeedMinKPH>14</windSpeedMinKPH>
<maxDewpointF>62</maxDewpointF>
<windSpeedMinMPH>8</windSpeedMinMPH>
<avgFeelslikeC>26</avgFeelslikeC>
<uvi>null</uvi>
<windDirMax80m>NNE</windDirMax80m>
<maxDewpointC>17</maxDewpointC>
<pressureIN>29.98</pressureIN>
<avgFeelslikeF>79</avgFeelslikeF>
<iceaccum>null</iceaccum>
<isDay>true</isDay>
<minTempC>21</minTempC>
<minDewpointF>51</minDewpointF>
<windSpeedKTS>8</windSpeedKTS>
<sunset>1665502153</sunset>
<solradWM2>5450</solradWM2>
<windSpeedKPH>15</windSpeedKPH>
<windGustMPH>17</windGustMPH>
<maxHumidity>71</maxHumidity>
<windSpeedMPH>9</windSpeedMPH>
<windGustKPH>28</windGustKPH>
<windDirMaxDEG>28</windDirMaxDEG>
<tempC>null</tempC>
</periods>
<periods>
<dateTimeISO>2022-10-12T07:00:00+02:00</dateTimeISO>
<windDirMin80m>NNE</windDirMin80m>
<windDirMin80mDEG>15</windDirMin80mDEG>
<feelslikeC>22</feelslikeC>
<visibilityMI>15</visibilityMI>
<windSpeedMaxMPH>16</windSpeedMaxMPH>
<windDirDEG>12</windDirDEG>
<windDir>NNE</windDir>
<sunriseISO>2022-10-12T05:54:55+02:00</sunriseISO>
<iceaccumMM>null</iceaccumMM>
<windSpeedMaxKTS>14</windSpeedMaxKTS>
<iceaccumIN>null</iceaccumIN>
<minTempF>69</minTempF>
<snowIN>0</snowIN>
<weather>Mostly Sunny</weather>
<sunsetISO>2022-10-12T17:28:04+02:00</sunsetISO>
<maxFeelslikeC>31</maxFeelslikeC>
<humidity>68</humidity>
<windDir80m>NNE</windDir80m>
<maxFeelslikeF>88</maxFeelslikeF>
<precipMM>0</precipMM>
<sky>27</sky>
<windGust80mMPH>21</windGust80mMPH>
<windSpeedMax80mMPH>21</windSpeedMax80mMPH>
<weatherPrimary>Mostly Sunny</weatherPrimary>
<windGust80mKPH>33</windGust80mKPH>
<avgDewpointF>55</avgDewpointF>
<windSpeedMax80mKPH>33</windSpeedMax80mKPH>
<windGust80mKTS>18</windGust80mKTS>
<avgDewpointC>13</avgDewpointC>
<precipIN>0</precipIN>
<windSpeedMax80mKTS>18</windSpeedMax80mKTS>
<windDirMinDEG>12</windDirMinDEG>
<windSpeedMaxKPH>26</windSpeedMaxKPH>
<windSpeedMin80mKTS>10</windSpeedMin80mKTS>
<feelslikeF>72</feelslikeF>
<validTime>2022-10-12T07:00:00+02:00</validTime>
<windSpeedMin80mMPH>11</windSpeedMin80mMPH>
<solradMaxWM2>743</solradMaxWM2>
<avgTempC>26</avgTempC>
<windSpeedMin80mKPH>18</windSpeedMin80mKPH>
<weatherPrimaryCoded>::FW</weatherPrimaryCoded>
<sunrise>1665546895</sunrise>
<avgTempF>79</avgTempF>
<windDirMin>NNE</windDirMin>
<maxCoverage/>
<icon>fair.png</icon>
<minFeelslikeC>22</minFeelslikeC>
<dewpointC>16</dewpointC>
<cloudsCoded>FW</cloudsCoded>
<minFeelslikeF>72</minFeelslikeF>
<minHumidity>29</minHumidity>
<dewpointF>60</dewpointF>
<windSpeed80mKTS>10</windSpeed80mKTS>
<pop>0</pop>
<snowCM>0</snowCM>
<windDirMax>E</windDirMax>
<windSpeed80mMPH>12</windSpeed80mMPH>
<windSpeed80mKPH>19</windSpeed80mKPH>
<windDir80mDEG>15</windDir80mDEG>
<maxTempC>31</maxTempC>
<pressureMB>1014</pressureMB>
<visibilityKM>24.135</visibilityKM>
<timestamp>1665550800</timestamp>
<maxTempF>88</maxTempF>
<tempF>null</tempF>
<minDewpointC>11</minDewpointC>
<solradMinWM2>0</solradMinWM2>
<windSpeedMinKTS>7</windSpeedMinKTS>
<windDirMax80mDEG>96</windDirMax80mDEG>
<windGustKTS>15</windGustKTS>
<windSpeedMinKPH>13</windSpeedMinKPH>
<maxDewpointF>60</maxDewpointF>
<windSpeedMinMPH>8</windSpeedMinMPH>
<avgFeelslikeC>26</avgFeelslikeC>
<uvi>null</uvi>
<windDirMax80m>E</windDirMax80m>
<maxDewpointC>16</maxDewpointC>
<pressureIN>29.95</pressureIN>
<avgFeelslikeF>80</avgFeelslikeF>
<iceaccum>null</iceaccum>
<isDay>true</isDay>
<minTempC>21</minTempC>
<minDewpointF>51</minDewpointF>
<windSpeedKTS>8</windSpeedKTS>
<sunset>1665588484</sunset>
<solradWM2>4740</solradWM2>
<windSpeedKPH>15</windSpeedKPH>
<windGustMPH>17</windGustMPH>
<maxHumidity>68</maxHumidity>
<windSpeedMPH>9</windSpeedMPH>
<windGustKPH>28</windGustKPH>
<windDirMaxDEG>96</windDirMaxDEG>
<tempC>null</tempC>
</periods>
<interval>day</interval>
<place>
<country>eg</country>
<name>cairo</name>
<state>qh</state>
</place>
</response>
<error>null</error>

View File

@ -0,0 +1,317 @@
[
{
"_id": "6606c27d2ab4a0102d49420a",
"index": 0,
"guid": "441331fb-84d1-4873-a649-3814621a0370",
"isActive": true,
"balance": "$2,691.63",
"picture": "http://example.abc/32x32",
"age": 26,
"eyeColor": "blue",
"name": "abc",
"gender": "female",
"company": "example",
"email": "abc@def.com",
"phone": "+1 (123) 456-7890",
"address": "123 Main St",
"about": "Laborum magna tempor officia irure cillum nulla incididunt Lorem dolor veniam elit cupidatat amet. Veniam veniam exercitation nulla consectetur officia esse ex sunt nulla nisi ea cillum nisi reprehenderit. Qui aliquip reprehenderit aliqua aliquip aliquip anim sit magna nostrud dolore veniam velit elit aliquip.\r\n",
"registered": "2016-07-22T03:18:11 -01:00",
"latitude": -21.544934,
"longitude": 72.765495,
"tags": [
"consectetur",
"minim",
"sunt",
"in",
"ut",
"velit",
"anim"
],
"friends": [
{
"id": 0,
"name": "abc def"
},
{
"id": 1,
"name": "ghi jkl"
},
{
"id": 2,
"name": "mno pqr"
}
],
"greeting": "Hello, abc! You have 10 unread messages.",
"favoriteFruit": "banana"
},
{
"_id": "6606c27d0a45df5121fb765f",
"index": 1,
"guid": "fd774715-de85-44b9-b498-c214d8f68d9f",
"isActive": true,
"balance": "$2,713.96",
"picture": "http://placehold.it/32x32",
"age": 27,
"eyeColor": "green",
"name": "def",
"gender": "female",
"company": "sample",
"email": "def@abc.com",
"phone": "+1 (123) 456-78910",
"address": "1234 Main St",
"about": "Ea id cupidatat eiusmod culpa. Nulla consequat esse elit enim et pariatur eiusmod ipsum. Consequat eu non reprehenderit in.\r\n",
"registered": "2015-04-06T07:54:22 -01:00",
"latitude": 83.512347,
"longitude": -9.368739,
"tags": [
"excepteur",
"non",
"nostrud",
"laboris",
"laboris",
"qui",
"aute"
],
"friends": [
{
"id": 0,
"name": "sample example"
},
{
"id": 1,
"name": "test name"
},
{
"id": 2,
"name": "aaa aaaa"
}
],
"greeting": "Hello, test! You have 7 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "6606c27dfb3a0e4e7e7183d3",
"index": 2,
"guid": "688b0c36-98e0-4ee7-86b8-863638d79b5f",
"isActive": false,
"balance": "$3,514.35",
"picture": "http://placehold.it/32x32",
"age": 32,
"eyeColor": "green",
"name": "test",
"gender": "female",
"company": "test",
"email": "test@test.com",
"phone": "+1 (123) 456-7890",
"address": "123 Main St",
"about": "Mollit officia adipisicing ex nisi non Lorem sunt quis est. Irure exercitation duis ipsum qui ullamco eu ea commodo occaecat minim proident. Incididunt nostrud ex cupidatat eiusmod mollit anim irure culpa. Labore voluptate voluptate labore nisi sit eu. Dolor sit proident velit dolor deserunt labore sit ipsum incididunt eiusmod reprehenderit voluptate. Duis anim velit officia laboris consequat officia dolor sint dolor nisi ex.\r\n",
"registered": "2021-11-02T12:50:05 -00:00",
"latitude": -82.969939,
"longitude": 86.415645,
"tags": [
"aliquip",
"et",
"est",
"nulla",
"nulla",
"tempor",
"adipisicing"
],
"friends": [
{
"id": 0,
"name": "test"
},
{
"id": 1,
"name": "sample"
},
{
"id": 2,
"name": "example"
}
],
"greeting": "Hello, test! You have 1 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "6606c27d204bc2327fc9ba23",
"index": 3,
"guid": "be970cba-306e-4cbd-be08-c265a43a61fa",
"isActive": true,
"balance": "$3,691.63",
"picture": "http://placehold.it/32x32",
"age": 35,
"eyeColor": "brown",
"name": "another test",
"gender": "male",
"company": "TEST",
"email": "anothertest@anothertest.com",
"phone": "+1 (321) 987-6543",
"address": "123 Example Main St",
"about": "Do proident consectetur minim quis. In adipisicing culpa Lorem fugiat cillum exercitation velit velit. Non voluptate laboris deserunt veniam et sint consectetur irure aliqua quis eiusmod consectetur elit id. Ex sint do anim Lorem excepteur eu nulla.\r\n",
"registered": "2020-06-25T04:55:25 -01:00",
"latitude": 63.614955,
"longitude": -109.299405,
"tags": [
"irure",
"esse",
"non",
"mollit",
"laborum",
"adipisicing",
"ad"
],
"friends": [
{
"id": 0,
"name": "test"
},
{
"id": 1,
"name": "sample"
},
{
"id": 2,
"name": "example"
}
],
"greeting": "Hello, another test! You have 5 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "6606c27df63eb5f390cb9989",
"index": 4,
"guid": "2c3e5115-758d-468e-99c5-c9afa26e1f9f",
"isActive": true,
"balance": "$1,047.20",
"picture": "http://test.it/32x32",
"age": 30,
"eyeColor": "green",
"name": "Test Name",
"gender": "female",
"company": "test",
"email": "testname@testname.com",
"phone": "+1 (999) 999-9999",
"address": "999 Test Main St",
"about": "Voluptate exercitation tempor consectetur velit magna ea occaecat cupidatat consectetur anim aute. Aliquip est aute ipsum laboris non irure qui consectetur tempor quis do ea Lorem. Cupidatat exercitation ad culpa aliqua amet commodo mollit reprehenderit exercitation adipisicing amet et laborum pariatur.\r\n",
"registered": "2023-01-19T02:43:18 -00:00",
"latitude": 14.15208,
"longitude": 170.411535,
"tags": [
"dolor",
"qui",
"cupidatat",
"aliqua",
"laboris",
"reprehenderit",
"sint"
],
"friends": [
{
"id": 0,
"name": "test"
},
{
"id": 1,
"name": "sample"
},
{
"id": 2,
"name": "example"
}
],
"greeting": "Hello, test! You have 6 unread messages.",
"favoriteFruit": "apple"
},
{
"_id": "6606c27d01d19fa29853d59c",
"index": 5,
"guid": "816cda74-5d4b-498f-9724-20f340d5f5bf",
"isActive": false,
"balance": "$2,628.74",
"picture": "http://testing.it/32x32",
"age": 28,
"eyeColor": "green",
"name": "Testing",
"gender": "female",
"company": "test",
"email": "testing@testing.com",
"phone": "+1 (888) 888-8888",
"address": "123 Main St",
"about": "Cupidatat non ut nulla qui excepteur in minim non et nulla fugiat. Dolor quis laborum occaecat veniam dolor ullamco deserunt amet veniam dolor quis proident tempor laboris. In cillum duis ut quis. Aliqua cupidatat magna proident velit tempor veniam et consequat laborum ex dolore qui. Incididunt deserunt magna minim Lorem consectetur.\r\n",
"registered": "2017-10-14T11:14:08 -01:00",
"latitude": -5.345728,
"longitude": -9.706491,
"tags": [
"officia",
"velit",
"laboris",
"qui",
"cupidatat",
"cupidatat",
"ad"
],
"friends": [
{
"id": 0,
"name": "test"
},
{
"id": 1,
"name": "sample"
},
{
"id": 2,
"name": "example"
}
],
"greeting": "Hello, testing! You have 2 unread messages.",
"favoriteFruit": "strawberry"
},
{
"_id": "6606c27d803003cede1d6deb",
"index": 6,
"guid": "4ee550bc-0920-4104-b3ce-ebf9db6a803f",
"isActive": true,
"balance": "$1,709.31",
"picture": "http://sample.it/32x32",
"age": 31,
"eyeColor": "blue",
"name": "Sample Name",
"gender": "female",
"company": "Sample",
"email": "sample@sample.com",
"phone": "+1 (777) 777-7777",
"address": "123 Main St",
"about": "Lorem ex proident ipsum ullamco velit sit nisi eiusmod cillum. Id tempor irure culpa nisi sit non qui veniam non ut. Aliquip reprehenderit excepteur mollit quis excepteur ex sit. Quis do eu veniam do ullamco occaecat eu cupidatat nisi laborum tempor minim fugiat pariatur. Ex in nulla ex velit.\r\n",
"registered": "2019-04-08T03:54:36 -01:00",
"latitude": -70.660321,
"longitude": 71.547525,
"tags": [
"consequat",
"veniam",
"pariatur",
"aliqua",
"cillum",
"eu",
"officia"
],
"friends": [
{
"id": 0,
"name": "Test"
},
{
"id": 1,
"name": "Sample"
},
{
"id": 2,
"name": "Example"
}
],
"greeting": "Hello, Sample! You have 6 unread messages.",
"favoriteFruit": "apple"
}
]

File diff suppressed because it is too large Load Diff