mirror of
https://github.com/stleary/JSON-java.git
synced 2026-01-24 00:03:17 -05:00
Compare commits
33 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbd8b18c4a | ||
|
|
f12fa9ba5f | ||
|
|
80e2ea2a80 | ||
|
|
2917104b53 | ||
|
|
9e0fc5e680 | ||
|
|
724fb888f7 | ||
|
|
eb806f4c14 | ||
|
|
5ff8b4cb08 | ||
|
|
5ef4f58ef1 | ||
|
|
413bb53b48 | ||
|
|
237376eca6 | ||
|
|
e0616a129e | ||
|
|
93ffca36c3 | ||
|
|
e477d7002b | ||
|
|
fb1db9341e | ||
|
|
adb0478f66 | ||
|
|
f58a0f4684 | ||
|
|
c11e09959c | ||
|
|
68f92eb395 | ||
|
|
34652a8706 | ||
|
|
a2d3b59394 | ||
|
|
c24be0e4ea | ||
|
|
88f65c5bea | ||
|
|
ebe69df8e4 | ||
|
|
2f2cd4dfc5 | ||
|
|
349a209df3 | ||
|
|
7851e9b2e8 | ||
|
|
7232a95c0b | ||
|
|
f96f505188 | ||
|
|
91107e3e82 | ||
|
|
4e8e24d49d | ||
|
|
f881b61c81 | ||
|
|
0c157cae75 |
@@ -25,6 +25,7 @@ SOFTWARE.
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
import java.util.Locale;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an HTTP header to a JSONObject and back.
|
* Convert an HTTP header to a JSONObject and back.
|
||||||
@@ -74,7 +75,7 @@ public class HTTP {
|
|||||||
String token;
|
String token;
|
||||||
|
|
||||||
token = x.nextToken();
|
token = x.nextToken();
|
||||||
if (token.toUpperCase().startsWith("HTTP")) {
|
if (token.toUpperCase(Locale.ROOT).startsWith("HTTP")) {
|
||||||
|
|
||||||
// Response
|
// Response
|
||||||
|
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ import java.util.Map;
|
|||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @author JSON.org
|
* @author JSON.org
|
||||||
* @version 2016-05-20
|
* @version 2016-08/15
|
||||||
*/
|
*/
|
||||||
public class JSONArray implements Iterable<Object> {
|
public class JSONArray implements Iterable<Object> {
|
||||||
|
|
||||||
@@ -961,7 +961,7 @@ public class JSONArray implements Iterable<Object> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a JSONPointer using an intialization string and tries to
|
* Creates a JSONPointer using an initialization string and tries to
|
||||||
* match it to an item within this JSONArray. For example, given a
|
* match it to an item within this JSONArray. For example, given a
|
||||||
* JSONArray initialized with this document:
|
* JSONArray initialized with this document:
|
||||||
* <pre>
|
* <pre>
|
||||||
@@ -980,7 +980,30 @@ public class JSONArray implements Iterable<Object> {
|
|||||||
* @return the item matched by the JSONPointer, otherwise null
|
* @return the item matched by the JSONPointer, otherwise null
|
||||||
*/
|
*/
|
||||||
public Object query(String jsonPointer) {
|
public Object query(String jsonPointer) {
|
||||||
return new JSONPointer(jsonPointer).queryFrom(this);
|
return query(new JSONPointer(jsonPointer));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Uses a uaer initialized JSONPointer and tries to
|
||||||
|
* match it to an item whithin this JSONArray. For example, given a
|
||||||
|
* JSONArray initialized with this document:
|
||||||
|
* <pre>
|
||||||
|
* [
|
||||||
|
* {"b":"c"}
|
||||||
|
* ]
|
||||||
|
* </pre>
|
||||||
|
* and this JSONPointer:
|
||||||
|
* <pre>
|
||||||
|
* "/0/b"
|
||||||
|
* </pre>
|
||||||
|
* Then this method will return the String "c"
|
||||||
|
* A JSONPointerException may be thrown from code called by this method.
|
||||||
|
*
|
||||||
|
* @param jsonPointer string that can be used to create a JSONPointer
|
||||||
|
* @return the item matched by the JSONPointer, otherwise null
|
||||||
|
*/
|
||||||
|
public Object query(JSONPointer jsonPointer) {
|
||||||
|
return jsonPointer.queryFrom(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -992,9 +1015,20 @@ public class JSONArray implements Iterable<Object> {
|
|||||||
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
|
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
|
||||||
*/
|
*/
|
||||||
public Object optQuery(String jsonPointer) {
|
public Object optQuery(String jsonPointer) {
|
||||||
JSONPointer pointer = new JSONPointer(jsonPointer);
|
return optQuery(new JSONPointer(jsonPointer));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries and returns a value from this object using {@code jsonPointer}, or
|
||||||
|
* returns null if the query fails due to a missing key.
|
||||||
|
*
|
||||||
|
* @param The JSON pointer
|
||||||
|
* @return the queried value or {@code null}
|
||||||
|
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
|
||||||
|
*/
|
||||||
|
public Object optQuery(JSONPointer jsonPointer) {
|
||||||
try {
|
try {
|
||||||
return pointer.queryFrom(this);
|
return jsonPointer.queryFrom(this);
|
||||||
} catch (JSONPointerException e) {
|
} catch (JSONPointerException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ public class JSONML {
|
|||||||
if (!(token instanceof String)) {
|
if (!(token instanceof String)) {
|
||||||
throw x.syntaxError("Missing value");
|
throw x.syntaxError("Missing value");
|
||||||
}
|
}
|
||||||
newjo.accumulate(attribute, keepStrings ? token :JSONObject.stringToValue((String)token));
|
newjo.accumulate(attribute, keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token));
|
||||||
token = null;
|
token = null;
|
||||||
} else {
|
} else {
|
||||||
newjo.accumulate(attribute, "");
|
newjo.accumulate(attribute, "");
|
||||||
@@ -226,7 +226,7 @@ public class JSONML {
|
|||||||
} else {
|
} else {
|
||||||
if (ja != null) {
|
if (ja != null) {
|
||||||
ja.put(token instanceof String
|
ja.put(token instanceof String
|
||||||
? keepStrings ? token :JSONObject.stringToValue((String)token)
|
? keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token)
|
||||||
: token);
|
: token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
109
JSONObject.java
109
JSONObject.java
@@ -93,7 +93,7 @@ import java.util.Set;
|
|||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
* @author JSON.org
|
* @author JSON.org
|
||||||
* @version 2016-05-20
|
* @version 2016-08-15
|
||||||
*/
|
*/
|
||||||
public class JSONObject {
|
public class JSONObject {
|
||||||
/**
|
/**
|
||||||
@@ -132,6 +132,7 @@ public class JSONObject {
|
|||||||
*
|
*
|
||||||
* @return The string "null".
|
* @return The string "null".
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "null";
|
return "null";
|
||||||
}
|
}
|
||||||
@@ -837,7 +838,7 @@ public class JSONObject {
|
|||||||
}
|
}
|
||||||
testValidity(number);
|
testValidity(number);
|
||||||
|
|
||||||
// Shave off trailing zeros and decimal point, if possible.
|
// Shave off trailing zeros and decimal point, if possible.
|
||||||
|
|
||||||
String string = number.toString();
|
String string = number.toString();
|
||||||
if (string.indexOf('.') > 0 && string.indexOf('e') < 0
|
if (string.indexOf('.') > 0 && string.indexOf('e') < 0
|
||||||
@@ -1156,9 +1157,9 @@ public class JSONObject {
|
|||||||
&& Character.isUpperCase(key.charAt(0))
|
&& Character.isUpperCase(key.charAt(0))
|
||||||
&& method.getParameterTypes().length == 0) {
|
&& method.getParameterTypes().length == 0) {
|
||||||
if (key.length() == 1) {
|
if (key.length() == 1) {
|
||||||
key = key.toLowerCase();
|
key = key.toLowerCase(Locale.ROOT);
|
||||||
} else if (!Character.isUpperCase(key.charAt(1))) {
|
} else if (!Character.isUpperCase(key.charAt(1))) {
|
||||||
key = key.substring(0, 1).toLowerCase()
|
key = key.substring(0, 1).toLowerCase(Locale.ROOT)
|
||||||
+ key.substring(1);
|
+ key.substring(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1358,7 +1359,29 @@ public class JSONObject {
|
|||||||
* @return the item matched by the JSONPointer, otherwise null
|
* @return the item matched by the JSONPointer, otherwise null
|
||||||
*/
|
*/
|
||||||
public Object query(String jsonPointer) {
|
public Object query(String jsonPointer) {
|
||||||
return new JSONPointer(jsonPointer).queryFrom(this);
|
return query(new JSONPointer(jsonPointer));
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Uses a uaer initialized JSONPointer and tries to
|
||||||
|
* match it to an item within this JSONObject. For example, given a
|
||||||
|
* JSONObject initialized with this document:
|
||||||
|
* <pre>
|
||||||
|
* {
|
||||||
|
* "a":{"b":"c"}
|
||||||
|
* }
|
||||||
|
* </pre>
|
||||||
|
* and this JSONPointer:
|
||||||
|
* <pre>
|
||||||
|
* "/a/b"
|
||||||
|
* </pre>
|
||||||
|
* Then this method will return the String "c".
|
||||||
|
* A JSONPointerException may be thrown from code called by this method.
|
||||||
|
*
|
||||||
|
* @param jsonPointer string that can be used to create a JSONPointer
|
||||||
|
* @return the item matched by the JSONPointer, otherwise null
|
||||||
|
*/
|
||||||
|
public Object query(JSONPointer jsonPointer) {
|
||||||
|
return jsonPointer.queryFrom(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -1370,9 +1393,20 @@ public class JSONObject {
|
|||||||
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
|
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
|
||||||
*/
|
*/
|
||||||
public Object optQuery(String jsonPointer) {
|
public Object optQuery(String jsonPointer) {
|
||||||
JSONPointer pointer = new JSONPointer(jsonPointer);
|
return optQuery(new JSONPointer(jsonPointer));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Queries and returns a value from this object using {@code jsonPointer}, or
|
||||||
|
* returns null if the query fails due to a missing key.
|
||||||
|
*
|
||||||
|
* @param The JSON pointer
|
||||||
|
* @return the queried value or {@code null}
|
||||||
|
* @throws IllegalArgumentException if {@code jsonPointer} has invalid syntax
|
||||||
|
*/
|
||||||
|
public Object optQuery(JSONPointer jsonPointer) {
|
||||||
try {
|
try {
|
||||||
return pointer.queryFrom(this);
|
return jsonPointer.queryFrom(this);
|
||||||
} catch (JSONPointerException e) {
|
} catch (JSONPointerException e) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
@@ -1621,6 +1655,7 @@ public class JSONObject {
|
|||||||
* brace)</small> and ending with <code>}</code> <small>(right
|
* brace)</small> and ending with <code>}</code> <small>(right
|
||||||
* brace)</small>.
|
* brace)</small>.
|
||||||
*/
|
*/
|
||||||
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
try {
|
try {
|
||||||
return this.toString(0);
|
return this.toString(0);
|
||||||
@@ -1691,7 +1726,18 @@ public class JSONObject {
|
|||||||
throw new JSONException("Bad value from toJSONString: " + object);
|
throw new JSONException("Bad value from toJSONString: " + object);
|
||||||
}
|
}
|
||||||
if (value instanceof Number) {
|
if (value instanceof Number) {
|
||||||
return numberToString((Number) value);
|
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
|
||||||
|
final String numberAsString = numberToString((Number) value);
|
||||||
|
try {
|
||||||
|
// Use the BigDecimal constructor for it's parser to validate the format.
|
||||||
|
new BigDecimal(numberAsString);
|
||||||
|
// Close enough to a JSON number that we will return it unquoted
|
||||||
|
return numberAsString;
|
||||||
|
} catch (NumberFormatException ex){
|
||||||
|
// The Number value is not a valid JSON number.
|
||||||
|
// Instead we will quote it as a string
|
||||||
|
return quote(numberAsString);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (value instanceof Boolean || value instanceof JSONObject
|
if (value instanceof Boolean || value instanceof JSONObject
|
||||||
|| value instanceof JSONArray) {
|
|| value instanceof JSONArray) {
|
||||||
@@ -1708,6 +1754,9 @@ public class JSONObject {
|
|||||||
if (value.getClass().isArray()) {
|
if (value.getClass().isArray()) {
|
||||||
return new JSONArray(value).toString();
|
return new JSONArray(value).toString();
|
||||||
}
|
}
|
||||||
|
if(value instanceof Enum<?>){
|
||||||
|
return quote(((Enum<?>)value).name());
|
||||||
|
}
|
||||||
return quote(value.toString());
|
return quote(value.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1735,7 +1784,7 @@ public class JSONObject {
|
|||||||
|| object instanceof Long || object instanceof Boolean
|
|| object instanceof Long || object instanceof Boolean
|
||||||
|| object instanceof Float || object instanceof Double
|
|| object instanceof Float || object instanceof Double
|
||||||
|| object instanceof String || object instanceof BigInteger
|
|| object instanceof String || object instanceof BigInteger
|
||||||
|| object instanceof BigDecimal) {
|
|| object instanceof BigDecimal || object instanceof Enum) {
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1781,6 +1830,32 @@ public class JSONObject {
|
|||||||
int indentFactor, int indent) throws JSONException, IOException {
|
int indentFactor, int indent) throws JSONException, IOException {
|
||||||
if (value == null || value.equals(null)) {
|
if (value == null || value.equals(null)) {
|
||||||
writer.write("null");
|
writer.write("null");
|
||||||
|
} else if (value instanceof JSONString) {
|
||||||
|
Object o;
|
||||||
|
try {
|
||||||
|
o = ((JSONString) value).toJSONString();
|
||||||
|
} catch (Exception e) {
|
||||||
|
throw new JSONException(e);
|
||||||
|
}
|
||||||
|
writer.write(o != null ? o.toString() : quote(value.toString()));
|
||||||
|
} else if (value instanceof Number) {
|
||||||
|
// not all Numbers may match actual JSON Numbers. i.e. fractions or Imaginary
|
||||||
|
final String numberAsString = numberToString((Number) value);
|
||||||
|
try {
|
||||||
|
// Use the BigDecimal constructor for it's parser to validate the format.
|
||||||
|
@SuppressWarnings("unused")
|
||||||
|
BigDecimal testNum = new BigDecimal(numberAsString);
|
||||||
|
// Close enough to a JSON number that we will use it unquoted
|
||||||
|
writer.write(numberAsString);
|
||||||
|
} catch (NumberFormatException ex){
|
||||||
|
// The Number value is not a valid JSON number.
|
||||||
|
// Instead we will quote it as a string
|
||||||
|
quote(numberAsString, writer);
|
||||||
|
}
|
||||||
|
} else if (value instanceof Boolean) {
|
||||||
|
writer.write(value.toString());
|
||||||
|
} else if (value instanceof Enum<?>) {
|
||||||
|
writer.write(quote(((Enum<?>)value).name()));
|
||||||
} else if (value instanceof JSONObject) {
|
} else if (value instanceof JSONObject) {
|
||||||
((JSONObject) value).write(writer, indentFactor, indent);
|
((JSONObject) value).write(writer, indentFactor, indent);
|
||||||
} else if (value instanceof JSONArray) {
|
} else if (value instanceof JSONArray) {
|
||||||
@@ -1793,18 +1868,6 @@ public class JSONObject {
|
|||||||
new JSONArray(coll).write(writer, indentFactor, indent);
|
new JSONArray(coll).write(writer, indentFactor, indent);
|
||||||
} else if (value.getClass().isArray()) {
|
} else if (value.getClass().isArray()) {
|
||||||
new JSONArray(value).write(writer, indentFactor, indent);
|
new JSONArray(value).write(writer, indentFactor, indent);
|
||||||
} else if (value instanceof Number) {
|
|
||||||
writer.write(numberToString((Number) value));
|
|
||||||
} else if (value instanceof Boolean) {
|
|
||||||
writer.write(value.toString());
|
|
||||||
} else if (value instanceof JSONString) {
|
|
||||||
Object o;
|
|
||||||
try {
|
|
||||||
o = ((JSONString) value).toJSONString();
|
|
||||||
} catch (Exception e) {
|
|
||||||
throw new JSONException(e);
|
|
||||||
}
|
|
||||||
writer.write(o != null ? o.toString() : quote(value.toString()));
|
|
||||||
} else {
|
} else {
|
||||||
quote(value.toString(), writer);
|
quote(value.toString(), writer);
|
||||||
}
|
}
|
||||||
@@ -1880,13 +1943,13 @@ public class JSONObject {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns a java.util.Map containing all of the entrys in this object.
|
* Returns a java.util.Map containing all of the entries in this object.
|
||||||
* If an entry in the object is a JSONArray or JSONObject it will also
|
* If an entry in the object is a JSONArray or JSONObject it will also
|
||||||
* be converted.
|
* be converted.
|
||||||
* <p>
|
* <p>
|
||||||
* Warning: This method assumes that the data structure is acyclical.
|
* Warning: This method assumes that the data structure is acyclical.
|
||||||
*
|
*
|
||||||
* @return a java.util.Map containing the entrys of this object
|
* @return a java.util.Map containing the entries of this object
|
||||||
*/
|
*/
|
||||||
public Map<String, Object> toMap() {
|
public Map<String, Object> toMap() {
|
||||||
Map<String, Object> results = new HashMap<String, Object>();
|
Map<String, Object> results = new HashMap<String, Object>();
|
||||||
|
|||||||
@@ -138,7 +138,7 @@ public class JSONPointer {
|
|||||||
if (pointer == null) {
|
if (pointer == null) {
|
||||||
throw new NullPointerException("pointer cannot be null");
|
throw new NullPointerException("pointer cannot be null");
|
||||||
}
|
}
|
||||||
if (pointer.isEmpty()) {
|
if (pointer.isEmpty() || pointer.equals("#")) {
|
||||||
refTokens = Collections.emptyList();
|
refTokens = Collections.emptyList();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package org.json;
|
package org.json;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.Writer;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2006 JSON.org
|
Copyright (c) 2006 JSON.org
|
||||||
@@ -50,11 +49,11 @@ SOFTWARE.
|
|||||||
* <p>
|
* <p>
|
||||||
* The first method called must be <code>array</code> or <code>object</code>.
|
* The first method called must be <code>array</code> or <code>object</code>.
|
||||||
* There are no methods for adding commas or colons. JSONWriter adds them for
|
* There are no methods for adding commas or colons. JSONWriter adds them for
|
||||||
* you. Objects and arrays can be nested up to 20 levels deep.
|
* you. Objects and arrays can be nested up to 200 levels deep.
|
||||||
* <p>
|
* <p>
|
||||||
* This can sometimes be easier than using a JSONObject to build a string.
|
* This can sometimes be easier than using a JSONObject to build a string.
|
||||||
* @author JSON.org
|
* @author JSON.org
|
||||||
* @version 2015-12-09
|
* @version 2016-08-08
|
||||||
*/
|
*/
|
||||||
public class JSONWriter {
|
public class JSONWriter {
|
||||||
private static final int maxdepth = 200;
|
private static final int maxdepth = 200;
|
||||||
@@ -88,12 +87,12 @@ public class JSONWriter {
|
|||||||
/**
|
/**
|
||||||
* The writer that will receive the output.
|
* The writer that will receive the output.
|
||||||
*/
|
*/
|
||||||
protected Writer writer;
|
protected Appendable writer;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a fresh JSONWriter. It can be used to build one JSON text.
|
* Make a fresh JSONWriter. It can be used to build one JSON text.
|
||||||
*/
|
*/
|
||||||
public JSONWriter(Writer w) {
|
public JSONWriter(Appendable w) {
|
||||||
this.comma = false;
|
this.comma = false;
|
||||||
this.mode = 'i';
|
this.mode = 'i';
|
||||||
this.stack = new JSONObject[maxdepth];
|
this.stack = new JSONObject[maxdepth];
|
||||||
@@ -114,9 +113,9 @@ public class JSONWriter {
|
|||||||
if (this.mode == 'o' || this.mode == 'a') {
|
if (this.mode == 'o' || this.mode == 'a') {
|
||||||
try {
|
try {
|
||||||
if (this.comma && this.mode == 'a') {
|
if (this.comma && this.mode == 'a') {
|
||||||
this.writer.write(',');
|
this.writer.append(',');
|
||||||
}
|
}
|
||||||
this.writer.write(string);
|
this.writer.append(string);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new JSONException(e);
|
throw new JSONException(e);
|
||||||
}
|
}
|
||||||
@@ -163,7 +162,7 @@ public class JSONWriter {
|
|||||||
}
|
}
|
||||||
this.pop(mode);
|
this.pop(mode);
|
||||||
try {
|
try {
|
||||||
this.writer.write(c);
|
this.writer.append(c);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new JSONException(e);
|
throw new JSONException(e);
|
||||||
}
|
}
|
||||||
@@ -207,10 +206,10 @@ public class JSONWriter {
|
|||||||
try {
|
try {
|
||||||
this.stack[this.top - 1].putOnce(string, Boolean.TRUE);
|
this.stack[this.top - 1].putOnce(string, Boolean.TRUE);
|
||||||
if (this.comma) {
|
if (this.comma) {
|
||||||
this.writer.write(',');
|
this.writer.append(',');
|
||||||
}
|
}
|
||||||
this.writer.write(JSONObject.quote(string));
|
this.writer.append(JSONObject.quote(string));
|
||||||
this.writer.write(':');
|
this.writer.append(':');
|
||||||
this.comma = false;
|
this.comma = false;
|
||||||
this.mode = 'o';
|
this.mode = 'o';
|
||||||
return this;
|
return this;
|
||||||
|
|||||||
2
LICENSE
2
LICENSE
@@ -1,3 +1,5 @@
|
|||||||
|
============================================================================
|
||||||
|
|
||||||
Copyright (c) 2002 JSON.org
|
Copyright (c) 2002 JSON.org
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
|||||||
3
README
3
README
@@ -22,7 +22,7 @@ JSONObject.java: The JSONObject can parse text from a String or a JSONTokener
|
|||||||
to produce a map-like object. The object provides methods for manipulating its
|
to produce a map-like object. The object provides methods for manipulating its
|
||||||
contents, and for producing a JSON compliant object serialization.
|
contents, and for producing a JSON compliant object serialization.
|
||||||
|
|
||||||
JSONArray.java: The JSONObject can parse text from a String or a JSONTokener
|
JSONArray.java: The JSONArray can parse text from a String or a JSONTokener
|
||||||
to produce a vector-like object. The object provides methods for manipulating
|
to produce a vector-like object. The object provides methods for manipulating
|
||||||
its contents, and for producing a JSON compliant array serialization.
|
its contents, and for producing a JSON compliant array serialization.
|
||||||
|
|
||||||
@@ -89,6 +89,7 @@ invalid number formats (1.2e6.3) will cause errors as such documents can not be
|
|||||||
reliably.
|
reliably.
|
||||||
|
|
||||||
Release history:
|
Release history:
|
||||||
|
20170516 Roll up recent commits.
|
||||||
|
|
||||||
20160810 Revert code that was breaking opt*() methods.
|
20160810 Revert code that was breaking opt*() methods.
|
||||||
|
|
||||||
|
|||||||
153
XML.java
153
XML.java
@@ -31,11 +31,10 @@ import java.util.Iterator;
|
|||||||
* covert a JSONObject into an XML text.
|
* covert a JSONObject into an XML text.
|
||||||
*
|
*
|
||||||
* @author JSON.org
|
* @author JSON.org
|
||||||
* @version 2016-01-30
|
* @version 2016-08-10
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("boxing")
|
@SuppressWarnings("boxing")
|
||||||
public class XML {
|
public class XML {
|
||||||
|
|
||||||
/** The Character '&'. */
|
/** The Character '&'. */
|
||||||
public static final Character AMP = '&';
|
public static final Character AMP = '&';
|
||||||
|
|
||||||
@@ -62,6 +61,46 @@ public class XML {
|
|||||||
|
|
||||||
/** The Character '/'. */
|
/** The Character '/'. */
|
||||||
public static final Character SLASH = '/';
|
public static final Character SLASH = '/';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates an iterator for navigating Code Points in a string instead of
|
||||||
|
* characters. Once Java7 support is dropped, this can be replaced with
|
||||||
|
* <code>
|
||||||
|
* string.codePoints()
|
||||||
|
* </code>
|
||||||
|
* which is available in Java8 and above.
|
||||||
|
*
|
||||||
|
* @see <a href=
|
||||||
|
* "http://stackoverflow.com/a/21791059/6030888">http://stackoverflow.com/a/21791059/6030888</a>
|
||||||
|
*/
|
||||||
|
private static Iterable<Integer> codePointIterator(final String string) {
|
||||||
|
return new Iterable<Integer>() {
|
||||||
|
@Override
|
||||||
|
public Iterator<Integer> iterator() {
|
||||||
|
return new Iterator<Integer>() {
|
||||||
|
private int nextIndex = 0;
|
||||||
|
private int length = string.length();
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean hasNext() {
|
||||||
|
return this.nextIndex < this.length;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Integer next() {
|
||||||
|
int result = string.codePointAt(this.nextIndex);
|
||||||
|
this.nextIndex += Character.charCount(result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void remove() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace special characters with XML escapes:
|
* Replace special characters with XML escapes:
|
||||||
@@ -71,6 +110,7 @@ public class XML {
|
|||||||
* < <small>(less than)</small> is replaced by &lt;
|
* < <small>(less than)</small> is replaced by &lt;
|
||||||
* > <small>(greater than)</small> is replaced by &gt;
|
* > <small>(greater than)</small> is replaced by &gt;
|
||||||
* " <small>(double quote)</small> is replaced by &quot;
|
* " <small>(double quote)</small> is replaced by &quot;
|
||||||
|
* ' <small>(single quote / apostrophe)</small> is replaced by &apos;
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param string
|
* @param string
|
||||||
@@ -79,9 +119,8 @@ public class XML {
|
|||||||
*/
|
*/
|
||||||
public static String escape(String string) {
|
public static String escape(String string) {
|
||||||
StringBuilder sb = new StringBuilder(string.length());
|
StringBuilder sb = new StringBuilder(string.length());
|
||||||
for (int i = 0, length = string.length(); i < length; i++) {
|
for (final int cp : codePointIterator(string)) {
|
||||||
char c = string.charAt(i);
|
switch (cp) {
|
||||||
switch (c) {
|
|
||||||
case '&':
|
case '&':
|
||||||
sb.append("&");
|
sb.append("&");
|
||||||
break;
|
break;
|
||||||
@@ -98,6 +137,93 @@ public class XML {
|
|||||||
sb.append("'");
|
sb.append("'");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
if (mustEscape(cp)) {
|
||||||
|
sb.append("&#x");
|
||||||
|
sb.append(Integer.toHexString(cp));
|
||||||
|
sb.append(";");
|
||||||
|
} else {
|
||||||
|
sb.appendCodePoint(cp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param cp code point to test
|
||||||
|
* @return true if the code point is not valid for an XML
|
||||||
|
*/
|
||||||
|
private static boolean mustEscape(int cp) {
|
||||||
|
/* Valid range from https://www.w3.org/TR/REC-xml/#charsets
|
||||||
|
*
|
||||||
|
* #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
|
||||||
|
*
|
||||||
|
* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
|
||||||
|
*/
|
||||||
|
// isISOControl is true when (cp >= 0 && cp <= 0x1F) || (cp >= 0x7F && cp <= 0x9F)
|
||||||
|
// all ISO control characters are out of range except tabs and new lines
|
||||||
|
return (Character.isISOControl(cp)
|
||||||
|
&& cp != 0x9
|
||||||
|
&& cp != 0xA
|
||||||
|
&& cp != 0xD
|
||||||
|
) || !(
|
||||||
|
// valid the range of acceptable characters that aren't control
|
||||||
|
(cp >= 0x20 && cp <= 0xD7FF)
|
||||||
|
|| (cp >= 0xE000 && cp <= 0xFFFD)
|
||||||
|
|| (cp >= 0x10000 && cp <= 0x10FFFF)
|
||||||
|
)
|
||||||
|
;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Removes XML escapes from the string.
|
||||||
|
*
|
||||||
|
* @param string
|
||||||
|
* string to remove escapes from
|
||||||
|
* @return string with converted entities
|
||||||
|
*/
|
||||||
|
public static String unescape(String string) {
|
||||||
|
StringBuilder sb = new StringBuilder(string.length());
|
||||||
|
for (int i = 0, length = string.length(); i < length; i++) {
|
||||||
|
char c = string.charAt(i);
|
||||||
|
if (c == '&') {
|
||||||
|
final int semic = string.indexOf(';', i);
|
||||||
|
if (semic > i) {
|
||||||
|
final String entity = string.substring(i + 1, semic);
|
||||||
|
if (entity.charAt(0) == '#') {
|
||||||
|
int cp;
|
||||||
|
if (entity.charAt(1) == 'x') {
|
||||||
|
// hex encoded unicode
|
||||||
|
cp = Integer.parseInt(entity.substring(2), 16);
|
||||||
|
} else {
|
||||||
|
// decimal encoded unicode
|
||||||
|
cp = Integer.parseInt(entity.substring(1));
|
||||||
|
}
|
||||||
|
sb.appendCodePoint(cp);
|
||||||
|
} else {
|
||||||
|
if ("quot".equalsIgnoreCase(entity)) {
|
||||||
|
sb.append('"');
|
||||||
|
} else if ("amp".equalsIgnoreCase(entity)) {
|
||||||
|
sb.append('&');
|
||||||
|
} else if ("apos".equalsIgnoreCase(entity)) {
|
||||||
|
sb.append('\'');
|
||||||
|
} else if ("lt".equalsIgnoreCase(entity)) {
|
||||||
|
sb.append('<');
|
||||||
|
} else if ("gt".equalsIgnoreCase(entity)) {
|
||||||
|
sb.append('>');
|
||||||
|
} else {
|
||||||
|
sb.append('&').append(entity).append(';');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// skip past the entity we just parsed.
|
||||||
|
i += entity.length() + 1;
|
||||||
|
} else {
|
||||||
|
// this shouldn't happen in most cases since the parser
|
||||||
|
// errors on unclosed enties.
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// not part of an entity
|
||||||
sb.append(c);
|
sb.append(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -227,7 +353,6 @@ public class XML {
|
|||||||
if (token == null) {
|
if (token == null) {
|
||||||
token = x.nextToken();
|
token = x.nextToken();
|
||||||
}
|
}
|
||||||
|
|
||||||
// attribute = value
|
// attribute = value
|
||||||
if (token instanceof String) {
|
if (token instanceof String) {
|
||||||
string = (String) token;
|
string = (String) token;
|
||||||
@@ -238,7 +363,7 @@ public class XML {
|
|||||||
throw x.syntaxError("Missing value");
|
throw x.syntaxError("Missing value");
|
||||||
}
|
}
|
||||||
jsonobject.accumulate(string,
|
jsonobject.accumulate(string,
|
||||||
keepStrings ? token : JSONObject.stringToValue((String) token));
|
keepStrings ? unescape((String)token) : stringToValue((String) token));
|
||||||
token = null;
|
token = null;
|
||||||
} else {
|
} else {
|
||||||
jsonobject.accumulate(string, "");
|
jsonobject.accumulate(string, "");
|
||||||
@@ -270,7 +395,7 @@ public class XML {
|
|||||||
string = (String) token;
|
string = (String) token;
|
||||||
if (string.length() > 0) {
|
if (string.length() > 0) {
|
||||||
jsonobject.accumulate("content",
|
jsonobject.accumulate("content",
|
||||||
keepStrings ? token : JSONObject.stringToValue(string));
|
keepStrings ? unescape(string) : stringToValue(string));
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (token == LT) {
|
} else if (token == LT) {
|
||||||
@@ -297,16 +422,18 @@ public class XML {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method has been deprecated in favor of the
|
* This method is the same as {@link JSONObject.stringToValue(String)}
|
||||||
* {@link JSONObject.stringToValue(String)} method. Use it instead.
|
* except that this also tries to unescape String values.
|
||||||
*
|
*
|
||||||
* @deprecated Use {@link JSONObject#stringToValue(String)} instead.
|
|
||||||
* @param string String to convert
|
* @param string String to convert
|
||||||
* @return JSON value of this string or the string
|
* @return JSON value of this string or the string
|
||||||
*/
|
*/
|
||||||
@Deprecated
|
|
||||||
public static Object stringToValue(String string) {
|
public static Object stringToValue(String string) {
|
||||||
return JSONObject.stringToValue(string);
|
Object ret = JSONObject.stringToValue(string);
|
||||||
|
if(ret instanceof String){
|
||||||
|
return unescape((String)ret);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
Reference in New Issue
Block a user