Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in / Register
Toggle navigation
S
spring-boot
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
DEMO
spring-boot
Commits
4568f14c
Commit
4568f14c
authored
Jan 08, 2018
by
Stephane Nicoll
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix javadoc warnings
parent
966d4251
Changes
6
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
2444 additions
and
2266 deletions
+2444
-2266
JSON.java
...pringframework/boot/configurationprocessor/json/JSON.java
+103
-89
JSONArray.java
...framework/boot/configurationprocessor/json/JSONArray.java
+639
-564
JSONException.java
...ework/boot/configurationprocessor/json/JSONException.java
+3
-3
JSONObject.java
...ramework/boot/configurationprocessor/json/JSONObject.java
+788
-694
JSONStringer.java
...mework/boot/configurationprocessor/json/JSONStringer.java
+403
-369
JSONTokener.java
...amework/boot/configurationprocessor/json/JSONTokener.java
+508
-547
No files found.
spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/json/JSON.java
View file @
4568f14c
...
@@ -17,100 +17,114 @@
...
@@ -17,100 +17,114 @@
package
org
.
springframework
.
boot
.
configurationprocessor
.
json
;
package
org
.
springframework
.
boot
.
configurationprocessor
.
json
;
class
JSON
{
class
JSON
{
/**
/**
* Returns the input if it is a JSON-permissible value; throws otherwise.
* Returns the input if it is a JSON-permissible value; throws otherwise.
*/
*/
static
double
checkDouble
(
double
d
)
throws
JSONException
{
static
double
checkDouble
(
double
d
)
throws
JSONException
{
if
(
Double
.
isInfinite
(
d
)
||
Double
.
isNaN
(
d
))
{
if
(
Double
.
isInfinite
(
d
)
||
Double
.
isNaN
(
d
))
{
throw
new
JSONException
(
"Forbidden numeric value: "
+
d
);
throw
new
JSONException
(
"Forbidden numeric value: "
+
d
);
}
}
return
d
;
return
d
;
}
}
static
Boolean
toBoolean
(
Object
value
)
{
static
Boolean
toBoolean
(
Object
value
)
{
if
(
value
instanceof
Boolean
)
{
if
(
value
instanceof
Boolean
)
{
return
(
Boolean
)
value
;
return
(
Boolean
)
value
;
}
else
if
(
value
instanceof
String
)
{
}
String
stringValue
=
(
String
)
value
;
else
if
(
value
instanceof
String
)
{
if
(
"true"
.
equalsIgnoreCase
(
stringValue
))
{
String
stringValue
=
(
String
)
value
;
return
true
;
if
(
"true"
.
equalsIgnoreCase
(
stringValue
))
{
}
else
if
(
"false"
.
equalsIgnoreCase
(
stringValue
))
{
return
true
;
return
false
;
}
}
else
if
(
"false"
.
equalsIgnoreCase
(
stringValue
))
{
}
return
false
;
return
null
;
}
}
}
return
null
;
}
static
Double
toDouble
(
Object
value
)
{
static
Double
toDouble
(
Object
value
)
{
if
(
value
instanceof
Double
)
{
if
(
value
instanceof
Double
)
{
return
(
Double
)
value
;
return
(
Double
)
value
;
}
else
if
(
value
instanceof
Number
)
{
}
return
((
Number
)
value
).
doubleValue
();
else
if
(
value
instanceof
Number
)
{
}
else
if
(
value
instanceof
String
)
{
return
((
Number
)
value
).
doubleValue
();
try
{
}
return
Double
.
valueOf
((
String
)
value
);
else
if
(
value
instanceof
String
)
{
}
catch
(
NumberFormatException
ignored
)
{
try
{
}
return
Double
.
valueOf
((
String
)
value
);
}
}
return
null
;
catch
(
NumberFormatException
ignored
)
{
}
}
}
return
null
;
}
static
Integer
toInteger
(
Object
value
)
{
static
Integer
toInteger
(
Object
value
)
{
if
(
value
instanceof
Integer
)
{
if
(
value
instanceof
Integer
)
{
return
(
Integer
)
value
;
return
(
Integer
)
value
;
}
else
if
(
value
instanceof
Number
)
{
}
return
((
Number
)
value
).
intValue
();
else
if
(
value
instanceof
Number
)
{
}
else
if
(
value
instanceof
String
)
{
return
((
Number
)
value
).
intValue
();
try
{
}
return
(
int
)
Double
.
parseDouble
((
String
)
value
);
else
if
(
value
instanceof
String
)
{
}
catch
(
NumberFormatException
ignored
)
{
try
{
}
return
(
int
)
Double
.
parseDouble
((
String
)
value
);
}
}
return
null
;
catch
(
NumberFormatException
ignored
)
{
}
}
}
return
null
;
}
static
Long
toLong
(
Object
value
)
{
static
Long
toLong
(
Object
value
)
{
if
(
value
instanceof
Long
)
{
if
(
value
instanceof
Long
)
{
return
(
Long
)
value
;
return
(
Long
)
value
;
}
else
if
(
value
instanceof
Number
)
{
}
return
((
Number
)
value
).
longValue
();
else
if
(
value
instanceof
Number
)
{
}
else
if
(
value
instanceof
String
)
{
return
((
Number
)
value
).
longValue
();
try
{
}
return
(
long
)
Double
.
parseDouble
((
String
)
value
);
else
if
(
value
instanceof
String
)
{
}
catch
(
NumberFormatException
ignored
)
{
try
{
}
return
(
long
)
Double
.
parseDouble
((
String
)
value
);
}
}
return
null
;
catch
(
NumberFormatException
ignored
)
{
}
}
}
return
null
;
}
static
String
toString
(
Object
value
)
{
static
String
toString
(
Object
value
)
{
if
(
value
instanceof
String
)
{
if
(
value
instanceof
String
)
{
return
(
String
)
value
;
return
(
String
)
value
;
}
else
if
(
value
!=
null
)
{
}
return
String
.
valueOf
(
value
);
else
if
(
value
!=
null
)
{
}
return
String
.
valueOf
(
value
);
return
null
;
}
}
return
null
;
}
public
static
JSONException
typeMismatch
(
Object
indexOrName
,
Object
actual
,
public
static
JSONException
typeMismatch
(
Object
indexOrName
,
Object
actual
,
String
requiredType
)
throws
JSONException
{
String
requiredType
)
throws
JSONException
{
if
(
actual
==
null
)
{
if
(
actual
==
null
)
{
throw
new
JSONException
(
"Value at "
+
indexOrName
+
" is null."
);
throw
new
JSONException
(
"Value at "
+
indexOrName
+
" is null."
);
}
else
{
}
throw
new
JSONException
(
"Value "
+
actual
+
" at "
+
indexOrName
else
{
+
" of type "
+
actual
.
getClass
().
getName
()
throw
new
JSONException
(
"Value "
+
actual
+
" at "
+
indexOrName
+
" cannot be converted to "
+
requiredType
);
+
" of type "
+
actual
.
getClass
().
getName
()
}
+
" cannot be converted to "
+
requiredType
);
}
}
}
public
static
JSONException
typeMismatch
(
Object
actual
,
String
requiredType
)
public
static
JSONException
typeMismatch
(
Object
actual
,
String
requiredType
)
throws
JSONException
{
throws
JSONException
{
if
(
actual
==
null
)
{
if
(
actual
==
null
)
{
throw
new
JSONException
(
"Value is null."
);
throw
new
JSONException
(
"Value is null."
);
}
else
{
}
throw
new
JSONException
(
"Value "
+
actual
else
{
+
" of type "
+
actual
.
getClass
().
getName
()
throw
new
JSONException
(
"Value "
+
actual
+
" cannot be converted to "
+
requiredType
);
+
" of type "
+
actual
.
getClass
().
getName
()
}
+
" cannot be converted to "
+
requiredType
);
}
}
}
}
}
spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/json/JSONArray.java
View file @
4568f14c
...
@@ -48,568 +48,643 @@ import java.util.List;
...
@@ -48,568 +48,643 @@ import java.util.List;
*/
*/
public
class
JSONArray
{
public
class
JSONArray
{
private
final
List
<
Object
>
values
;
private
final
List
<
Object
>
values
;
/**
/**
* Creates a {@code JSONArray} with no values.
* Creates a {@code JSONArray} with no values.
*/
*/
public
JSONArray
()
{
public
JSONArray
()
{
values
=
new
ArrayList
<
Object
>();
this
.
values
=
new
ArrayList
<
Object
>();
}
}
/**
/**
* Creates a new {@code JSONArray} by copying all values from the given
* Creates a new {@code JSONArray} by copying all values from the given
* collection.
* collection.
*
*
* @param copyFrom a collection whose values are of supported types.
* @param copyFrom a collection whose values are of supported types.
* Unsupported values are not permitted and will yield an array in an
* Unsupported values are not permitted and will yield an array in an
* inconsistent state.
* inconsistent state.
*/
*/
/* Accept a raw type for API compatibility */
/* Accept a raw type for API compatibility */
public
JSONArray
(
Collection
copyFrom
)
{
public
JSONArray
(
Collection
copyFrom
)
{
this
();
this
();
if
(
copyFrom
!=
null
)
{
if
(
copyFrom
!=
null
)
{
for
(
Iterator
it
=
copyFrom
.
iterator
();
it
.
hasNext
();)
{
for
(
Iterator
it
=
copyFrom
.
iterator
();
it
.
hasNext
();
)
{
put
(
JSONObject
.
wrap
(
it
.
next
()));
put
(
JSONObject
.
wrap
(
it
.
next
()));
}
}
}
}
}
}
/**
/**
* Creates a new {@code JSONArray} with values from the next array in the
* Creates a new {@code JSONArray} with values from the next array in the
* tokener.
* tokener.
*
*
* @param readFrom a tokener whose nextValue() method will yield a
* @param readFrom a tokener whose nextValue() method will yield a
* {@code JSONArray}.
* {@code JSONArray}.
* @throws JSONException if the parse fails or doesn't yield a
* @throws JSONException if the parse fails or doesn't yield a
* {@code JSONArray}.
* {@code JSONArray}.
*/
* @throws JSONException if processing of json failed
public
JSONArray
(
JSONTokener
readFrom
)
throws
JSONException
{
*/
/*
public
JSONArray
(
JSONTokener
readFrom
)
throws
JSONException
{
* Getting the parser to populate this could get tricky. Instead, just
/*
* parse to temporary JSONArray and then steal the data from that.
* Getting the parser to populate this could get tricky. Instead, just
*/
* parse to temporary JSONArray and then steal the data from that.
Object
object
=
readFrom
.
nextValue
();
*/
if
(
object
instanceof
JSONArray
)
{
Object
object
=
readFrom
.
nextValue
();
values
=
((
JSONArray
)
object
).
values
;
if
(
object
instanceof
JSONArray
)
{
}
else
{
this
.
values
=
((
JSONArray
)
object
).
values
;
throw
JSON
.
typeMismatch
(
object
,
"JSONArray"
);
}
}
else
{
}
throw
JSON
.
typeMismatch
(
object
,
"JSONArray"
);
}
/**
}
* Creates a new {@code JSONArray} with values from the JSON string.
*
/**
* @param json a JSON-encoded string containing an array.
* Creates a new {@code JSONArray} with values from the JSON string.
* @throws JSONException if the parse fails or doesn't yield a {@code
*
* JSONArray}.
* @param json a JSON-encoded string containing an array.
*/
* @throws JSONException if the parse fails or doesn't yield a {@code
public
JSONArray
(
String
json
)
throws
JSONException
{
* JSONArray}.
this
(
new
JSONTokener
(
json
));
*/
}
public
JSONArray
(
String
json
)
throws
JSONException
{
this
(
new
JSONTokener
(
json
));
/**
}
* Creates a new {@code JSONArray} with values from the given primitive array.
*/
/**
public
JSONArray
(
Object
array
)
throws
JSONException
{
* Creates a new {@code JSONArray} with values from the given primitive array.
if
(!
array
.
getClass
().
isArray
())
{
* @param array a primitive array
throw
new
JSONException
(
"Not a primitive array: "
+
array
.
getClass
());
* @throws JSONException if processing of json failed
}
*/
final
int
length
=
Array
.
getLength
(
array
);
public
JSONArray
(
Object
array
)
throws
JSONException
{
values
=
new
ArrayList
<
Object
>(
length
);
if
(!
array
.
getClass
().
isArray
())
{
for
(
int
i
=
0
;
i
<
length
;
++
i
)
{
throw
new
JSONException
(
"Not a primitive array: "
+
array
.
getClass
());
put
(
JSONObject
.
wrap
(
Array
.
get
(
array
,
i
)));
}
}
final
int
length
=
Array
.
getLength
(
array
);
}
this
.
values
=
new
ArrayList
<
Object
>(
length
);
for
(
int
i
=
0
;
i
<
length
;
++
i
)
{
/**
put
(
JSONObject
.
wrap
(
Array
.
get
(
array
,
i
)));
* Returns the number of values in this array.
}
*/
}
public
int
length
()
{
return
values
.
size
();
/**
}
* Returns the number of values in this array.
* @return the length of this array
/**
*/
* Appends {@code value} to the end of this array.
public
int
length
()
{
*
return
this
.
values
.
size
();
* @return this array.
}
*/
public
JSONArray
put
(
boolean
value
)
{
/**
values
.
add
(
value
);
* Appends {@code value} to the end of this array.
return
this
;
*
}
* @param value the value
* @return this array.
/**
*/
* Appends {@code value} to the end of this array.
public
JSONArray
put
(
boolean
value
)
{
*
this
.
values
.
add
(
value
);
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
return
this
;
* {@link Double#isInfinite() infinities}.
}
* @return this array.
*/
/**
public
JSONArray
put
(
double
value
)
throws
JSONException
{
* Appends {@code value} to the end of this array.
values
.
add
(
JSON
.
checkDouble
(
value
));
*
return
this
;
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
}
* {@link Double#isInfinite() infinities}.
* @return this array.
/**
* @throws JSONException if processing of json failed
* Appends {@code value} to the end of this array.
*/
*
public
JSONArray
put
(
double
value
)
throws
JSONException
{
* @return this array.
this
.
values
.
add
(
JSON
.
checkDouble
(
value
));
*/
return
this
;
public
JSONArray
put
(
int
value
)
{
}
values
.
add
(
value
);
return
this
;
/**
}
* Appends {@code value} to the end of this array.
* @param value the value
/**
* @return this array.
* Appends {@code value} to the end of this array.
*/
*
public
JSONArray
put
(
int
value
)
{
* @return this array.
this
.
values
.
add
(
value
);
*/
return
this
;
public
JSONArray
put
(
long
value
)
{
}
values
.
add
(
value
);
return
this
;
/**
}
* Appends {@code value} to the end of this array.
* @param value the value
/**
* @return this array.
* Appends {@code value} to the end of this array.
*/
*
public
JSONArray
put
(
long
value
)
{
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
this
.
values
.
add
(
value
);
* Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May
return
this
;
* not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
}
* infinities}. Unsupported values are not permitted and will cause the
* array to be in an inconsistent state.
/**
* @return this array.
* Appends {@code value} to the end of this array.
*/
*
public
JSONArray
put
(
Object
value
)
{
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
values
.
add
(
value
);
* Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May
return
this
;
* not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
}
* infinities}. Unsupported values are not permitted and will cause the
* array to be in an inconsistent state.
/**
* @return this array.
* Sets the value at {@code index} to {@code value}, null padding this array
*/
* to the required length if necessary. If a value already exists at {@code
public
JSONArray
put
(
Object
value
)
{
* index}, it will be replaced.
this
.
values
.
add
(
value
);
*
return
this
;
* @return this array.
}
*/
public
JSONArray
put
(
int
index
,
boolean
value
)
throws
JSONException
{
/**
return
put
(
index
,
(
Boolean
)
value
);
* Sets the value at {@code index} to {@code value}, null padding this array
}
* to the required length if necessary. If a value already exists at {@code
* index}, it will be replaced.
/**
* @param index the index to set the value to
* Sets the value at {@code index} to {@code value}, null padding this array
* @param value the value
* to the required length if necessary. If a value already exists at {@code
* @return this array.
* index}, it will be replaced.
* @throws JSONException if processing of json failed
*
*/
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
public
JSONArray
put
(
int
index
,
boolean
value
)
throws
JSONException
{
* {@link Double#isInfinite() infinities}.
return
put
(
index
,
(
Boolean
)
value
);
* @return this array.
}
*/
public
JSONArray
put
(
int
index
,
double
value
)
throws
JSONException
{
/**
return
put
(
index
,
(
Double
)
value
);
* Sets the value at {@code index} to {@code value}, null padding this array
}
* to the required length if necessary. If a value already exists at {@code
* index}, it will be replaced.
/**
* @param index the index to set the value to
* Sets the value at {@code index} to {@code value}, null padding this array
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
* to the required length if necessary. If a value already exists at {@code
* {@link Double#isInfinite() infinities}.
* index}, it will be replaced.
* @return this array.
*
* @throws JSONException if processing of json failed
* @return this array.
*/
*/
public
JSONArray
put
(
int
index
,
double
value
)
throws
JSONException
{
public
JSONArray
put
(
int
index
,
int
value
)
throws
JSONException
{
return
put
(
index
,
(
Double
)
value
);
return
put
(
index
,
(
Integer
)
value
);
}
}
/**
/**
* Sets the value at {@code index} to {@code value}, null padding this array
* Sets the value at {@code index} to {@code value}, null padding this array
* to the required length if necessary. If a value already exists at {@code
* to the required length if necessary. If a value already exists at {@code
* index}, it will be replaced.
* index}, it will be replaced.
* @param index the index to set the value to
*
* @param value the value
* @return this array.
* @return this array.
*/
* @throws JSONException if processing of json failed
public
JSONArray
put
(
int
index
,
long
value
)
throws
JSONException
{
*/
return
put
(
index
,
(
Long
)
value
);
public
JSONArray
put
(
int
index
,
int
value
)
throws
JSONException
{
}
return
put
(
index
,
(
Integer
)
value
);
}
/**
* Sets the value at {@code index} to {@code value}, null padding this array
/**
* to the required length if necessary. If a value already exists at {@code
* Sets the value at {@code index} to {@code value}, null padding this array
* index}, it will be replaced.
* to the required length if necessary. If a value already exists at {@code
*
* index}, it will be replaced.
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* @param index the index to set the value to
* Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May
* @param value the value
* not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
* @return this array.
* infinities}.
* @throws JSONException if processing of json failed
* @return this array.
*/
*/
public
JSONArray
put
(
int
index
,
long
value
)
throws
JSONException
{
public
JSONArray
put
(
int
index
,
Object
value
)
throws
JSONException
{
return
put
(
index
,
(
Long
)
value
);
if
(
value
instanceof
Number
)
{
}
// deviate from the original by checking all Numbers, not just floats & doubles
JSON
.
checkDouble
(((
Number
)
value
).
doubleValue
());
/**
}
* Sets the value at {@code index} to {@code value}, null padding this array
while
(
values
.
size
()
<=
index
)
{
* to the required length if necessary. If a value already exists at {@code
values
.
add
(
null
);
* index}, it will be replaced.
}
* @param index the index to set the value to
values
.
set
(
index
,
value
);
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
return
this
;
* Integer, Long, Double, {@link JSONObject#NULL}, or {@code null}. May
}
* not be {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
* infinities}.
/**
* @return this array.
* Returns true if this array has no value at {@code index}, or if its value
* @throws JSONException if processing of json failed
* is the {@code null} reference or {@link JSONObject#NULL}.
*/
*/
public
JSONArray
put
(
int
index
,
Object
value
)
throws
JSONException
{
public
boolean
isNull
(
int
index
)
{
if
(
value
instanceof
Number
)
{
Object
value
=
opt
(
index
);
// deviate from the original by checking all Numbers, not just floats & doubles
return
value
==
null
||
value
==
JSONObject
.
NULL
;
JSON
.
checkDouble
(((
Number
)
value
).
doubleValue
());
}
}
while
(
this
.
values
.
size
()
<=
index
)
{
/**
this
.
values
.
add
(
null
);
* Returns the value at {@code index}.
}
*
this
.
values
.
set
(
index
,
value
);
* @throws JSONException if this array has no value at {@code index}, or if
return
this
;
* that value is the {@code null} reference. This method returns
}
* normally if the value is {@code JSONObject#NULL}.
*/
/**
public
Object
get
(
int
index
)
throws
JSONException
{
* Returns true if this array has no value at {@code index}, or if its value
try
{
* is the {@code null} reference or {@link JSONObject#NULL}.
Object
value
=
values
.
get
(
index
);
* @param index the index to set the value to
if
(
value
==
null
)
{
* @return true if this array has no value at {@code index}
throw
new
JSONException
(
"Value at "
+
index
+
" is null."
);
*/
}
public
boolean
isNull
(
int
index
)
{
return
value
;
Object
value
=
opt
(
index
);
}
catch
(
IndexOutOfBoundsException
e
)
{
return
value
==
null
||
value
==
JSONObject
.
NULL
;
throw
new
JSONException
(
"Index "
+
index
+
" out of range [0.."
+
values
.
size
()
+
")"
);
}
}
}
/**
* Returns the value at {@code index}.
/**
* @param index the index to get the value from
* Returns the value at {@code index}, or null if the array has no value
* @return the value at {@code index}.
* at {@code index}.
* @throws JSONException if this array has no value at {@code index}, or if
*/
* that value is the {@code null} reference. This method returns
public
Object
opt
(
int
index
)
{
* normally if the value is {@code JSONObject#NULL}.
if
(
index
<
0
||
index
>=
values
.
size
())
{
*/
return
null
;
public
Object
get
(
int
index
)
throws
JSONException
{
}
try
{
return
values
.
get
(
index
);
Object
value
=
this
.
values
.
get
(
index
);
}
if
(
value
==
null
)
{
throw
new
JSONException
(
"Value at "
+
index
+
" is null."
);
/**
}
* Removes and returns the value at {@code index}, or null if the array has no value
return
value
;
* at {@code index}.
}
*/
catch
(
IndexOutOfBoundsException
e
)
{
public
Object
remove
(
int
index
)
{
throw
new
JSONException
(
"Index "
+
index
+
" out of range [0.."
+
this
.
values
.
size
()
+
")"
);
if
(
index
<
0
||
index
>=
values
.
size
())
{
}
return
null
;
}
}
return
values
.
remove
(
index
);
/**
}
* Returns the value at {@code index}, or null if the array has no value
* at {@code index}.
/**
* @param index the index to get the value from
* Returns the value at {@code index} if it exists and is a boolean or can
* @return the value at {@code index} or {@code null}
* be coerced to a boolean.
*/
*
public
Object
opt
(
int
index
)
{
* @throws JSONException if the value at {@code index} doesn't exist or
if
(
index
<
0
||
index
>=
this
.
values
.
size
())
{
* cannot be coerced to a boolean.
return
null
;
*/
}
public
boolean
getBoolean
(
int
index
)
throws
JSONException
{
return
this
.
values
.
get
(
index
);
Object
object
=
get
(
index
);
}
Boolean
result
=
JSON
.
toBoolean
(
object
);
if
(
result
==
null
)
{
/**
throw
JSON
.
typeMismatch
(
index
,
object
,
"boolean"
);
* Removes and returns the value at {@code index}, or null if the array has no value
}
* at {@code index}.
return
result
;
* @param index the index of the value to remove
}
* @return the previous value at {@code index}
*/
/**
public
Object
remove
(
int
index
)
{
* Returns the value at {@code index} if it exists and is a boolean or can
if
(
index
<
0
||
index
>=
this
.
values
.
size
())
{
* be coerced to a boolean. Returns false otherwise.
return
null
;
*/
}
public
boolean
optBoolean
(
int
index
)
{
return
this
.
values
.
remove
(
index
);
return
optBoolean
(
index
,
false
);
}
}
/**
/**
* Returns the value at {@code index} if it exists and is a boolean or can
* Returns the value at {@code index} if it exists and is a boolean or can
* be coerced to a boolean.
* be coerced to a boolean. Returns {@code fallback} otherwise.
* @param index the index to get the value from
*/
* @return the value at {@code index}
public
boolean
optBoolean
(
int
index
,
boolean
fallback
)
{
* @throws JSONException if the value at {@code index} doesn't exist or
Object
object
=
opt
(
index
);
* cannot be coerced to a boolean.
Boolean
result
=
JSON
.
toBoolean
(
object
);
*/
return
result
!=
null
?
result
:
fallback
;
public
boolean
getBoolean
(
int
index
)
throws
JSONException
{
}
Object
object
=
get
(
index
);
Boolean
result
=
JSON
.
toBoolean
(
object
);
/**
if
(
result
==
null
)
{
* Returns the value at {@code index} if it exists and is a double or can
throw
JSON
.
typeMismatch
(
index
,
object
,
"boolean"
);
* be coerced to a double.
}
*
return
result
;
* @throws JSONException if the value at {@code index} doesn't exist or
}
* cannot be coerced to a double.
*/
/**
public
double
getDouble
(
int
index
)
throws
JSONException
{
* Returns the value at {@code index} if it exists and is a boolean or can
Object
object
=
get
(
index
);
* be coerced to a boolean. Returns false otherwise.
Double
result
=
JSON
.
toDouble
(
object
);
* @param index the index to get the value from
if
(
result
==
null
)
{
* @return the {@code value} or {@code false}
throw
JSON
.
typeMismatch
(
index
,
object
,
"double"
);
*/
}
public
boolean
optBoolean
(
int
index
)
{
return
result
;
return
optBoolean
(
index
,
false
);
}
}
/**
/**
* Returns the value at {@code index} if it exists and is a double or can
* Returns the value at {@code index} if it exists and is a boolean or can
* be coerced to a double. Returns {@code NaN} otherwise.
* be coerced to a boolean. Returns {@code fallback} otherwise.
*/
* @param index the index to get the value from
public
double
optDouble
(
int
index
)
{
* @param fallback the fallback value
return
optDouble
(
index
,
Double
.
NaN
);
* @return the value at {@code index} of {@code fallback}
}
*/
public
boolean
optBoolean
(
int
index
,
boolean
fallback
)
{
/**
Object
object
=
opt
(
index
);
* Returns the value at {@code index} if it exists and is a double or can
Boolean
result
=
JSON
.
toBoolean
(
object
);
* be coerced to a double. Returns {@code fallback} otherwise.
return
result
!=
null
?
result
:
fallback
;
*/
}
public
double
optDouble
(
int
index
,
double
fallback
)
{
Object
object
=
opt
(
index
);
/**
Double
result
=
JSON
.
toDouble
(
object
);
* Returns the value at {@code index} if it exists and is a double or can
return
result
!=
null
?
result
:
fallback
;
* be coerced to a double.
}
* @param index the index to get the value from
* @return the {@code value}
/**
* @throws JSONException if the value at {@code index} doesn't exist or
* Returns the value at {@code index} if it exists and is an int or
* cannot be coerced to a double.
* can be coerced to an int.
*/
*
public
double
getDouble
(
int
index
)
throws
JSONException
{
* @throws JSONException if the value at {@code index} doesn't exist or
Object
object
=
get
(
index
);
* cannot be coerced to a int.
Double
result
=
JSON
.
toDouble
(
object
);
*/
if
(
result
==
null
)
{
public
int
getInt
(
int
index
)
throws
JSONException
{
throw
JSON
.
typeMismatch
(
index
,
object
,
"double"
);
Object
object
=
get
(
index
);
}
Integer
result
=
JSON
.
toInteger
(
object
);
return
result
;
if
(
result
==
null
)
{
}
throw
JSON
.
typeMismatch
(
index
,
object
,
"int"
);
}
/**
return
result
;
* Returns the value at {@code index} if it exists and is a double or can
}
* be coerced to a double. Returns {@code NaN} otherwise.
* @param index the index to get the value from
/**
* @return the {@code value} or {@code NaN}
* Returns the value at {@code index} if it exists and is an int or
*/
* can be coerced to an int. Returns 0 otherwise.
public
double
optDouble
(
int
index
)
{
*/
return
optDouble
(
index
,
Double
.
NaN
);
public
int
optInt
(
int
index
)
{
}
return
optInt
(
index
,
0
);
}
/**
* Returns the value at {@code index} if it exists and is a double or can
/**
* be coerced to a double. Returns {@code fallback} otherwise.
* Returns the value at {@code index} if it exists and is an int or
* @param index the index to get the value from
* can be coerced to an int. Returns {@code fallback} otherwise.
* @param fallback the fallback value
*/
* @return the value at {@code index} of {@code fallback}
public
int
optInt
(
int
index
,
int
fallback
)
{
*/
Object
object
=
opt
(
index
);
public
double
optDouble
(
int
index
,
double
fallback
)
{
Integer
result
=
JSON
.
toInteger
(
object
);
Object
object
=
opt
(
index
);
return
result
!=
null
?
result
:
fallback
;
Double
result
=
JSON
.
toDouble
(
object
);
}
return
result
!=
null
?
result
:
fallback
;
}
/**
* Returns the value at {@code index} if it exists and is a long or
/**
* can be coerced to a long.
* Returns the value at {@code index} if it exists and is an int or
*
* can be coerced to an int.
* @throws JSONException if the value at {@code index} doesn't exist or
* @param index the index to get the value from
* cannot be coerced to a long.
* @return the {@code value}
*/
* @throws JSONException if the value at {@code index} doesn't exist or
public
long
getLong
(
int
index
)
throws
JSONException
{
* cannot be coerced to a int.
Object
object
=
get
(
index
);
*/
Long
result
=
JSON
.
toLong
(
object
);
public
int
getInt
(
int
index
)
throws
JSONException
{
if
(
result
==
null
)
{
Object
object
=
get
(
index
);
throw
JSON
.
typeMismatch
(
index
,
object
,
"long"
);
Integer
result
=
JSON
.
toInteger
(
object
);
}
if
(
result
==
null
)
{
return
result
;
throw
JSON
.
typeMismatch
(
index
,
object
,
"int"
);
}
}
return
result
;
/**
}
* Returns the value at {@code index} if it exists and is a long or
* can be coerced to a long. Returns 0 otherwise.
/**
*/
* Returns the value at {@code index} if it exists and is an int or
public
long
optLong
(
int
index
)
{
* can be coerced to an int. Returns 0 otherwise.
return
optLong
(
index
,
0L
);
* @param index the index to get the value from
}
* @return the {@code value} or {@code 0}
*/
/**
public
int
optInt
(
int
index
)
{
* Returns the value at {@code index} if it exists and is a long or
return
optInt
(
index
,
0
);
* can be coerced to a long. Returns {@code fallback} otherwise.
}
*/
public
long
optLong
(
int
index
,
long
fallback
)
{
/**
Object
object
=
opt
(
index
);
* Returns the value at {@code index} if it exists and is an int or
Long
result
=
JSON
.
toLong
(
object
);
* can be coerced to an int. Returns {@code fallback} otherwise.
return
result
!=
null
?
result
:
fallback
;
* @param index the index to get the value from
}
* @param fallback the fallback value
* @return the value at {@code index} of {@code fallback}
/**
*/
* Returns the value at {@code index} if it exists, coercing it if
public
int
optInt
(
int
index
,
int
fallback
)
{
* necessary.
Object
object
=
opt
(
index
);
*
Integer
result
=
JSON
.
toInteger
(
object
);
* @throws JSONException if no such value exists.
return
result
!=
null
?
result
:
fallback
;
*/
}
public
String
getString
(
int
index
)
throws
JSONException
{
Object
object
=
get
(
index
);
/**
String
result
=
JSON
.
toString
(
object
);
* Returns the value at {@code index} if it exists and is a long or
if
(
result
==
null
)
{
* can be coerced to a long.
throw
JSON
.
typeMismatch
(
index
,
object
,
"String"
);
* @param index the index to get the value from
}
* @return the {@code value}
return
result
;
*
}
* @throws JSONException if the value at {@code index} doesn't exist or
* cannot be coerced to a long.
/**
*/
* Returns the value at {@code index} if it exists, coercing it if
public
long
getLong
(
int
index
)
throws
JSONException
{
* necessary. Returns the empty string if no such value exists.
Object
object
=
get
(
index
);
*/
Long
result
=
JSON
.
toLong
(
object
);
public
String
optString
(
int
index
)
{
if
(
result
==
null
)
{
return
optString
(
index
,
""
);
throw
JSON
.
typeMismatch
(
index
,
object
,
"long"
);
}
}
return
result
;
/**
}
* Returns the value at {@code index} if it exists, coercing it if
* necessary. Returns {@code fallback} if no such value exists.
/**
*/
* Returns the value at {@code index} if it exists and is a long or
public
String
optString
(
int
index
,
String
fallback
)
{
* can be coerced to a long. Returns 0 otherwise.
Object
object
=
opt
(
index
);
* @param index the index to get the value from
String
result
=
JSON
.
toString
(
object
);
* @return the {@code value} or {@code 0}
return
result
!=
null
?
result
:
fallback
;
*/
}
public
long
optLong
(
int
index
)
{
return
optLong
(
index
,
0L
);
/**
}
* Returns the value at {@code index} if it exists and is a {@code
* JSONArray}.
/**
*
* Returns the value at {@code index} if it exists and is a long or
* @throws JSONException if the value doesn't exist or is not a {@code
* can be coerced to a long. Returns {@code fallback} otherwise.
* JSONArray}.
* @param index the index to get the value from
*/
* @param fallback the fallback value
public
JSONArray
getJSONArray
(
int
index
)
throws
JSONException
{
* @return the value at {@code index} of {@code fallback}
Object
object
=
get
(
index
);
*/
if
(
object
instanceof
JSONArray
)
{
public
long
optLong
(
int
index
,
long
fallback
)
{
return
(
JSONArray
)
object
;
Object
object
=
opt
(
index
);
}
else
{
Long
result
=
JSON
.
toLong
(
object
);
throw
JSON
.
typeMismatch
(
index
,
object
,
"JSONArray"
);
return
result
!=
null
?
result
:
fallback
;
}
}
}
/**
/**
* Returns the value at {@code index} if it exists, coercing it if
* Returns the value at {@code index} if it exists and is a {@code
* necessary.
* JSONArray}. Returns null otherwise.
* @param index the index to get the value from
*/
* @return the {@code value}
public
JSONArray
optJSONArray
(
int
index
)
{
* @throws JSONException if no such value exists.
Object
object
=
opt
(
index
);
*/
return
object
instanceof
JSONArray
?
(
JSONArray
)
object
:
null
;
public
String
getString
(
int
index
)
throws
JSONException
{
}
Object
object
=
get
(
index
);
String
result
=
JSON
.
toString
(
object
);
/**
if
(
result
==
null
)
{
* Returns the value at {@code index} if it exists and is a {@code
throw
JSON
.
typeMismatch
(
index
,
object
,
"String"
);
* JSONObject}.
}
*
return
result
;
* @throws JSONException if the value doesn't exist or is not a {@code
}
* JSONObject}.
*/
/**
public
JSONObject
getJSONObject
(
int
index
)
throws
JSONException
{
* Returns the value at {@code index} if it exists, coercing it if
Object
object
=
get
(
index
);
* necessary. Returns the empty string if no such value exists.
if
(
object
instanceof
JSONObject
)
{
* @param index the index to get the value from
return
(
JSONObject
)
object
;
* @return the {@code value} or an empty string
}
else
{
*/
throw
JSON
.
typeMismatch
(
index
,
object
,
"JSONObject"
);
public
String
optString
(
int
index
)
{
}
return
optString
(
index
,
""
);
}
}
/**
/**
* Returns the value at {@code index} if it exists and is a {@code
* Returns the value at {@code index} if it exists, coercing it if
* JSONObject}. Returns null otherwise.
* necessary. Returns {@code fallback} if no such value exists.
*/
* @param index the index to get the value from
public
JSONObject
optJSONObject
(
int
index
)
{
* @param fallback the fallback value
Object
object
=
opt
(
index
);
* @return the value at {@code index} of {@code fallback}
return
object
instanceof
JSONObject
?
(
JSONObject
)
object
:
null
;
*/
}
public
String
optString
(
int
index
,
String
fallback
)
{
Object
object
=
opt
(
index
);
/**
String
result
=
JSON
.
toString
(
object
);
* Returns a new object whose values are the values in this array, and whose
return
result
!=
null
?
result
:
fallback
;
* names are the values in {@code names}. Names and values are paired up by
}
* index from 0 through to the shorter array's length. Names that are not
* strings will be coerced to strings. This method returns null if either
/**
* array is empty.
* Returns the value at {@code index} if it exists and is a {@code
*/
* JSONArray}.
public
JSONObject
toJSONObject
(
JSONArray
names
)
throws
JSONException
{
* @param index the index to get the value from
JSONObject
result
=
new
JSONObject
();
* @return the array at {@code index}
int
length
=
Math
.
min
(
names
.
length
(),
values
.
size
());
* @throws JSONException if the value doesn't exist or is not a {@code
if
(
length
==
0
)
{
* JSONArray}.
return
null
;
*/
}
public
JSONArray
getJSONArray
(
int
index
)
throws
JSONException
{
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
Object
object
=
get
(
index
);
String
name
=
JSON
.
toString
(
names
.
opt
(
i
));
if
(
object
instanceof
JSONArray
)
{
result
.
put
(
name
,
opt
(
i
));
return
(
JSONArray
)
object
;
}
}
return
result
;
else
{
}
throw
JSON
.
typeMismatch
(
index
,
object
,
"JSONArray"
);
}
/**
}
* Returns a new string by alternating this array's values with {@code
* separator}. This array's string values are quoted and have their special
/**
* characters escaped. For example, the array containing the strings '12"
* Returns the value at {@code index} if it exists and is a {@code
* pizza', 'taco' and 'soda' joined on '+' returns this:
* JSONArray}. Returns null otherwise.
* <pre>"12\" pizza"+"taco"+"soda"</pre>
* @param index the index to get the value from
*/
* @return the array at {@code index} or {@code null}
public
String
join
(
String
separator
)
throws
JSONException
{
*/
JSONStringer
stringer
=
new
JSONStringer
();
public
JSONArray
optJSONArray
(
int
index
)
{
stringer
.
open
(
JSONStringer
.
Scope
.
NULL
,
""
);
Object
object
=
opt
(
index
);
for
(
int
i
=
0
,
size
=
values
.
size
();
i
<
size
;
i
++)
{
return
object
instanceof
JSONArray
?
(
JSONArray
)
object
:
null
;
if
(
i
>
0
)
{
}
stringer
.
out
.
append
(
separator
);
}
/**
stringer
.
value
(
values
.
get
(
i
));
* Returns the value at {@code index} if it exists and is a {@code
}
* JSONObject}.
stringer
.
close
(
JSONStringer
.
Scope
.
NULL
,
JSONStringer
.
Scope
.
NULL
,
""
);
* @param index the index to get the value from
return
stringer
.
out
.
toString
();
* @return the object at {@code index}
}
* @throws JSONException if the value doesn't exist or is not a {@code
* JSONObject}.
/**
*/
* Encodes this array as a compact JSON string, such as:
public
JSONObject
getJSONObject
(
int
index
)
throws
JSONException
{
* <pre>[94043,90210]</pre>
Object
object
=
get
(
index
);
*/
if
(
object
instanceof
JSONObject
)
{
@Override
public
String
toString
()
{
return
(
JSONObject
)
object
;
try
{
}
JSONStringer
stringer
=
new
JSONStringer
();
else
{
writeTo
(
stringer
);
throw
JSON
.
typeMismatch
(
index
,
object
,
"JSONObject"
);
return
stringer
.
toString
();
}
}
catch
(
JSONException
e
)
{
}
return
null
;
}
/**
}
* Returns the value at {@code index} if it exists and is a {@code
* JSONObject}. Returns null otherwise.
/**
* @param index the index to get the value from
* Encodes this array as a human readable JSON string for debugging, such
* @return the object at {@code index} or {@code null}
* as:
*/
* <pre>
public
JSONObject
optJSONObject
(
int
index
)
{
* [
Object
object
=
opt
(
index
);
* 94043,
return
object
instanceof
JSONObject
?
(
JSONObject
)
object
:
null
;
* 90210
}
* ]</pre>
*
/**
* @param indentSpaces the number of spaces to indent for each level of
* Returns a new object whose values are the values in this array, and whose
* nesting.
* names are the values in {@code names}. Names and values are paired up by
*/
* index from 0 through to the shorter array's length. Names that are not
public
String
toString
(
int
indentSpaces
)
throws
JSONException
{
* strings will be coerced to strings. This method returns null if either
JSONStringer
stringer
=
new
JSONStringer
(
indentSpaces
);
* array is empty.
writeTo
(
stringer
);
* @param names the property names
return
stringer
.
toString
();
* @return a json object
}
* @throws JSONException if processing of json failed
*/
void
writeTo
(
JSONStringer
stringer
)
throws
JSONException
{
public
JSONObject
toJSONObject
(
JSONArray
names
)
throws
JSONException
{
stringer
.
array
();
JSONObject
result
=
new
JSONObject
();
for
(
Object
value
:
values
)
{
int
length
=
Math
.
min
(
names
.
length
(),
this
.
values
.
size
());
stringer
.
value
(
value
);
if
(
length
==
0
)
{
}
return
null
;
stringer
.
endArray
();
}
}
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
String
name
=
JSON
.
toString
(
names
.
opt
(
i
));
@Override
public
boolean
equals
(
Object
o
)
{
result
.
put
(
name
,
opt
(
i
));
return
o
instanceof
JSONArray
&&
((
JSONArray
)
o
).
values
.
equals
(
values
);
}
}
return
result
;
}
@Override
public
int
hashCode
()
{
// diverge from the original, which doesn't implement hashCode
/**
return
values
.
hashCode
();
* Returns a new string by alternating this array's values with {@code
}
* separator}. This array's string values are quoted and have their special
* characters escaped. For example, the array containing the strings '12"
* pizza', 'taco' and 'soda' joined on '+' returns this:
* <pre>"12\" pizza"+"taco"+"soda"</pre>
* @param separator the separator to use
* @return the joined value
* @throws JSONException if processing of json failed
*/
public
String
join
(
String
separator
)
throws
JSONException
{
JSONStringer
stringer
=
new
JSONStringer
();
stringer
.
open
(
JSONStringer
.
Scope
.
NULL
,
""
);
for
(
int
i
=
0
,
size
=
this
.
values
.
size
();
i
<
size
;
i
++)
{
if
(
i
>
0
)
{
stringer
.
out
.
append
(
separator
);
}
stringer
.
value
(
this
.
values
.
get
(
i
));
}
stringer
.
close
(
JSONStringer
.
Scope
.
NULL
,
JSONStringer
.
Scope
.
NULL
,
""
);
return
stringer
.
out
.
toString
();
}
/**
* Encodes this array as a compact JSON string, such as:
* <pre>[94043,90210]</pre>
* @return a compact JSON string representation of this array
*/
@Override
public
String
toString
()
{
try
{
JSONStringer
stringer
=
new
JSONStringer
();
writeTo
(
stringer
);
return
stringer
.
toString
();
}
catch
(
JSONException
e
)
{
return
null
;
}
}
/**
* Encodes this array as a human readable JSON string for debugging, such
* as:
* <pre>
* [
* 94043,
* 90210
* ]</pre>
*
* @param indentSpaces the number of spaces to indent for each level of
* nesting.
* @return a human readable JSON string of this array
* @throws JSONException if processing of json failed
*/
public
String
toString
(
int
indentSpaces
)
throws
JSONException
{
JSONStringer
stringer
=
new
JSONStringer
(
indentSpaces
);
writeTo
(
stringer
);
return
stringer
.
toString
();
}
void
writeTo
(
JSONStringer
stringer
)
throws
JSONException
{
stringer
.
array
();
for
(
Object
value
:
this
.
values
)
{
stringer
.
value
(
value
);
}
stringer
.
endArray
();
}
@Override
public
boolean
equals
(
Object
o
)
{
return
o
instanceof
JSONArray
&&
((
JSONArray
)
o
).
values
.
equals
(
this
.
values
);
}
@Override
public
int
hashCode
()
{
// diverge from the original, which doesn't implement hashCode
return
this
.
values
.
hashCode
();
}
}
}
spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/json/JSONException.java
View file @
4568f14c
...
@@ -43,7 +43,7 @@ package org.springframework.boot.configurationprocessor.json;
...
@@ -43,7 +43,7 @@ package org.springframework.boot.configurationprocessor.json;
*/
*/
public
class
JSONException
extends
Exception
{
public
class
JSONException
extends
Exception
{
public
JSONException
(
String
s
)
{
public
JSONException
(
String
s
)
{
super
(
s
);
super
(
s
);
}
}
}
}
spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/json/JSONObject.java
View file @
4568f14c
...
@@ -78,698 +78,792 @@ import java.util.Map;
...
@@ -78,698 +78,792 @@ import java.util.Map;
*/
*/
public
class
JSONObject
{
public
class
JSONObject
{
private
static
final
Double
NEGATIVE_ZERO
=
-
0
d
;
private
static
final
Double
NEGATIVE_ZERO
=
-
0
d
;
/**
/**
* A sentinel value used to explicitly define a name with no value. Unlike
* A sentinel value used to explicitly define a name with no value. Unlike
* {@code null}, names with this value:
* {@code null}, names with this value:
* <ul>
* <ul>
* <li>show up in the {@link #names} array
* <li>show up in the {@link #names} array
* <li>show up in the {@link #keys} iterator
* <li>show up in the {@link #keys} iterator
* <li>return {@code true} for {@link #has(String)}
* <li>return {@code true} for {@link #has(String)}
* <li>do not throw on {@link #get(String)}
* <li>do not throw on {@link #get(String)}
* <li>are included in the encoded JSON string.
* <li>are included in the encoded JSON string.
* </ul>
* </ul>
*
*
* <p>This value violates the general contract of {@link Object#equals} by
* <p>This value violates the general contract of {@link Object#equals} by
* returning true when compared to {@code null}. Its {@link #toString}
* returning true when compared to {@code null}. Its {@link #toString}
* method returns "null".
* method returns "null".
*/
*/
public
static
final
Object
NULL
=
new
Object
()
{
public
static
final
Object
NULL
=
new
Object
()
{
@Override
public
boolean
equals
(
Object
o
)
{
@Override
return
o
==
this
||
o
==
null
;
// API specifies this broken equals implementation
public
boolean
equals
(
Object
o
)
{
}
return
o
==
this
||
o
==
null
;
// API specifies this broken equals implementation
@Override
public
String
toString
()
{
}
return
"null"
;
}
@Override
};
public
String
toString
()
{
return
"null"
;
private
final
Map
<
String
,
Object
>
nameValuePairs
;
}
};
/**
* Creates a {@code JSONObject} with no name/value mappings.
private
final
Map
<
String
,
Object
>
nameValuePairs
;
*/
public
JSONObject
()
{
/**
nameValuePairs
=
new
HashMap
<
String
,
Object
>();
* Creates a {@code JSONObject} with no name/value mappings.
}
*/
public
JSONObject
()
{
/**
this
.
nameValuePairs
=
new
HashMap
<
String
,
Object
>();
* Creates a new {@code JSONObject} by copying all name/value mappings from
}
* the given map.
*
/**
* @param copyFrom a map whose keys are of type {@link String} and whose
* Creates a new {@code JSONObject} by copying all name/value mappings from
* values are of supported types.
* the given map.
* @throws NullPointerException if any of the map's keys are null.
*
*/
* @param copyFrom a map whose keys are of type {@link String} and whose
/* (accept a raw type for API compatibility) */
* values are of supported types.
public
JSONObject
(
Map
copyFrom
)
{
* @throws NullPointerException if any of the map's keys are null.
this
();
*/
Map
<?,
?>
contentsTyped
=
(
Map
<?,
?>)
copyFrom
;
/* (accept a raw type for API compatibility) */
for
(
Map
.
Entry
<?,
?>
entry
:
contentsTyped
.
entrySet
())
{
public
JSONObject
(
Map
copyFrom
)
{
/*
this
();
* Deviate from the original by checking that keys are non-null and
Map
<?,
?>
contentsTyped
=
(
Map
<?,
?>)
copyFrom
;
* of the proper type. (We still defer validating the values).
for
(
Map
.
Entry
<?,
?>
entry
:
contentsTyped
.
entrySet
())
{
*/
/*
String
key
=
(
String
)
entry
.
getKey
();
* Deviate from the original by checking that keys are non-null and
if
(
key
==
null
)
{
* of the proper type. (We still defer validating the values).
throw
new
NullPointerException
(
"key == null"
);
*/
}
String
key
=
(
String
)
entry
.
getKey
();
nameValuePairs
.
put
(
key
,
wrap
(
entry
.
getValue
()));
if
(
key
==
null
)
{
}
throw
new
NullPointerException
(
"key == null"
);
}
}
this
.
nameValuePairs
.
put
(
key
,
wrap
(
entry
.
getValue
()));
/**
}
* Creates a new {@code JSONObject} with name/value mappings from the next
}
* object in the tokener.
*
/**
* @param readFrom a tokener whose nextValue() method will yield a
* Creates a new {@code JSONObject} with name/value mappings from the next
* {@code JSONObject}.
* object in the tokener.
* @throws JSONException if the parse fails or doesn't yield a
*
* {@code JSONObject}.
* @param readFrom a tokener whose nextValue() method will yield a
*/
* {@code JSONObject}.
public
JSONObject
(
JSONTokener
readFrom
)
throws
JSONException
{
* @throws JSONException if the parse fails or doesn't yield a
/*
* {@code JSONObject}.
* Getting the parser to populate this could get tricky. Instead, just
*/
* parse to temporary JSONObject and then steal the data from that.
public
JSONObject
(
JSONTokener
readFrom
)
throws
JSONException
{
*/
/*
Object
object
=
readFrom
.
nextValue
();
* Getting the parser to populate this could get tricky. Instead, just
if
(
object
instanceof
JSONObject
)
{
* parse to temporary JSONObject and then steal the data from that.
this
.
nameValuePairs
=
((
JSONObject
)
object
).
nameValuePairs
;
*/
}
else
{
Object
object
=
readFrom
.
nextValue
();
throw
JSON
.
typeMismatch
(
object
,
"JSONObject"
);
if
(
object
instanceof
JSONObject
)
{
}
this
.
nameValuePairs
=
((
JSONObject
)
object
).
nameValuePairs
;
}
}
else
{
/**
throw
JSON
.
typeMismatch
(
object
,
"JSONObject"
);
* Creates a new {@code JSONObject} with name/value mappings from the JSON
}
* string.
}
*
* @param json a JSON-encoded string containing an object.
/**
* @throws JSONException if the parse fails or doesn't yield a {@code
* Creates a new {@code JSONObject} with name/value mappings from the JSON
* JSONObject}.
* string.
*/
*
public
JSONObject
(
String
json
)
throws
JSONException
{
* @param json a JSON-encoded string containing an object.
this
(
new
JSONTokener
(
json
));
* @throws JSONException if the parse fails or doesn't yield a {@code
}
* JSONObject}.
*/
/**
public
JSONObject
(
String
json
)
throws
JSONException
{
* Creates a new {@code JSONObject} by copying mappings for the listed names
this
(
new
JSONTokener
(
json
));
* from the given object. Names that aren't present in {@code copyFrom} will
}
* be skipped.
*/
/**
public
JSONObject
(
JSONObject
copyFrom
,
String
[]
names
)
throws
JSONException
{
* Creates a new {@code JSONObject} by copying mappings for the listed names
this
();
* from the given object. Names that aren't present in {@code copyFrom} will
for
(
String
name
:
names
)
{
* be skipped.
Object
value
=
copyFrom
.
opt
(
name
);
* @param copyFrom the source
if
(
value
!=
null
)
{
* @param names the property names
nameValuePairs
.
put
(
name
,
value
);
* @throws JSONException if an error occurs
}
*/
}
public
JSONObject
(
JSONObject
copyFrom
,
String
[]
names
)
throws
JSONException
{
}
this
();
for
(
String
name
:
names
)
{
/**
Object
value
=
copyFrom
.
opt
(
name
);
* Returns the number of name/value mappings in this object.
if
(
value
!=
null
)
{
*/
this
.
nameValuePairs
.
put
(
name
,
value
);
public
int
length
()
{
}
return
nameValuePairs
.
size
();
}
}
}
/**
/**
* Maps {@code name} to {@code value}, clobbering any existing name/value
* Returns the number of name/value mappings in this object.
* mapping with the same name.
* @return the number of name/value mappings in this object
*
*/
* @return this object.
public
int
length
()
{
*/
return
this
.
nameValuePairs
.
size
();
public
JSONObject
put
(
String
name
,
boolean
value
)
throws
JSONException
{
}
nameValuePairs
.
put
(
checkName
(
name
),
value
);
return
this
;
/**
}
* Maps {@code name} to {@code value}, clobbering any existing name/value
* mapping with the same name.
/**
* @param name the name of the property
* Maps {@code name} to {@code value}, clobbering any existing name/value
* @param value the value of the property
* mapping with the same name.
* @return this object.
*
* @throws JSONException if an error occurs
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
*/
* {@link Double#isInfinite() infinities}.
public
JSONObject
put
(
String
name
,
boolean
value
)
throws
JSONException
{
* @return this object.
this
.
nameValuePairs
.
put
(
checkName
(
name
),
value
);
*/
return
this
;
public
JSONObject
put
(
String
name
,
double
value
)
throws
JSONException
{
}
nameValuePairs
.
put
(
checkName
(
name
),
JSON
.
checkDouble
(
value
));
return
this
;
/**
}
* Maps {@code name} to {@code value}, clobbering any existing name/value
* mapping with the same name.
/**
*
* Maps {@code name} to {@code value}, clobbering any existing name/value
* @param name the name of the property
* mapping with the same name.
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
*
* {@link Double#isInfinite() infinities}.
* @return this object.
* @return this object.
*/
* @throws JSONException if an error occurs
public
JSONObject
put
(
String
name
,
int
value
)
throws
JSONException
{
*/
nameValuePairs
.
put
(
checkName
(
name
),
value
);
public
JSONObject
put
(
String
name
,
double
value
)
throws
JSONException
{
return
this
;
this
.
nameValuePairs
.
put
(
checkName
(
name
),
JSON
.
checkDouble
(
value
));
}
return
this
;
}
/**
* Maps {@code name} to {@code value}, clobbering any existing name/value
/**
* mapping with the same name.
* Maps {@code name} to {@code value}, clobbering any existing name/value
*
* mapping with the same name.
* @return this object.
*
*/
* @param name the name of the property
public
JSONObject
put
(
String
name
,
long
value
)
throws
JSONException
{
* @param value the value of the property
nameValuePairs
.
put
(
checkName
(
name
),
value
);
* @return this object.
return
this
;
* @throws JSONException if an error occurs
}
*/
public
JSONObject
put
(
String
name
,
int
value
)
throws
JSONException
{
/**
this
.
nameValuePairs
.
put
(
checkName
(
name
),
value
);
* Maps {@code name} to {@code value}, clobbering any existing name/value
return
this
;
* mapping with the same name. If the value is {@code null}, any existing
}
* mapping for {@code name} is removed.
*
/**
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Maps {@code name} to {@code value}, clobbering any existing name/value
* Integer, Long, Double, {@link #NULL}, or {@code null}. May not be
* mapping with the same name.
* {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
*
* infinities}.
* @param name the name of the property
* @return this object.
* @param value the value of the property
*/
* @return this object.
public
JSONObject
put
(
String
name
,
Object
value
)
throws
JSONException
{
* @throws JSONException if an error occurs
if
(
value
==
null
)
{
*/
nameValuePairs
.
remove
(
name
);
public
JSONObject
put
(
String
name
,
long
value
)
throws
JSONException
{
return
this
;
this
.
nameValuePairs
.
put
(
checkName
(
name
),
value
);
}
return
this
;
if
(
value
instanceof
Number
)
{
}
// deviate from the original by checking all Numbers, not just floats & doubles
JSON
.
checkDouble
(((
Number
)
value
).
doubleValue
());
/**
}
* Maps {@code name} to {@code value}, clobbering any existing name/value
nameValuePairs
.
put
(
checkName
(
name
),
value
);
* mapping with the same name. If the value is {@code null}, any existing
return
this
;
* mapping for {@code name} is removed.
}
*
* @param name the name of the property
/**
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Equivalent to {@code put(name, value)} when both parameters are non-null;
* Integer, Long, Double, {@link #NULL}, or {@code null}. May not be
* does nothing otherwise.
* {@link Double#isNaN() NaNs} or {@link Double#isInfinite()
*/
* infinities}.
public
JSONObject
putOpt
(
String
name
,
Object
value
)
throws
JSONException
{
* @return this object.
if
(
name
==
null
||
value
==
null
)
{
* @throws JSONException if an error occurs
return
this
;
*/
}
public
JSONObject
put
(
String
name
,
Object
value
)
throws
JSONException
{
return
put
(
name
,
value
);
if
(
value
==
null
)
{
}
this
.
nameValuePairs
.
remove
(
name
);
return
this
;
/**
}
* Appends {@code value} to the array already mapped to {@code name}. If
if
(
value
instanceof
Number
)
{
* this object has no mapping for {@code name}, this inserts a new mapping.
// deviate from the original by checking all Numbers, not just floats & doubles
* If the mapping exists but its value is not an array, the existing
JSON
.
checkDouble
(((
Number
)
value
).
doubleValue
());
* and new values are inserted in order into a new array which is itself
}
* mapped to {@code name}. In aggregate, this allows values to be added to a
this
.
nameValuePairs
.
put
(
checkName
(
name
),
value
);
* mapping one at a time.
return
this
;
*
}
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double, {@link #NULL} or null. May not be {@link
/**
* Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}.
* Equivalent to {@code put(name, value)} when both parameters are non-null;
*/
* does nothing otherwise.
public
JSONObject
accumulate
(
String
name
,
Object
value
)
throws
JSONException
{
* @param name the name of the property
Object
current
=
nameValuePairs
.
get
(
checkName
(
name
));
* @param value the value of the property
if
(
current
==
null
)
{
* @return this object.
return
put
(
name
,
value
);
* @throws JSONException if an error occurs
}
*/
public
JSONObject
putOpt
(
String
name
,
Object
value
)
throws
JSONException
{
// check in accumulate, since array.put(Object) doesn't do any checking
if
(
name
==
null
||
value
==
null
)
{
if
(
value
instanceof
Number
)
{
return
this
;
JSON
.
checkDouble
(((
Number
)
value
).
doubleValue
());
}
}
return
put
(
name
,
value
);
}
if
(
current
instanceof
JSONArray
)
{
JSONArray
array
=
(
JSONArray
)
current
;
/**
array
.
put
(
value
);
* Appends {@code value} to the array already mapped to {@code name}. If
}
else
{
* this object has no mapping for {@code name}, this inserts a new mapping.
JSONArray
array
=
new
JSONArray
();
* If the mapping exists but its value is not an array, the existing
array
.
put
(
current
);
* and new values are inserted in order into a new array which is itself
array
.
put
(
value
);
* mapped to {@code name}. In aggregate, this allows values to be added to a
nameValuePairs
.
put
(
name
,
array
);
* mapping one at a time.
}
*
return
this
;
* @param name the name of the property
}
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double, {@link #NULL} or null. May not be {@link
String
checkName
(
String
name
)
throws
JSONException
{
* Double#isNaN() NaNs} or {@link Double#isInfinite() infinities}.
if
(
name
==
null
)
{
* @return this object.
throw
new
JSONException
(
"Names must be non-null"
);
* @throws JSONException if an error occurs
}
*/
return
name
;
public
JSONObject
accumulate
(
String
name
,
Object
value
)
throws
JSONException
{
}
Object
current
=
this
.
nameValuePairs
.
get
(
checkName
(
name
));
if
(
current
==
null
)
{
/**
return
put
(
name
,
value
);
* Removes the named mapping if it exists; does nothing otherwise.
}
*
* @return the value previously mapped by {@code name}, or null if there was
// check in accumulate, since array.put(Object) doesn't do any checking
* no such mapping.
if
(
value
instanceof
Number
)
{
*/
JSON
.
checkDouble
(((
Number
)
value
).
doubleValue
());
public
Object
remove
(
String
name
)
{
}
return
nameValuePairs
.
remove
(
name
);
}
if
(
current
instanceof
JSONArray
)
{
JSONArray
array
=
(
JSONArray
)
current
;
/**
array
.
put
(
value
);
* Returns true if this object has no mapping for {@code name} or if it has
}
* a mapping whose value is {@link #NULL}.
else
{
*/
JSONArray
array
=
new
JSONArray
();
public
boolean
isNull
(
String
name
)
{
array
.
put
(
current
);
Object
value
=
nameValuePairs
.
get
(
name
);
array
.
put
(
value
);
return
value
==
null
||
value
==
NULL
;
this
.
nameValuePairs
.
put
(
name
,
array
);
}
}
return
this
;
/**
}
* Returns true if this object has a mapping for {@code name}. The mapping
* may be {@link #NULL}.
String
checkName
(
String
name
)
throws
JSONException
{
*/
if
(
name
==
null
)
{
public
boolean
has
(
String
name
)
{
throw
new
JSONException
(
"Names must be non-null"
);
return
nameValuePairs
.
containsKey
(
name
);
}
}
return
name
;
}
/**
* Returns the value mapped by {@code name}.
/**
*
* Removes the named mapping if it exists; does nothing otherwise.
* @throws JSONException if no such mapping exists.
*
*/
* @param name the name of the property
public
Object
get
(
String
name
)
throws
JSONException
{
* @return the value previously mapped by {@code name}, or null if there was
Object
result
=
nameValuePairs
.
get
(
name
);
* no such mapping.
if
(
result
==
null
)
{
*/
throw
new
JSONException
(
"No value for "
+
name
);
public
Object
remove
(
String
name
)
{
}
return
this
.
nameValuePairs
.
remove
(
name
);
return
result
;
}
}
/**
/**
* Returns true if this object has no mapping for {@code name} or if it has
* Returns the value mapped by {@code name}, or null if no such mapping
* a mapping whose value is {@link #NULL}.
* exists.
* @param name the name of the property
*/
* @return true if this object has no mapping for {@code name}
public
Object
opt
(
String
name
)
{
*/
return
nameValuePairs
.
get
(
name
);
public
boolean
isNull
(
String
name
)
{
}
Object
value
=
this
.
nameValuePairs
.
get
(
name
);
return
value
==
null
||
value
==
NULL
;
/**
}
* Returns the value mapped by {@code name} if it exists and is a boolean or
* can be coerced to a boolean.
/**
*
* Returns true if this object has a mapping for {@code name}. The mapping
* @throws JSONException if the mapping doesn't exist or cannot be coerced
* may be {@link #NULL}.
* to a boolean.
* @param name the name of the property
*/
* @return true if this object has a mapping for {@code name}
public
boolean
getBoolean
(
String
name
)
throws
JSONException
{
*/
Object
object
=
get
(
name
);
public
boolean
has
(
String
name
)
{
Boolean
result
=
JSON
.
toBoolean
(
object
);
return
this
.
nameValuePairs
.
containsKey
(
name
);
if
(
result
==
null
)
{
}
throw
JSON
.
typeMismatch
(
name
,
object
,
"boolean"
);
}
/**
return
result
;
* Returns the value mapped by {@code name}.
}
* @param name the name of the property
* @return the value
/**
* @throws JSONException if no such mapping exists.
* Returns the value mapped by {@code name} if it exists and is a boolean or
*/
* can be coerced to a boolean. Returns false otherwise.
public
Object
get
(
String
name
)
throws
JSONException
{
*/
Object
result
=
this
.
nameValuePairs
.
get
(
name
);
public
boolean
optBoolean
(
String
name
)
{
if
(
result
==
null
)
{
return
optBoolean
(
name
,
false
);
throw
new
JSONException
(
"No value for "
+
name
);
}
}
return
result
;
/**
}
* Returns the value mapped by {@code name} if it exists and is a boolean or
* can be coerced to a boolean. Returns {@code fallback} otherwise.
/**
*/
* Returns the value mapped by {@code name}, or null if no such mapping
public
boolean
optBoolean
(
String
name
,
boolean
fallback
)
{
* exists.
Object
object
=
opt
(
name
);
* @param name the name of the property
Boolean
result
=
JSON
.
toBoolean
(
object
);
* @return the value or {@code null}
return
result
!=
null
?
result
:
fallback
;
*/
}
public
Object
opt
(
String
name
)
{
return
this
.
nameValuePairs
.
get
(
name
);
/**
}
* Returns the value mapped by {@code name} if it exists and is a double or
* can be coerced to a double.
/**
*
* Returns the value mapped by {@code name} if it exists and is a boolean or
* @throws JSONException if the mapping doesn't exist or cannot be coerced
* can be coerced to a boolean.
* to a double.
*
*/
* @param name the name of the property
public
double
getDouble
(
String
name
)
throws
JSONException
{
* @return the value
Object
object
=
get
(
name
);
* @throws JSONException if the mapping doesn't exist or cannot be coerced
Double
result
=
JSON
.
toDouble
(
object
);
* to a boolean.
if
(
result
==
null
)
{
*/
throw
JSON
.
typeMismatch
(
name
,
object
,
"double"
);
public
boolean
getBoolean
(
String
name
)
throws
JSONException
{
}
Object
object
=
get
(
name
);
return
result
;
Boolean
result
=
JSON
.
toBoolean
(
object
);
}
if
(
result
==
null
)
{
throw
JSON
.
typeMismatch
(
name
,
object
,
"boolean"
);
/**
}
* Returns the value mapped by {@code name} if it exists and is a double or
return
result
;
* can be coerced to a double. Returns {@code NaN} otherwise.
}
*/
public
double
optDouble
(
String
name
)
{
/**
return
optDouble
(
name
,
Double
.
NaN
);
* Returns the value mapped by {@code name} if it exists and is a boolean or
}
* can be coerced to a boolean. Returns false otherwise.
* @param name the name of the property
/**
* @return the value or {@code null}
* Returns the value mapped by {@code name} if it exists and is a double or
*/
* can be coerced to a double. Returns {@code fallback} otherwise.
public
boolean
optBoolean
(
String
name
)
{
*/
return
optBoolean
(
name
,
false
);
public
double
optDouble
(
String
name
,
double
fallback
)
{
}
Object
object
=
opt
(
name
);
Double
result
=
JSON
.
toDouble
(
object
);
/**
return
result
!=
null
?
result
:
fallback
;
* Returns the value mapped by {@code name} if it exists and is a boolean or
}
* can be coerced to a boolean. Returns {@code fallback} otherwise.
* @param name the name of the property
/**
* @param fallback a fallback value
* Returns the value mapped by {@code name} if it exists and is an int or
* @return the value or {@code fallback}
* can be coerced to an int.
*/
*
public
boolean
optBoolean
(
String
name
,
boolean
fallback
)
{
* @throws JSONException if the mapping doesn't exist or cannot be coerced
Object
object
=
opt
(
name
);
* to an int.
Boolean
result
=
JSON
.
toBoolean
(
object
);
*/
return
result
!=
null
?
result
:
fallback
;
public
int
getInt
(
String
name
)
throws
JSONException
{
}
Object
object
=
get
(
name
);
Integer
result
=
JSON
.
toInteger
(
object
);
/**
if
(
result
==
null
)
{
* Returns the value mapped by {@code name} if it exists and is a double or
throw
JSON
.
typeMismatch
(
name
,
object
,
"int"
);
* can be coerced to a double.
}
*
return
result
;
* @param name the name of the property
}
* @return the value
* @throws JSONException if the mapping doesn't exist or cannot be coerced
/**
* to a double.
* Returns the value mapped by {@code name} if it exists and is an int or
*/
* can be coerced to an int. Returns 0 otherwise.
public
double
getDouble
(
String
name
)
throws
JSONException
{
*/
Object
object
=
get
(
name
);
public
int
optInt
(
String
name
)
{
Double
result
=
JSON
.
toDouble
(
object
);
return
optInt
(
name
,
0
);
if
(
result
==
null
)
{
}
throw
JSON
.
typeMismatch
(
name
,
object
,
"double"
);
}
/**
return
result
;
* Returns the value mapped by {@code name} if it exists and is an int or
}
* can be coerced to an int. Returns {@code fallback} otherwise.
*/
/**
public
int
optInt
(
String
name
,
int
fallback
)
{
* Returns the value mapped by {@code name} if it exists and is a double or
Object
object
=
opt
(
name
);
* can be coerced to a double. Returns {@code NaN} otherwise.
Integer
result
=
JSON
.
toInteger
(
object
);
* @param name the name of the property
return
result
!=
null
?
result
:
fallback
;
* @return the value or {@code NaN}
}
*/
public
double
optDouble
(
String
name
)
{
/**
return
optDouble
(
name
,
Double
.
NaN
);
* Returns the value mapped by {@code name} if it exists and is a long or
}
* can be coerced to a long. Note that JSON represents numbers as doubles,
* so this is <a href="#lossy">lossy</a>; use strings to transfer numbers via JSON.
/**
*
* Returns the value mapped by {@code name} if it exists and is a double or
* @throws JSONException if the mapping doesn't exist or cannot be coerced
* can be coerced to a double. Returns {@code fallback} otherwise.
* to a long.
* @param name the name of the property
*/
* @param fallback a fallback value
public
long
getLong
(
String
name
)
throws
JSONException
{
* @return the value or {@code fallback}
Object
object
=
get
(
name
);
*/
Long
result
=
JSON
.
toLong
(
object
);
public
double
optDouble
(
String
name
,
double
fallback
)
{
if
(
result
==
null
)
{
Object
object
=
opt
(
name
);
throw
JSON
.
typeMismatch
(
name
,
object
,
"long"
);
Double
result
=
JSON
.
toDouble
(
object
);
}
return
result
!=
null
?
result
:
fallback
;
return
result
;
}
}
/**
/**
* Returns the value mapped by {@code name} if it exists and is an int or
* Returns the value mapped by {@code name} if it exists and is a long or
* can be coerced to an int.
* can be coerced to a long. Returns 0 otherwise. Note that JSON represents numbers as doubles,
* @param name the name of the property
* so this is <a href="#lossy">lossy</a>; use strings to transfer numbers via JSON.
* @return the value
*/
* @throws JSONException if the mapping doesn't exist or cannot be coerced
public
long
optLong
(
String
name
)
{
* to an int.
return
optLong
(
name
,
0L
);
*/
}
public
int
getInt
(
String
name
)
throws
JSONException
{
Object
object
=
get
(
name
);
/**
Integer
result
=
JSON
.
toInteger
(
object
);
* Returns the value mapped by {@code name} if it exists and is a long or
if
(
result
==
null
)
{
* can be coerced to a long. Returns {@code fallback} otherwise. Note that JSON represents
throw
JSON
.
typeMismatch
(
name
,
object
,
"int"
);
* numbers as doubles, so this is <a href="#lossy">lossy</a>; use strings to transfer
}
* numbers via JSON.
return
result
;
*/
}
public
long
optLong
(
String
name
,
long
fallback
)
{
Object
object
=
opt
(
name
);
/**
Long
result
=
JSON
.
toLong
(
object
);
* Returns the value mapped by {@code name} if it exists and is an int or
return
result
!=
null
?
result
:
fallback
;
* can be coerced to an int. Returns 0 otherwise.
}
* @param name the name of the property
* @return the value of {@code 0}
/**
*/
* Returns the value mapped by {@code name} if it exists, coercing it if
public
int
optInt
(
String
name
)
{
* necessary.
return
optInt
(
name
,
0
);
*
}
* @throws JSONException if no such mapping exists.
*/
/**
public
String
getString
(
String
name
)
throws
JSONException
{
* Returns the value mapped by {@code name} if it exists and is an int or
Object
object
=
get
(
name
);
* can be coerced to an int. Returns {@code fallback} otherwise.
String
result
=
JSON
.
toString
(
object
);
* @param name the name of the property
if
(
result
==
null
)
{
* @param fallback a fallback value
throw
JSON
.
typeMismatch
(
name
,
object
,
"String"
);
* @return the value or {@code fallback}
}
*/
return
result
;
public
int
optInt
(
String
name
,
int
fallback
)
{
}
Object
object
=
opt
(
name
);
Integer
result
=
JSON
.
toInteger
(
object
);
/**
return
result
!=
null
?
result
:
fallback
;
* Returns the value mapped by {@code name} if it exists, coercing it if
}
* necessary. Returns the empty string if no such mapping exists.
*/
/**
public
String
optString
(
String
name
)
{
* Returns the value mapped by {@code name} if it exists and is a long or
return
optString
(
name
,
""
);
* can be coerced to a long. Note that JSON represents numbers as doubles,
}
* so this is <a href="#lossy">lossy</a>; use strings to transfer numbers via JSON.
*
/**
* @param name the name of the property
* Returns the value mapped by {@code name} if it exists, coercing it if
* @return the value
* necessary. Returns {@code fallback} if no such mapping exists.
* @throws JSONException if the mapping doesn't exist or cannot be coerced
*/
* to a long.
public
String
optString
(
String
name
,
String
fallback
)
{
*/
Object
object
=
opt
(
name
);
public
long
getLong
(
String
name
)
throws
JSONException
{
String
result
=
JSON
.
toString
(
object
);
Object
object
=
get
(
name
);
return
result
!=
null
?
result
:
fallback
;
Long
result
=
JSON
.
toLong
(
object
);
}
if
(
result
==
null
)
{
throw
JSON
.
typeMismatch
(
name
,
object
,
"long"
);
/**
}
* Returns the value mapped by {@code name} if it exists and is a {@code
return
result
;
* JSONArray}.
}
*
* @throws JSONException if the mapping doesn't exist or is not a {@code
/**
* JSONArray}.
* Returns the value mapped by {@code name} if it exists and is a long or
*/
* can be coerced to a long. Returns 0 otherwise. Note that JSON represents numbers as doubles,
public
JSONArray
getJSONArray
(
String
name
)
throws
JSONException
{
* so this is <a href="#lossy">lossy</a>; use strings to transfer numbers via JSON.
Object
object
=
get
(
name
);
* @param name the name of the property
if
(
object
instanceof
JSONArray
)
{
* @return the value or {@code 0L}
return
(
JSONArray
)
object
;
*/
}
else
{
public
long
optLong
(
String
name
)
{
throw
JSON
.
typeMismatch
(
name
,
object
,
"JSONArray"
);
return
optLong
(
name
,
0L
);
}
}
}
/**
/**
* Returns the value mapped by {@code name} if it exists and is a long or
* Returns the value mapped by {@code name} if it exists and is a {@code
* can be coerced to a long. Returns {@code fallback} otherwise. Note that JSON represents
* JSONArray}. Returns null otherwise.
* numbers as doubles, so this is <a href="#lossy">lossy</a>; use strings to transfer
*/
* numbers via JSON.
public
JSONArray
optJSONArray
(
String
name
)
{
* @param name the name of the property
Object
object
=
opt
(
name
);
* @param fallback a fallback value
return
object
instanceof
JSONArray
?
(
JSONArray
)
object
:
null
;
* @return the value or {@code fallback}
}
*/
public
long
optLong
(
String
name
,
long
fallback
)
{
/**
Object
object
=
opt
(
name
);
* Returns the value mapped by {@code name} if it exists and is a {@code
Long
result
=
JSON
.
toLong
(
object
);
* JSONObject}.
return
result
!=
null
?
result
:
fallback
;
*
}
* @throws JSONException if the mapping doesn't exist or is not a {@code
* JSONObject}.
/**
*/
* Returns the value mapped by {@code name} if it exists, coercing it if
public
JSONObject
getJSONObject
(
String
name
)
throws
JSONException
{
* necessary.
Object
object
=
get
(
name
);
* @param name the name of the property
if
(
object
instanceof
JSONObject
)
{
* @return the value
return
(
JSONObject
)
object
;
* @throws JSONException if no such mapping exists.
}
else
{
*/
throw
JSON
.
typeMismatch
(
name
,
object
,
"JSONObject"
);
public
String
getString
(
String
name
)
throws
JSONException
{
}
Object
object
=
get
(
name
);
}
String
result
=
JSON
.
toString
(
object
);
if
(
result
==
null
)
{
/**
throw
JSON
.
typeMismatch
(
name
,
object
,
"String"
);
* Returns the value mapped by {@code name} if it exists and is a {@code
}
* JSONObject}. Returns null otherwise.
return
result
;
*/
}
public
JSONObject
optJSONObject
(
String
name
)
{
Object
object
=
opt
(
name
);
/**
return
object
instanceof
JSONObject
?
(
JSONObject
)
object
:
null
;
* Returns the value mapped by {@code name} if it exists, coercing it if
}
* necessary. Returns the empty string if no such mapping exists.
* @param name the name of the property
/**
* @return the value or an empty string
* Returns an array with the values corresponding to {@code names}. The
*/
* array contains null for names that aren't mapped. This method returns
public
String
optString
(
String
name
)
{
* null if {@code names} is either null or empty.
return
optString
(
name
,
""
);
*/
}
public
JSONArray
toJSONArray
(
JSONArray
names
)
throws
JSONException
{
JSONArray
result
=
new
JSONArray
();
/**
if
(
names
==
null
)
{
* Returns the value mapped by {@code name} if it exists, coercing it if
return
null
;
* necessary. Returns {@code fallback} if no such mapping exists.
}
* @param name the name of the property
int
length
=
names
.
length
();
* @param fallback a fallback value
if
(
length
==
0
)
{
* @return the value or {@code fallback}
return
null
;
*/
}
public
String
optString
(
String
name
,
String
fallback
)
{
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
Object
object
=
opt
(
name
);
String
name
=
JSON
.
toString
(
names
.
opt
(
i
));
String
result
=
JSON
.
toString
(
object
);
result
.
put
(
opt
(
name
));
return
result
!=
null
?
result
:
fallback
;
}
}
return
result
;
}
/**
* Returns the value mapped by {@code name} if it exists and is a {@code
/**
* JSONArray}.
* Returns an iterator of the {@code String} names in this object. The
* @param name the name of the property
* returned iterator supports {@link Iterator#remove() remove}, which will
* @return the value
* remove the corresponding mapping from this object. If this object is
* @throws JSONException if the mapping doesn't exist or is not a {@code
* modified after the iterator is returned, the iterator's behavior is
* JSONArray}.
* undefined. The order of the keys is undefined.
*/
*/
public
JSONArray
getJSONArray
(
String
name
)
throws
JSONException
{
/* Return a raw type for API compatibility */
Object
object
=
get
(
name
);
public
Iterator
keys
()
{
if
(
object
instanceof
JSONArray
)
{
return
nameValuePairs
.
keySet
().
iterator
();
return
(
JSONArray
)
object
;
}
}
else
{
/**
throw
JSON
.
typeMismatch
(
name
,
object
,
"JSONArray"
);
* Returns an array containing the string names in this object. This method
}
* returns null if this object contains no mappings.
}
*/
public
JSONArray
names
()
{
/**
return
nameValuePairs
.
isEmpty
()
* Returns the value mapped by {@code name} if it exists and is a {@code
?
null
* JSONArray}. Returns null otherwise.
:
new
JSONArray
(
new
ArrayList
<
String
>(
nameValuePairs
.
keySet
()));
* @param name the name of the property
}
* @return the value or {@code null}
*/
/**
public
JSONArray
optJSONArray
(
String
name
)
{
* Encodes this object as a compact JSON string, such as:
Object
object
=
opt
(
name
);
* <pre>{"query":"Pizza","locations":[94043,90210]}</pre>
return
object
instanceof
JSONArray
?
(
JSONArray
)
object
:
null
;
*/
}
@Override
public
String
toString
()
{
try
{
/**
JSONStringer
stringer
=
new
JSONStringer
();
* Returns the value mapped by {@code name} if it exists and is a {@code
writeTo
(
stringer
);
* JSONObject}.
return
stringer
.
toString
();
* @param name the name of the property
}
catch
(
JSONException
e
)
{
* @return the value
return
null
;
* @throws JSONException if the mapping doesn't exist or is not a {@code
}
* JSONObject}.
}
*/
public
JSONObject
getJSONObject
(
String
name
)
throws
JSONException
{
/**
Object
object
=
get
(
name
);
* Encodes this object as a human readable JSON string for debugging, such
if
(
object
instanceof
JSONObject
)
{
* as:
return
(
JSONObject
)
object
;
* <pre>
}
* {
else
{
* "query": "Pizza",
throw
JSON
.
typeMismatch
(
name
,
object
,
"JSONObject"
);
* "locations": [
}
* 94043,
}
* 90210
* ]
/**
* }</pre>
* Returns the value mapped by {@code name} if it exists and is a {@code
*
* JSONObject}. Returns null otherwise.
* @param indentSpaces the number of spaces to indent for each level of
* @param name the name of the property
* nesting.
* @return the value or {@code null}
*/
*/
public
String
toString
(
int
indentSpaces
)
throws
JSONException
{
public
JSONObject
optJSONObject
(
String
name
)
{
JSONStringer
stringer
=
new
JSONStringer
(
indentSpaces
);
Object
object
=
opt
(
name
);
writeTo
(
stringer
);
return
object
instanceof
JSONObject
?
(
JSONObject
)
object
:
null
;
return
stringer
.
toString
();
}
}
/**
void
writeTo
(
JSONStringer
stringer
)
throws
JSONException
{
* Returns an array with the values corresponding to {@code names}. The
stringer
.
object
();
* array contains null for names that aren't mapped. This method returns
for
(
Map
.
Entry
<
String
,
Object
>
entry
:
nameValuePairs
.
entrySet
())
{
* null if {@code names} is either null or empty.
stringer
.
key
(
entry
.
getKey
()).
value
(
entry
.
getValue
());
* @param names the names of the properties
}
* @return the array
stringer
.
endObject
();
*/
}
public
JSONArray
toJSONArray
(
JSONArray
names
)
{
JSONArray
result
=
new
JSONArray
();
/**
if
(
names
==
null
)
{
* Encodes the number as a JSON string.
return
null
;
*
}
* @param number a finite value. May not be {@link Double#isNaN() NaNs} or
int
length
=
names
.
length
();
* {@link Double#isInfinite() infinities}.
if
(
length
==
0
)
{
*/
return
null
;
public
static
String
numberToString
(
Number
number
)
throws
JSONException
{
}
if
(
number
==
null
)
{
for
(
int
i
=
0
;
i
<
length
;
i
++)
{
throw
new
JSONException
(
"Number must be non-null"
);
String
name
=
JSON
.
toString
(
names
.
opt
(
i
));
}
result
.
put
(
opt
(
name
));
}
double
doubleValue
=
number
.
doubleValue
();
return
result
;
JSON
.
checkDouble
(
doubleValue
);
}
// the original returns "-0" instead of "-0.0" for negative zero
/**
if
(
number
.
equals
(
NEGATIVE_ZERO
))
{
* Returns an iterator of the {@code String} names in this object. The
return
"-0"
;
* returned iterator supports {@link Iterator#remove() remove}, which will
}
* remove the corresponding mapping from this object. If this object is
* modified after the iterator is returned, the iterator's behavior is
long
longValue
=
number
.
longValue
();
* undefined. The order of the keys is undefined.
if
(
doubleValue
==
(
double
)
longValue
)
{
* @return the keys
return
Long
.
toString
(
longValue
);
*/
}
/* Return a raw type for API compatibility */
public
Iterator
keys
()
{
return
number
.
toString
();
return
this
.
nameValuePairs
.
keySet
().
iterator
();
}
}
/**
/**
* Encodes {@code data} as a JSON string. This applies quotes and any
* Returns an array containing the string names in this object. This method
* necessary character escaping.
* returns null if this object contains no mappings.
*
* @return the array
* @param data the string to encode. Null will be interpreted as an empty
*/
* string.
public
JSONArray
names
()
{
*/
return
this
.
nameValuePairs
.
isEmpty
()
public
static
String
quote
(
String
data
)
{
?
null
if
(
data
==
null
)
{
:
new
JSONArray
(
new
ArrayList
<
String
>(
this
.
nameValuePairs
.
keySet
()));
return
"\"\""
;
}
}
try
{
/**
JSONStringer
stringer
=
new
JSONStringer
();
* Encodes this object as a compact JSON string, such as:
stringer
.
open
(
JSONStringer
.
Scope
.
NULL
,
""
);
* <pre>{"query":"Pizza","locations":[94043,90210]}</pre>
stringer
.
value
(
data
);
* @return a string representation of the object.
stringer
.
close
(
JSONStringer
.
Scope
.
NULL
,
JSONStringer
.
Scope
.
NULL
,
""
);
*/
return
stringer
.
toString
();
@Override
}
catch
(
JSONException
e
)
{
public
String
toString
()
{
throw
new
AssertionError
();
try
{
}
JSONStringer
stringer
=
new
JSONStringer
();
}
writeTo
(
stringer
);
return
stringer
.
toString
();
/**
}
* Wraps the given object if necessary.
catch
(
JSONException
e
)
{
*
return
null
;
* <p>If the object is null or , returns {@link #NULL}.
}
* If the object is a {@code JSONArray} or {@code JSONObject}, no wrapping is necessary.
}
* If the object is {@code NULL}, no wrapping is necessary.
* If the object is an array or {@code Collection}, returns an equivalent {@code JSONArray}.
/**
* If the object is a {@code Map}, returns an equivalent {@code JSONObject}.
* Encodes this object as a human readable JSON string for debugging, such
* If the object is a primitive wrapper type or {@code String}, returns the object.
* as:
* Otherwise if the object is from a {@code java} package, returns the result of {@code toString}.
* <pre>
* If wrapping fails, returns null.
* {
*/
* "query": "Pizza",
public
static
Object
wrap
(
Object
o
)
{
* "locations": [
if
(
o
==
null
)
{
* 94043,
return
NULL
;
* 90210
}
* ]
if
(
o
instanceof
JSONArray
||
o
instanceof
JSONObject
)
{
* }</pre>
return
o
;
*
}
* @param indentSpaces the number of spaces to indent for each level of
if
(
o
.
equals
(
NULL
))
{
* nesting.
return
o
;
* @return a string representation of the object.
}
* @throws JSONException if an error occurs
try
{
*/
if
(
o
instanceof
Collection
)
{
public
String
toString
(
int
indentSpaces
)
throws
JSONException
{
return
new
JSONArray
((
Collection
)
o
);
JSONStringer
stringer
=
new
JSONStringer
(
indentSpaces
);
}
else
if
(
o
.
getClass
().
isArray
())
{
writeTo
(
stringer
);
return
new
JSONArray
(
o
);
return
stringer
.
toString
();
}
}
if
(
o
instanceof
Map
)
{
return
new
JSONObject
((
Map
)
o
);
void
writeTo
(
JSONStringer
stringer
)
throws
JSONException
{
}
stringer
.
object
();
if
(
o
instanceof
Boolean
||
for
(
Map
.
Entry
<
String
,
Object
>
entry
:
this
.
nameValuePairs
.
entrySet
())
{
o
instanceof
Byte
||
stringer
.
key
(
entry
.
getKey
()).
value
(
entry
.
getValue
());
o
instanceof
Character
||
}
o
instanceof
Double
||
stringer
.
endObject
();
o
instanceof
Float
||
}
o
instanceof
Integer
||
o
instanceof
Long
||
/**
o
instanceof
Short
||
* Encodes the number as a JSON string.
o
instanceof
String
)
{
*
return
o
;
* @param number a finite value. May not be {@link Double#isNaN() NaNs} or
}
* {@link Double#isInfinite() infinities}.
if
(
o
.
getClass
().
getPackage
().
getName
().
startsWith
(
"java."
))
{
* @return the encoded value
return
o
.
toString
();
* @throws JSONException if an error occurs
}
*/
}
catch
(
Exception
ignored
)
{
public
static
String
numberToString
(
Number
number
)
throws
JSONException
{
}
if
(
number
==
null
)
{
return
null
;
throw
new
JSONException
(
"Number must be non-null"
);
}
}
double
doubleValue
=
number
.
doubleValue
();
JSON
.
checkDouble
(
doubleValue
);
// the original returns "-0" instead of "-0.0" for negative zero
if
(
number
.
equals
(
NEGATIVE_ZERO
))
{
return
"-0"
;
}
long
longValue
=
number
.
longValue
();
if
(
doubleValue
==
(
double
)
longValue
)
{
return
Long
.
toString
(
longValue
);
}
return
number
.
toString
();
}
/**
* Encodes {@code data} as a JSON string. This applies quotes and any
* necessary character escaping.
*
* @param data the string to encode. Null will be interpreted as an empty
* string.
* @return the quoted value
*/
public
static
String
quote
(
String
data
)
{
if
(
data
==
null
)
{
return
"\"\""
;
}
try
{
JSONStringer
stringer
=
new
JSONStringer
();
stringer
.
open
(
JSONStringer
.
Scope
.
NULL
,
""
);
stringer
.
value
(
data
);
stringer
.
close
(
JSONStringer
.
Scope
.
NULL
,
JSONStringer
.
Scope
.
NULL
,
""
);
return
stringer
.
toString
();
}
catch
(
JSONException
e
)
{
throw
new
AssertionError
();
}
}
/**
* Wraps the given object if necessary.
*
* <p>If the object is null or , returns {@link #NULL}.
* If the object is a {@code JSONArray} or {@code JSONObject}, no wrapping is necessary.
* If the object is {@code NULL}, no wrapping is necessary.
* If the object is an array or {@code Collection}, returns an equivalent {@code JSONArray}.
* If the object is a {@code Map}, returns an equivalent {@code JSONObject}.
* If the object is a primitive wrapper type or {@code String}, returns the object.
* Otherwise if the object is from a {@code java} package, returns the result of {@code toString}.
* If wrapping fails, returns null.
* @param o the object to wrap
* @return the wrapped object
*/
public
static
Object
wrap
(
Object
o
)
{
if
(
o
==
null
)
{
return
NULL
;
}
if
(
o
instanceof
JSONArray
||
o
instanceof
JSONObject
)
{
return
o
;
}
if
(
o
.
equals
(
NULL
))
{
return
o
;
}
try
{
if
(
o
instanceof
Collection
)
{
return
new
JSONArray
((
Collection
)
o
);
}
else
if
(
o
.
getClass
().
isArray
())
{
return
new
JSONArray
(
o
);
}
if
(
o
instanceof
Map
)
{
return
new
JSONObject
((
Map
)
o
);
}
if
(
o
instanceof
Boolean
||
o
instanceof
Byte
||
o
instanceof
Character
||
o
instanceof
Double
||
o
instanceof
Float
||
o
instanceof
Integer
||
o
instanceof
Long
||
o
instanceof
Short
||
o
instanceof
String
)
{
return
o
;
}
if
(
o
.
getClass
().
getPackage
().
getName
().
startsWith
(
"java."
))
{
return
o
.
toString
();
}
}
catch
(
Exception
ignored
)
{
}
return
null
;
}
}
}
spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/json/JSONStringer.java
View file @
4568f14c
...
@@ -60,373 +60,407 @@ import java.util.List;
...
@@ -60,373 +60,407 @@ import java.util.List;
*/
*/
public
class
JSONStringer
{
public
class
JSONStringer
{
/** The output data, containing at most one top-level array or object. */
/** The output data, containing at most one top-level array or object. */
final
StringBuilder
out
=
new
StringBuilder
();
final
StringBuilder
out
=
new
StringBuilder
();
/**
/**
* Lexical scoping elements within this stringer, necessary to insert the
* Lexical scoping elements within this stringer, necessary to insert the
* appropriate separator characters (ie. commas and colons) and to detect
* appropriate separator characters (ie. commas and colons) and to detect
* nesting errors.
* nesting errors.
*/
*/
enum
Scope
{
enum
Scope
{
/**
/**
* An array with no elements requires no separators or newlines before
* An array with no elements requires no separators or newlines before
* it is closed.
* it is closed.
*/
*/
EMPTY_ARRAY
,
EMPTY_ARRAY
,
/**
/**
* A array with at least one value requires a comma and newline before
* A array with at least one value requires a comma and newline before
* the next element.
* the next element.
*/
*/
NONEMPTY_ARRAY
,
NONEMPTY_ARRAY
,
/**
/**
* An object with no keys or values requires no separators or newlines
* An object with no keys or values requires no separators or newlines
* before it is closed.
* before it is closed.
*/
*/
EMPTY_OBJECT
,
EMPTY_OBJECT
,
/**
/**
* An object whose most recent element is a key. The next element must
* An object whose most recent element is a key. The next element must
* be a value.
* be a value.
*/
*/
DANGLING_KEY
,
DANGLING_KEY
,
/**
/**
* An object with at least one name/value pair requires a comma and
* An object with at least one name/value pair requires a comma and
* newline before the next element.
* newline before the next element.
*/
*/
NONEMPTY_OBJECT
,
NONEMPTY_OBJECT
,
/**
/**
* A special bracketless array needed by JSONStringer.join() and
* A special bracketless array needed by JSONStringer.join() and
* JSONObject.quote() only. Not used for JSON encoding.
* JSONObject.quote() only. Not used for JSON encoding.
*/
*/
NULL
,
NULL
,
}
}
/**
/**
* Unlike the original implementation, this stack isn't limited to 20
* Unlike the original implementation, this stack isn't limited to 20
* levels of nesting.
* levels of nesting.
*/
*/
private
final
List
<
Scope
>
stack
=
new
ArrayList
<
Scope
>();
private
final
List
<
Scope
>
stack
=
new
ArrayList
<
Scope
>();
/**
/**
* A string containing a full set of spaces for a single level of
* A string containing a full set of spaces for a single level of
* indentation, or null for no pretty printing.
* indentation, or null for no pretty printing.
*/
*/
private
final
String
indent
;
private
final
String
indent
;
public
JSONStringer
()
{
public
JSONStringer
()
{
indent
=
null
;
this
.
indent
=
null
;
}
}
JSONStringer
(
int
indentSpaces
)
{
JSONStringer
(
int
indentSpaces
)
{
char
[]
indentChars
=
new
char
[
indentSpaces
];
char
[]
indentChars
=
new
char
[
indentSpaces
];
Arrays
.
fill
(
indentChars
,
' '
);
Arrays
.
fill
(
indentChars
,
' '
);
indent
=
new
String
(
indentChars
);
this
.
indent
=
new
String
(
indentChars
);
}
}
/**
/**
* Begins encoding a new array. Each call to this method must be paired with
* Begins encoding a new array. Each call to this method must be paired with
* a call to {@link #endArray}.
* a call to {@link #endArray}.
*
*
* @return this stringer.
* @return this stringer.
*/
* @throws JSONException if processing of json failed
public
JSONStringer
array
()
throws
JSONException
{
*/
return
open
(
Scope
.
EMPTY_ARRAY
,
"["
);
public
JSONStringer
array
()
throws
JSONException
{
}
return
open
(
Scope
.
EMPTY_ARRAY
,
"["
);
}
/**
* Ends encoding the current array.
/**
*
* Ends encoding the current array.
* @return this stringer.
*
*/
* @return this stringer.
public
JSONStringer
endArray
()
throws
JSONException
{
* @throws JSONException if processing of json failed
return
close
(
Scope
.
EMPTY_ARRAY
,
Scope
.
NONEMPTY_ARRAY
,
"]"
);
*/
}
public
JSONStringer
endArray
()
throws
JSONException
{
return
close
(
Scope
.
EMPTY_ARRAY
,
Scope
.
NONEMPTY_ARRAY
,
"]"
);
/**
}
* Begins encoding a new object. Each call to this method must be paired
* with a call to {@link #endObject}.
/**
*
* Begins encoding a new object. Each call to this method must be paired
* @return this stringer.
* with a call to {@link #endObject}.
*/
*
public
JSONStringer
object
()
throws
JSONException
{
* @return this stringer.
return
open
(
Scope
.
EMPTY_OBJECT
,
"{"
);
* @throws JSONException if processing of json failed
}
*/
public
JSONStringer
object
()
throws
JSONException
{
/**
return
open
(
Scope
.
EMPTY_OBJECT
,
"{"
);
* Ends encoding the current object.
}
*
* @return this stringer.
/**
*/
* Ends encoding the current object.
public
JSONStringer
endObject
()
throws
JSONException
{
*
return
close
(
Scope
.
EMPTY_OBJECT
,
Scope
.
NONEMPTY_OBJECT
,
"}"
);
* @return this stringer.
}
* @throws JSONException if processing of json failed
*/
/**
public
JSONStringer
endObject
()
throws
JSONException
{
* Enters a new scope by appending any necessary whitespace and the given
return
close
(
Scope
.
EMPTY_OBJECT
,
Scope
.
NONEMPTY_OBJECT
,
"}"
);
* bracket.
}
*/
JSONStringer
open
(
Scope
empty
,
String
openBracket
)
throws
JSONException
{
/**
if
(
stack
.
isEmpty
()
&&
out
.
length
()
>
0
)
{
* Enters a new scope by appending any necessary whitespace and the given
throw
new
JSONException
(
"Nesting problem: multiple top-level roots"
);
* bracket.
}
* @param empty any necessary whitespace
beforeValue
();
* @param openBracket the open bracket
stack
.
add
(
empty
);
* @return this object
out
.
append
(
openBracket
);
* @throws JSONException if processing of json failed
return
this
;
*/
}
JSONStringer
open
(
Scope
empty
,
String
openBracket
)
throws
JSONException
{
if
(
this
.
stack
.
isEmpty
()
&&
this
.
out
.
length
()
>
0
)
{
/**
throw
new
JSONException
(
"Nesting problem: multiple top-level roots"
);
* Closes the current scope by appending any necessary whitespace and the
}
* given bracket.
beforeValue
();
*/
this
.
stack
.
add
(
empty
);
JSONStringer
close
(
Scope
empty
,
Scope
nonempty
,
String
closeBracket
)
throws
JSONException
{
this
.
out
.
append
(
openBracket
);
Scope
context
=
peek
();
return
this
;
if
(
context
!=
nonempty
&&
context
!=
empty
)
{
}
throw
new
JSONException
(
"Nesting problem"
);
}
/**
* Closes the current scope by appending any necessary whitespace and the
stack
.
remove
(
stack
.
size
()
-
1
);
* given bracket.
if
(
context
==
nonempty
)
{
* @param empty any necessary whitespace
newline
();
* @param nonempty the current scope
}
* @param closeBracket the close bracket
out
.
append
(
closeBracket
);
* @throws JSONException if processing of json failed
return
this
;
*/
}
JSONStringer
close
(
Scope
empty
,
Scope
nonempty
,
String
closeBracket
)
throws
JSONException
{
Scope
context
=
peek
();
/**
if
(
context
!=
nonempty
&&
context
!=
empty
)
{
* Returns the value on the top of the stack.
throw
new
JSONException
(
"Nesting problem"
);
*/
}
private
Scope
peek
()
throws
JSONException
{
if
(
stack
.
isEmpty
())
{
this
.
stack
.
remove
(
this
.
stack
.
size
()
-
1
);
throw
new
JSONException
(
"Nesting problem"
);
if
(
context
==
nonempty
)
{
}
newline
();
return
stack
.
get
(
stack
.
size
()
-
1
);
}
}
this
.
out
.
append
(
closeBracket
);
return
this
;
/**
}
* Replace the value on the top of the stack with the given value.
*/
/**
private
void
replaceTop
(
Scope
topOfStack
)
{
* Returns the value on the top of the stack.
stack
.
set
(
stack
.
size
()
-
1
,
topOfStack
);
* @return the scope
}
* @throws JSONException if processing of json failed
*/
/**
private
Scope
peek
()
throws
JSONException
{
* Encodes {@code value}.
if
(
this
.
stack
.
isEmpty
())
{
*
throw
new
JSONException
(
"Nesting problem"
);
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
}
* Integer, Long, Double or null. May not be {@link Double#isNaN() NaNs}
return
this
.
stack
.
get
(
this
.
stack
.
size
()
-
1
);
* or {@link Double#isInfinite() infinities}.
}
* @return this stringer.
*/
/**
public
JSONStringer
value
(
Object
value
)
throws
JSONException
{
* Replace the value on the top of the stack with the given value.
if
(
stack
.
isEmpty
())
{
* @param topOfStack the scope at the top of the stack
throw
new
JSONException
(
"Nesting problem"
);
*/
}
private
void
replaceTop
(
Scope
topOfStack
)
{
this
.
stack
.
set
(
this
.
stack
.
size
()
-
1
,
topOfStack
);
if
(
value
instanceof
JSONArray
)
{
}
((
JSONArray
)
value
).
writeTo
(
this
);
return
this
;
/**
* Encodes {@code value}.
}
else
if
(
value
instanceof
JSONObject
)
{
*
((
JSONObject
)
value
).
writeTo
(
this
);
* @param value a {@link JSONObject}, {@link JSONArray}, String, Boolean,
return
this
;
* Integer, Long, Double or null. May not be {@link Double#isNaN() NaNs}
}
* or {@link Double#isInfinite() infinities}.
* @return this stringer.
beforeValue
();
* @throws JSONException if processing of json failed
*/
if
(
value
==
null
public
JSONStringer
value
(
Object
value
)
throws
JSONException
{
||
value
instanceof
Boolean
if
(
this
.
stack
.
isEmpty
())
{
||
value
==
JSONObject
.
NULL
)
{
throw
new
JSONException
(
"Nesting problem"
);
out
.
append
(
value
);
}
}
else
if
(
value
instanceof
Number
)
{
if
(
value
instanceof
JSONArray
)
{
out
.
append
(
JSONObject
.
numberToString
((
Number
)
value
));
((
JSONArray
)
value
).
writeTo
(
this
);
return
this
;
}
else
{
string
(
value
.
toString
());
}
}
else
if
(
value
instanceof
JSONObject
)
{
((
JSONObject
)
value
).
writeTo
(
this
);
return
this
;
return
this
;
}
}
/**
beforeValue
();
* Encodes {@code value} to this stringer.
*
if
(
value
==
null
* @return this stringer.
||
value
instanceof
Boolean
*/
||
value
==
JSONObject
.
NULL
)
{
public
JSONStringer
value
(
boolean
value
)
throws
JSONException
{
this
.
out
.
append
(
value
);
if
(
stack
.
isEmpty
())
{
throw
new
JSONException
(
"Nesting problem"
);
}
}
else
if
(
value
instanceof
Number
)
{
beforeValue
();
this
.
out
.
append
(
JSONObject
.
numberToString
((
Number
)
value
));
out
.
append
(
value
);
return
this
;
}
}
else
{
string
(
value
.
toString
());
/**
}
* Encodes {@code value} to this stringer.
*
return
this
;
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
}
* {@link Double#isInfinite() infinities}.
* @return this stringer.
/**
*/
* Encodes {@code value} to this stringer.
public
JSONStringer
value
(
double
value
)
throws
JSONException
{
*
if
(
stack
.
isEmpty
())
{
* @param value the value to encode
throw
new
JSONException
(
"Nesting problem"
);
* @return this stringer.
}
* @throws JSONException if processing of json failed
beforeValue
();
*/
out
.
append
(
JSONObject
.
numberToString
(
value
));
public
JSONStringer
value
(
boolean
value
)
throws
JSONException
{
return
this
;
if
(
this
.
stack
.
isEmpty
())
{
}
throw
new
JSONException
(
"Nesting problem"
);
}
/**
beforeValue
();
* Encodes {@code value} to this stringer.
this
.
out
.
append
(
value
);
*
return
this
;
* @return this stringer.
}
*/
public
JSONStringer
value
(
long
value
)
throws
JSONException
{
/**
if
(
stack
.
isEmpty
())
{
* Encodes {@code value} to this stringer.
throw
new
JSONException
(
"Nesting problem"
);
*
}
* @param value a finite value. May not be {@link Double#isNaN() NaNs} or
beforeValue
();
* {@link Double#isInfinite() infinities}.
out
.
append
(
value
);
* @return this stringer.
return
this
;
* @throws JSONException if processing of json failed
}
*/
public
JSONStringer
value
(
double
value
)
throws
JSONException
{
private
void
string
(
String
value
)
{
if
(
this
.
stack
.
isEmpty
())
{
out
.
append
(
"\""
);
throw
new
JSONException
(
"Nesting problem"
);
for
(
int
i
=
0
,
length
=
value
.
length
();
i
<
length
;
i
++)
{
}
char
c
=
value
.
charAt
(
i
);
beforeValue
();
this
.
out
.
append
(
JSONObject
.
numberToString
(
value
));
/*
return
this
;
* From RFC 4627, "All Unicode characters may be placed within the
}
* quotation marks except for the characters that must be escaped:
* quotation mark, reverse solidus, and the control characters
/**
* (U+0000 through U+001F)."
* Encodes {@code value} to this stringer.
*/
*
switch
(
c
)
{
* @param value the value to encode
case
'"'
:
* @return this stringer.
case
'\\'
:
* @throws JSONException if processing of json failed
case
'/'
:
*/
out
.
append
(
'\\'
).
append
(
c
);
public
JSONStringer
value
(
long
value
)
throws
JSONException
{
break
;
if
(
this
.
stack
.
isEmpty
())
{
throw
new
JSONException
(
"Nesting problem"
);
case
'\t'
:
}
out
.
append
(
"\\t"
);
beforeValue
();
break
;
this
.
out
.
append
(
value
);
return
this
;
case
'\b'
:
}
out
.
append
(
"\\b"
);
break
;
private
void
string
(
String
value
)
{
this
.
out
.
append
(
"\""
);
case
'\n'
:
for
(
int
i
=
0
,
length
=
value
.
length
();
i
<
length
;
i
++)
{
out
.
append
(
"\\n"
);
char
c
=
value
.
charAt
(
i
);
break
;
/*
case
'\r'
:
* From RFC 4627, "All Unicode characters may be placed within the
out
.
append
(
"\\r"
);
* quotation marks except for the characters that must be escaped:
break
;
* quotation mark, reverse solidus, and the control characters
* (U+0000 through U+001F)."
case
'\f'
:
*/
out
.
append
(
"\\f"
);
switch
(
c
)
{
break
;
case
'"'
:
case
'\\'
:
default
:
case
'/'
:
if
(
c
<=
0x1F
)
{
this
.
out
.
append
(
'\\'
).
append
(
c
);
out
.
append
(
String
.
format
(
"\\u%04x"
,
(
int
)
c
));
break
;
}
else
{
out
.
append
(
c
);
case
'\t'
:
}
this
.
out
.
append
(
"\\t"
);
break
;
break
;
}
case
'\b'
:
}
this
.
out
.
append
(
"\\b"
);
out
.
append
(
"\""
);
break
;
}
case
'\n'
:
private
void
newline
()
{
this
.
out
.
append
(
"\\n"
);
if
(
indent
==
null
)
{
break
;
return
;
}
case
'\r'
:
this
.
out
.
append
(
"\\r"
);
out
.
append
(
"\n"
);
break
;
for
(
int
i
=
0
;
i
<
stack
.
size
();
i
++)
{
out
.
append
(
indent
);
case
'\f'
:
}
this
.
out
.
append
(
"\\f"
);
}
break
;
/**
default
:
* Encodes the key (property name) to this stringer.
if
(
c
<=
0x1F
)
{
*
this
.
out
.
append
(
String
.
format
(
"\\u%04x"
,
(
int
)
c
));
* @param name the name of the forthcoming value. May not be null.
}
* @return this stringer.
else
{
*/
this
.
out
.
append
(
c
);
public
JSONStringer
key
(
String
name
)
throws
JSONException
{
}
if
(
name
==
null
)
{
break
;
throw
new
JSONException
(
"Names must be non-null"
);
}
}
beforeKey
();
}
string
(
name
);
this
.
out
.
append
(
"\""
);
return
this
;
}
}
private
void
newline
()
{
/**
if
(
this
.
indent
==
null
)
{
* Inserts any necessary separators and whitespace before a name. Also
return
;
* adjusts the stack to expect the key's value.
}
*/
private
void
beforeKey
()
throws
JSONException
{
this
.
out
.
append
(
"\n"
);
Scope
context
=
peek
();
for
(
int
i
=
0
;
i
<
this
.
stack
.
size
();
i
++)
{
if
(
context
==
Scope
.
NONEMPTY_OBJECT
)
{
// first in object
this
.
out
.
append
(
this
.
indent
);
out
.
append
(
','
);
}
}
else
if
(
context
!=
Scope
.
EMPTY_OBJECT
)
{
// not in an object!
}
throw
new
JSONException
(
"Nesting problem"
);
}
/**
newline
();
* Encodes the key (property name) to this stringer.
replaceTop
(
Scope
.
DANGLING_KEY
);
*
}
* @param name the name of the forthcoming value. May not be null.
* @return this stringer.
/**
* @throws JSONException if processing of json failed
* Inserts any necessary separators and whitespace before a literal value,
*/
* inline array, or inline object. Also adjusts the stack to expect either a
public
JSONStringer
key
(
String
name
)
throws
JSONException
{
* closing bracket or another element.
if
(
name
==
null
)
{
*/
throw
new
JSONException
(
"Names must be non-null"
);
private
void
beforeValue
()
throws
JSONException
{
}
if
(
stack
.
isEmpty
())
{
beforeKey
();
return
;
string
(
name
);
}
return
this
;
}
Scope
context
=
peek
();
if
(
context
==
Scope
.
EMPTY_ARRAY
)
{
// first in array
/**
replaceTop
(
Scope
.
NONEMPTY_ARRAY
);
* Inserts any necessary separators and whitespace before a name. Also
newline
();
* adjusts the stack to expect the key's value.
}
else
if
(
context
==
Scope
.
NONEMPTY_ARRAY
)
{
// another in array
* @throws JSONException if processing of json failed
out
.
append
(
','
);
*/
newline
();
private
void
beforeKey
()
throws
JSONException
{
}
else
if
(
context
==
Scope
.
DANGLING_KEY
)
{
// value for key
Scope
context
=
peek
();
out
.
append
(
indent
==
null
?
":"
:
": "
);
if
(
context
==
Scope
.
NONEMPTY_OBJECT
)
{
// first in object
replaceTop
(
Scope
.
NONEMPTY_OBJECT
);
this
.
out
.
append
(
','
);
}
else
if
(
context
!=
Scope
.
NULL
)
{
}
throw
new
JSONException
(
"Nesting problem"
);
else
if
(
context
!=
Scope
.
EMPTY_OBJECT
)
{
// not in an object!
}
throw
new
JSONException
(
"Nesting problem"
);
}
}
newline
();
/**
replaceTop
(
Scope
.
DANGLING_KEY
);
* Returns the encoded JSON string.
}
*
* <p>If invoked with unterminated arrays or unclosed objects, this method's
/**
* return value is undefined.
* Inserts any necessary separators and whitespace before a literal value,
*
* inline array, or inline object. Also adjusts the stack to expect either a
* <p><strong>Warning:</strong> although it contradicts the general contract
* closing bracket or another element.
* of {@link Object#toString}, this method returns null if the stringer
* @throws JSONException if processing of json failed
* contains no data.
*/
*/
private
void
beforeValue
()
throws
JSONException
{
@Override
public
String
toString
()
{
if
(
this
.
stack
.
isEmpty
())
{
return
out
.
length
()
==
0
?
null
:
out
.
toString
();
return
;
}
}
Scope
context
=
peek
();
if
(
context
==
Scope
.
EMPTY_ARRAY
)
{
// first in array
replaceTop
(
Scope
.
NONEMPTY_ARRAY
);
newline
();
}
else
if
(
context
==
Scope
.
NONEMPTY_ARRAY
)
{
// another in array
this
.
out
.
append
(
','
);
newline
();
}
else
if
(
context
==
Scope
.
DANGLING_KEY
)
{
// value for key
this
.
out
.
append
(
this
.
indent
==
null
?
":"
:
": "
);
replaceTop
(
Scope
.
NONEMPTY_OBJECT
);
}
else
if
(
context
!=
Scope
.
NULL
)
{
throw
new
JSONException
(
"Nesting problem"
);
}
}
/**
* Returns the encoded JSON string.
*
* <p>If invoked with unterminated arrays or unclosed objects, this method's
* return value is undefined.
*
* <p><strong>Warning:</strong> although it contradicts the general contract
* of {@link Object#toString}, this method returns null if the stringer
* contains no data.
* @return the encoded JSON string.
*/
@Override
public
String
toString
()
{
return
this
.
out
.
length
()
==
0
?
null
:
this
.
out
.
toString
();
}
}
}
spring-boot-tools/spring-boot-configuration-processor/src/main/java/org/springframework/boot/configurationprocessor/json/JSONTokener.java
View file @
4568f14c
...
@@ -61,551 +61,512 @@ package org.springframework.boot.configurationprocessor.json;
...
@@ -61,551 +61,512 @@ package org.springframework.boot.configurationprocessor.json;
*/
*/
public
class
JSONTokener
{
public
class
JSONTokener
{
/** The input JSON. */
/** The input JSON. */
private
final
String
in
;
private
final
String
in
;
/**
/**
* The index of the next character to be returned by {@link #next}. When
* The index of the next character to be returned by {@link #next}. When
* the input is exhausted, this equals the input's length.
* the input is exhausted, this equals the input's length.
*/
*/
private
int
pos
;
private
int
pos
;
/**
/**
* @param in JSON encoded string. Null is not permitted and will yield a
* @param in JSON encoded string. Null is not permitted and will yield a
* tokener that throws {@code NullPointerExceptions} when methods are
* tokener that throws {@code NullPointerExceptions} when methods are
* called.
* called.
*/
*/
public
JSONTokener
(
String
in
)
{
public
JSONTokener
(
String
in
)
{
// consume an optional byte order mark (BOM) if it exists
// consume an optional byte order mark (BOM) if it exists
if
(
in
!=
null
&&
in
.
startsWith
(
"\ufeff"
))
{
if
(
in
!=
null
&&
in
.
startsWith
(
"\ufeff"
))
{
in
=
in
.
substring
(
1
);
in
=
in
.
substring
(
1
);
}
}
this
.
in
=
in
;
this
.
in
=
in
;
}
}
/**
/**
* Returns the next value from the input.
* Returns the next value from the input.
*
*
* @return a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* @return a {@link JSONObject}, {@link JSONArray}, String, Boolean,
* Integer, Long, Double or {@link JSONObject#NULL}.
* Integer, Long, Double or {@link JSONObject#NULL}.
* @throws JSONException if the input is malformed.
* @throws JSONException if the input is malformed.
*/
*/
public
Object
nextValue
()
throws
JSONException
{
public
Object
nextValue
()
throws
JSONException
{
int
c
=
nextCleanInternal
();
int
c
=
nextCleanInternal
();
switch
(
c
)
{
switch
(
c
)
{
case
-
1
:
case
-
1
:
throw
syntaxError
(
"End of input"
);
throw
syntaxError
(
"End of input"
);
case
'{'
:
case
'{'
:
return
readObject
();
return
readObject
();
case
'['
:
case
'['
:
return
readArray
();
return
readArray
();
case
'\''
:
case
'\''
:
case
'"'
:
case
'"'
:
return
nextString
((
char
)
c
);
return
nextString
((
char
)
c
);
default
:
default
:
pos
--;
this
.
pos
--;
return
readLiteral
();
return
readLiteral
();
}
}
}
}
private
int
nextCleanInternal
()
throws
JSONException
{
private
int
nextCleanInternal
()
throws
JSONException
{
while
(
pos
<
in
.
length
())
{
while
(
this
.
pos
<
this
.
in
.
length
())
{
int
c
=
in
.
charAt
(
pos
++);
int
c
=
this
.
in
.
charAt
(
this
.
pos
++);
switch
(
c
)
{
switch
(
c
)
{
case
'\t'
:
case
'\t'
:
case
' '
:
case
' '
:
case
'\n'
:
case
'\n'
:
case
'\r'
:
case
'\r'
:
continue
;
continue
;
case
'/'
:
case
'/'
:
if
(
pos
==
in
.
length
())
{
if
(
this
.
pos
==
this
.
in
.
length
())
{
return
c
;
return
c
;
}
}
char
peek
=
in
.
charAt
(
pos
);
char
peek
=
this
.
in
.
charAt
(
this
.
pos
);
switch
(
peek
)
{
switch
(
peek
)
{
case
'*'
:
case
'*'
:
// skip a /* c-style comment */
// skip a /* c-style comment */
pos
++;
this
.
pos
++;
int
commentEnd
=
in
.
indexOf
(
"*/"
,
pos
);
int
commentEnd
=
this
.
in
.
indexOf
(
"*/"
,
this
.
pos
);
if
(
commentEnd
==
-
1
)
{
if
(
commentEnd
==
-
1
)
{
throw
syntaxError
(
"Unterminated comment"
);
throw
syntaxError
(
"Unterminated comment"
);
}
}
pos
=
commentEnd
+
2
;
this
.
pos
=
commentEnd
+
2
;
continue
;
continue
;
case
'/'
:
case
'/'
:
// skip a // end-of-line comment
// skip a // end-of-line comment
pos
++;
this
.
pos
++;
skipToEndOfLine
();
skipToEndOfLine
();
continue
;
continue
;
default
:
default
:
return
c
;
return
c
;
}
}
case
'#'
:
case
'#'
:
/*
/*
* Skip a # hash end-of-line comment. The JSON RFC doesn't
* Skip a # hash end-of-line comment. The JSON RFC doesn't
* specify this behavior, but it's required to parse
* specify this behavior, but it's required to parse
* existing documents. See http://b/2571423.
* existing documents. See http://b/2571423.
*/
*/
skipToEndOfLine
();
skipToEndOfLine
();
continue
;
continue
;
default
:
default
:
return
c
;
return
c
;
}
}
}
}
return
-
1
;
return
-
1
;
}
}
/**
/**
* Advances the position until after the next newline character. If the line
* Advances the position until after the next newline character. If the line
* is terminated by "\r\n", the '\n' must be consumed as whitespace by the
* is terminated by "\r\n", the '\n' must be consumed as whitespace by the
* caller.
* caller.
*/
*/
private
void
skipToEndOfLine
()
{
private
void
skipToEndOfLine
()
{
for
(;
pos
<
in
.
length
();
pos
++)
{
for
(;
this
.
pos
<
this
.
in
.
length
();
this
.
pos
++)
{
char
c
=
in
.
charAt
(
pos
);
char
c
=
this
.
in
.
charAt
(
this
.
pos
);
if
(
c
==
'\r'
||
c
==
'\n'
)
{
if
(
c
==
'\r'
||
c
==
'\n'
)
{
pos
++;
this
.
pos
++;
break
;
break
;
}
}
}
}
}
}
/**
/**
* Returns the string up to but not including {@code quote}, unescaping any
* Returns the string up to but not including {@code quote}, unescaping any
* character escape sequences encountered along the way. The opening quote
* character escape sequences encountered along the way. The opening quote
* should have already been read. This consumes the closing quote, but does
* should have already been read. This consumes the closing quote, but does
* not include it in the returned string.
* not include it in the returned string.
*
*
* @param quote either ' or ".
* @param quote either ' or ".
* @throws NumberFormatException if any unicode escape sequences are
* @return the string up to but not including {@code quote}
* malformed.
* @throws NumberFormatException if any unicode escape sequences are
*/
* malformed.
public
String
nextString
(
char
quote
)
throws
JSONException
{
* @throws JSONException if processing of json failed
/*
*/
* For strings that are free of escape sequences, we can just extract
public
String
nextString
(
char
quote
)
throws
JSONException
{
* the result as a substring of the input. But if we encounter an escape
/*
* sequence, we need to use a StringBuilder to compose the result.
* For strings that are free of escape sequences, we can just extract
*/
* the result as a substring of the input. But if we encounter an escape
StringBuilder
builder
=
null
;
* sequence, we need to use a StringBuilder to compose the result.
*/
/* the index of the first character not yet appended to the builder. */
StringBuilder
builder
=
null
;
int
start
=
pos
;
/* the index of the first character not yet appended to the builder. */
while
(
pos
<
in
.
length
())
{
int
start
=
this
.
pos
;
int
c
=
in
.
charAt
(
pos
++);
if
(
c
==
quote
)
{
while
(
this
.
pos
<
this
.
in
.
length
())
{
if
(
builder
==
null
)
{
int
c
=
this
.
in
.
charAt
(
this
.
pos
++);
// a new string avoids leaking memory
if
(
c
==
quote
)
{
return
new
String
(
in
.
substring
(
start
,
pos
-
1
));
if
(
builder
==
null
)
{
}
else
{
// a new string avoids leaking memory
builder
.
append
(
in
,
start
,
pos
-
1
);
return
new
String
(
this
.
in
.
substring
(
start
,
this
.
pos
-
1
));
return
builder
.
toString
();
}
}
else
{
}
builder
.
append
(
this
.
in
,
start
,
this
.
pos
-
1
);
return
builder
.
toString
();
if
(
c
==
'\\'
)
{
}
if
(
pos
==
in
.
length
())
{
}
throw
syntaxError
(
"Unterminated escape sequence"
);
}
if
(
c
==
'\\'
)
{
if
(
builder
==
null
)
{
if
(
this
.
pos
==
this
.
in
.
length
())
{
builder
=
new
StringBuilder
();
throw
syntaxError
(
"Unterminated escape sequence"
);
}
}
builder
.
append
(
in
,
start
,
pos
-
1
);
if
(
builder
==
null
)
{
builder
.
append
(
readEscapeCharacter
());
builder
=
new
StringBuilder
();
start
=
pos
;
}
}
builder
.
append
(
this
.
in
,
start
,
this
.
pos
-
1
);
}
builder
.
append
(
readEscapeCharacter
());
start
=
this
.
pos
;
throw
syntaxError
(
"Unterminated string"
);
}
}
}
/**
throw
syntaxError
(
"Unterminated string"
);
* Unescapes the character identified by the character or characters that
}
* immediately follow a backslash. The backslash '\' should have already
* been read. This supports both unicode escapes "u000A" and two-character
/**
* escapes "\n".
* Unescapes the character identified by the character or characters that
*
* immediately follow a backslash. The backslash '\' should have already
* @throws NumberFormatException if any unicode escape sequences are
* been read. This supports both unicode escapes "u000A" and two-character
* malformed.
* escapes "\n".
*/
*
private
char
readEscapeCharacter
()
throws
JSONException
{
* @return the unescaped char
char
escaped
=
in
.
charAt
(
pos
++);
* @throws NumberFormatException if any unicode escape sequences are
switch
(
escaped
)
{
* malformed.
case
'u'
:
* @throws JSONException if processing of json failed
if
(
pos
+
4
>
in
.
length
())
{
*/
throw
syntaxError
(
"Unterminated escape sequence"
);
private
char
readEscapeCharacter
()
throws
JSONException
{
}
char
escaped
=
this
.
in
.
charAt
(
this
.
pos
++);
String
hex
=
in
.
substring
(
pos
,
pos
+
4
);
switch
(
escaped
)
{
pos
+=
4
;
case
'u'
:
return
(
char
)
Integer
.
parseInt
(
hex
,
16
);
if
(
this
.
pos
+
4
>
this
.
in
.
length
())
{
throw
syntaxError
(
"Unterminated escape sequence"
);
case
't'
:
}
return
'\t'
;
String
hex
=
this
.
in
.
substring
(
this
.
pos
,
this
.
pos
+
4
);
this
.
pos
+=
4
;
case
'b'
:
return
(
char
)
Integer
.
parseInt
(
hex
,
16
);
return
'\b'
;
case
't'
:
case
'n'
:
return
'\t'
;
return
'\n'
;
case
'b'
:
case
'r'
:
return
'\b'
;
return
'\r'
;
case
'n'
:
case
'f'
:
return
'\n'
;
return
'\f'
;
case
'r'
:
case
'\''
:
return
'\r'
;
case
'"'
:
case
'\\'
:
case
'f'
:
default
:
return
'\f'
;
return
escaped
;
}
case
'\''
:
}
case
'"'
:
case
'\\'
:
/**
default
:
* Reads a null, boolean, numeric or unquoted string literal value. Numeric
return
escaped
;
* values will be returned as an Integer, Long, or Double, in that order of
}
* preference.
}
*/
private
Object
readLiteral
()
throws
JSONException
{
/**
String
literal
=
nextToInternal
(
"{}[]/\\:,=;# \t\f"
);
* Reads a null, boolean, numeric or unquoted string literal value. Numeric
* values will be returned as an Integer, Long, or Double, in that order of
if
(
literal
.
length
()
==
0
)
{
* preference.
throw
syntaxError
(
"Expected literal value"
);
* @return a literal value
}
else
if
(
"null"
.
equalsIgnoreCase
(
literal
))
{
* @throws JSONException if processing of json failed
return
JSONObject
.
NULL
;
*/
}
else
if
(
"true"
.
equalsIgnoreCase
(
literal
))
{
private
Object
readLiteral
()
throws
JSONException
{
return
Boolean
.
TRUE
;
String
literal
=
nextToInternal
(
"{}[]/\\:,=;# \t\f"
);
}
else
if
(
"false"
.
equalsIgnoreCase
(
literal
))
{
return
Boolean
.
FALSE
;
if
(
literal
.
length
()
==
0
)
{
}
throw
syntaxError
(
"Expected literal value"
);
}
/* try to parse as an integral type... */
else
if
(
"null"
.
equalsIgnoreCase
(
literal
))
{
if
(
literal
.
indexOf
(
'.'
)
==
-
1
)
{
return
JSONObject
.
NULL
;
int
base
=
10
;
}
String
number
=
literal
;
else
if
(
"true"
.
equalsIgnoreCase
(
literal
))
{
if
(
number
.
startsWith
(
"0x"
)
||
number
.
startsWith
(
"0X"
))
{
return
Boolean
.
TRUE
;
number
=
number
.
substring
(
2
);
}
base
=
16
;
else
if
(
"false"
.
equalsIgnoreCase
(
literal
))
{
}
else
if
(
number
.
startsWith
(
"0"
)
&&
number
.
length
()
>
1
)
{
return
Boolean
.
FALSE
;
number
=
number
.
substring
(
1
);
}
base
=
8
;
}
/* try to parse as an integral type... */
try
{
if
(
literal
.
indexOf
(
'.'
)
==
-
1
)
{
long
longValue
=
Long
.
parseLong
(
number
,
base
);
int
base
=
10
;
if
(
longValue
<=
Integer
.
MAX_VALUE
&&
longValue
>=
Integer
.
MIN_VALUE
)
{
String
number
=
literal
;
return
(
int
)
longValue
;
if
(
number
.
startsWith
(
"0x"
)
||
number
.
startsWith
(
"0X"
))
{
}
else
{
number
=
number
.
substring
(
2
);
return
longValue
;
base
=
16
;
}
}
}
catch
(
NumberFormatException
e
)
{
else
if
(
number
.
startsWith
(
"0"
)
&&
number
.
length
()
>
1
)
{
/*
number
=
number
.
substring
(
1
);
* This only happens for integral numbers greater than
base
=
8
;
* Long.MAX_VALUE, numbers in exponential form (5e-10) and
}
* unquoted strings. Fall through to try floating point.
try
{
*/
long
longValue
=
Long
.
parseLong
(
number
,
base
);
}
if
(
longValue
<=
Integer
.
MAX_VALUE
&&
longValue
>=
Integer
.
MIN_VALUE
)
{
}
return
(
int
)
longValue
;
}
/* ...next try to parse as a floating point... */
else
{
try
{
return
longValue
;
return
Double
.
valueOf
(
literal
);
}
}
catch
(
NumberFormatException
ignored
)
{
}
}
catch
(
NumberFormatException
e
)
{
/*
/* ... finally give up. We have an unquoted string */
* This only happens for integral numbers greater than
return
new
String
(
literal
);
// a new string avoids leaking memory
* Long.MAX_VALUE, numbers in exponential form (5e-10) and
}
* unquoted strings. Fall through to try floating point.
*/
/**
}
* Returns the string up to but not including any of the given characters or
}
* a newline character. This does not consume the excluded character.
*/
/* ...next try to parse as a floating point... */
private
String
nextToInternal
(
String
excluded
)
{
try
{
int
start
=
pos
;
return
Double
.
valueOf
(
literal
);
for
(;
pos
<
in
.
length
();
pos
++)
{
}
char
c
=
in
.
charAt
(
pos
);
catch
(
NumberFormatException
ignored
)
{
if
(
c
==
'\r'
||
c
==
'\n'
||
excluded
.
indexOf
(
c
)
!=
-
1
)
{
}
return
in
.
substring
(
start
,
pos
);
}
/* ... finally give up. We have an unquoted string */
}
return
new
String
(
literal
);
// a new string avoids leaking memory
return
in
.
substring
(
start
);
}
}
/**
/**
* Returns the string up to but not including any of the given characters or
* Reads a sequence of key/value pairs and the trailing closing brace '}' of
* a newline character. This does not consume the excluded character.
* an object. The opening brace '{' should have already been read.
* @return the string up to but not including any of the given characters or
*/
* a newline character
private
JSONObject
readObject
()
throws
JSONException
{
*/
JSONObject
result
=
new
JSONObject
();
private
String
nextToInternal
(
String
excluded
)
{
int
start
=
this
.
pos
;
/* Peek to see if this is the empty object. */
for
(;
this
.
pos
<
this
.
in
.
length
();
this
.
pos
++)
{
int
first
=
nextCleanInternal
();
char
c
=
this
.
in
.
charAt
(
this
.
pos
);
if
(
first
==
'}'
)
{
if
(
c
==
'\r'
||
c
==
'\n'
||
excluded
.
indexOf
(
c
)
!=
-
1
)
{
return
result
;
return
this
.
in
.
substring
(
start
,
this
.
pos
);
}
else
if
(
first
!=
-
1
)
{
}
pos
--;
}
}
return
this
.
in
.
substring
(
start
);
}
while
(
true
)
{
Object
name
=
nextValue
();
/**
if
(!(
name
instanceof
String
))
{
* Reads a sequence of key/value pairs and the trailing closing brace '}' of
if
(
name
==
null
)
{
* an object. The opening brace '{' should have already been read.
throw
syntaxError
(
"Names cannot be null"
);
* @return an object
}
else
{
* @throws JSONException if processing of json failed
throw
syntaxError
(
"Names must be strings, but "
+
name
*/
+
" is of type "
+
name
.
getClass
().
getName
());
private
JSONObject
readObject
()
throws
JSONException
{
}
JSONObject
result
=
new
JSONObject
();
}
/* Peek to see if this is the empty object. */
/*
int
first
=
nextCleanInternal
();
* Expect the name/value separator to be either a colon ':', an
if
(
first
==
'}'
)
{
* equals sign '=', or an arrow "=>". The last two are bogus but we
return
result
;
* include them because that's what the original implementation did.
}
*/
else
if
(
first
!=
-
1
)
{
int
separator
=
nextCleanInternal
();
this
.
pos
--;
if
(
separator
!=
':'
&&
separator
!=
'='
)
{
}
throw
syntaxError
(
"Expected ':' after "
+
name
);
}
while
(
true
)
{
if
(
pos
<
in
.
length
()
&&
in
.
charAt
(
pos
)
==
'>'
)
{
Object
name
=
nextValue
();
pos
++;
if
(!(
name
instanceof
String
))
{
}
if
(
name
==
null
)
{
throw
syntaxError
(
"Names cannot be null"
);
result
.
put
((
String
)
name
,
nextValue
());
}
else
{
switch
(
nextCleanInternal
())
{
throw
syntaxError
(
"Names must be strings, but "
+
name
case
'}'
:
+
" is of type "
+
name
.
getClass
().
getName
());
return
result
;
}
case
';'
:
}
case
','
:
continue
;
/*
default
:
* Expect the name/value separator to be either a colon ':', an
throw
syntaxError
(
"Unterminated object"
);
* equals sign '=', or an arrow "=>". The last two are bogus but we
}
* include them because that's what the original implementation did.
}
*/
}
int
separator
=
nextCleanInternal
();
if
(
separator
!=
':'
&&
separator
!=
'='
)
{
/**
throw
syntaxError
(
"Expected ':' after "
+
name
);
* Reads a sequence of values and the trailing closing brace ']' of an
}
* array. The opening brace '[' should have already been read. Note that
if
(
this
.
pos
<
this
.
in
.
length
()
&&
this
.
in
.
charAt
(
this
.
pos
)
==
'>'
)
{
* "[]" yields an empty array, but "[,]" returns a two-element array
this
.
pos
++;
* equivalent to "[null,null]".
}
*/
private
JSONArray
readArray
()
throws
JSONException
{
result
.
put
((
String
)
name
,
nextValue
());
JSONArray
result
=
new
JSONArray
();
switch
(
nextCleanInternal
())
{
/* to cover input that ends with ",]". */
case
'}'
:
boolean
hasTrailingSeparator
=
false
;
return
result
;
case
';'
:
while
(
true
)
{
case
','
:
switch
(
nextCleanInternal
())
{
continue
;
case
-
1
:
default
:
throw
syntaxError
(
"Unterminated array"
);
throw
syntaxError
(
"Unterminated object"
);
case
']'
:
}
if
(
hasTrailingSeparator
)
{
}
result
.
put
(
null
);
}
}
return
result
;
/**
case
','
:
* Reads a sequence of values and the trailing closing brace ']' of an
case
';'
:
* array. The opening brace '[' should have already been read. Note that
/* A separator without a value first means "null". */
* "[]" yields an empty array, but "[,]" returns a two-element array
result
.
put
(
null
);
* equivalent to "[null,null]".
hasTrailingSeparator
=
true
;
* @return an array
continue
;
* @throws JSONException if processing of json failed
default
:
*/
pos
--;
private
JSONArray
readArray
()
throws
JSONException
{
}
JSONArray
result
=
new
JSONArray
();
result
.
put
(
nextValue
());
/* to cover input that ends with ",]". */
boolean
hasTrailingSeparator
=
false
;
switch
(
nextCleanInternal
())
{
case
']'
:
while
(
true
)
{
return
result
;
switch
(
nextCleanInternal
())
{
case
','
:
case
-
1
:
case
';'
:
throw
syntaxError
(
"Unterminated array"
);
hasTrailingSeparator
=
true
;
case
']'
:
continue
;
if
(
hasTrailingSeparator
)
{
default
:
result
.
put
(
null
);
throw
syntaxError
(
"Unterminated array"
);
}
}
return
result
;
}
case
','
:
}
case
';'
:
/* A separator without a value first means "null". */
/**
result
.
put
(
null
);
* Returns an exception containing the given message plus the current
hasTrailingSeparator
=
true
;
* position and the entire input string.
continue
;
*/
default
:
public
JSONException
syntaxError
(
String
message
)
{
this
.
pos
--;
return
new
JSONException
(
message
+
this
);
}
}
result
.
put
(
nextValue
());
/**
* Returns the current position and the entire input string.
switch
(
nextCleanInternal
())
{
*/
case
']'
:
@Override
public
String
toString
()
{
return
result
;
// consistent with the original implementation
case
','
:
return
" at character "
+
pos
+
" of "
+
in
;
case
';'
:
}
hasTrailingSeparator
=
true
;
continue
;
/*
default
:
* Legacy APIs.
throw
syntaxError
(
"Unterminated array"
);
*
}
* None of the methods below are on the critical path of parsing JSON
}
* documents. They exist only because they were exposed by the original
}
* implementation and may be used by some clients.
*/
/**
* Returns an exception containing the given message plus the current
/**
* position and the entire input string.
* Returns true until the input has been exhausted.
* @param message the message
*/
* @return an exception
public
boolean
more
()
{
*/
return
pos
<
in
.
length
();
public
JSONException
syntaxError
(
String
message
)
{
}
return
new
JSONException
(
message
+
this
);
}
/**
* Returns the next available character, or the null character '\0' if all
/**
* input has been exhausted. The return value of this method is ambiguous
* Returns the current position and the entire input string.
* for JSON strings that contain the character '\0'.
* @return the current position and the entire input string.
*/
*/
public
char
next
()
{
@Override
return
pos
<
in
.
length
()
?
in
.
charAt
(
pos
++)
:
'\0'
;
public
String
toString
()
{
}
// consistent with the original implementation
return
" at character "
+
this
.
pos
+
" of "
+
this
.
in
;
/**
}
* Returns the next available character if it equals {@code c}. Otherwise an
* exception is thrown.
/*
*/
* Legacy APIs.
public
char
next
(
char
c
)
throws
JSONException
{
*
char
result
=
next
();
* None of the methods below are on the critical path of parsing JSON
if
(
result
!=
c
)
{
* documents. They exist only because they were exposed by the original
throw
syntaxError
(
"Expected "
+
c
+
" but was "
+
result
);
* implementation and may be used by some clients.
}
*/
return
result
;
}
public
boolean
more
()
{
return
this
.
pos
<
this
.
in
.
length
();
/**
}
* Returns the next character that is not whitespace and does not belong to
* a comment. If the input is exhausted before such a character can be
public
char
next
()
{
* found, the null character '\0' is returned. The return value of this
return
this
.
pos
<
this
.
in
.
length
()
?
this
.
in
.
charAt
(
this
.
pos
++)
:
'\0'
;
* method is ambiguous for JSON strings that contain the character '\0'.
}
*/
public
char
nextClean
()
throws
JSONException
{
public
char
next
(
char
c
)
throws
JSONException
{
int
nextCleanInt
=
nextCleanInternal
();
char
result
=
next
();
return
nextCleanInt
==
-
1
?
'\0'
:
(
char
)
nextCleanInt
;
if
(
result
!=
c
)
{
}
throw
syntaxError
(
"Expected "
+
c
+
" but was "
+
result
);
}
/**
return
result
;
* Returns the next {@code length} characters of the input.
}
*
* <p>The returned string shares its backing character array with this
public
char
nextClean
()
throws
JSONException
{
* tokener's input string. If a reference to the returned string may be held
int
nextCleanInt
=
nextCleanInternal
();
* indefinitely, you should use {@code new String(result)} to copy it first
return
nextCleanInt
==
-
1
?
'\0'
:
(
char
)
nextCleanInt
;
* to avoid memory leaks.
}
*
* @throws JSONException if the remaining input is not long enough to
public
String
next
(
int
length
)
throws
JSONException
{
* satisfy this request.
if
(
this
.
pos
+
length
>
this
.
in
.
length
())
{
*/
throw
syntaxError
(
length
+
" is out of bounds"
);
public
String
next
(
int
length
)
throws
JSONException
{
}
if
(
pos
+
length
>
in
.
length
())
{
String
result
=
this
.
in
.
substring
(
this
.
pos
,
this
.
pos
+
length
);
throw
syntaxError
(
length
+
" is out of bounds"
);
this
.
pos
+=
length
;
}
return
result
;
String
result
=
in
.
substring
(
pos
,
pos
+
length
);
}
pos
+=
length
;
return
result
;
public
String
nextTo
(
String
excluded
)
{
}
if
(
excluded
==
null
)
{
throw
new
NullPointerException
(
"excluded == null"
);
/**
}
* Returns the {@link String#trim trimmed} string holding the characters up
return
nextToInternal
(
excluded
).
trim
();
* to but not including the first of:
}
* <ul>
* <li>any character in {@code excluded}
public
String
nextTo
(
char
excluded
)
{
* <li>a newline character '\n'
return
nextToInternal
(
String
.
valueOf
(
excluded
)).
trim
();
* <li>a carriage return '\r'
}
* </ul>
*
public
void
skipPast
(
String
thru
)
{
* <p>The returned string shares its backing character array with this
int
thruStart
=
this
.
in
.
indexOf
(
thru
,
this
.
pos
);
* tokener's input string. If a reference to the returned string may be held
this
.
pos
=
thruStart
==
-
1
?
this
.
in
.
length
()
:
(
thruStart
+
thru
.
length
());
* indefinitely, you should use {@code new String(result)} to copy it first
}
* to avoid memory leaks.
*
public
char
skipTo
(
char
to
)
{
* @return a possibly-empty string
int
index
=
this
.
in
.
indexOf
(
to
,
this
.
pos
);
*/
if
(
index
!=
-
1
)
{
public
String
nextTo
(
String
excluded
)
{
this
.
pos
=
index
;
if
(
excluded
==
null
)
{
return
to
;
throw
new
NullPointerException
(
"excluded == null"
);
}
}
else
{
return
nextToInternal
(
excluded
).
trim
();
return
'\0'
;
}
}
}
/**
* Equivalent to {@code nextTo(String.valueOf(excluded))}.
public
void
back
()
{
*/
if
(--
this
.
pos
==
-
1
)
{
public
String
nextTo
(
char
excluded
)
{
this
.
pos
=
0
;
return
nextToInternal
(
String
.
valueOf
(
excluded
)).
trim
();
}
}
}
/**
public
static
int
dehexchar
(
char
hex
)
{
* Advances past all input up to and including the next occurrence of
if
(
hex
>=
'0'
&&
hex
<=
'9'
)
{
* {@code thru}. If the remaining input doesn't contain {@code thru}, the
return
hex
-
'0'
;
* input is exhausted.
}
*/
else
if
(
hex
>=
'A'
&&
hex
<=
'F'
)
{
public
void
skipPast
(
String
thru
)
{
return
hex
-
'A'
+
10
;
int
thruStart
=
in
.
indexOf
(
thru
,
pos
);
}
pos
=
thruStart
==
-
1
?
in
.
length
()
:
(
thruStart
+
thru
.
length
());
else
if
(
hex
>=
'a'
&&
hex
<=
'f'
)
{
}
return
hex
-
'a'
+
10
;
}
/**
else
{
* Advances past all input up to but not including the next occurrence of
return
-
1
;
* {@code to}. If the remaining input doesn't contain {@code to}, the input
}
* is unchanged.
}
*/
public
char
skipTo
(
char
to
)
{
int
index
=
in
.
indexOf
(
to
,
pos
);
if
(
index
!=
-
1
)
{
pos
=
index
;
return
to
;
}
else
{
return
'\0'
;
}
}
/**
* Unreads the most recent character of input. If no input characters have
* been read, the input is unchanged.
*/
public
void
back
()
{
if
(--
pos
==
-
1
)
{
pos
=
0
;
}
}
/**
* Returns the integer [0..15] value for the given hex character, or -1
* for non-hex input.
*
* @param hex a character in the ranges [0-9], [A-F] or [a-f]. Any other
* character will yield a -1 result.
*/
public
static
int
dehexchar
(
char
hex
)
{
if
(
hex
>=
'0'
&&
hex
<=
'9'
)
{
return
hex
-
'0'
;
}
else
if
(
hex
>=
'A'
&&
hex
<=
'F'
)
{
return
hex
-
'A'
+
10
;
}
else
if
(
hex
>=
'a'
&&
hex
<=
'f'
)
{
return
hex
-
'a'
+
10
;
}
else
{
return
-
1
;
}
}
}
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment