Config en .json terminée + advancedstatus refait.
This commit is contained in:
parent
f0a0e539a3
commit
bdad98669b
@ -40,6 +40,7 @@ SOFTWARE.
|
|||||||
* A comma delimited list can be converted into a JSONArray of JSONObjects.
|
* A comma delimited list can be converted into a JSONArray of JSONObjects.
|
||||||
* The names for the elements in the JSONObjects can be taken from the names
|
* The names for the elements in the JSONObjects can be taken from the names
|
||||||
* in the first row.
|
* in the first row.
|
||||||
|
*
|
||||||
* @author JSON.org
|
* @author JSON.org
|
||||||
* @version 2016-05-01
|
* @version 2016-05-01
|
||||||
*/
|
*/
|
||||||
@ -48,6 +49,7 @@ public class CDL {
|
|||||||
/**
|
/**
|
||||||
* Get the next value. The value can be wrapped in quotes. The value can
|
* Get the next value. The value can be wrapped in quotes. The value can
|
||||||
* be empty.
|
* be empty.
|
||||||
|
*
|
||||||
* @param x A JSONTokener of the source text.
|
* @param x A JSONTokener of the source text.
|
||||||
* @return The value string, or null if empty.
|
* @return The value string, or null if empty.
|
||||||
* @throws JSONException if the quoted string is badly formed.
|
* @throws JSONException if the quoted string is badly formed.
|
||||||
@ -60,49 +62,50 @@ public class CDL {
|
|||||||
c = x.next();
|
c = x.next();
|
||||||
} while (c == ' ' || c == '\t');
|
} while (c == ' ' || c == '\t');
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0:
|
case 0:
|
||||||
return null;
|
return null;
|
||||||
case '"':
|
case '"':
|
||||||
case '\'':
|
case '\'':
|
||||||
q = c;
|
q = c;
|
||||||
sb = new StringBuffer();
|
sb = new StringBuffer();
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
c = x.next();
|
c = x.next();
|
||||||
if (c == q) {
|
if (c == q) {
|
||||||
//Handle escaped double-quote
|
//Handle escaped double-quote
|
||||||
char nextC = x.next();
|
char nextC = x.next();
|
||||||
if(nextC != '\"') {
|
if (nextC != '\"') {
|
||||||
// if our quote was the end of the file, don't step
|
// if our quote was the end of the file, don't step
|
||||||
if(nextC > 0) {
|
if (nextC > 0) {
|
||||||
x.back();
|
x.back();
|
||||||
|
}
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
if (c == 0 || c == '\n' || c == '\r') {
|
||||||
|
throw x.syntaxError("Missing close quote '" + q + "'.");
|
||||||
|
}
|
||||||
|
sb.append(c);
|
||||||
}
|
}
|
||||||
if (c == 0 || c == '\n' || c == '\r') {
|
return sb.toString();
|
||||||
throw x.syntaxError("Missing close quote '" + q + "'.");
|
case ',':
|
||||||
}
|
x.back();
|
||||||
sb.append(c);
|
return "";
|
||||||
}
|
default:
|
||||||
return sb.toString();
|
x.back();
|
||||||
case ',':
|
return x.nextTo(',');
|
||||||
x.back();
|
|
||||||
return "";
|
|
||||||
default:
|
|
||||||
x.back();
|
|
||||||
return x.nextTo(',');
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce a JSONArray of strings from a row of comma delimited values.
|
* Produce a JSONArray of strings from a row of comma delimited values.
|
||||||
|
*
|
||||||
* @param x A JSONTokener of the source text.
|
* @param x A JSONTokener of the source text.
|
||||||
* @return A JSONArray of strings.
|
* @return A JSONArray of strings.
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException {
|
public static JSONArray rowToJSONArray(JSONTokener x) throws JSONException {
|
||||||
JSONArray ja = new JSONArray();
|
JSONArray ja = new JSONArray();
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
String value = getValue(x);
|
String value = getValue(x);
|
||||||
char c = x.next();
|
char c = x.next();
|
||||||
if (value == null ||
|
if (value == null ||
|
||||||
@ -110,7 +113,7 @@ public class CDL {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ja.put(value);
|
ja.put(value);
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
if (c == ',') {
|
if (c == ',') {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -119,7 +122,7 @@ public class CDL {
|
|||||||
return ja;
|
return ja;
|
||||||
}
|
}
|
||||||
throw x.syntaxError("Bad character '" + c + "' (" +
|
throw x.syntaxError("Bad character '" + c + "' (" +
|
||||||
(int)c + ").");
|
(int) c + ").");
|
||||||
}
|
}
|
||||||
c = x.next();
|
c = x.next();
|
||||||
}
|
}
|
||||||
@ -129,23 +132,25 @@ public class CDL {
|
|||||||
/**
|
/**
|
||||||
* Produce a JSONObject from a row of comma delimited text, using a
|
* Produce a JSONObject from a row of comma delimited text, using a
|
||||||
* parallel JSONArray of strings to provides the names of the elements.
|
* parallel JSONArray of strings to provides the names of the elements.
|
||||||
|
*
|
||||||
* @param names A JSONArray of names. This is commonly obtained from the
|
* @param names A JSONArray of names. This is commonly obtained from the
|
||||||
* first row of a comma delimited text file using the rowToJSONArray
|
* first row of a comma delimited text file using the rowToJSONArray
|
||||||
* method.
|
* method.
|
||||||
* @param x A JSONTokener of the source text.
|
* @param x A JSONTokener of the source text.
|
||||||
* @return A JSONObject combining the names and values.
|
* @return A JSONObject combining the names and values.
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x)
|
public static JSONObject rowToJSONObject(JSONArray names, JSONTokener x)
|
||||||
throws JSONException {
|
throws JSONException {
|
||||||
JSONArray ja = rowToJSONArray(x);
|
JSONArray ja = rowToJSONArray(x);
|
||||||
return ja != null ? ja.toJSONObject(names) : null;
|
return ja != null ? ja.toJSONObject(names) : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Produce a comma delimited text row from a JSONArray. Values containing
|
* Produce a comma delimited text row from a JSONArray. Values containing
|
||||||
* the comma character will be quoted. Troublesome characters may be
|
* the comma character will be quoted. Troublesome characters may be
|
||||||
* removed.
|
* removed.
|
||||||
|
*
|
||||||
* @param ja A JSONArray of strings.
|
* @param ja A JSONArray of strings.
|
||||||
* @return A string ending in NEWLINE.
|
* @return A string ending in NEWLINE.
|
||||||
*/
|
*/
|
||||||
@ -182,6 +187,7 @@ public class CDL {
|
|||||||
/**
|
/**
|
||||||
* Produce a JSONArray of JSONObjects from a comma delimited text string,
|
* Produce a JSONArray of JSONObjects from a comma delimited text string,
|
||||||
* using the first row as a source of names.
|
* using the first row as a source of names.
|
||||||
|
*
|
||||||
* @param string The comma delimited text.
|
* @param string The comma delimited text.
|
||||||
* @return A JSONArray of JSONObjects.
|
* @return A JSONArray of JSONObjects.
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
@ -193,6 +199,7 @@ public class CDL {
|
|||||||
/**
|
/**
|
||||||
* Produce a JSONArray of JSONObjects from a comma delimited text string,
|
* Produce a JSONArray of JSONObjects from a comma delimited text string,
|
||||||
* using the first row as a source of names.
|
* using the first row as a source of names.
|
||||||
|
*
|
||||||
* @param x The JSONTokener containing the comma delimited text.
|
* @param x The JSONTokener containing the comma delimited text.
|
||||||
* @return A JSONArray of JSONObjects.
|
* @return A JSONArray of JSONObjects.
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
@ -204,7 +211,8 @@ public class CDL {
|
|||||||
/**
|
/**
|
||||||
* Produce a JSONArray of JSONObjects from a comma delimited text string
|
* Produce a JSONArray of JSONObjects from a comma delimited text string
|
||||||
* using a supplied JSONArray as the source of element names.
|
* using a supplied JSONArray as the source of element names.
|
||||||
* @param names A JSONArray of strings.
|
*
|
||||||
|
* @param names A JSONArray of strings.
|
||||||
* @param string The comma delimited text.
|
* @param string The comma delimited text.
|
||||||
* @return A JSONArray of JSONObjects.
|
* @return A JSONArray of JSONObjects.
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
@ -217,8 +225,9 @@ public class CDL {
|
|||||||
/**
|
/**
|
||||||
* Produce a JSONArray of JSONObjects from a comma delimited text string
|
* Produce a JSONArray of JSONObjects from a comma delimited text string
|
||||||
* using a supplied JSONArray as the source of element names.
|
* using a supplied JSONArray as the source of element names.
|
||||||
|
*
|
||||||
* @param names A JSONArray of strings.
|
* @param names A JSONArray of strings.
|
||||||
* @param x A JSONTokener of the source text.
|
* @param x A JSONTokener of the source text.
|
||||||
* @return A JSONArray of JSONObjects.
|
* @return A JSONArray of JSONObjects.
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
@ -228,7 +237,7 @@ public class CDL {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
JSONArray ja = new JSONArray();
|
JSONArray ja = new JSONArray();
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
JSONObject jo = rowToJSONObject(names, x);
|
JSONObject jo = rowToJSONObject(names, x);
|
||||||
if (jo == null) {
|
if (jo == null) {
|
||||||
break;
|
break;
|
||||||
@ -246,6 +255,7 @@ public class CDL {
|
|||||||
* Produce a comma delimited text from a JSONArray of JSONObjects. The
|
* Produce a comma delimited text from a JSONArray of JSONObjects. The
|
||||||
* first row will be a list of names obtained by inspecting the first
|
* first row will be a list of names obtained by inspecting the first
|
||||||
* JSONObject.
|
* JSONObject.
|
||||||
|
*
|
||||||
* @param ja A JSONArray of JSONObjects.
|
* @param ja A JSONArray of JSONObjects.
|
||||||
* @return A comma delimited text.
|
* @return A comma delimited text.
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
@ -265,8 +275,9 @@ public class CDL {
|
|||||||
* Produce a comma delimited text from a JSONArray of JSONObjects using
|
* Produce a comma delimited text from a JSONArray of JSONObjects using
|
||||||
* a provided list of names. The list of names is not included in the
|
* a provided list of names. The list of names is not included in the
|
||||||
* output.
|
* output.
|
||||||
|
*
|
||||||
* @param names A JSONArray of strings.
|
* @param names A JSONArray of strings.
|
||||||
* @param ja A JSONArray of JSONObjects.
|
* @param ja A JSONArray of JSONObjects.
|
||||||
* @return A comma delimited text.
|
* @return A comma delimited text.
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
|
@ -27,6 +27,7 @@ SOFTWARE.
|
|||||||
/**
|
/**
|
||||||
* Convert a web browser cookie specification to a JSONObject and back.
|
* Convert a web browser cookie specification to a JSONObject and back.
|
||||||
* JSON and Cookies are both notations for name/value pairs.
|
* JSON and Cookies are both notations for name/value pairs.
|
||||||
|
*
|
||||||
* @author JSON.org
|
* @author JSON.org
|
||||||
* @version 2015-12-09
|
* @version 2015-12-09
|
||||||
*/
|
*/
|
||||||
@ -41,20 +42,21 @@ public class Cookie {
|
|||||||
* only a convention, not a standard. Often, cookies are expected to have
|
* only a convention, not a standard. Often, cookies are expected to have
|
||||||
* encoded values. We encode '=' and ';' because we must. We encode '%' and
|
* encoded values. We encode '=' and ';' because we must. We encode '%' and
|
||||||
* '+' because they are meta characters in URL encoding.
|
* '+' because they are meta characters in URL encoding.
|
||||||
|
*
|
||||||
* @param string The source string.
|
* @param string The source string.
|
||||||
* @return The escaped result.
|
* @return The escaped result.
|
||||||
*/
|
*/
|
||||||
public static String escape(String string) {
|
public static String escape(String string) {
|
||||||
char c;
|
char c;
|
||||||
String s = string.trim();
|
String s = string.trim();
|
||||||
int length = s.length();
|
int length = s.length();
|
||||||
StringBuilder sb = new StringBuilder(length);
|
StringBuilder sb = new StringBuilder(length);
|
||||||
for (int i = 0; i < length; i += 1) {
|
for (int i = 0; i < length; i += 1) {
|
||||||
c = s.charAt(i);
|
c = s.charAt(i);
|
||||||
if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') {
|
if (c < ' ' || c == '+' || c == '%' || c == '=' || c == ';') {
|
||||||
sb.append('%');
|
sb.append('%');
|
||||||
sb.append(Character.forDigit((char)((c >>> 4) & 0x0f), 16));
|
sb.append(Character.forDigit((char) ((c >>> 4) & 0x0f), 16));
|
||||||
sb.append(Character.forDigit((char)(c & 0x0f), 16));
|
sb.append(Character.forDigit((char) (c & 0x0f), 16));
|
||||||
} else {
|
} else {
|
||||||
sb.append(c);
|
sb.append(c);
|
||||||
}
|
}
|
||||||
@ -73,15 +75,16 @@ public class Cookie {
|
|||||||
* stored under the key "value". This method does not do checking or
|
* stored under the key "value". This method does not do checking or
|
||||||
* validation of the parameters. It only converts the cookie string into
|
* validation of the parameters. It only converts the cookie string into
|
||||||
* a JSONObject.
|
* a JSONObject.
|
||||||
|
*
|
||||||
* @param string The cookie specification string.
|
* @param string The cookie specification string.
|
||||||
* @return A JSONObject containing "name", "value", and possibly other
|
* @return A JSONObject containing "name", "value", and possibly other
|
||||||
* members.
|
* members.
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||||
String name;
|
String name;
|
||||||
JSONObject jo = new JSONObject();
|
JSONObject jo = new JSONObject();
|
||||||
Object value;
|
Object value;
|
||||||
JSONTokener x = new JSONTokener(string);
|
JSONTokener x = new JSONTokener(string);
|
||||||
jo.put("name", x.nextTo('='));
|
jo.put("name", x.nextTo('='));
|
||||||
x.next('=');
|
x.next('=');
|
||||||
@ -111,6 +114,7 @@ public class Cookie {
|
|||||||
* If the JSONObject contains "expires", "domain", "path", or "secure"
|
* If the JSONObject contains "expires", "domain", "path", or "secure"
|
||||||
* members, they will be appended to the cookie specification string.
|
* members, they will be appended to the cookie specification string.
|
||||||
* All other members are ignored.
|
* All other members are ignored.
|
||||||
|
*
|
||||||
* @param jo A JSONObject
|
* @param jo A JSONObject
|
||||||
* @return A cookie specification string
|
* @return A cookie specification string
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
@ -142,9 +146,10 @@ public class Cookie {
|
|||||||
/**
|
/**
|
||||||
* Convert <code>%</code><i>hh</i> sequences to single characters, and
|
* Convert <code>%</code><i>hh</i> sequences to single characters, and
|
||||||
* convert plus to space.
|
* convert plus to space.
|
||||||
|
*
|
||||||
* @param string A string that may contain
|
* @param string A string that may contain
|
||||||
* <code>+</code> <small>(plus)</small> and
|
* <code>+</code> <small>(plus)</small> and
|
||||||
* <code>%</code><i>hh</i> sequences.
|
* <code>%</code><i>hh</i> sequences.
|
||||||
* @return The unescaped string.
|
* @return The unescaped string.
|
||||||
*/
|
*/
|
||||||
public static String unescape(String string) {
|
public static String unescape(String string) {
|
||||||
@ -158,7 +163,7 @@ public class Cookie {
|
|||||||
int d = JSONTokener.dehexchar(string.charAt(i + 1));
|
int d = JSONTokener.dehexchar(string.charAt(i + 1));
|
||||||
int e = JSONTokener.dehexchar(string.charAt(i + 2));
|
int e = JSONTokener.dehexchar(string.charAt(i + 2));
|
||||||
if (d >= 0 && e >= 0) {
|
if (d >= 0 && e >= 0) {
|
||||||
c = (char)(d * 16 + e);
|
c = (char) (d * 16 + e);
|
||||||
i += 2;
|
i += 2;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -26,6 +26,7 @@ SOFTWARE.
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a web browser cookie list string to a JSONObject and back.
|
* Convert a web browser cookie list string to a JSONObject and back.
|
||||||
|
*
|
||||||
* @author JSON.org
|
* @author JSON.org
|
||||||
* @version 2015-12-09
|
* @version 2015-12-09
|
||||||
*/
|
*/
|
||||||
@ -36,11 +37,12 @@ public class CookieList {
|
|||||||
* of name/value pairs. The names are separated from the values by '='.
|
* of name/value pairs. The names are separated from the values by '='.
|
||||||
* The pairs are separated by ';'. The names and the values
|
* The pairs are separated by ';'. The names and the values
|
||||||
* will be unescaped, possibly converting '+' and '%' sequences.
|
* will be unescaped, possibly converting '+' and '%' sequences.
|
||||||
*
|
* <p>
|
||||||
* To add a cookie to a cookie list,
|
* To add a cookie to a cookie list,
|
||||||
* cookielistJSONObject.put(cookieJSONObject.getString("name"),
|
* cookielistJSONObject.put(cookieJSONObject.getString("name"),
|
||||||
* cookieJSONObject.getString("value"));
|
* cookieJSONObject.getString("value"));
|
||||||
* @param string A cookie list string
|
*
|
||||||
|
* @param string A cookie list string
|
||||||
* @return A JSONObject
|
* @return A JSONObject
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
@ -61,12 +63,13 @@ public class CookieList {
|
|||||||
* of name/value pairs. The names are separated from the values by '='.
|
* of name/value pairs. The names are separated from the values by '='.
|
||||||
* The pairs are separated by ';'. The characters '%', '+', '=', and ';'
|
* The pairs are separated by ';'. The characters '%', '+', '=', and ';'
|
||||||
* in the names and values are replaced by "%hh".
|
* in the names and values are replaced by "%hh".
|
||||||
|
*
|
||||||
* @param jo A JSONObject
|
* @param jo A JSONObject
|
||||||
* @return A cookie list string
|
* @return A cookie list string
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
public static String toString(JSONObject jo) throws JSONException {
|
public static String toString(JSONObject jo) throws JSONException {
|
||||||
boolean b = false;
|
boolean b = false;
|
||||||
final StringBuilder sb = new StringBuilder();
|
final StringBuilder sb = new StringBuilder();
|
||||||
// Don't use the new entrySet API to maintain Android support
|
// Don't use the new entrySet API to maintain Android support
|
||||||
for (final String key : jo.keySet()) {
|
for (final String key : jo.keySet()) {
|
||||||
|
@ -28,12 +28,15 @@ import java.util.Locale;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert an HTTP header to a JSONObject and back.
|
* Convert an HTTP header to a JSONObject and back.
|
||||||
|
*
|
||||||
* @author JSON.org
|
* @author JSON.org
|
||||||
* @version 2015-12-09
|
* @version 2015-12-09
|
||||||
*/
|
*/
|
||||||
public class HTTP {
|
public class HTTP {
|
||||||
|
|
||||||
/** Carriage return/line feed. */
|
/**
|
||||||
|
* Carriage return/line feed.
|
||||||
|
*/
|
||||||
public static final String CRLF = "\r\n";
|
public static final String CRLF = "\r\n";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -63,15 +66,16 @@ public class HTTP {
|
|||||||
* ...}</pre>
|
* ...}</pre>
|
||||||
* It does no further checking or conversion. It does not parse dates.
|
* It does no further checking or conversion. It does not parse dates.
|
||||||
* It does not do '%' transforms on URLs.
|
* It does not do '%' transforms on URLs.
|
||||||
|
*
|
||||||
* @param string An HTTP header string.
|
* @param string An HTTP header string.
|
||||||
* @return A JSONObject containing the elements and attributes
|
* @return A JSONObject containing the elements and attributes
|
||||||
* of the XML string.
|
* of the XML string.
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||||
JSONObject jo = new JSONObject();
|
JSONObject jo = new JSONObject();
|
||||||
HTTPTokener x = new HTTPTokener(string);
|
HTTPTokener x = new HTTPTokener(string);
|
||||||
String token;
|
String token;
|
||||||
|
|
||||||
token = x.nextToken();
|
token = x.nextToken();
|
||||||
if (token.toUpperCase(Locale.ROOT).startsWith("HTTP")) {
|
if (token.toUpperCase(Locale.ROOT).startsWith("HTTP")) {
|
||||||
@ -119,13 +123,14 @@ public class HTTP {
|
|||||||
* }</pre>
|
* }</pre>
|
||||||
* Any other members of the JSONObject will be output as HTTP fields.
|
* Any other members of the JSONObject will be output as HTTP fields.
|
||||||
* The result will end with two CRLF pairs.
|
* The result will end with two CRLF pairs.
|
||||||
|
*
|
||||||
* @param jo A JSONObject
|
* @param jo A JSONObject
|
||||||
* @return An HTTP header string.
|
* @return An HTTP header string.
|
||||||
* @throws JSONException if the object does not contain enough
|
* @throws JSONException if the object does not contain enough
|
||||||
* information.
|
* information.
|
||||||
*/
|
*/
|
||||||
public static String toString(JSONObject jo) throws JSONException {
|
public static String toString(JSONObject jo) throws JSONException {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
if (jo.has("Status-Code") && jo.has("Reason-Phrase")) {
|
if (jo.has("Status-Code") && jo.has("Reason-Phrase")) {
|
||||||
sb.append(jo.getString("HTTP-Version"));
|
sb.append(jo.getString("HTTP-Version"));
|
||||||
sb.append(' ');
|
sb.append(' ');
|
||||||
@ -147,9 +152,9 @@ public class HTTP {
|
|||||||
// Don't use the new entrySet API to maintain Android support
|
// Don't use the new entrySet API to maintain Android support
|
||||||
for (final String key : jo.keySet()) {
|
for (final String key : jo.keySet()) {
|
||||||
String value = jo.optString(key);
|
String value = jo.optString(key);
|
||||||
if (!"HTTP-Version".equals(key) && !"Status-Code".equals(key) &&
|
if (!"HTTP-Version".equals(key) && !"Status-Code".equals(key) &&
|
||||||
!"Reason-Phrase".equals(key) && !"Method".equals(key) &&
|
!"Reason-Phrase".equals(key) && !"Method".equals(key) &&
|
||||||
!"Request-URI".equals(key) && !JSONObject.NULL.equals(value)) {
|
!"Request-URI".equals(key) && !JSONObject.NULL.equals(value)) {
|
||||||
sb.append(key);
|
sb.append(key);
|
||||||
sb.append(": ");
|
sb.append(": ");
|
||||||
sb.append(jo.optString(key));
|
sb.append(jo.optString(key));
|
||||||
|
@ -27,6 +27,7 @@ SOFTWARE.
|
|||||||
/**
|
/**
|
||||||
* The HTTPTokener extends the JSONTokener to provide additional methods
|
* The HTTPTokener extends the JSONTokener to provide additional methods
|
||||||
* for the parsing of HTTP headers.
|
* for the parsing of HTTP headers.
|
||||||
|
*
|
||||||
* @author JSON.org
|
* @author JSON.org
|
||||||
* @version 2015-12-09
|
* @version 2015-12-09
|
||||||
*/
|
*/
|
||||||
@ -34,6 +35,7 @@ public class HTTPTokener extends JSONTokener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an HTTPTokener from a string.
|
* Construct an HTTPTokener from a string.
|
||||||
|
*
|
||||||
* @param string A source string.
|
* @param string A source string.
|
||||||
*/
|
*/
|
||||||
public HTTPTokener(String string) {
|
public HTTPTokener(String string) {
|
||||||
@ -43,8 +45,9 @@ public class HTTPTokener extends JSONTokener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the next token or string. This is used in parsing HTTP headers.
|
* Get the next token or string. This is used in parsing HTTP headers.
|
||||||
* @throws JSONException
|
*
|
||||||
* @return A String.
|
* @return A String.
|
||||||
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
public String nextToken() throws JSONException {
|
public String nextToken() throws JSONException {
|
||||||
char c;
|
char c;
|
||||||
@ -55,7 +58,7 @@ public class HTTPTokener extends JSONTokener {
|
|||||||
} while (Character.isWhitespace(c));
|
} while (Character.isWhitespace(c));
|
||||||
if (c == '"' || c == '\'') {
|
if (c == '"' || c == '\'') {
|
||||||
q = c;
|
q = c;
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
c = next();
|
c = next();
|
||||||
if (c < ' ') {
|
if (c < ' ') {
|
||||||
throw syntaxError("Unterminated string.");
|
throw syntaxError("Unterminated string.");
|
||||||
@ -66,7 +69,7 @@ public class HTTPTokener extends JSONTokener {
|
|||||||
sb.append(c);
|
sb.append(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
if (c == 0 || Character.isWhitespace(c)) {
|
if (c == 0 || Character.isWhitespace(c)) {
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -7,14 +7,15 @@ package ch.m4th1eu.json;
|
|||||||
* @version 2015-12-09
|
* @version 2015-12-09
|
||||||
*/
|
*/
|
||||||
public class JSONException extends RuntimeException {
|
public class JSONException extends RuntimeException {
|
||||||
/** Serialization ID */
|
/**
|
||||||
|
* Serialization ID
|
||||||
|
*/
|
||||||
private static final long serialVersionUID = 0;
|
private static final long serialVersionUID = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructs a JSONException with an explanatory message.
|
* Constructs a JSONException with an explanatory message.
|
||||||
*
|
*
|
||||||
* @param message
|
* @param message Detail about the reason for the exception.
|
||||||
* Detail about the reason for the exception.
|
|
||||||
*/
|
*/
|
||||||
public JSONException(final String message) {
|
public JSONException(final String message) {
|
||||||
super(message);
|
super(message);
|
||||||
@ -23,10 +24,8 @@ public class JSONException extends RuntimeException {
|
|||||||
/**
|
/**
|
||||||
* Constructs a JSONException with an explanatory message and cause.
|
* Constructs a JSONException with an explanatory message and cause.
|
||||||
*
|
*
|
||||||
* @param message
|
* @param message Detail about the reason for the exception.
|
||||||
* Detail about the reason for the exception.
|
* @param cause The cause.
|
||||||
* @param cause
|
|
||||||
* The cause.
|
|
||||||
*/
|
*/
|
||||||
public JSONException(final String message, final Throwable cause) {
|
public JSONException(final String message, final Throwable cause) {
|
||||||
super(message, cause);
|
super(message, cause);
|
||||||
@ -35,8 +34,7 @@ public class JSONException extends RuntimeException {
|
|||||||
/**
|
/**
|
||||||
* Constructs a new JSONException with the specified cause.
|
* Constructs a new JSONException with the specified cause.
|
||||||
*
|
*
|
||||||
* @param cause
|
* @param cause The cause.
|
||||||
* The cause.
|
|
||||||
*/
|
*/
|
||||||
public JSONException(final Throwable cause) {
|
public JSONException(final Throwable cause) {
|
||||||
super(cause.getMessage(), cause);
|
super(cause.getMessage(), cause);
|
||||||
|
@ -35,28 +35,29 @@ SOFTWARE.
|
|||||||
public class JSONML {
|
public class JSONML {
|
||||||
/**
|
/**
|
||||||
* Parse XML values and store them in a JSONArray.
|
* Parse XML values and store them in a JSONArray.
|
||||||
* @param x The XMLTokener containing the source string.
|
*
|
||||||
* @param arrayForm true if array form, false if object form.
|
* @param x The XMLTokener containing the source string.
|
||||||
* @param ja The JSONArray that is containing the current tag or null
|
* @param arrayForm true if array form, false if object form.
|
||||||
* if we are at the outermost level.
|
* @param ja The JSONArray that is containing the current tag or null
|
||||||
* @param keepStrings Don't type-convert text nodes and attribute values
|
* if we are at the outermost level.
|
||||||
|
* @param keepStrings Don't type-convert text nodes and attribute values
|
||||||
* @return A JSONArray if the value is the outermost tag, otherwise null.
|
* @return A JSONArray if the value is the outermost tag, otherwise null.
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
private static Object parse(
|
private static Object parse(
|
||||||
XMLTokener x,
|
XMLTokener x,
|
||||||
boolean arrayForm,
|
boolean arrayForm,
|
||||||
JSONArray ja,
|
JSONArray ja,
|
||||||
boolean keepStrings
|
boolean keepStrings
|
||||||
) throws JSONException {
|
) throws JSONException {
|
||||||
String attribute;
|
String attribute;
|
||||||
char c;
|
char c;
|
||||||
String closeTag = null;
|
String closeTag = null;
|
||||||
int i;
|
int i;
|
||||||
JSONArray newja = null;
|
JSONArray newja = null;
|
||||||
JSONObject newjo = null;
|
JSONObject newjo = null;
|
||||||
Object token;
|
Object token;
|
||||||
String tagName = null;
|
String tagName = null;
|
||||||
|
|
||||||
// Test for and skip past these forms:
|
// Test for and skip past these forms:
|
||||||
// <!-- ... -->
|
// <!-- ... -->
|
||||||
@ -80,7 +81,7 @@ public class JSONML {
|
|||||||
if (!(token instanceof String)) {
|
if (!(token instanceof String)) {
|
||||||
throw new JSONException(
|
throw new JSONException(
|
||||||
"Expected a closing name instead of '" +
|
"Expected a closing name instead of '" +
|
||||||
token + "'.");
|
token + "'.");
|
||||||
}
|
}
|
||||||
if (x.nextToken() != XML.GT) {
|
if (x.nextToken() != XML.GT) {
|
||||||
throw x.syntaxError("Misshaped close tag");
|
throw x.syntaxError("Misshaped close tag");
|
||||||
@ -134,7 +135,7 @@ public class JSONML {
|
|||||||
if (!(token instanceof String)) {
|
if (!(token instanceof String)) {
|
||||||
throw x.syntaxError("Bad tagName '" + token + "'.");
|
throw x.syntaxError("Bad tagName '" + token + "'.");
|
||||||
}
|
}
|
||||||
tagName = (String)token;
|
tagName = (String) token;
|
||||||
newja = new JSONArray();
|
newja = new JSONArray();
|
||||||
newjo = new JSONObject();
|
newjo = new JSONObject();
|
||||||
if (arrayForm) {
|
if (arrayForm) {
|
||||||
@ -149,7 +150,7 @@ public class JSONML {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
token = null;
|
token = null;
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
token = x.nextToken();
|
token = x.nextToken();
|
||||||
}
|
}
|
||||||
@ -162,7 +163,7 @@ public class JSONML {
|
|||||||
|
|
||||||
// attribute = value
|
// attribute = value
|
||||||
|
|
||||||
attribute = (String)token;
|
attribute = (String) token;
|
||||||
if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) {
|
if (!arrayForm && ("tagName".equals(attribute) || "childNode".equals(attribute))) {
|
||||||
throw x.syntaxError("Reserved attribute.");
|
throw x.syntaxError("Reserved attribute.");
|
||||||
}
|
}
|
||||||
@ -172,7 +173,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 ? ((String)token) :XML.stringToValue((String)token));
|
newjo.accumulate(attribute, keepStrings ? ((String) token) : XML.stringToValue((String) token));
|
||||||
token = null;
|
token = null;
|
||||||
} else {
|
} else {
|
||||||
newjo.accumulate(attribute, "");
|
newjo.accumulate(attribute, "");
|
||||||
@ -201,7 +202,7 @@ public class JSONML {
|
|||||||
if (token != XML.GT) {
|
if (token != XML.GT) {
|
||||||
throw x.syntaxError("Misshaped tag");
|
throw x.syntaxError("Misshaped tag");
|
||||||
}
|
}
|
||||||
closeTag = (String)parse(x, arrayForm, newja, keepStrings);
|
closeTag = (String) parse(x, arrayForm, newja, keepStrings);
|
||||||
if (closeTag != null) {
|
if (closeTag != null) {
|
||||||
if (!closeTag.equals(tagName)) {
|
if (!closeTag.equals(tagName)) {
|
||||||
throw x.syntaxError("Mismatched '" + tagName +
|
throw x.syntaxError("Mismatched '" + tagName +
|
||||||
@ -223,8 +224,8 @@ public class JSONML {
|
|||||||
} else {
|
} else {
|
||||||
if (ja != null) {
|
if (ja != null) {
|
||||||
ja.put(token instanceof String
|
ja.put(token instanceof String
|
||||||
? keepStrings ? XML.unescape((String)token) :XML.stringToValue((String)token)
|
? keepStrings ? XML.unescape((String) token) : XML.stringToValue((String) token)
|
||||||
: token);
|
: token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,12 +240,13 @@ public class JSONML {
|
|||||||
* name/value pairs. If the tag contains children, then strings and
|
* name/value pairs. If the tag contains children, then strings and
|
||||||
* JSONArrays will represent the child tags.
|
* JSONArrays will represent the child tags.
|
||||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||||
|
*
|
||||||
* @param string The source string.
|
* @param string The source string.
|
||||||
* @return A JSONArray containing the structured data from the XML string.
|
* @return A JSONArray containing the structured data from the XML string.
|
||||||
* @throws JSONException Thrown on error converting to a JSONArray
|
* @throws JSONException Thrown on error converting to a JSONArray
|
||||||
*/
|
*/
|
||||||
public static JSONArray toJSONArray(String string) throws JSONException {
|
public static JSONArray toJSONArray(String string) throws JSONException {
|
||||||
return (JSONArray)parse(new XMLTokener(string), true, null, false);
|
return (JSONArray) parse(new XMLTokener(string), true, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -259,14 +261,15 @@ public class JSONML {
|
|||||||
* any text node or attribute value to any type
|
* any text node or attribute value to any type
|
||||||
* but just leaves it as a string.
|
* but just leaves it as a string.
|
||||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||||
* @param string The source string.
|
*
|
||||||
|
* @param string The source string.
|
||||||
* @param keepStrings If true, then values will not be coerced into boolean
|
* @param keepStrings If true, then values will not be coerced into boolean
|
||||||
* or numeric values and will instead be left as strings
|
* or numeric values and will instead be left as strings
|
||||||
* @return A JSONArray containing the structured data from the XML string.
|
* @return A JSONArray containing the structured data from the XML string.
|
||||||
* @throws JSONException Thrown on error converting to a JSONArray
|
* @throws JSONException Thrown on error converting to a JSONArray
|
||||||
*/
|
*/
|
||||||
public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException {
|
public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException {
|
||||||
return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings);
|
return (JSONArray) parse(new XMLTokener(string), true, null, keepStrings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -281,14 +284,15 @@ public class JSONML {
|
|||||||
* any text node or attribute value to any type
|
* any text node or attribute value to any type
|
||||||
* but just leaves it as a string.
|
* but just leaves it as a string.
|
||||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||||
* @param x An XMLTokener.
|
*
|
||||||
|
* @param x An XMLTokener.
|
||||||
* @param keepStrings If true, then values will not be coerced into boolean
|
* @param keepStrings If true, then values will not be coerced into boolean
|
||||||
* or numeric values and will instead be left as strings
|
* or numeric values and will instead be left as strings
|
||||||
* @return A JSONArray containing the structured data from the XML string.
|
* @return A JSONArray containing the structured data from the XML string.
|
||||||
* @throws JSONException Thrown on error converting to a JSONArray
|
* @throws JSONException Thrown on error converting to a JSONArray
|
||||||
*/
|
*/
|
||||||
public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException {
|
public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException {
|
||||||
return (JSONArray)parse(x, true, null, keepStrings);
|
return (JSONArray) parse(x, true, null, keepStrings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -300,12 +304,13 @@ public class JSONML {
|
|||||||
* name/value pairs. If the tag contains children, then strings and
|
* name/value pairs. If the tag contains children, then strings and
|
||||||
* JSONArrays will represent the child content and tags.
|
* JSONArrays will represent the child content and tags.
|
||||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||||
|
*
|
||||||
* @param x An XMLTokener.
|
* @param x An XMLTokener.
|
||||||
* @return A JSONArray containing the structured data from the XML string.
|
* @return A JSONArray containing the structured data from the XML string.
|
||||||
* @throws JSONException Thrown on error converting to a JSONArray
|
* @throws JSONException Thrown on error converting to a JSONArray
|
||||||
*/
|
*/
|
||||||
public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
|
public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
|
||||||
return (JSONArray)parse(x, true, null, false);
|
return (JSONArray) parse(x, true, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -316,14 +321,15 @@ public class JSONML {
|
|||||||
* the attributes will be in the JSONObject as properties. If the tag
|
* the attributes will be in the JSONObject as properties. If the tag
|
||||||
* contains children, the object will have a "childNodes" property which
|
* contains children, the object will have a "childNodes" property which
|
||||||
* will be an array of strings and JsonML JSONObjects.
|
* will be an array of strings and JsonML JSONObjects.
|
||||||
|
* <p>
|
||||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||||
|
*
|
||||||
* @param string The XML source text.
|
* @param string The XML source text.
|
||||||
* @return A JSONObject containing the structured data from the XML string.
|
* @return A JSONObject containing the structured data from the XML string.
|
||||||
* @throws JSONException Thrown on error converting to a JSONObject
|
* @throws JSONException Thrown on error converting to a JSONObject
|
||||||
*/
|
*/
|
||||||
public static JSONObject toJSONObject(String string) throws JSONException {
|
public static JSONObject toJSONObject(String string) throws JSONException {
|
||||||
return (JSONObject)parse(new XMLTokener(string), false, null, false);
|
return (JSONObject) parse(new XMLTokener(string), false, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -334,16 +340,17 @@ public class JSONML {
|
|||||||
* the attributes will be in the JSONObject as properties. If the tag
|
* the attributes will be in the JSONObject as properties. If the tag
|
||||||
* contains children, the object will have a "childNodes" property which
|
* contains children, the object will have a "childNodes" property which
|
||||||
* will be an array of strings and JsonML JSONObjects.
|
* will be an array of strings and JsonML JSONObjects.
|
||||||
|
* <p>
|
||||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||||
* @param string The XML source text.
|
*
|
||||||
|
* @param string The XML source text.
|
||||||
* @param keepStrings If true, then values will not be coerced into boolean
|
* @param keepStrings If true, then values will not be coerced into boolean
|
||||||
* or numeric values and will instead be left as strings
|
* or numeric values and will instead be left as strings
|
||||||
* @return A JSONObject containing the structured data from the XML string.
|
* @return A JSONObject containing the structured data from the XML string.
|
||||||
* @throws JSONException Thrown on error converting to a JSONObject
|
* @throws JSONException Thrown on error converting to a JSONObject
|
||||||
*/
|
*/
|
||||||
public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
|
public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
|
||||||
return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings);
|
return (JSONObject) parse(new XMLTokener(string), false, null, keepStrings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -354,14 +361,15 @@ public class JSONML {
|
|||||||
* the attributes will be in the JSONObject as properties. If the tag
|
* the attributes will be in the JSONObject as properties. If the tag
|
||||||
* contains children, the object will have a "childNodes" property which
|
* contains children, the object will have a "childNodes" property which
|
||||||
* will be an array of strings and JsonML JSONObjects.
|
* will be an array of strings and JsonML JSONObjects.
|
||||||
|
* <p>
|
||||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||||
|
*
|
||||||
* @param x An XMLTokener of the XML source text.
|
* @param x An XMLTokener of the XML source text.
|
||||||
* @return A JSONObject containing the structured data from the XML string.
|
* @return A JSONObject containing the structured data from the XML string.
|
||||||
* @throws JSONException Thrown on error converting to a JSONObject
|
* @throws JSONException Thrown on error converting to a JSONObject
|
||||||
*/
|
*/
|
||||||
public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
|
public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
|
||||||
return (JSONObject)parse(x, false, null, false);
|
return (JSONObject) parse(x, false, null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -372,32 +380,34 @@ public class JSONML {
|
|||||||
* the attributes will be in the JSONObject as properties. If the tag
|
* the attributes will be in the JSONObject as properties. If the tag
|
||||||
* contains children, the object will have a "childNodes" property which
|
* contains children, the object will have a "childNodes" property which
|
||||||
* will be an array of strings and JsonML JSONObjects.
|
* will be an array of strings and JsonML JSONObjects.
|
||||||
|
* <p>
|
||||||
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
* Comments, prologs, DTDs, and <code><[ [ ]]></code> are ignored.
|
||||||
* @param x An XMLTokener of the XML source text.
|
*
|
||||||
|
* @param x An XMLTokener of the XML source text.
|
||||||
* @param keepStrings If true, then values will not be coerced into boolean
|
* @param keepStrings If true, then values will not be coerced into boolean
|
||||||
* or numeric values and will instead be left as strings
|
* or numeric values and will instead be left as strings
|
||||||
* @return A JSONObject containing the structured data from the XML string.
|
* @return A JSONObject containing the structured data from the XML string.
|
||||||
* @throws JSONException Thrown on error converting to a JSONObject
|
* @throws JSONException Thrown on error converting to a JSONObject
|
||||||
*/
|
*/
|
||||||
public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) throws JSONException {
|
public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) throws JSONException {
|
||||||
return (JSONObject)parse(x, false, null, keepStrings);
|
return (JSONObject) parse(x, false, null, keepStrings);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reverse the JSONML transformation, making an XML text from a JSONArray.
|
* Reverse the JSONML transformation, making an XML text from a JSONArray.
|
||||||
|
*
|
||||||
* @param ja A JSONArray.
|
* @param ja A JSONArray.
|
||||||
* @return An XML string.
|
* @return An XML string.
|
||||||
* @throws JSONException Thrown on error converting to a string
|
* @throws JSONException Thrown on error converting to a string
|
||||||
*/
|
*/
|
||||||
public static String toString(JSONArray ja) throws JSONException {
|
public static String toString(JSONArray ja) throws JSONException {
|
||||||
int i;
|
int i;
|
||||||
JSONObject jo;
|
JSONObject jo;
|
||||||
int length;
|
int length;
|
||||||
Object object;
|
Object object;
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
String tagName;
|
String tagName;
|
||||||
|
|
||||||
// Emit <tagName
|
// Emit <tagName
|
||||||
|
|
||||||
@ -410,7 +420,7 @@ public class JSONML {
|
|||||||
object = ja.opt(1);
|
object = ja.opt(1);
|
||||||
if (object instanceof JSONObject) {
|
if (object instanceof JSONObject) {
|
||||||
i = 2;
|
i = 2;
|
||||||
jo = (JSONObject)object;
|
jo = (JSONObject) object;
|
||||||
|
|
||||||
// Emit the attributes
|
// Emit the attributes
|
||||||
|
|
||||||
@ -446,9 +456,9 @@ public class JSONML {
|
|||||||
if (object instanceof String) {
|
if (object instanceof String) {
|
||||||
sb.append(XML.escape(object.toString()));
|
sb.append(XML.escape(object.toString()));
|
||||||
} else if (object instanceof JSONObject) {
|
} else if (object instanceof JSONObject) {
|
||||||
sb.append(toString((JSONObject)object));
|
sb.append(toString((JSONObject) object));
|
||||||
} else if (object instanceof JSONArray) {
|
} else if (object instanceof JSONArray) {
|
||||||
sb.append(toString((JSONArray)object));
|
sb.append(toString((JSONArray) object));
|
||||||
} else {
|
} else {
|
||||||
sb.append(object.toString());
|
sb.append(object.toString());
|
||||||
}
|
}
|
||||||
@ -467,18 +477,19 @@ public class JSONML {
|
|||||||
* The JSONObject must contain a "tagName" property. If it has children,
|
* The JSONObject must contain a "tagName" property. If it has children,
|
||||||
* then it must have a "childNodes" property containing an array of objects.
|
* then it must have a "childNodes" property containing an array of objects.
|
||||||
* The other properties are attributes with string values.
|
* The other properties are attributes with string values.
|
||||||
|
*
|
||||||
* @param jo A JSONObject.
|
* @param jo A JSONObject.
|
||||||
* @return An XML string.
|
* @return An XML string.
|
||||||
* @throws JSONException Thrown on error converting to a string
|
* @throws JSONException Thrown on error converting to a string
|
||||||
*/
|
*/
|
||||||
public static String toString(JSONObject jo) throws JSONException {
|
public static String toString(JSONObject jo) throws JSONException {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
int i;
|
int i;
|
||||||
JSONArray ja;
|
JSONArray ja;
|
||||||
int length;
|
int length;
|
||||||
Object object;
|
Object object;
|
||||||
String tagName;
|
String tagName;
|
||||||
Object value;
|
Object value;
|
||||||
|
|
||||||
//Emit <tagName
|
//Emit <tagName
|
||||||
|
|
||||||
@ -524,9 +535,9 @@ public class JSONML {
|
|||||||
if (object instanceof String) {
|
if (object instanceof String) {
|
||||||
sb.append(XML.escape(object.toString()));
|
sb.append(XML.escape(object.toString()));
|
||||||
} else if (object instanceof JSONObject) {
|
} else if (object instanceof JSONObject) {
|
||||||
sb.append(toString((JSONObject)object));
|
sb.append(toString((JSONObject) object));
|
||||||
} else if (object instanceof JSONArray) {
|
} else if (object instanceof JSONArray) {
|
||||||
sb.append(toString((JSONArray)object));
|
sb.append(toString((JSONArray) object));
|
||||||
} else {
|
} else {
|
||||||
sb.append(object.toString());
|
sb.append(object.toString());
|
||||||
}
|
}
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -1,7 +1,5 @@
|
|||||||
package ch.m4th1eu.json;
|
package ch.m4th1eu.json;
|
||||||
|
|
||||||
import static java.lang.String.format;
|
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLDecoder;
|
import java.net.URLDecoder;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
@ -9,6 +7,8 @@ import java.util.ArrayList;
|
|||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
|
import static java.lang.String.format;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2002 JSON.org
|
Copyright (c) 2002 JSON.org
|
||||||
|
|
||||||
@ -36,7 +36,7 @@ SOFTWARE.
|
|||||||
/**
|
/**
|
||||||
* A JSON Pointer is a simple query language defined for JSON documents by
|
* A JSON Pointer is a simple query language defined for JSON documents by
|
||||||
* <a href="https://tools.ietf.org/html/rfc6901">RFC 6901</a>.
|
* <a href="https://tools.ietf.org/html/rfc6901">RFC 6901</a>.
|
||||||
*
|
* <p>
|
||||||
* In a nutshell, JSONPointer allows the user to navigate into a JSON document
|
* In a nutshell, JSONPointer allows the user to navigate into a JSON document
|
||||||
* using strings, and retrieve targeted objects, like a simple form of XPATH.
|
* using strings, and retrieve targeted objects, like a simple form of XPATH.
|
||||||
* Path segments are separated by the '/' char, which signifies the root of
|
* Path segments are separated by the '/' char, which signifies the root of
|
||||||
@ -55,76 +55,6 @@ public class JSONPointer {
|
|||||||
|
|
||||||
// used for URL encoding and decoding
|
// used for URL encoding and decoding
|
||||||
private static final String ENCODING = "utf-8";
|
private static final String ENCODING = "utf-8";
|
||||||
|
|
||||||
/**
|
|
||||||
* This class allows the user to build a JSONPointer in steps, using
|
|
||||||
* exactly one segment in each step.
|
|
||||||
*/
|
|
||||||
public static class Builder {
|
|
||||||
|
|
||||||
// Segments for the eventual JSONPointer string
|
|
||||||
private final List<String> refTokens = new ArrayList<String>();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Creates a {@code JSONPointer} instance using the tokens previously set using the
|
|
||||||
* {@link #append(String)} method calls.
|
|
||||||
*/
|
|
||||||
public JSONPointer build() {
|
|
||||||
return new JSONPointer(this.refTokens);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an arbitrary token to the list of reference tokens. It can be any non-null value.
|
|
||||||
*
|
|
||||||
* Unlike in the case of JSON string or URI fragment representation of JSON pointers, the
|
|
||||||
* argument of this method MUST NOT be escaped. If you want to query the property called
|
|
||||||
* {@code "a~b"} then you should simply pass the {@code "a~b"} string as-is, there is no
|
|
||||||
* need to escape it as {@code "a~0b"}.
|
|
||||||
*
|
|
||||||
* @param token the new token to be appended to the list
|
|
||||||
* @return {@code this}
|
|
||||||
* @throws NullPointerException if {@code token} is null
|
|
||||||
*/
|
|
||||||
public Builder append(String token) {
|
|
||||||
if (token == null) {
|
|
||||||
throw new NullPointerException("token cannot be null");
|
|
||||||
}
|
|
||||||
this.refTokens.add(token);
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Adds an integer to the reference token list. Although not necessarily, mostly this token will
|
|
||||||
* denote an array index.
|
|
||||||
*
|
|
||||||
* @param arrayIndex the array index to be added to the token list
|
|
||||||
* @return {@code this}
|
|
||||||
*/
|
|
||||||
public Builder append(int arrayIndex) {
|
|
||||||
this.refTokens.add(String.valueOf(arrayIndex));
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Static factory method for {@link Builder}. Example usage:
|
|
||||||
*
|
|
||||||
* <pre><code>
|
|
||||||
* JSONPointer pointer = JSONPointer.builder()
|
|
||||||
* .append("obj")
|
|
||||||
* .append("other~key").append("another/key")
|
|
||||||
* .append("\"")
|
|
||||||
* .append(0)
|
|
||||||
* .build();
|
|
||||||
* </code></pre>
|
|
||||||
*
|
|
||||||
* @return a builder instance which can be used to construct a {@code JSONPointer} instance by chained
|
|
||||||
* {@link Builder#append(String)} calls.
|
|
||||||
*/
|
|
||||||
public static Builder builder() {
|
|
||||||
return new Builder();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Segments for the JSONPointer string
|
// Segments for the JSONPointer string
|
||||||
private final List<String> refTokens;
|
private final List<String> refTokens;
|
||||||
|
|
||||||
@ -163,7 +93,7 @@ public class JSONPointer {
|
|||||||
do {
|
do {
|
||||||
prevSlashIdx = slashIdx + 1;
|
prevSlashIdx = slashIdx + 1;
|
||||||
slashIdx = refs.indexOf('/', prevSlashIdx);
|
slashIdx = refs.indexOf('/', prevSlashIdx);
|
||||||
if(prevSlashIdx == slashIdx || prevSlashIdx == refs.length()) {
|
if (prevSlashIdx == slashIdx || prevSlashIdx == refs.length()) {
|
||||||
// found 2 slashes in a row ( obj//next )
|
// found 2 slashes in a row ( obj//next )
|
||||||
// or single slash at the end of a string ( obj/test/ )
|
// or single slash at the end of a string ( obj/test/ )
|
||||||
this.refTokens.add("");
|
this.refTokens.add("");
|
||||||
@ -186,6 +116,25 @@ public class JSONPointer {
|
|||||||
this.refTokens = new ArrayList<String>(refTokens);
|
this.refTokens = new ArrayList<String>(refTokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Static factory method for {@link Builder}. Example usage:
|
||||||
|
*
|
||||||
|
* <pre><code>
|
||||||
|
* JSONPointer pointer = JSONPointer.builder()
|
||||||
|
* .append("obj")
|
||||||
|
* .append("other~key").append("another/key")
|
||||||
|
* .append("\"")
|
||||||
|
* .append(0)
|
||||||
|
* .build();
|
||||||
|
* </code></pre>
|
||||||
|
*
|
||||||
|
* @return a builder instance which can be used to construct a {@code JSONPointer} instance by chained
|
||||||
|
* {@link Builder#append(String)} calls.
|
||||||
|
*/
|
||||||
|
public static Builder builder() {
|
||||||
|
return new Builder();
|
||||||
|
}
|
||||||
|
|
||||||
private String unescape(String token) {
|
private String unescape(String token) {
|
||||||
return token.replace("~1", "/").replace("~0", "~")
|
return token.replace("~1", "/").replace("~0", "~")
|
||||||
.replace("\\\"", "\"")
|
.replace("\\\"", "\"")
|
||||||
@ -223,7 +172,8 @@ public class JSONPointer {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Matches a JSONArray element by ordinal position
|
* Matches a JSONArray element by ordinal position
|
||||||
* @param current the JSONArray to be evaluated
|
*
|
||||||
|
* @param current the JSONArray to be evaluated
|
||||||
* @param indexToken the array index in string form
|
* @param indexToken the array index in string form
|
||||||
* @return the matched object. If no matching item is found a
|
* @return the matched object. If no matching item is found a
|
||||||
* @throws JSONPointerException is thrown if the index is out of bounds
|
* @throws JSONPointerException is thrown if the index is out of bounds
|
||||||
@ -237,10 +187,10 @@ public class JSONPointer {
|
|||||||
Integer.valueOf(currentArr.length())));
|
Integer.valueOf(currentArr.length())));
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
return currentArr.get(index);
|
return currentArr.get(index);
|
||||||
} catch (JSONException e) {
|
} catch (JSONException e) {
|
||||||
throw new JSONPointerException("Error reading value at index position " + index, e);
|
throw new JSONPointerException("Error reading value at index position " + index, e);
|
||||||
}
|
}
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw new JSONPointerException(format("%s is not an array index", indexToken), e);
|
throw new JSONPointerException(format("%s is not an array index", indexToken), e);
|
||||||
}
|
}
|
||||||
@ -252,8 +202,8 @@ public class JSONPointer {
|
|||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder rval = new StringBuilder("");
|
StringBuilder rval = new StringBuilder();
|
||||||
for (String token: this.refTokens) {
|
for (String token : this.refTokens) {
|
||||||
rval.append('/').append(escape(token));
|
rval.append('/').append(escape(token));
|
||||||
}
|
}
|
||||||
return rval.toString();
|
return rval.toString();
|
||||||
@ -264,6 +214,7 @@ public class JSONPointer {
|
|||||||
* The escape char to be inserted is '~'. The chars to be escaped
|
* The escape char to be inserted is '~'. The chars to be escaped
|
||||||
* are ~, which maps to ~0, and /, which maps to ~1. Backslashes
|
* are ~, which maps to ~0, and /, which maps to ~1. Backslashes
|
||||||
* and double quote chars are also escaped.
|
* and double quote chars are also escaped.
|
||||||
|
*
|
||||||
* @param token the JSONPointer segment value to be escaped
|
* @param token the JSONPointer segment value to be escaped
|
||||||
* @return the escaped value for the token
|
* @return the escaped value for the token
|
||||||
*/
|
*/
|
||||||
@ -290,4 +241,54 @@ public class JSONPointer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class allows the user to build a JSONPointer in steps, using
|
||||||
|
* exactly one segment in each step.
|
||||||
|
*/
|
||||||
|
public static class Builder {
|
||||||
|
|
||||||
|
// Segments for the eventual JSONPointer string
|
||||||
|
private final List<String> refTokens = new ArrayList<String>();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a {@code JSONPointer} instance using the tokens previously set using the
|
||||||
|
* {@link #append(String)} method calls.
|
||||||
|
*/
|
||||||
|
public JSONPointer build() {
|
||||||
|
return new JSONPointer(this.refTokens);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an arbitrary token to the list of reference tokens. It can be any non-null value.
|
||||||
|
* <p>
|
||||||
|
* Unlike in the case of JSON string or URI fragment representation of JSON pointers, the
|
||||||
|
* argument of this method MUST NOT be escaped. If you want to query the property called
|
||||||
|
* {@code "a~b"} then you should simply pass the {@code "a~b"} string as-is, there is no
|
||||||
|
* need to escape it as {@code "a~0b"}.
|
||||||
|
*
|
||||||
|
* @param token the new token to be appended to the list
|
||||||
|
* @return {@code this}
|
||||||
|
* @throws NullPointerException if {@code token} is null
|
||||||
|
*/
|
||||||
|
public Builder append(String token) {
|
||||||
|
if (token == null) {
|
||||||
|
throw new NullPointerException("token cannot be null");
|
||||||
|
}
|
||||||
|
this.refTokens.add(token);
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Adds an integer to the reference token list. Although not necessarily, mostly this token will
|
||||||
|
* denote an array index.
|
||||||
|
*
|
||||||
|
* @param arrayIndex the array index to be added to the token list
|
||||||
|
* @return {@code this}
|
||||||
|
*/
|
||||||
|
public Builder append(int arrayIndex) {
|
||||||
|
this.refTokens.add(String.valueOf(arrayIndex));
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -24,13 +24,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.METHOD;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
@Documented
|
@Documented
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
@Target({METHOD})
|
@Target({METHOD})
|
||||||
@ -40,4 +40,5 @@ import java.lang.annotation.Target;
|
|||||||
* present at any level in the class hierarchy, then the method will
|
* present at any level in the class hierarchy, then the method will
|
||||||
* not be serialized from the bean into the JSONObject.
|
* not be serialized from the bean into the JSONObject.
|
||||||
*/
|
*/
|
||||||
public @interface JSONPropertyIgnore { }
|
public @interface JSONPropertyIgnore {
|
||||||
|
}
|
||||||
|
@ -24,13 +24,13 @@ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|||||||
SOFTWARE.
|
SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import static java.lang.annotation.ElementType.METHOD;
|
|
||||||
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
|
||||||
|
|
||||||
import java.lang.annotation.Documented;
|
import java.lang.annotation.Documented;
|
||||||
import java.lang.annotation.Retention;
|
import java.lang.annotation.Retention;
|
||||||
import java.lang.annotation.Target;
|
import java.lang.annotation.Target;
|
||||||
|
|
||||||
|
import static java.lang.annotation.ElementType.METHOD;
|
||||||
|
import static java.lang.annotation.RetentionPolicy.RUNTIME;
|
||||||
|
|
||||||
@Documented
|
@Documented
|
||||||
@Retention(RUNTIME)
|
@Retention(RUNTIME)
|
||||||
@Target({METHOD})
|
@Target({METHOD})
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
package ch.m4th1eu.json;
|
package ch.m4th1eu.json;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The <code>JSONString</code> interface allows a <code>toJSONString()</code>
|
* The <code>JSONString</code> interface allows a <code>toJSONString()</code>
|
||||||
* method so that a class can change the behavior of
|
* method so that a class can change the behavior of
|
||||||
@ -14,5 +15,5 @@ public interface JSONString {
|
|||||||
*
|
*
|
||||||
* @return A strictly syntactically correct JSON text.
|
* @return A strictly syntactically correct JSON text.
|
||||||
*/
|
*/
|
||||||
public String toJSONString();
|
String toJSONString();
|
||||||
}
|
}
|
||||||
|
@ -53,6 +53,7 @@ import java.io.StringWriter;
|
|||||||
* you. Objects and arrays can be nested up to 20 levels deep.
|
* you. Objects and arrays can be nested up to 20 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 2015-12-09
|
||||||
*/
|
*/
|
||||||
@ -70,6 +71,7 @@ public class JSONStringer extends JSONWriter {
|
|||||||
* problem in the construction of the JSON text (such as the calls to
|
* problem in the construction of the JSON text (such as the calls to
|
||||||
* <code>array</code> were not properly balanced with calls to
|
* <code>array</code> were not properly balanced with calls to
|
||||||
* <code>endArray</code>).
|
* <code>endArray</code>).
|
||||||
|
*
|
||||||
* @return The JSON text.
|
* @return The JSON text.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
|
@ -1,11 +1,6 @@
|
|||||||
package ch.m4th1eu.json;
|
package ch.m4th1eu.json;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.*;
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.InputStreamReader;
|
|
||||||
import java.io.Reader;
|
|
||||||
import java.io.StringReader;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Copyright (c) 2002 JSON.org
|
Copyright (c) 2002 JSON.org
|
||||||
@ -35,37 +30,54 @@ SOFTWARE.
|
|||||||
* A JSONTokener takes a source string and extracts characters and tokens from
|
* A JSONTokener takes a source string and extracts characters and tokens from
|
||||||
* it. It is used by the JSONObject and JSONArray constructors to parse
|
* it. It is used by the JSONObject and JSONArray constructors to parse
|
||||||
* JSON source strings.
|
* JSON source strings.
|
||||||
|
*
|
||||||
* @author JSON.org
|
* @author JSON.org
|
||||||
* @version 2014-05-03
|
* @version 2014-05-03
|
||||||
*/
|
*/
|
||||||
public class JSONTokener {
|
public class JSONTokener {
|
||||||
/** current read character position on the current line. */
|
/**
|
||||||
private long character;
|
* Reader for the input.
|
||||||
/** flag to indicate if the end of the input has been found. */
|
*/
|
||||||
private boolean eof;
|
|
||||||
/** current read index of the input. */
|
|
||||||
private long index;
|
|
||||||
/** current line of the input. */
|
|
||||||
private long line;
|
|
||||||
/** previous character read from the input. */
|
|
||||||
private char previous;
|
|
||||||
/** Reader for the input. */
|
|
||||||
private final Reader reader;
|
private final Reader reader;
|
||||||
/** flag to indicate that a previous character was requested. */
|
/**
|
||||||
|
* current read character position on the current line.
|
||||||
|
*/
|
||||||
|
private long character;
|
||||||
|
/**
|
||||||
|
* flag to indicate if the end of the input has been found.
|
||||||
|
*/
|
||||||
|
private boolean eof;
|
||||||
|
/**
|
||||||
|
* current read index of the input.
|
||||||
|
*/
|
||||||
|
private long index;
|
||||||
|
/**
|
||||||
|
* current line of the input.
|
||||||
|
*/
|
||||||
|
private long line;
|
||||||
|
/**
|
||||||
|
* previous character read from the input.
|
||||||
|
*/
|
||||||
|
private char previous;
|
||||||
|
/**
|
||||||
|
* flag to indicate that a previous character was requested.
|
||||||
|
*/
|
||||||
private boolean usePrevious;
|
private boolean usePrevious;
|
||||||
/** the number of characters read in the previous line. */
|
/**
|
||||||
|
* the number of characters read in the previous line.
|
||||||
|
*/
|
||||||
private long characterPreviousLine;
|
private long characterPreviousLine;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a JSONTokener from a Reader. The caller must close the Reader.
|
* Construct a JSONTokener from a Reader. The caller must close the Reader.
|
||||||
*
|
*
|
||||||
* @param reader A reader.
|
* @param reader A reader.
|
||||||
*/
|
*/
|
||||||
public JSONTokener(Reader reader) {
|
public JSONTokener(Reader reader) {
|
||||||
this.reader = reader.markSupported()
|
this.reader = reader.markSupported()
|
||||||
? reader
|
? reader
|
||||||
: new BufferedReader(reader);
|
: new BufferedReader(reader);
|
||||||
this.eof = false;
|
this.eof = false;
|
||||||
this.usePrevious = false;
|
this.usePrevious = false;
|
||||||
this.previous = 0;
|
this.previous = 0;
|
||||||
@ -78,6 +90,7 @@ public class JSONTokener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct a JSONTokener from an InputStream. The caller must close the input stream.
|
* Construct a JSONTokener from an InputStream. The caller must close the input stream.
|
||||||
|
*
|
||||||
* @param inputStream The source.
|
* @param inputStream The source.
|
||||||
*/
|
*/
|
||||||
public JSONTokener(InputStream inputStream) {
|
public JSONTokener(InputStream inputStream) {
|
||||||
@ -88,47 +101,18 @@ public class JSONTokener {
|
|||||||
/**
|
/**
|
||||||
* Construct a JSONTokener from a string.
|
* Construct a JSONTokener from a string.
|
||||||
*
|
*
|
||||||
* @param s A source string.
|
* @param s A source string.
|
||||||
*/
|
*/
|
||||||
public JSONTokener(String s) {
|
public JSONTokener(String s) {
|
||||||
this(new StringReader(s));
|
this(new StringReader(s));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Back up one character. This provides a sort of lookahead capability,
|
|
||||||
* so that you can test for a digit or letter before attempting to parse
|
|
||||||
* the next number or identifier.
|
|
||||||
* @throws JSONException Thrown if trying to step back more than 1 step
|
|
||||||
* or if already at the start of the string
|
|
||||||
*/
|
|
||||||
public void back() throws JSONException {
|
|
||||||
if (this.usePrevious || this.index <= 0) {
|
|
||||||
throw new JSONException("Stepping back two steps is not supported");
|
|
||||||
}
|
|
||||||
this.decrementIndexes();
|
|
||||||
this.usePrevious = true;
|
|
||||||
this.eof = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Decrements the indexes for the {@link #back()} method based on the previous character read.
|
|
||||||
*/
|
|
||||||
private void decrementIndexes() {
|
|
||||||
this.index--;
|
|
||||||
if(this.previous=='\r' || this.previous == '\n') {
|
|
||||||
this.line--;
|
|
||||||
this.character=this.characterPreviousLine ;
|
|
||||||
} else if(this.character > 0){
|
|
||||||
this.character--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the hex value of a character (base16).
|
* Get the hex value of a character (base16).
|
||||||
|
*
|
||||||
* @param c A character between '0' and '9' or between 'A' and 'F' or
|
* @param c A character between '0' and '9' or between 'A' and 'F' or
|
||||||
* between 'a' and 'f'.
|
* between 'a' and 'f'.
|
||||||
* @return An int between 0 and 15, or -1 if c was not a hex digit.
|
* @return An int between 0 and 15, or -1 if c was not a hex digit.
|
||||||
*/
|
*/
|
||||||
public static int dehexchar(char c) {
|
public static int dehexchar(char c) {
|
||||||
if (c >= '0' && c <= '9') {
|
if (c >= '0' && c <= '9') {
|
||||||
@ -143,6 +127,36 @@ public class JSONTokener {
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Back up one character. This provides a sort of lookahead capability,
|
||||||
|
* so that you can test for a digit or letter before attempting to parse
|
||||||
|
* the next number or identifier.
|
||||||
|
*
|
||||||
|
* @throws JSONException Thrown if trying to step back more than 1 step
|
||||||
|
* or if already at the start of the string
|
||||||
|
*/
|
||||||
|
public void back() throws JSONException {
|
||||||
|
if (this.usePrevious || this.index <= 0) {
|
||||||
|
throw new JSONException("Stepping back two steps is not supported");
|
||||||
|
}
|
||||||
|
this.decrementIndexes();
|
||||||
|
this.usePrevious = true;
|
||||||
|
this.eof = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrements the indexes for the {@link #back()} method based on the previous character read.
|
||||||
|
*/
|
||||||
|
private void decrementIndexes() {
|
||||||
|
this.index--;
|
||||||
|
if (this.previous == '\r' || this.previous == '\n') {
|
||||||
|
this.line--;
|
||||||
|
this.character = this.characterPreviousLine;
|
||||||
|
} else if (this.character > 0) {
|
||||||
|
this.character--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Checks if the end of the input has been reached.
|
* Checks if the end of the input has been reached.
|
||||||
*
|
*
|
||||||
@ -156,12 +170,13 @@ public class JSONTokener {
|
|||||||
/**
|
/**
|
||||||
* Determine if the source string still contains characters that next()
|
* Determine if the source string still contains characters that next()
|
||||||
* can consume.
|
* can consume.
|
||||||
|
*
|
||||||
* @return true if not yet at the end of the source.
|
* @return true if not yet at the end of the source.
|
||||||
* @throws JSONException thrown if there is an error stepping forward
|
* @throws JSONException thrown if there is an error stepping forward
|
||||||
* or backward while checking for more data.
|
* or backward while checking for more data.
|
||||||
*/
|
*/
|
||||||
public boolean more() throws JSONException {
|
public boolean more() throws JSONException {
|
||||||
if(this.usePrevious) {
|
if (this.usePrevious) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
@ -171,7 +186,7 @@ public class JSONTokener {
|
|||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
// -1 is EOF, but next() can not consume the null character '\0'
|
// -1 is EOF, but next() can not consume the null character '\0'
|
||||||
if(this.reader.read() <= 0) {
|
if (this.reader.read() <= 0) {
|
||||||
this.eof = true;
|
this.eof = true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -213,21 +228,22 @@ public class JSONTokener {
|
|||||||
/**
|
/**
|
||||||
* Increments the internal indexes according to the previous character
|
* Increments the internal indexes according to the previous character
|
||||||
* read and the character passed as the current character.
|
* read and the character passed as the current character.
|
||||||
|
*
|
||||||
* @param c the current character read.
|
* @param c the current character read.
|
||||||
*/
|
*/
|
||||||
private void incrementIndexes(int c) {
|
private void incrementIndexes(int c) {
|
||||||
if(c > 0) {
|
if (c > 0) {
|
||||||
this.index++;
|
this.index++;
|
||||||
if(c=='\r') {
|
if (c == '\r') {
|
||||||
this.line++;
|
this.line++;
|
||||||
this.characterPreviousLine = this.character;
|
this.characterPreviousLine = this.character;
|
||||||
this.character=0;
|
this.character = 0;
|
||||||
}else if (c=='\n') {
|
} else if (c == '\n') {
|
||||||
if(this.previous != '\r') {
|
if (this.previous != '\r') {
|
||||||
this.line++;
|
this.line++;
|
||||||
this.characterPreviousLine = this.character;
|
this.characterPreviousLine = this.character;
|
||||||
}
|
}
|
||||||
this.character=0;
|
this.character = 0;
|
||||||
} else {
|
} else {
|
||||||
this.character++;
|
this.character++;
|
||||||
}
|
}
|
||||||
@ -237,6 +253,7 @@ public class JSONTokener {
|
|||||||
/**
|
/**
|
||||||
* Consume the next character, and check that it matches a specified
|
* Consume the next character, and check that it matches a specified
|
||||||
* character.
|
* character.
|
||||||
|
*
|
||||||
* @param c The character to match.
|
* @param c The character to match.
|
||||||
* @return The character.
|
* @return The character.
|
||||||
* @throws JSONException if the character does not match.
|
* @throws JSONException if the character does not match.
|
||||||
@ -244,7 +261,7 @@ public class JSONTokener {
|
|||||||
public char next(char c) throws JSONException {
|
public char next(char c) throws JSONException {
|
||||||
char n = this.next();
|
char n = this.next();
|
||||||
if (n != c) {
|
if (n != c) {
|
||||||
if(n > 0) {
|
if (n > 0) {
|
||||||
throw this.syntaxError("Expected '" + c + "' and instead saw '" +
|
throw this.syntaxError("Expected '" + c + "' and instead saw '" +
|
||||||
n + "'");
|
n + "'");
|
||||||
}
|
}
|
||||||
@ -257,11 +274,10 @@ public class JSONTokener {
|
|||||||
/**
|
/**
|
||||||
* Get the next n characters.
|
* Get the next n characters.
|
||||||
*
|
*
|
||||||
* @param n The number of characters to take.
|
* @param n The number of characters to take.
|
||||||
* @return A string of n characters.
|
* @return A string of n characters.
|
||||||
* @throws JSONException
|
* @throws JSONException Substring bounds error if there are not
|
||||||
* Substring bounds error if there are not
|
* n characters remaining in the source string.
|
||||||
* n characters remaining in the source string.
|
|
||||||
*/
|
*/
|
||||||
public String next(int n) throws JSONException {
|
public String next(int n) throws JSONException {
|
||||||
if (n == 0) {
|
if (n == 0) {
|
||||||
@ -284,11 +300,12 @@ public class JSONTokener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the next char in the string, skipping whitespace.
|
* Get the next char in the string, skipping whitespace.
|
||||||
|
*
|
||||||
|
* @return A character, or 0 if there are no more characters.
|
||||||
* @throws JSONException Thrown if there is an error reading the source string.
|
* @throws JSONException Thrown if there is an error reading the source string.
|
||||||
* @return A character, or 0 if there are no more characters.
|
|
||||||
*/
|
*/
|
||||||
public char nextClean() throws JSONException {
|
public char nextClean() throws JSONException {
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
char c = this.next();
|
char c = this.next();
|
||||||
if (c == 0 || c > ' ') {
|
if (c == 0 || c > ' ') {
|
||||||
return c;
|
return c;
|
||||||
@ -302,62 +319,63 @@ public class JSONTokener {
|
|||||||
* Backslash processing is done. The formal JSON format does not
|
* Backslash processing is done. The formal JSON format does not
|
||||||
* allow strings in single quotes, but an implementation is allowed to
|
* allow strings in single quotes, but an implementation is allowed to
|
||||||
* accept them.
|
* accept them.
|
||||||
|
*
|
||||||
* @param quote The quoting character, either
|
* @param quote The quoting character, either
|
||||||
* <code>"</code> <small>(double quote)</small> or
|
* <code>"</code> <small>(double quote)</small> or
|
||||||
* <code>'</code> <small>(single quote)</small>.
|
* <code>'</code> <small>(single quote)</small>.
|
||||||
* @return A String.
|
* @return A String.
|
||||||
* @throws JSONException Unterminated string.
|
* @throws JSONException Unterminated string.
|
||||||
*/
|
*/
|
||||||
public String nextString(char quote) throws JSONException {
|
public String nextString(char quote) throws JSONException {
|
||||||
char c;
|
char c;
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
c = this.next();
|
c = this.next();
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0:
|
case 0:
|
||||||
case '\n':
|
case '\n':
|
||||||
case '\r':
|
case '\r':
|
||||||
throw this.syntaxError("Unterminated string");
|
throw this.syntaxError("Unterminated string");
|
||||||
case '\\':
|
case '\\':
|
||||||
c = this.next();
|
c = this.next();
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 'b':
|
case 'b':
|
||||||
sb.append('\b');
|
sb.append('\b');
|
||||||
break;
|
break;
|
||||||
case 't':
|
case 't':
|
||||||
sb.append('\t');
|
sb.append('\t');
|
||||||
break;
|
break;
|
||||||
case 'n':
|
case 'n':
|
||||||
sb.append('\n');
|
sb.append('\n');
|
||||||
break;
|
break;
|
||||||
case 'f':
|
case 'f':
|
||||||
sb.append('\f');
|
sb.append('\f');
|
||||||
break;
|
break;
|
||||||
case 'r':
|
case 'r':
|
||||||
sb.append('\r');
|
sb.append('\r');
|
||||||
break;
|
break;
|
||||||
case 'u':
|
case 'u':
|
||||||
try {
|
try {
|
||||||
sb.append((char)Integer.parseInt(this.next(4), 16));
|
sb.append((char) Integer.parseInt(this.next(4), 16));
|
||||||
} catch (NumberFormatException e) {
|
} catch (NumberFormatException e) {
|
||||||
throw this.syntaxError("Illegal escape.", e);
|
throw this.syntaxError("Illegal escape.", e);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case '"':
|
||||||
|
case '\'':
|
||||||
|
case '\\':
|
||||||
|
case '/':
|
||||||
|
sb.append(c);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
throw this.syntaxError("Illegal escape.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case '"':
|
|
||||||
case '\'':
|
|
||||||
case '\\':
|
|
||||||
case '/':
|
|
||||||
sb.append(c);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
throw this.syntaxError("Illegal escape.");
|
if (c == quote) {
|
||||||
}
|
return sb.toString();
|
||||||
break;
|
}
|
||||||
default:
|
sb.append(c);
|
||||||
if (c == quote) {
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
sb.append(c);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -366,14 +384,15 @@ public class JSONTokener {
|
|||||||
/**
|
/**
|
||||||
* Get the text up but not including the specified character or the
|
* Get the text up but not including the specified character or the
|
||||||
* end of line, whichever comes first.
|
* end of line, whichever comes first.
|
||||||
* @param delimiter A delimiter character.
|
*
|
||||||
* @return A string.
|
* @param delimiter A delimiter character.
|
||||||
|
* @return A string.
|
||||||
* @throws JSONException Thrown if there is an error while searching
|
* @throws JSONException Thrown if there is an error while searching
|
||||||
* for the delimiter
|
* for the delimiter
|
||||||
*/
|
*/
|
||||||
public String nextTo(char delimiter) throws JSONException {
|
public String nextTo(char delimiter) throws JSONException {
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
char c = this.next();
|
char c = this.next();
|
||||||
if (c == delimiter || c == 0 || c == '\n' || c == '\r') {
|
if (c == delimiter || c == 0 || c == '\n' || c == '\r') {
|
||||||
if (c != 0) {
|
if (c != 0) {
|
||||||
@ -389,15 +408,16 @@ public class JSONTokener {
|
|||||||
/**
|
/**
|
||||||
* Get the text up but not including one of the specified delimiter
|
* Get the text up but not including one of the specified delimiter
|
||||||
* characters or the end of line, whichever comes first.
|
* characters or the end of line, whichever comes first.
|
||||||
|
*
|
||||||
* @param delimiters A set of delimiter characters.
|
* @param delimiters A set of delimiter characters.
|
||||||
* @return A string, trimmed.
|
* @return A string, trimmed.
|
||||||
* @throws JSONException Thrown if there is an error while searching
|
* @throws JSONException Thrown if there is an error while searching
|
||||||
* for the delimiter
|
* for the delimiter
|
||||||
*/
|
*/
|
||||||
public String nextTo(String delimiters) throws JSONException {
|
public String nextTo(String delimiters) throws JSONException {
|
||||||
char c;
|
char c;
|
||||||
StringBuilder sb = new StringBuilder();
|
StringBuilder sb = new StringBuilder();
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
c = this.next();
|
c = this.next();
|
||||||
if (delimiters.indexOf(c) >= 0 || c == 0 ||
|
if (delimiters.indexOf(c) >= 0 || c == 0 ||
|
||||||
c == '\n' || c == '\r') {
|
c == '\n' || c == '\r') {
|
||||||
@ -414,24 +434,24 @@ public class JSONTokener {
|
|||||||
/**
|
/**
|
||||||
* Get the next value. The value can be a Boolean, Double, Integer,
|
* Get the next value. The value can be a Boolean, Double, Integer,
|
||||||
* JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
|
* JSONArray, JSONObject, Long, or String, or the JSONObject.NULL object.
|
||||||
* @throws JSONException If syntax error.
|
|
||||||
*
|
*
|
||||||
* @return An object.
|
* @return An object.
|
||||||
|
* @throws JSONException If syntax error.
|
||||||
*/
|
*/
|
||||||
public Object nextValue() throws JSONException {
|
public Object nextValue() throws JSONException {
|
||||||
char c = this.nextClean();
|
char c = this.nextClean();
|
||||||
String string;
|
String string;
|
||||||
|
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case '"':
|
case '"':
|
||||||
case '\'':
|
case '\'':
|
||||||
return this.nextString(c);
|
return this.nextString(c);
|
||||||
case '{':
|
case '{':
|
||||||
this.back();
|
this.back();
|
||||||
return new JSONObject(this);
|
return new JSONObject(this);
|
||||||
case '[':
|
case '[':
|
||||||
this.back();
|
this.back();
|
||||||
return new JSONArray(this);
|
return new JSONArray(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -463,11 +483,12 @@ public class JSONTokener {
|
|||||||
/**
|
/**
|
||||||
* Skip characters until the next character is the requested character.
|
* Skip characters until the next character is the requested character.
|
||||||
* If the requested character is not found, no characters are skipped.
|
* If the requested character is not found, no characters are skipped.
|
||||||
|
*
|
||||||
* @param to A character to skip to.
|
* @param to A character to skip to.
|
||||||
* @return The requested character, or zero if the requested character
|
* @return The requested character, or zero if the requested character
|
||||||
* is not found.
|
* is not found.
|
||||||
* @throws JSONException Thrown if there is an error while searching
|
* @throws JSONException Thrown if there is an error while searching
|
||||||
* for the to character
|
* for the to character
|
||||||
*/
|
*/
|
||||||
public char skipTo(char to) throws JSONException {
|
public char skipTo(char to) throws JSONException {
|
||||||
char c;
|
char c;
|
||||||
@ -501,7 +522,7 @@ public class JSONTokener {
|
|||||||
* Make a JSONException to signal a syntax error.
|
* Make a JSONException to signal a syntax error.
|
||||||
*
|
*
|
||||||
* @param message The error message.
|
* @param message The error message.
|
||||||
* @return A JSONException object, suitable for throwing
|
* @return A JSONException object, suitable for throwing
|
||||||
*/
|
*/
|
||||||
public JSONException syntaxError(String message) {
|
public JSONException syntaxError(String message) {
|
||||||
return new JSONException(message + this.toString());
|
return new JSONException(message + this.toString());
|
||||||
@ -510,9 +531,9 @@ public class JSONTokener {
|
|||||||
/**
|
/**
|
||||||
* Make a JSONException to signal a syntax error.
|
* Make a JSONException to signal a syntax error.
|
||||||
*
|
*
|
||||||
* @param message The error message.
|
* @param message The error message.
|
||||||
* @param causedBy The throwable that caused the error.
|
* @param causedBy The throwable that caused the error.
|
||||||
* @return A JSONException object, suitable for throwing
|
* @return A JSONException object, suitable for throwing
|
||||||
*/
|
*/
|
||||||
public JSONException syntaxError(String message, Throwable causedBy) {
|
public JSONException syntaxError(String message, Throwable causedBy) {
|
||||||
return new JSONException(message + this.toString(), causedBy);
|
return new JSONException(message + this.toString(), causedBy);
|
||||||
|
@ -54,18 +54,16 @@ SOFTWARE.
|
|||||||
* you. Objects and arrays can be nested up to 200 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 2016-08-08
|
* @version 2016-08-08
|
||||||
*/
|
*/
|
||||||
public class JSONWriter {
|
public class JSONWriter {
|
||||||
private static final int maxdepth = 200;
|
private static final int maxdepth = 200;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The comma flag determines if a comma should be output before the next
|
* The object/array stack.
|
||||||
* value.
|
|
||||||
*/
|
*/
|
||||||
private boolean comma;
|
private final JSONObject[] stack;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The current mode. Values:
|
* The current mode. Values:
|
||||||
* 'a' (array),
|
* 'a' (array),
|
||||||
@ -75,21 +73,19 @@ public class JSONWriter {
|
|||||||
* 'o' (object).
|
* 'o' (object).
|
||||||
*/
|
*/
|
||||||
protected char mode;
|
protected char mode;
|
||||||
|
|
||||||
/**
|
|
||||||
* The object/array stack.
|
|
||||||
*/
|
|
||||||
private final JSONObject stack[];
|
|
||||||
|
|
||||||
/**
|
|
||||||
* The stack top index. A value of 0 indicates that the stack is empty.
|
|
||||||
*/
|
|
||||||
private int top;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The writer that will receive the output.
|
* The writer that will receive the output.
|
||||||
*/
|
*/
|
||||||
protected Appendable writer;
|
protected Appendable writer;
|
||||||
|
/**
|
||||||
|
* The comma flag determines if a comma should be output before the next
|
||||||
|
* value.
|
||||||
|
*/
|
||||||
|
private boolean comma;
|
||||||
|
/**
|
||||||
|
* The stack top index. A value of 0 indicates that the stack is empty.
|
||||||
|
*/
|
||||||
|
private int top;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
@ -102,200 +98,6 @@ public class JSONWriter {
|
|||||||
this.writer = w;
|
this.writer = w;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a value.
|
|
||||||
* @param string A string value.
|
|
||||||
* @return this
|
|
||||||
* @throws JSONException If the value is out of sequence.
|
|
||||||
*/
|
|
||||||
private JSONWriter append(String string) throws JSONException {
|
|
||||||
if (string == null) {
|
|
||||||
throw new JSONException("Null pointer");
|
|
||||||
}
|
|
||||||
if (this.mode == 'o' || this.mode == 'a') {
|
|
||||||
try {
|
|
||||||
if (this.comma && this.mode == 'a') {
|
|
||||||
this.writer.append(',');
|
|
||||||
}
|
|
||||||
this.writer.append(string);
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Android as of API 25 does not support this exception constructor
|
|
||||||
// however we won't worry about it. If an exception is happening here
|
|
||||||
// it will just throw a "Method not found" exception instead.
|
|
||||||
throw new JSONException(e);
|
|
||||||
}
|
|
||||||
if (this.mode == 'o') {
|
|
||||||
this.mode = 'k';
|
|
||||||
}
|
|
||||||
this.comma = true;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
throw new JSONException("Value out of sequence.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Begin appending a new array. All values until the balancing
|
|
||||||
* <code>endArray</code> will be appended to this array. The
|
|
||||||
* <code>endArray</code> method must be called to mark the array's end.
|
|
||||||
* @return this
|
|
||||||
* @throws JSONException If the nesting is too deep, or if the object is
|
|
||||||
* started in the wrong place (for example as a key or after the end of the
|
|
||||||
* outermost array or object).
|
|
||||||
*/
|
|
||||||
public JSONWriter array() throws JSONException {
|
|
||||||
if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
|
|
||||||
this.push(null);
|
|
||||||
this.append("[");
|
|
||||||
this.comma = false;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
throw new JSONException("Misplaced array.");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* End something.
|
|
||||||
* @param m Mode
|
|
||||||
* @param c Closing character
|
|
||||||
* @return this
|
|
||||||
* @throws JSONException If unbalanced.
|
|
||||||
*/
|
|
||||||
private JSONWriter end(char m, char c) throws JSONException {
|
|
||||||
if (this.mode != m) {
|
|
||||||
throw new JSONException(m == 'a'
|
|
||||||
? "Misplaced endArray."
|
|
||||||
: "Misplaced endObject.");
|
|
||||||
}
|
|
||||||
this.pop(m);
|
|
||||||
try {
|
|
||||||
this.writer.append(c);
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Android as of API 25 does not support this exception constructor
|
|
||||||
// however we won't worry about it. If an exception is happening here
|
|
||||||
// it will just throw a "Method not found" exception instead.
|
|
||||||
throw new JSONException(e);
|
|
||||||
}
|
|
||||||
this.comma = true;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* End an array. This method most be called to balance calls to
|
|
||||||
* <code>array</code>.
|
|
||||||
* @return this
|
|
||||||
* @throws JSONException If incorrectly nested.
|
|
||||||
*/
|
|
||||||
public JSONWriter endArray() throws JSONException {
|
|
||||||
return this.end('a', ']');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* End an object. This method most be called to balance calls to
|
|
||||||
* <code>object</code>.
|
|
||||||
* @return this
|
|
||||||
* @throws JSONException If incorrectly nested.
|
|
||||||
*/
|
|
||||||
public JSONWriter endObject() throws JSONException {
|
|
||||||
return this.end('k', '}');
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Append a key. The key will be associated with the next value. In an
|
|
||||||
* object, every value must be preceded by a key.
|
|
||||||
* @param string A key string.
|
|
||||||
* @return this
|
|
||||||
* @throws JSONException If the key is out of place. For example, keys
|
|
||||||
* do not belong in arrays or if the key is null.
|
|
||||||
*/
|
|
||||||
public JSONWriter key(String string) throws JSONException {
|
|
||||||
if (string == null) {
|
|
||||||
throw new JSONException("Null key.");
|
|
||||||
}
|
|
||||||
if (this.mode == 'k') {
|
|
||||||
try {
|
|
||||||
JSONObject topObject = this.stack[this.top - 1];
|
|
||||||
// don't use the built in putOnce method to maintain Android support
|
|
||||||
if(topObject.has(string)) {
|
|
||||||
throw new JSONException("Duplicate key \"" + string + "\"");
|
|
||||||
}
|
|
||||||
topObject.put(string, true);
|
|
||||||
if (this.comma) {
|
|
||||||
this.writer.append(',');
|
|
||||||
}
|
|
||||||
this.writer.append(JSONObject.quote(string));
|
|
||||||
this.writer.append(':');
|
|
||||||
this.comma = false;
|
|
||||||
this.mode = 'o';
|
|
||||||
return this;
|
|
||||||
} catch (IOException e) {
|
|
||||||
// Android as of API 25 does not support this exception constructor
|
|
||||||
// however we won't worry about it. If an exception is happening here
|
|
||||||
// it will just throw a "Method not found" exception instead.
|
|
||||||
throw new JSONException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw new JSONException("Misplaced key.");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Begin appending a new object. All keys and values until the balancing
|
|
||||||
* <code>endObject</code> will be appended to this object. The
|
|
||||||
* <code>endObject</code> method must be called to mark the object's end.
|
|
||||||
* @return this
|
|
||||||
* @throws JSONException If the nesting is too deep, or if the object is
|
|
||||||
* started in the wrong place (for example as a key or after the end of the
|
|
||||||
* outermost array or object).
|
|
||||||
*/
|
|
||||||
public JSONWriter object() throws JSONException {
|
|
||||||
if (this.mode == 'i') {
|
|
||||||
this.mode = 'o';
|
|
||||||
}
|
|
||||||
if (this.mode == 'o' || this.mode == 'a') {
|
|
||||||
this.append("{");
|
|
||||||
this.push(new JSONObject());
|
|
||||||
this.comma = false;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
throw new JSONException("Misplaced object.");
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Pop an array or object scope.
|
|
||||||
* @param c The scope to close.
|
|
||||||
* @throws JSONException If nesting is wrong.
|
|
||||||
*/
|
|
||||||
private void pop(char c) throws JSONException {
|
|
||||||
if (this.top <= 0) {
|
|
||||||
throw new JSONException("Nesting error.");
|
|
||||||
}
|
|
||||||
char m = this.stack[this.top - 1] == null ? 'a' : 'k';
|
|
||||||
if (m != c) {
|
|
||||||
throw new JSONException("Nesting error.");
|
|
||||||
}
|
|
||||||
this.top -= 1;
|
|
||||||
this.mode = this.top == 0
|
|
||||||
? 'd'
|
|
||||||
: this.stack[this.top - 1] == null
|
|
||||||
? 'a'
|
|
||||||
: 'k';
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Push an array or object scope.
|
|
||||||
* @param jo The scope to open.
|
|
||||||
* @throws JSONException If nesting is too deep.
|
|
||||||
*/
|
|
||||||
private void push(JSONObject jo) throws JSONException {
|
|
||||||
if (this.top >= maxdepth) {
|
|
||||||
throw new JSONException("Nesting too deep.");
|
|
||||||
}
|
|
||||||
this.stack[this.top] = jo;
|
|
||||||
this.mode = jo == null ? 'a' : 'k';
|
|
||||||
this.top += 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Make a JSON text of an Object value. If the object has an
|
* Make a JSON text of an Object value. If the object has an
|
||||||
* value.toJSONString() method, then that method will be used to produce the
|
* value.toJSONString() method, then that method will be used to produce the
|
||||||
@ -311,14 +113,12 @@ public class JSONWriter {
|
|||||||
* <p>
|
* <p>
|
||||||
* Warning: This method assumes that the data structure is acyclical.
|
* Warning: This method assumes that the data structure is acyclical.
|
||||||
*
|
*
|
||||||
* @param value
|
* @param value The value to be serialized.
|
||||||
* The value to be serialized.
|
|
||||||
* @return a printable, displayable, transmittable representation of the
|
* @return a printable, displayable, transmittable representation of the
|
||||||
* object, beginning with <code>{</code> <small>(left
|
* object, beginning with <code>{</code> <small>(left
|
||||||
* brace)</small> and ending with <code>}</code> <small>(right
|
* brace)</small> and ending with <code>}</code> <small>(right
|
||||||
* brace)</small>.
|
* brace)</small>.
|
||||||
* @throws JSONException
|
* @throws JSONException If the value is or contains an invalid number.
|
||||||
* If the value is or contains an invalid number.
|
|
||||||
*/
|
*/
|
||||||
public static String valueToString(Object value) throws JSONException {
|
public static String valueToString(Object value) throws JSONException {
|
||||||
if (value == null || value.equals(null)) {
|
if (value == null || value.equals(null)) {
|
||||||
@ -339,7 +139,7 @@ public class JSONWriter {
|
|||||||
if (value instanceof Number) {
|
if (value instanceof Number) {
|
||||||
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
|
// not all Numbers may match actual JSON Numbers. i.e. Fractions or Complex
|
||||||
final String numberAsString = JSONObject.numberToString((Number) value);
|
final String numberAsString = JSONObject.numberToString((Number) value);
|
||||||
if(JSONObject.NUMBER_PATTERN.matcher(numberAsString).matches()) {
|
if (JSONObject.NUMBER_PATTERN.matcher(numberAsString).matches()) {
|
||||||
// Close enough to a JSON number that we will return it unquoted
|
// Close enough to a JSON number that we will return it unquoted
|
||||||
return numberAsString;
|
return numberAsString;
|
||||||
}
|
}
|
||||||
@ -362,15 +162,217 @@ public class JSONWriter {
|
|||||||
if (value.getClass().isArray()) {
|
if (value.getClass().isArray()) {
|
||||||
return new JSONArray(value).toString();
|
return new JSONArray(value).toString();
|
||||||
}
|
}
|
||||||
if(value instanceof Enum<?>){
|
if (value instanceof Enum<?>) {
|
||||||
return JSONObject.quote(((Enum<?>)value).name());
|
return JSONObject.quote(((Enum<?>) value).name());
|
||||||
}
|
}
|
||||||
return JSONObject.quote(value.toString());
|
return JSONObject.quote(value.toString());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a value.
|
||||||
|
*
|
||||||
|
* @param string A string value.
|
||||||
|
* @return this
|
||||||
|
* @throws JSONException If the value is out of sequence.
|
||||||
|
*/
|
||||||
|
private JSONWriter append(String string) throws JSONException {
|
||||||
|
if (string == null) {
|
||||||
|
throw new JSONException("Null pointer");
|
||||||
|
}
|
||||||
|
if (this.mode == 'o' || this.mode == 'a') {
|
||||||
|
try {
|
||||||
|
if (this.comma && this.mode == 'a') {
|
||||||
|
this.writer.append(',');
|
||||||
|
}
|
||||||
|
this.writer.append(string);
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Android as of API 25 does not support this exception constructor
|
||||||
|
// however we won't worry about it. If an exception is happening here
|
||||||
|
// it will just throw a "Method not found" exception instead.
|
||||||
|
throw new JSONException(e);
|
||||||
|
}
|
||||||
|
if (this.mode == 'o') {
|
||||||
|
this.mode = 'k';
|
||||||
|
}
|
||||||
|
this.comma = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
throw new JSONException("Value out of sequence.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begin appending a new array. All values until the balancing
|
||||||
|
* <code>endArray</code> will be appended to this array. The
|
||||||
|
* <code>endArray</code> method must be called to mark the array's end.
|
||||||
|
*
|
||||||
|
* @return this
|
||||||
|
* @throws JSONException If the nesting is too deep, or if the object is
|
||||||
|
* started in the wrong place (for example as a key or after the end of the
|
||||||
|
* outermost array or object).
|
||||||
|
*/
|
||||||
|
public JSONWriter array() throws JSONException {
|
||||||
|
if (this.mode == 'i' || this.mode == 'o' || this.mode == 'a') {
|
||||||
|
this.push(null);
|
||||||
|
this.append("[");
|
||||||
|
this.comma = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
throw new JSONException("Misplaced array.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End something.
|
||||||
|
*
|
||||||
|
* @param m Mode
|
||||||
|
* @param c Closing character
|
||||||
|
* @return this
|
||||||
|
* @throws JSONException If unbalanced.
|
||||||
|
*/
|
||||||
|
private JSONWriter end(char m, char c) throws JSONException {
|
||||||
|
if (this.mode != m) {
|
||||||
|
throw new JSONException(m == 'a'
|
||||||
|
? "Misplaced endArray."
|
||||||
|
: "Misplaced endObject.");
|
||||||
|
}
|
||||||
|
this.pop(m);
|
||||||
|
try {
|
||||||
|
this.writer.append(c);
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Android as of API 25 does not support this exception constructor
|
||||||
|
// however we won't worry about it. If an exception is happening here
|
||||||
|
// it will just throw a "Method not found" exception instead.
|
||||||
|
throw new JSONException(e);
|
||||||
|
}
|
||||||
|
this.comma = true;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End an array. This method most be called to balance calls to
|
||||||
|
* <code>array</code>.
|
||||||
|
*
|
||||||
|
* @return this
|
||||||
|
* @throws JSONException If incorrectly nested.
|
||||||
|
*/
|
||||||
|
public JSONWriter endArray() throws JSONException {
|
||||||
|
return this.end('a', ']');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* End an object. This method most be called to balance calls to
|
||||||
|
* <code>object</code>.
|
||||||
|
*
|
||||||
|
* @return this
|
||||||
|
* @throws JSONException If incorrectly nested.
|
||||||
|
*/
|
||||||
|
public JSONWriter endObject() throws JSONException {
|
||||||
|
return this.end('k', '}');
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Append a key. The key will be associated with the next value. In an
|
||||||
|
* object, every value must be preceded by a key.
|
||||||
|
*
|
||||||
|
* @param string A key string.
|
||||||
|
* @return this
|
||||||
|
* @throws JSONException If the key is out of place. For example, keys
|
||||||
|
* do not belong in arrays or if the key is null.
|
||||||
|
*/
|
||||||
|
public JSONWriter key(String string) throws JSONException {
|
||||||
|
if (string == null) {
|
||||||
|
throw new JSONException("Null key.");
|
||||||
|
}
|
||||||
|
if (this.mode == 'k') {
|
||||||
|
try {
|
||||||
|
JSONObject topObject = this.stack[this.top - 1];
|
||||||
|
// don't use the built in putOnce method to maintain Android support
|
||||||
|
if (topObject.has(string)) {
|
||||||
|
throw new JSONException("Duplicate key \"" + string + "\"");
|
||||||
|
}
|
||||||
|
topObject.put(string, true);
|
||||||
|
if (this.comma) {
|
||||||
|
this.writer.append(',');
|
||||||
|
}
|
||||||
|
this.writer.append(JSONObject.quote(string));
|
||||||
|
this.writer.append(':');
|
||||||
|
this.comma = false;
|
||||||
|
this.mode = 'o';
|
||||||
|
return this;
|
||||||
|
} catch (IOException e) {
|
||||||
|
// Android as of API 25 does not support this exception constructor
|
||||||
|
// however we won't worry about it. If an exception is happening here
|
||||||
|
// it will just throw a "Method not found" exception instead.
|
||||||
|
throw new JSONException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw new JSONException("Misplaced key.");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begin appending a new object. All keys and values until the balancing
|
||||||
|
* <code>endObject</code> will be appended to this object. The
|
||||||
|
* <code>endObject</code> method must be called to mark the object's end.
|
||||||
|
*
|
||||||
|
* @return this
|
||||||
|
* @throws JSONException If the nesting is too deep, or if the object is
|
||||||
|
* started in the wrong place (for example as a key or after the end of the
|
||||||
|
* outermost array or object).
|
||||||
|
*/
|
||||||
|
public JSONWriter object() throws JSONException {
|
||||||
|
if (this.mode == 'i') {
|
||||||
|
this.mode = 'o';
|
||||||
|
}
|
||||||
|
if (this.mode == 'o' || this.mode == 'a') {
|
||||||
|
this.append("{");
|
||||||
|
this.push(new JSONObject());
|
||||||
|
this.comma = false;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
throw new JSONException("Misplaced object.");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Pop an array or object scope.
|
||||||
|
*
|
||||||
|
* @param c The scope to close.
|
||||||
|
* @throws JSONException If nesting is wrong.
|
||||||
|
*/
|
||||||
|
private void pop(char c) throws JSONException {
|
||||||
|
if (this.top <= 0) {
|
||||||
|
throw new JSONException("Nesting error.");
|
||||||
|
}
|
||||||
|
char m = this.stack[this.top - 1] == null ? 'a' : 'k';
|
||||||
|
if (m != c) {
|
||||||
|
throw new JSONException("Nesting error.");
|
||||||
|
}
|
||||||
|
this.top -= 1;
|
||||||
|
this.mode = this.top == 0
|
||||||
|
? 'd'
|
||||||
|
: this.stack[this.top - 1] == null
|
||||||
|
? 'a'
|
||||||
|
: 'k';
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Push an array or object scope.
|
||||||
|
*
|
||||||
|
* @param jo The scope to open.
|
||||||
|
* @throws JSONException If nesting is too deep.
|
||||||
|
*/
|
||||||
|
private void push(JSONObject jo) throws JSONException {
|
||||||
|
if (this.top >= maxdepth) {
|
||||||
|
throw new JSONException("Nesting too deep.");
|
||||||
|
}
|
||||||
|
this.stack[this.top] = jo;
|
||||||
|
this.mode = jo == null ? 'a' : 'k';
|
||||||
|
this.top += 1;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Append either the value <code>true</code> or the value
|
* Append either the value <code>true</code> or the value
|
||||||
* <code>false</code>.
|
* <code>false</code>.
|
||||||
|
*
|
||||||
* @param b A boolean.
|
* @param b A boolean.
|
||||||
* @return this
|
* @return this
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
@ -381,6 +383,7 @@ public class JSONWriter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a double value.
|
* Append a double value.
|
||||||
|
*
|
||||||
* @param d A double.
|
* @param d A double.
|
||||||
* @return this
|
* @return this
|
||||||
* @throws JSONException If the number is not finite.
|
* @throws JSONException If the number is not finite.
|
||||||
@ -391,6 +394,7 @@ public class JSONWriter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Append a long value.
|
* Append a long value.
|
||||||
|
*
|
||||||
* @param l A long.
|
* @param l A long.
|
||||||
* @return this
|
* @return this
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
@ -402,8 +406,9 @@ public class JSONWriter {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Append an object value.
|
* Append an object value.
|
||||||
|
*
|
||||||
* @param object The object to append. It can be null, or a Boolean, Number,
|
* @param object The object to append. It can be null, or a Boolean, Number,
|
||||||
* String, JSONObject, or JSONArray, or an object that implements JSONString.
|
* String, JSONObject, or JSONArray, or an object that implements JSONString.
|
||||||
* @return this
|
* @return this
|
||||||
* @throws JSONException If the value is out of sequence.
|
* @throws JSONException If the value is out of sequence.
|
||||||
*/
|
*/
|
||||||
|
@ -29,12 +29,14 @@ import java.util.Properties;
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts a Property file data into JSONObject and back.
|
* Converts a Property file data into JSONObject and back.
|
||||||
|
*
|
||||||
* @author JSON.org
|
* @author JSON.org
|
||||||
* @version 2015-05-05
|
* @version 2015-05-05
|
||||||
*/
|
*/
|
||||||
public class Property {
|
public class Property {
|
||||||
/**
|
/**
|
||||||
* Converts a property file object into a JSONObject. The property file object is a table of name value pairs.
|
* Converts a property file object into a JSONObject. The property file object is a table of name value pairs.
|
||||||
|
*
|
||||||
* @param properties java.util.Properties
|
* @param properties java.util.Properties
|
||||||
* @return JSONObject
|
* @return JSONObject
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
@ -45,8 +47,8 @@ public class Property {
|
|||||||
JSONObject jo = new JSONObject();
|
JSONObject jo = new JSONObject();
|
||||||
if (properties != null && !properties.isEmpty()) {
|
if (properties != null && !properties.isEmpty()) {
|
||||||
Enumeration<?> enumProperties = properties.propertyNames();
|
Enumeration<?> enumProperties = properties.propertyNames();
|
||||||
while(enumProperties.hasMoreElements()) {
|
while (enumProperties.hasMoreElements()) {
|
||||||
String name = (String)enumProperties.nextElement();
|
String name = (String) enumProperties.nextElement();
|
||||||
jo.put(name, properties.getProperty(name));
|
jo.put(name, properties.getProperty(name));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -55,14 +57,15 @@ public class Property {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Converts the JSONObject into a property file object.
|
* Converts the JSONObject into a property file object.
|
||||||
|
*
|
||||||
* @param jo JSONObject
|
* @param jo JSONObject
|
||||||
* @return java.util.Properties
|
* @return java.util.Properties
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
public static Properties toProperties(JSONObject jo) throws JSONException {
|
public static Properties toProperties(JSONObject jo) throws JSONException {
|
||||||
Properties properties = new Properties();
|
Properties properties = new Properties();
|
||||||
if (jo != null) {
|
if (jo != null) {
|
||||||
// Don't use the new entrySet API to maintain Android support
|
// Don't use the new entrySet API to maintain Android support
|
||||||
for (final String key : jo.keySet()) {
|
for (final String key : jo.keySet()) {
|
||||||
Object value = jo.opt(key);
|
Object value = jo.opt(key);
|
||||||
if (!JSONObject.NULL.equals(value)) {
|
if (!JSONObject.NULL.equals(value)) {
|
||||||
|
@ -38,31 +38,49 @@ import java.util.Iterator;
|
|||||||
@SuppressWarnings("boxing")
|
@SuppressWarnings("boxing")
|
||||||
public class XML {
|
public class XML {
|
||||||
|
|
||||||
/** The Character '&'. */
|
/**
|
||||||
|
* The Character '&'.
|
||||||
|
*/
|
||||||
public static final Character AMP = '&';
|
public static final Character AMP = '&';
|
||||||
|
|
||||||
/** The Character '''. */
|
/**
|
||||||
|
* The Character '''.
|
||||||
|
*/
|
||||||
public static final Character APOS = '\'';
|
public static final Character APOS = '\'';
|
||||||
|
|
||||||
/** The Character '!'. */
|
/**
|
||||||
|
* The Character '!'.
|
||||||
|
*/
|
||||||
public static final Character BANG = '!';
|
public static final Character BANG = '!';
|
||||||
|
|
||||||
/** The Character '='. */
|
/**
|
||||||
|
* The Character '='.
|
||||||
|
*/
|
||||||
public static final Character EQ = '=';
|
public static final Character EQ = '=';
|
||||||
|
|
||||||
/** The Character '>'. */
|
/**
|
||||||
|
* The Character '>'.
|
||||||
|
*/
|
||||||
public static final Character GT = '>';
|
public static final Character GT = '>';
|
||||||
|
|
||||||
/** The Character '<'. */
|
/**
|
||||||
|
* The Character '<'.
|
||||||
|
*/
|
||||||
public static final Character LT = '<';
|
public static final Character LT = '<';
|
||||||
|
|
||||||
/** The Character '?'. */
|
/**
|
||||||
|
* The Character '?'.
|
||||||
|
*/
|
||||||
public static final Character QUEST = '?';
|
public static final Character QUEST = '?';
|
||||||
|
|
||||||
/** The Character '"'. */
|
/**
|
||||||
|
* The Character '"'.
|
||||||
|
*/
|
||||||
public static final Character QUOT = '"';
|
public static final Character QUOT = '"';
|
||||||
|
|
||||||
/** The Character '/'. */
|
/**
|
||||||
|
* The Character '/'.
|
||||||
|
*/
|
||||||
public static final Character SLASH = '/';
|
public static final Character SLASH = '/';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -79,7 +97,7 @@ public class XML {
|
|||||||
* which is available in Java8 and above.
|
* which is available in Java8 and above.
|
||||||
*
|
*
|
||||||
* @see <a href=
|
* @see <a href=
|
||||||
* "http://stackoverflow.com/a/21791059/6030888">http://stackoverflow.com/a/21791059/6030888</a>
|
* "http://stackoverflow.com/a/21791059/6030888">http://stackoverflow.com/a/21791059/6030888</a>
|
||||||
*/
|
*/
|
||||||
private static Iterable<Integer> codePointIterator(final String string) {
|
private static Iterable<Integer> codePointIterator(final String string) {
|
||||||
return new Iterable<Integer>() {
|
return new Iterable<Integer>() {
|
||||||
@ -121,37 +139,36 @@ public class XML {
|
|||||||
* ' <small>(single quote / apostrophe)</small> is replaced by &apos;
|
* ' <small>(single quote / apostrophe)</small> is replaced by &apos;
|
||||||
* </pre>
|
* </pre>
|
||||||
*
|
*
|
||||||
* @param string
|
* @param string The string to be escaped.
|
||||||
* The string to be escaped.
|
|
||||||
* @return The escaped string.
|
* @return The escaped string.
|
||||||
*/
|
*/
|
||||||
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 (final int cp : codePointIterator(string)) {
|
for (final int cp : codePointIterator(string)) {
|
||||||
switch (cp) {
|
switch (cp) {
|
||||||
case '&':
|
case '&':
|
||||||
sb.append("&");
|
sb.append("&");
|
||||||
break;
|
break;
|
||||||
case '<':
|
case '<':
|
||||||
sb.append("<");
|
sb.append("<");
|
||||||
break;
|
break;
|
||||||
case '>':
|
case '>':
|
||||||
sb.append(">");
|
sb.append(">");
|
||||||
break;
|
break;
|
||||||
case '"':
|
case '"':
|
||||||
sb.append(""");
|
sb.append(""");
|
||||||
break;
|
break;
|
||||||
case '\'':
|
case '\'':
|
||||||
sb.append("'");
|
sb.append("'");
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
if (mustEscape(cp)) {
|
if (mustEscape(cp)) {
|
||||||
sb.append("&#x");
|
sb.append("&#x");
|
||||||
sb.append(Integer.toHexString(cp));
|
sb.append(Integer.toHexString(cp));
|
||||||
sb.append(';');
|
sb.append(';');
|
||||||
} else {
|
} else {
|
||||||
sb.appendCodePoint(cp);
|
sb.appendCodePoint(cp);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
@ -174,20 +191,19 @@ public class XML {
|
|||||||
&& cp != 0x9
|
&& cp != 0x9
|
||||||
&& cp != 0xA
|
&& cp != 0xA
|
||||||
&& cp != 0xD
|
&& cp != 0xD
|
||||||
) || !(
|
) || !(
|
||||||
// valid the range of acceptable characters that aren't control
|
// valid the range of acceptable characters that aren't control
|
||||||
(cp >= 0x20 && cp <= 0xD7FF)
|
(cp >= 0x20 && cp <= 0xD7FF)
|
||||||
|| (cp >= 0xE000 && cp <= 0xFFFD)
|
|| (cp >= 0xE000 && cp <= 0xFFFD)
|
||||||
|| (cp >= 0x10000 && cp <= 0x10FFFF)
|
|| (cp >= 0x10000 && cp <= 0x10FFFF)
|
||||||
)
|
)
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Removes XML escapes from the string.
|
* Removes XML escapes from the string.
|
||||||
*
|
*
|
||||||
* @param string
|
* @param string string to remove escapes from
|
||||||
* string to remove escapes from
|
|
||||||
* @return string with converted entities
|
* @return string with converted entities
|
||||||
*/
|
*/
|
||||||
public static String unescape(String string) {
|
public static String unescape(String string) {
|
||||||
@ -218,8 +234,7 @@ public class XML {
|
|||||||
* Throw an exception if the string contains whitespace. Whitespace is not
|
* Throw an exception if the string contains whitespace. Whitespace is not
|
||||||
* allowed in tagNames and attributes.
|
* allowed in tagNames and attributes.
|
||||||
*
|
*
|
||||||
* @param string
|
* @param string A string.
|
||||||
* A string.
|
|
||||||
* @throws JSONException Thrown if the string contains whitespace or is empty.
|
* @throws JSONException Thrown if the string contains whitespace or is empty.
|
||||||
*/
|
*/
|
||||||
public static void noSpace(String string) throws JSONException {
|
public static void noSpace(String string) throws JSONException {
|
||||||
@ -238,12 +253,9 @@ public class XML {
|
|||||||
/**
|
/**
|
||||||
* Scan the content following the named tag, attaching it to the context.
|
* Scan the content following the named tag, attaching it to the context.
|
||||||
*
|
*
|
||||||
* @param x
|
* @param x The XMLTokener containing the source string.
|
||||||
* The XMLTokener containing the source string.
|
* @param context The JSONObject that will include the new material.
|
||||||
* @param context
|
* @param name The tag name.
|
||||||
* The JSONObject that will include the new material.
|
|
||||||
* @param name
|
|
||||||
* The tag name.
|
|
||||||
* @return true if the close tag is processed.
|
* @return true if the close tag is processed.
|
||||||
* @throws JSONException
|
* @throws JSONException
|
||||||
*/
|
*/
|
||||||
@ -334,7 +346,7 @@ public class XML {
|
|||||||
token = null;
|
token = null;
|
||||||
jsonobject = new JSONObject();
|
jsonobject = new JSONObject();
|
||||||
boolean nilAttributeFound = false;
|
boolean nilAttributeFound = false;
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
token = x.nextToken();
|
token = x.nextToken();
|
||||||
}
|
}
|
||||||
@ -380,7 +392,7 @@ public class XML {
|
|||||||
|
|
||||||
} else if (token == GT) {
|
} else if (token == GT) {
|
||||||
// Content, between <...> and </...>
|
// Content, between <...> and </...>
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
token = x.nextContent();
|
token = x.nextContent();
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
if (tagName != null) {
|
if (tagName != null) {
|
||||||
@ -481,8 +493,7 @@ public class XML {
|
|||||||
* "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
|
* "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
|
||||||
* are ignored.
|
* are ignored.
|
||||||
*
|
*
|
||||||
* @param string
|
* @param string The source string.
|
||||||
* The source string.
|
|
||||||
* @return A JSONObject containing the structured data from the XML string.
|
* @return A JSONObject containing the structured data from the XML string.
|
||||||
* @throws JSONException Thrown if there is an errors while parsing the string
|
* @throws JSONException Thrown if there is an errors while parsing the string
|
||||||
*/
|
*/
|
||||||
@ -519,18 +530,18 @@ public class XML {
|
|||||||
* elements are represented as JSONArrays. Content text may be placed in a
|
* elements are represented as JSONArrays. Content text may be placed in a
|
||||||
* "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
|
* "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
|
||||||
* are ignored.
|
* are ignored.
|
||||||
*
|
* <p>
|
||||||
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
|
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
|
||||||
* numbers but will instead be the exact value as seen in the XML document.
|
* numbers but will instead be the exact value as seen in the XML document.
|
||||||
*
|
*
|
||||||
* @param reader The XML source reader.
|
* @param reader The XML source reader.
|
||||||
* @param keepStrings If true, then values will not be coerced into boolean
|
* @param keepStrings If true, then values will not be coerced into boolean
|
||||||
* or numeric values and will instead be left as strings
|
* or numeric values and will instead be left as strings
|
||||||
* @return A JSONObject containing the structured data from the XML string.
|
* @return A JSONObject containing the structured data from the XML string.
|
||||||
* @throws JSONException Thrown if there is an errors while parsing the string
|
* @throws JSONException Thrown if there is an errors while parsing the string
|
||||||
*/
|
*/
|
||||||
public static JSONObject toJSONObject(Reader reader, boolean keepStrings) throws JSONException {
|
public static JSONObject toJSONObject(Reader reader, boolean keepStrings) throws JSONException {
|
||||||
if(keepStrings) {
|
if (keepStrings) {
|
||||||
return toJSONObject(reader, XMLParserConfiguration.KEEP_STRINGS);
|
return toJSONObject(reader, XMLParserConfiguration.KEEP_STRINGS);
|
||||||
}
|
}
|
||||||
return toJSONObject(reader, XMLParserConfiguration.ORIGINAL);
|
return toJSONObject(reader, XMLParserConfiguration.ORIGINAL);
|
||||||
@ -546,7 +557,7 @@ public class XML {
|
|||||||
* elements are represented as JSONArrays. Content text may be placed in a
|
* elements are represented as JSONArrays. Content text may be placed in a
|
||||||
* "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
|
* "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
|
||||||
* are ignored.
|
* are ignored.
|
||||||
*
|
* <p>
|
||||||
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
|
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
|
||||||
* numbers but will instead be the exact value as seen in the XML document.
|
* numbers but will instead be the exact value as seen in the XML document.
|
||||||
*
|
*
|
||||||
@ -560,7 +571,7 @@ public class XML {
|
|||||||
XMLTokener x = new XMLTokener(reader);
|
XMLTokener x = new XMLTokener(reader);
|
||||||
while (x.more()) {
|
while (x.more()) {
|
||||||
x.skipPast("<");
|
x.skipPast("<");
|
||||||
if(x.more()) {
|
if (x.more()) {
|
||||||
parse(x, jo, null, config);
|
parse(x, jo, null, config);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -577,14 +588,13 @@ public class XML {
|
|||||||
* elements are represented as JSONArrays. Content text may be placed in a
|
* elements are represented as JSONArrays. Content text may be placed in a
|
||||||
* "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
|
* "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
|
||||||
* are ignored.
|
* are ignored.
|
||||||
*
|
* <p>
|
||||||
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
|
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
|
||||||
* numbers but will instead be the exact value as seen in the XML document.
|
* numbers but will instead be the exact value as seen in the XML document.
|
||||||
*
|
*
|
||||||
* @param string
|
* @param string The source string.
|
||||||
* The source string.
|
|
||||||
* @param keepStrings If true, then values will not be coerced into boolean
|
* @param keepStrings If true, then values will not be coerced into boolean
|
||||||
* or numeric values and will instead be left as strings
|
* or numeric values and will instead be left as strings
|
||||||
* @return A JSONObject containing the structured data from the XML string.
|
* @return A JSONObject containing the structured data from the XML string.
|
||||||
* @throws JSONException Thrown if there is an errors while parsing the string
|
* @throws JSONException Thrown if there is an errors while parsing the string
|
||||||
*/
|
*/
|
||||||
@ -602,12 +612,11 @@ public class XML {
|
|||||||
* elements are represented as JSONArrays. Content text may be placed in a
|
* elements are represented as JSONArrays. Content text may be placed in a
|
||||||
* "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
|
* "content" member. Comments, prologs, DTDs, and <code><[ [ ]]></code>
|
||||||
* are ignored.
|
* are ignored.
|
||||||
*
|
* <p>
|
||||||
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
|
* All values are converted as strings, for 1, 01, 29.0 will not be coerced to
|
||||||
* numbers but will instead be the exact value as seen in the XML document.
|
* numbers but will instead be the exact value as seen in the XML document.
|
||||||
*
|
*
|
||||||
* @param string
|
* @param string The source string.
|
||||||
* The source string.
|
|
||||||
* @param config Configuration options for the parser.
|
* @param config Configuration options for the parser.
|
||||||
* @return A JSONObject containing the structured data from the XML string.
|
* @return A JSONObject containing the structured data from the XML string.
|
||||||
* @throws JSONException Thrown if there is an errors while parsing the string
|
* @throws JSONException Thrown if there is an errors while parsing the string
|
||||||
@ -619,8 +628,7 @@ public class XML {
|
|||||||
/**
|
/**
|
||||||
* Convert a JSONObject into a well-formed, element-normal XML string.
|
* Convert a JSONObject into a well-formed, element-normal XML string.
|
||||||
*
|
*
|
||||||
* @param object
|
* @param object A JSONObject.
|
||||||
* A JSONObject.
|
|
||||||
* @return A string.
|
* @return A string.
|
||||||
* @throws JSONException Thrown if there is an error parsing the string
|
* @throws JSONException Thrown if there is an error parsing the string
|
||||||
*/
|
*/
|
||||||
@ -631,10 +639,8 @@ public class XML {
|
|||||||
/**
|
/**
|
||||||
* Convert a JSONObject into a well-formed, element-normal XML string.
|
* Convert a JSONObject into a well-formed, element-normal XML string.
|
||||||
*
|
*
|
||||||
* @param object
|
* @param object A JSONObject.
|
||||||
* A JSONObject.
|
* @param tagName The optional name of the enclosing tag.
|
||||||
* @param tagName
|
|
||||||
* The optional name of the enclosing tag.
|
|
||||||
* @return A string.
|
* @return A string.
|
||||||
* @throws JSONException Thrown if there is an error parsing the string
|
* @throws JSONException Thrown if there is an error parsing the string
|
||||||
*/
|
*/
|
||||||
@ -645,12 +651,9 @@ public class XML {
|
|||||||
/**
|
/**
|
||||||
* Convert a JSONObject into a well-formed, element-normal XML string.
|
* Convert a JSONObject into a well-formed, element-normal XML string.
|
||||||
*
|
*
|
||||||
* @param object
|
* @param object A JSONObject.
|
||||||
* A JSONObject.
|
* @param tagName The optional name of the enclosing tag.
|
||||||
* @param tagName
|
* @param config Configuration that can control output to XML.
|
||||||
* The optional name of the enclosing tag.
|
|
||||||
* @param config
|
|
||||||
* Configuration that can control output to XML.
|
|
||||||
* @return A string.
|
* @return A string.
|
||||||
* @throws JSONException Thrown if there is an error parsing the string
|
* @throws JSONException Thrown if there is an error parsing the string
|
||||||
*/
|
*/
|
||||||
@ -687,7 +690,7 @@ public class XML {
|
|||||||
ja = (JSONArray) value;
|
ja = (JSONArray) value;
|
||||||
int jaLength = ja.length();
|
int jaLength = ja.length();
|
||||||
// don't use the new iterator API to maintain support for Android
|
// don't use the new iterator API to maintain support for Android
|
||||||
for (int i = 0; i < jaLength; i++) {
|
for (int i = 0; i < jaLength; i++) {
|
||||||
if (i > 0) {
|
if (i > 0) {
|
||||||
sb.append('\n');
|
sb.append('\n');
|
||||||
}
|
}
|
||||||
@ -704,7 +707,7 @@ public class XML {
|
|||||||
ja = (JSONArray) value;
|
ja = (JSONArray) value;
|
||||||
int jaLength = ja.length();
|
int jaLength = ja.length();
|
||||||
// don't use the new iterator API to maintain support for Android
|
// don't use the new iterator API to maintain support for Android
|
||||||
for (int i = 0; i < jaLength; i++) {
|
for (int i = 0; i < jaLength; i++) {
|
||||||
Object val = ja.opt(i);
|
Object val = ja.opt(i);
|
||||||
if (val instanceof JSONArray) {
|
if (val instanceof JSONArray) {
|
||||||
sb.append('<');
|
sb.append('<');
|
||||||
@ -740,15 +743,15 @@ public class XML {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (object != null && (object instanceof JSONArray || object.getClass().isArray())) {
|
if (object != null && (object instanceof JSONArray || object.getClass().isArray())) {
|
||||||
if(object.getClass().isArray()) {
|
if (object.getClass().isArray()) {
|
||||||
ja = new JSONArray(object);
|
ja = new JSONArray(object);
|
||||||
} else {
|
} else {
|
||||||
ja = (JSONArray) object;
|
ja = (JSONArray) object;
|
||||||
}
|
}
|
||||||
int jaLength = ja.length();
|
int jaLength = ja.length();
|
||||||
// don't use the new iterator API to maintain support for Android
|
// don't use the new iterator API to maintain support for Android
|
||||||
for (int i = 0; i < jaLength; i++) {
|
for (int i = 0; i < jaLength; i++) {
|
||||||
Object val = ja.opt(i);
|
Object val = ja.opt(i);
|
||||||
// XML does not have good support for arrays. If an array
|
// XML does not have good support for arrays. If an array
|
||||||
// appears in a place where XML is lacking, synthesize an
|
// appears in a place where XML is lacking, synthesize an
|
||||||
@ -761,7 +764,7 @@ public class XML {
|
|||||||
string = (object == null) ? "null" : escape(object.toString());
|
string = (object == null) ? "null" : escape(object.toString());
|
||||||
return (tagName == null) ? "\"" + string + "\""
|
return (tagName == null) ? "\"" + string + "\""
|
||||||
: (string.length() == 0) ? "<" + tagName + "/>" : "<" + tagName
|
: (string.length() == 0) ? "<" + tagName + "/>" : "<" + tagName
|
||||||
+ ">" + string + "</" + tagName + ">";
|
+ ">" + string + "</" + tagName + ">";
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -25,13 +25,17 @@ SOFTWARE.
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Configuration object for the XML parser.
|
* Configuration object for the XML parser.
|
||||||
* @author AylwardJ
|
|
||||||
*
|
*
|
||||||
|
* @author AylwardJ
|
||||||
*/
|
*/
|
||||||
public class XMLParserConfiguration {
|
public class XMLParserConfiguration {
|
||||||
/** Original Configuration of the XML Parser. */
|
/**
|
||||||
|
* Original Configuration of the XML Parser.
|
||||||
|
*/
|
||||||
public static final XMLParserConfiguration ORIGINAL = new XMLParserConfiguration();
|
public static final XMLParserConfiguration ORIGINAL = new XMLParserConfiguration();
|
||||||
/** Original configuration of the XML Parser except that values are kept as strings. */
|
/**
|
||||||
|
* Original configuration of the XML Parser except that values are kept as strings.
|
||||||
|
*/
|
||||||
public static final XMLParserConfiguration KEEP_STRINGS = new XMLParserConfiguration(true);
|
public static final XMLParserConfiguration KEEP_STRINGS = new XMLParserConfiguration(true);
|
||||||
/**
|
/**
|
||||||
* When parsing the XML into JSON, specifies if values should be kept as strings (true), or if
|
* When parsing the XML into JSON, specifies if values should be kept as strings (true), or if
|
||||||
@ -53,16 +57,17 @@ public class XMLParserConfiguration {
|
|||||||
/**
|
/**
|
||||||
* Default parser configuration. Does not keep strings, and the CDATA Tag Name is "content".
|
* Default parser configuration. Does not keep strings, and the CDATA Tag Name is "content".
|
||||||
*/
|
*/
|
||||||
public XMLParserConfiguration () {
|
public XMLParserConfiguration() {
|
||||||
this(false, "content", false);
|
this(false, "content", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure the parser string processing and use the default CDATA Tag Name as "content".
|
* Configure the parser string processing and use the default CDATA Tag Name as "content".
|
||||||
|
*
|
||||||
* @param keepStrings <code>true</code> to parse all values as string.
|
* @param keepStrings <code>true</code> to parse all values as string.
|
||||||
* <code>false</code> to try and convert XML string values into a JSON value.
|
* <code>false</code> to try and convert XML string values into a JSON value.
|
||||||
*/
|
*/
|
||||||
public XMLParserConfiguration (final boolean keepStrings) {
|
public XMLParserConfiguration(final boolean keepStrings) {
|
||||||
this(keepStrings, "content", false);
|
this(keepStrings, "content", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -70,21 +75,23 @@ public class XMLParserConfiguration {
|
|||||||
* Configure the parser string processing to try and convert XML values to JSON values and
|
* Configure the parser string processing to try and convert XML values to JSON values and
|
||||||
* use the passed CDATA Tag Name the processing value. Pass <code>null</code> to
|
* use the passed CDATA Tag Name the processing value. Pass <code>null</code> to
|
||||||
* disable CDATA processing
|
* disable CDATA processing
|
||||||
|
*
|
||||||
* @param cDataTagName<code>null</code> to disable CDATA processing. Any other value
|
* @param cDataTagName<code>null</code> to disable CDATA processing. Any other value
|
||||||
* to use that value as the JSONObject key name to process as CDATA.
|
* to use that value as the JSONObject key name to process as CDATA.
|
||||||
*/
|
*/
|
||||||
public XMLParserConfiguration (final String cDataTagName) {
|
public XMLParserConfiguration(final String cDataTagName) {
|
||||||
this(false, cDataTagName, false);
|
this(false, cDataTagName, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure the parser to use custom settings.
|
* Configure the parser to use custom settings.
|
||||||
* @param keepStrings <code>true</code> to parse all values as string.
|
*
|
||||||
* <code>false</code> to try and convert XML string values into a JSON value.
|
* @param keepStrings <code>true</code> to parse all values as string.
|
||||||
|
* <code>false</code> to try and convert XML string values into a JSON value.
|
||||||
* @param cDataTagName<code>null</code> to disable CDATA processing. Any other value
|
* @param cDataTagName<code>null</code> to disable CDATA processing. Any other value
|
||||||
* to use that value as the JSONObject key name to process as CDATA.
|
* to use that value as the JSONObject key name to process as CDATA.
|
||||||
*/
|
*/
|
||||||
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName) {
|
public XMLParserConfiguration(final boolean keepStrings, final String cDataTagName) {
|
||||||
this.keepStrings = keepStrings;
|
this.keepStrings = keepStrings;
|
||||||
this.cDataTagName = cDataTagName;
|
this.cDataTagName = cDataTagName;
|
||||||
this.convertNilAttributeToNull = false;
|
this.convertNilAttributeToNull = false;
|
||||||
@ -92,14 +99,15 @@ public class XMLParserConfiguration {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure the parser to use custom settings.
|
* Configure the parser to use custom settings.
|
||||||
* @param keepStrings <code>true</code> to parse all values as string.
|
*
|
||||||
* <code>false</code> to try and convert XML string values into a JSON value.
|
* @param keepStrings <code>true</code> to parse all values as string.
|
||||||
* @param cDataTagName <code>null</code> to disable CDATA processing. Any other value
|
* <code>false</code> to try and convert XML string values into a JSON value.
|
||||||
* to use that value as the JSONObject key name to process as CDATA.
|
* @param cDataTagName <code>null</code> to disable CDATA processing. Any other value
|
||||||
|
* to use that value as the JSONObject key name to process as CDATA.
|
||||||
* @param convertNilAttributeToNull <code>true</code> to parse values with attribute xsi:nil="true" as null.
|
* @param convertNilAttributeToNull <code>true</code> to parse values with attribute xsi:nil="true" as null.
|
||||||
* <code>false</code> to parse values with attribute xsi:nil="true" as {"xsi:nil":true}.
|
* <code>false</code> to parse values with attribute xsi:nil="true" as {"xsi:nil":true}.
|
||||||
*/
|
*/
|
||||||
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName, final boolean convertNilAttributeToNull) {
|
public XMLParserConfiguration(final boolean keepStrings, final String cDataTagName, final boolean convertNilAttributeToNull) {
|
||||||
this.keepStrings = keepStrings;
|
this.keepStrings = keepStrings;
|
||||||
this.cDataTagName = cDataTagName;
|
this.cDataTagName = cDataTagName;
|
||||||
this.convertNilAttributeToNull = convertNilAttributeToNull;
|
this.convertNilAttributeToNull = convertNilAttributeToNull;
|
||||||
|
@ -29,28 +29,31 @@ import java.io.Reader;
|
|||||||
/**
|
/**
|
||||||
* The XMLTokener extends the JSONTokener to provide additional methods
|
* The XMLTokener extends the JSONTokener to provide additional methods
|
||||||
* for the parsing of XML texts.
|
* for the parsing of XML texts.
|
||||||
|
*
|
||||||
* @author JSON.org
|
* @author JSON.org
|
||||||
* @version 2015-12-09
|
* @version 2015-12-09
|
||||||
*/
|
*/
|
||||||
public class XMLTokener extends JSONTokener {
|
public class XMLTokener extends JSONTokener {
|
||||||
|
|
||||||
|
|
||||||
/** The table of entity values. It initially contains Character values for
|
/**
|
||||||
* amp, apos, gt, lt, quot.
|
* The table of entity values. It initially contains Character values for
|
||||||
*/
|
* amp, apos, gt, lt, quot.
|
||||||
public static final java.util.HashMap<String, Character> entity;
|
*/
|
||||||
|
public static final java.util.HashMap<String, Character> entity;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
entity = new java.util.HashMap<String, Character>(8);
|
entity = new java.util.HashMap<String, Character>(8);
|
||||||
entity.put("amp", XML.AMP);
|
entity.put("amp", XML.AMP);
|
||||||
entity.put("apos", XML.APOS);
|
entity.put("apos", XML.APOS);
|
||||||
entity.put("gt", XML.GT);
|
entity.put("gt", XML.GT);
|
||||||
entity.put("lt", XML.LT);
|
entity.put("lt", XML.LT);
|
||||||
entity.put("quot", XML.QUOT);
|
entity.put("quot", XML.QUOT);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an XMLTokener from a Reader.
|
* Construct an XMLTokener from a Reader.
|
||||||
|
*
|
||||||
* @param r A source reader.
|
* @param r A source reader.
|
||||||
*/
|
*/
|
||||||
public XMLTokener(Reader r) {
|
public XMLTokener(Reader r) {
|
||||||
@ -59,100 +62,16 @@ public class XMLTokener extends JSONTokener {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Construct an XMLTokener from a string.
|
* Construct an XMLTokener from a string.
|
||||||
|
*
|
||||||
* @param s A source string.
|
* @param s A source string.
|
||||||
*/
|
*/
|
||||||
public XMLTokener(String s) {
|
public XMLTokener(String s) {
|
||||||
super(s);
|
super(s);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the text in the CDATA block.
|
|
||||||
* @return The string up to the <code>]]></code>.
|
|
||||||
* @throws JSONException If the <code>]]></code> is not found.
|
|
||||||
*/
|
|
||||||
public String nextCDATA() throws JSONException {
|
|
||||||
char c;
|
|
||||||
int i;
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
while (more()) {
|
|
||||||
c = next();
|
|
||||||
sb.append(c);
|
|
||||||
i = sb.length() - 3;
|
|
||||||
if (i >= 0 && sb.charAt(i) == ']' &&
|
|
||||||
sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') {
|
|
||||||
sb.setLength(i);
|
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
throw syntaxError("Unclosed CDATA");
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the next XML outer token, trimming whitespace. There are two kinds
|
|
||||||
* of tokens: the '<' character which begins a markup tag, and the content
|
|
||||||
* text between markup tags.
|
|
||||||
*
|
|
||||||
* @return A string, or a '<' Character, or null if there is no more
|
|
||||||
* source text.
|
|
||||||
* @throws JSONException
|
|
||||||
*/
|
|
||||||
public Object nextContent() throws JSONException {
|
|
||||||
char c;
|
|
||||||
StringBuilder sb;
|
|
||||||
do {
|
|
||||||
c = next();
|
|
||||||
} while (Character.isWhitespace(c));
|
|
||||||
if (c == 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
if (c == '<') {
|
|
||||||
return XML.LT;
|
|
||||||
}
|
|
||||||
sb = new StringBuilder();
|
|
||||||
for (;;) {
|
|
||||||
if (c == 0) {
|
|
||||||
return sb.toString().trim();
|
|
||||||
}
|
|
||||||
if (c == '<') {
|
|
||||||
back();
|
|
||||||
return sb.toString().trim();
|
|
||||||
}
|
|
||||||
if (c == '&') {
|
|
||||||
sb.append(nextEntity(c));
|
|
||||||
} else {
|
|
||||||
sb.append(c);
|
|
||||||
}
|
|
||||||
c = next();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Return the next entity. These entities are translated to Characters:
|
|
||||||
* <code>& ' > < "</code>.
|
|
||||||
* @param ampersand An ampersand character.
|
|
||||||
* @return A Character or an entity String if the entity is not recognized.
|
|
||||||
* @throws JSONException If missing ';' in XML entity.
|
|
||||||
*/
|
|
||||||
public Object nextEntity(@SuppressWarnings("unused") char ampersand) throws JSONException {
|
|
||||||
StringBuilder sb = new StringBuilder();
|
|
||||||
for (;;) {
|
|
||||||
char c = next();
|
|
||||||
if (Character.isLetterOrDigit(c) || c == '#') {
|
|
||||||
sb.append(Character.toLowerCase(c));
|
|
||||||
} else if (c == ';') {
|
|
||||||
break;
|
|
||||||
} else {
|
|
||||||
throw syntaxError("Missing ';' in XML entity: &" + sb);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
String string = sb.toString();
|
|
||||||
return unescapeEntity(string);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Unescapes an XML entity encoding;
|
* Unescapes an XML entity encoding;
|
||||||
|
*
|
||||||
* @param e entity (only the actual entity value, not the preceding & or ending ;
|
* @param e entity (only the actual entity value, not the preceding & or ending ;
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
@ -171,25 +90,111 @@ public class XMLTokener extends JSONTokener {
|
|||||||
// decimal encoded unicode
|
// decimal encoded unicode
|
||||||
cp = Integer.parseInt(e.substring(1));
|
cp = Integer.parseInt(e.substring(1));
|
||||||
}
|
}
|
||||||
return new String(new int[] {cp},0,1);
|
return new String(new int[]{cp}, 0, 1);
|
||||||
}
|
}
|
||||||
Character knownEntity = entity.get(e);
|
Character knownEntity = entity.get(e);
|
||||||
if(knownEntity==null) {
|
if (knownEntity == null) {
|
||||||
// we don't know the entity so keep it encoded
|
// we don't know the entity so keep it encoded
|
||||||
return '&' + e + ';';
|
return '&' + e + ';';
|
||||||
}
|
}
|
||||||
return knownEntity.toString();
|
return knownEntity.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the text in the CDATA block.
|
||||||
|
*
|
||||||
|
* @return The string up to the <code>]]></code>.
|
||||||
|
* @throws JSONException If the <code>]]></code> is not found.
|
||||||
|
*/
|
||||||
|
public String nextCDATA() throws JSONException {
|
||||||
|
char c;
|
||||||
|
int i;
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
while (more()) {
|
||||||
|
c = next();
|
||||||
|
sb.append(c);
|
||||||
|
i = sb.length() - 3;
|
||||||
|
if (i >= 0 && sb.charAt(i) == ']' &&
|
||||||
|
sb.charAt(i + 1) == ']' && sb.charAt(i + 2) == '>') {
|
||||||
|
sb.setLength(i);
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
throw syntaxError("Unclosed CDATA");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the next XML outer token, trimming whitespace. There are two kinds
|
||||||
|
* of tokens: the '<' character which begins a markup tag, and the content
|
||||||
|
* text between markup tags.
|
||||||
|
*
|
||||||
|
* @return A string, or a '<' Character, or null if there is no more
|
||||||
|
* source text.
|
||||||
|
* @throws JSONException
|
||||||
|
*/
|
||||||
|
public Object nextContent() throws JSONException {
|
||||||
|
char c;
|
||||||
|
StringBuilder sb;
|
||||||
|
do {
|
||||||
|
c = next();
|
||||||
|
} while (Character.isWhitespace(c));
|
||||||
|
if (c == 0) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
if (c == '<') {
|
||||||
|
return XML.LT;
|
||||||
|
}
|
||||||
|
sb = new StringBuilder();
|
||||||
|
for (; ; ) {
|
||||||
|
if (c == 0) {
|
||||||
|
return sb.toString().trim();
|
||||||
|
}
|
||||||
|
if (c == '<') {
|
||||||
|
back();
|
||||||
|
return sb.toString().trim();
|
||||||
|
}
|
||||||
|
if (c == '&') {
|
||||||
|
sb.append(nextEntity(c));
|
||||||
|
} else {
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
|
c = next();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Return the next entity. These entities are translated to Characters:
|
||||||
|
* <code>& ' > < "</code>.
|
||||||
|
*
|
||||||
|
* @param ampersand An ampersand character.
|
||||||
|
* @return A Character or an entity String if the entity is not recognized.
|
||||||
|
* @throws JSONException If missing ';' in XML entity.
|
||||||
|
*/
|
||||||
|
public Object nextEntity(@SuppressWarnings("unused") char ampersand) throws JSONException {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
for (; ; ) {
|
||||||
|
char c = next();
|
||||||
|
if (Character.isLetterOrDigit(c) || c == '#') {
|
||||||
|
sb.append(Character.toLowerCase(c));
|
||||||
|
} else if (c == ';') {
|
||||||
|
break;
|
||||||
|
} else {
|
||||||
|
throw syntaxError("Missing ';' in XML entity: &" + sb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
String string = sb.toString();
|
||||||
|
return unescapeEntity(string);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the next XML meta token. This is used for skipping over <!...>
|
* Returns the next XML meta token. This is used for skipping over <!...>
|
||||||
* and <?...?> structures.
|
* and <?...?> structures.
|
||||||
|
*
|
||||||
* @return Syntax characters (<code>< > / = ! ?</code>) are returned as
|
* @return Syntax characters (<code>< > / = ! ?</code>) are returned as
|
||||||
* Character, and strings and names are returned as Boolean. We don't care
|
* Character, and strings and names are returned as Boolean. We don't care
|
||||||
* what the values actually are.
|
* what the values actually are.
|
||||||
* @throws JSONException If a string is not properly closed or if the XML
|
* @throws JSONException If a string is not properly closed or if the XML
|
||||||
* is badly structured.
|
* is badly structured.
|
||||||
*/
|
*/
|
||||||
public Object nextMeta() throws JSONException {
|
public Object nextMeta() throws JSONException {
|
||||||
char c;
|
char c;
|
||||||
@ -198,52 +203,52 @@ public class XMLTokener extends JSONTokener {
|
|||||||
c = next();
|
c = next();
|
||||||
} while (Character.isWhitespace(c));
|
} while (Character.isWhitespace(c));
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0:
|
case 0:
|
||||||
throw syntaxError("Misshaped meta tag");
|
throw syntaxError("Misshaped meta tag");
|
||||||
case '<':
|
case '<':
|
||||||
return XML.LT;
|
return XML.LT;
|
||||||
case '>':
|
case '>':
|
||||||
return XML.GT;
|
return XML.GT;
|
||||||
case '/':
|
case '/':
|
||||||
return XML.SLASH;
|
return XML.SLASH;
|
||||||
case '=':
|
case '=':
|
||||||
return XML.EQ;
|
return XML.EQ;
|
||||||
case '!':
|
case '!':
|
||||||
return XML.BANG;
|
return XML.BANG;
|
||||||
case '?':
|
case '?':
|
||||||
return XML.QUEST;
|
return XML.QUEST;
|
||||||
case '"':
|
case '"':
|
||||||
case '\'':
|
case '\'':
|
||||||
q = c;
|
q = c;
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
c = next();
|
c = next();
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
throw syntaxError("Unterminated string");
|
throw syntaxError("Unterminated string");
|
||||||
|
}
|
||||||
|
if (c == q) {
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (c == q) {
|
default:
|
||||||
return Boolean.TRUE;
|
for (; ; ) {
|
||||||
|
c = next();
|
||||||
|
if (Character.isWhitespace(c)) {
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
|
switch (c) {
|
||||||
|
case 0:
|
||||||
|
case '<':
|
||||||
|
case '>':
|
||||||
|
case '/':
|
||||||
|
case '=':
|
||||||
|
case '!':
|
||||||
|
case '?':
|
||||||
|
case '"':
|
||||||
|
case '\'':
|
||||||
|
back();
|
||||||
|
return Boolean.TRUE;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
default:
|
|
||||||
for (;;) {
|
|
||||||
c = next();
|
|
||||||
if (Character.isWhitespace(c)) {
|
|
||||||
return Boolean.TRUE;
|
|
||||||
}
|
|
||||||
switch (c) {
|
|
||||||
case 0:
|
|
||||||
case '<':
|
|
||||||
case '>':
|
|
||||||
case '/':
|
|
||||||
case '=':
|
|
||||||
case '!':
|
|
||||||
case '?':
|
|
||||||
case '"':
|
|
||||||
case '\'':
|
|
||||||
back();
|
|
||||||
return Boolean.TRUE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -253,6 +258,7 @@ public class XMLTokener extends JSONTokener {
|
|||||||
* brackets. It may be one of these characters: <code>/ > = ! ?</code> or it
|
* brackets. It may be one of these characters: <code>/ > = ! ?</code> or it
|
||||||
* may be a string wrapped in single quotes or double quotes, or it may be a
|
* may be a string wrapped in single quotes or double quotes, or it may be a
|
||||||
* name.
|
* name.
|
||||||
|
*
|
||||||
* @return a String or a Character.
|
* @return a String or a Character.
|
||||||
* @throws JSONException If the XML is not well formed.
|
* @throws JSONException If the XML is not well formed.
|
||||||
*/
|
*/
|
||||||
@ -264,70 +270,70 @@ public class XMLTokener extends JSONTokener {
|
|||||||
c = next();
|
c = next();
|
||||||
} while (Character.isWhitespace(c));
|
} while (Character.isWhitespace(c));
|
||||||
switch (c) {
|
switch (c) {
|
||||||
case 0:
|
case 0:
|
||||||
throw syntaxError("Misshaped element");
|
throw syntaxError("Misshaped element");
|
||||||
case '<':
|
case '<':
|
||||||
throw syntaxError("Misplaced '<'");
|
throw syntaxError("Misplaced '<'");
|
||||||
case '>':
|
case '>':
|
||||||
return XML.GT;
|
return XML.GT;
|
||||||
case '/':
|
case '/':
|
||||||
return XML.SLASH;
|
return XML.SLASH;
|
||||||
case '=':
|
case '=':
|
||||||
return XML.EQ;
|
return XML.EQ;
|
||||||
case '!':
|
case '!':
|
||||||
return XML.BANG;
|
return XML.BANG;
|
||||||
case '?':
|
case '?':
|
||||||
return XML.QUEST;
|
return XML.QUEST;
|
||||||
|
|
||||||
// Quoted string
|
// Quoted string
|
||||||
|
|
||||||
case '"':
|
case '"':
|
||||||
case '\'':
|
case '\'':
|
||||||
q = c;
|
q = c;
|
||||||
sb = new StringBuilder();
|
sb = new StringBuilder();
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
c = next();
|
c = next();
|
||||||
if (c == 0) {
|
if (c == 0) {
|
||||||
throw syntaxError("Unterminated string");
|
throw syntaxError("Unterminated string");
|
||||||
|
}
|
||||||
|
if (c == q) {
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
if (c == '&') {
|
||||||
|
sb.append(nextEntity(c));
|
||||||
|
} else {
|
||||||
|
sb.append(c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (c == q) {
|
default:
|
||||||
return sb.toString();
|
|
||||||
}
|
|
||||||
if (c == '&') {
|
|
||||||
sb.append(nextEntity(c));
|
|
||||||
} else {
|
|
||||||
sb.append(c);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
|
|
||||||
// Name
|
// Name
|
||||||
|
|
||||||
sb = new StringBuilder();
|
sb = new StringBuilder();
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
sb.append(c);
|
sb.append(c);
|
||||||
c = next();
|
c = next();
|
||||||
if (Character.isWhitespace(c)) {
|
if (Character.isWhitespace(c)) {
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
|
}
|
||||||
|
switch (c) {
|
||||||
|
case 0:
|
||||||
|
return sb.toString();
|
||||||
|
case '>':
|
||||||
|
case '/':
|
||||||
|
case '=':
|
||||||
|
case '!':
|
||||||
|
case '?':
|
||||||
|
case '[':
|
||||||
|
case ']':
|
||||||
|
back();
|
||||||
|
return sb.toString();
|
||||||
|
case '<':
|
||||||
|
case '"':
|
||||||
|
case '\'':
|
||||||
|
throw syntaxError("Bad character in a name");
|
||||||
|
}
|
||||||
}
|
}
|
||||||
switch (c) {
|
|
||||||
case 0:
|
|
||||||
return sb.toString();
|
|
||||||
case '>':
|
|
||||||
case '/':
|
|
||||||
case '=':
|
|
||||||
case '!':
|
|
||||||
case '?':
|
|
||||||
case '[':
|
|
||||||
case ']':
|
|
||||||
back();
|
|
||||||
return sb.toString();
|
|
||||||
case '<':
|
|
||||||
case '"':
|
|
||||||
case '\'':
|
|
||||||
throw syntaxError("Bad character in a name");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -335,6 +341,7 @@ public class XMLTokener extends JSONTokener {
|
|||||||
/**
|
/**
|
||||||
* Skip characters until past the requested string.
|
* Skip characters until past the requested string.
|
||||||
* If it is not found, we are left at the end of the source with a result of false.
|
* If it is not found, we are left at the end of the source with a result of false.
|
||||||
|
*
|
||||||
* @param to A string to skip past.
|
* @param to A string to skip past.
|
||||||
*/
|
*/
|
||||||
// The Android implementation of JSONTokener has a public method of public void skipPast(String to)
|
// The Android implementation of JSONTokener has a public method of public void skipPast(String to)
|
||||||
@ -364,7 +371,7 @@ public class XMLTokener extends JSONTokener {
|
|||||||
|
|
||||||
/* We will loop, possibly for all of the remaining characters. */
|
/* We will loop, possibly for all of the remaining characters. */
|
||||||
|
|
||||||
for (;;) {
|
for (; ; ) {
|
||||||
j = offset;
|
j = offset;
|
||||||
b = true;
|
b = true;
|
||||||
|
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package ch.m4th1eu.richpresence;
|
package ch.m4th1eu.richpresence;
|
||||||
|
|
||||||
import ch.m4th1eu.json.JSONArray;
|
|
||||||
import ch.m4th1eu.json.JSONObject;
|
import ch.m4th1eu.json.JSONObject;
|
||||||
import ch.m4th1eu.richpresence.events.AdvancedStatusEvent;
|
import ch.m4th1eu.richpresence.events.AdvancedStatusEvent;
|
||||||
import ch.m4th1eu.richpresence.events.EventPresence;
|
import ch.m4th1eu.richpresence.events.EventPresence;
|
||||||
import ch.m4th1eu.richpresence.proxy.CommonProxy;
|
import ch.m4th1eu.richpresence.proxy.CommonProxy;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraftforge.common.MinecraftForge;
|
import net.minecraftforge.common.MinecraftForge;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
import net.minecraftforge.fml.common.Mod.EventHandler;
|
import net.minecraftforge.fml.common.Mod.EventHandler;
|
||||||
@ -29,8 +29,7 @@ public class Main {
|
|||||||
/**
|
/**
|
||||||
* Variables pour la config
|
* Variables pour la config
|
||||||
*/
|
*/
|
||||||
public static String applicationId, largeimage, largeimagetext, serveurIP;
|
public static String applicationId, largeimage, largeimagetext;
|
||||||
public static boolean advancedstatus;
|
|
||||||
|
|
||||||
|
|
||||||
public static Logger logger;
|
public static Logger logger;
|
||||||
@ -38,18 +37,17 @@ public class Main {
|
|||||||
|
|
||||||
|
|
||||||
public Main() {
|
public Main() {
|
||||||
if (advancedstatus) {
|
MinecraftForge.EVENT_BUS.register(new AdvancedStatusEvent());
|
||||||
MinecraftForge.EVENT_BUS.register(new AdvancedStatusEvent());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void preInit(FMLPreInitializationEvent event) {
|
public void preInit(FMLPreInitializationEvent event) {
|
||||||
logger = event.getModLog();
|
logger = event.getModLog();
|
||||||
proxy.preInit(event.getSuggestedConfigurationFile());
|
proxy.preInit(event.getSuggestedConfigurationFile());
|
||||||
|
|
||||||
//Configuration
|
|
||||||
|
|
||||||
|
//Configuration
|
||||||
event.getModConfigurationDirectory().mkdir();
|
event.getModConfigurationDirectory().mkdir();
|
||||||
File config_file = new File(event.getModConfigurationDirectory(), "\\" + Main.MODID + ".json");
|
File config_file = new File(event.getModConfigurationDirectory(), "\\" + Main.MODID + ".json");
|
||||||
if (!config_file.exists()) {
|
if (!config_file.exists()) {
|
||||||
@ -66,29 +64,40 @@ public class Main {
|
|||||||
try {
|
try {
|
||||||
PrintWriter writer = new PrintWriter(config_file, "UTF-8");
|
PrintWriter writer = new PrintWriter(config_file, "UTF-8");
|
||||||
writer.println("{\n" +
|
writer.println("{\n" +
|
||||||
" \"application-settings\": [\n" +
|
" \"_comment\": \"Variables disponibles :\",\n" +
|
||||||
" {\n" +
|
" \"_comment2\": \"%player-name% - Nom du joueur.\",\n" +
|
||||||
" \"applicationID\": \"601875975533232158\",\n" +
|
" \"_comment3\": \"%server-connected-player% - Nombre de joueur connecté au serveur.\",\n" +
|
||||||
" \"large-image-name\": \"discord_logo\",\n" +
|
" \"_comment4\": \"%server-max-slot% - Nombre de slots du serveur\",\n" +
|
||||||
" \"large-image-text\": \"En train de tester ce mod !\"\n" +
|
" \"server-ip\": \"mc.hypixel.net\",\n" +
|
||||||
|
" \"server-port\": \"25565\",\n" +
|
||||||
|
" \"application-settings\": {\n" +
|
||||||
|
" \"applicationID\": \"601875975533232158\",\n" +
|
||||||
|
" \"large-image-name\": \"discord_logo\",\n" +
|
||||||
|
" \"large-image-text\": \"En train de tester ce mod !\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"advanced-status-custom\": {\n" +
|
||||||
|
" \"onJoinServer\": {\n" +
|
||||||
|
" \"enable\": true,\n" +
|
||||||
|
" \"message\": \"En jeu.\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"onQuitServer\": {\n" +
|
||||||
|
" \"enable\": true,\n" +
|
||||||
|
" \"message\": \"Dans le menu principal.\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"inPauseMenu\": {\n" +
|
||||||
|
" \"enable\": true,\n" +
|
||||||
|
" \"message\": \"Dans le menu pause.\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"inMainMenu\": {\n" +
|
||||||
|
" \"enable\": true,\n" +
|
||||||
|
" \"message\": \"Dans le menu principal.\"\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"inInventory\": {\n" +
|
||||||
|
" \"enable\": false,\n" +
|
||||||
|
" \"message\": \"Dans l'inventaire.\"\n" +
|
||||||
" }\n" +
|
" }\n" +
|
||||||
" ],\n" +
|
" }\n" +
|
||||||
" \"advanced-status\": true,\n" +
|
"}");
|
||||||
" \"advanced-status-custom\": [\n" +
|
|
||||||
" {\n" +
|
|
||||||
" \"onJoinServer\": {\n" +
|
|
||||||
" \"message\": \"En jeu.\"\n" +
|
|
||||||
" },\n" +
|
|
||||||
" \"onQuitServer\": {\n" +
|
|
||||||
" \"message\": \"Dans le menu principal.\"\n" +
|
|
||||||
" },\n" +
|
|
||||||
" \"inPauseMenu\": {\n" +
|
|
||||||
" \"message\": \"Dans le menu pause\"\n" +
|
|
||||||
" }\n" +
|
|
||||||
" }\n" +
|
|
||||||
" ]\n" +
|
|
||||||
"}\n" +
|
|
||||||
"\n");
|
|
||||||
writer.close();
|
writer.close();
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -102,23 +111,24 @@ public class Main {
|
|||||||
|
|
||||||
applicationId = config.getJSONObject("application-settings").getString("applicationID");
|
applicationId = config.getJSONObject("application-settings").getString("applicationID");
|
||||||
largeimage = config.getJSONObject("application-settings").getString("large-image-name");
|
largeimage = config.getJSONObject("application-settings").getString("large-image-name");
|
||||||
largeimagetext = config.getJSONObject("application-settings").getString("large-image-text");
|
largeimagetext = Utils.replaceArgsString(config.getJSONObject("application-settings").getString("large-image-text"));
|
||||||
|
|
||||||
|
|
||||||
advancedstatus = config.getBoolean("advanced-status");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@EventHandler
|
@EventHandler
|
||||||
public void init(FMLInitializationEvent event) {
|
public void init(FMLInitializationEvent event) {
|
||||||
|
JSONObject config = new JSONObject(Utils.readFileToString(new File(Minecraft.getMinecraft().mcDataDir, "\\config\\" + Main.MODID + ".json")));
|
||||||
|
|
||||||
proxy.init();
|
proxy.init();
|
||||||
rpcClient = new EventPresence();
|
rpcClient = new EventPresence();
|
||||||
|
|
||||||
proxy.rpcinit();
|
|
||||||
if (advancedstatus) {
|
|
||||||
proxy.rpcupdate("Dans le menu.", null);
|
|
||||||
} else {
|
|
||||||
proxy.rpcupdate("", null);
|
|
||||||
|
|
||||||
|
proxy.rpcinit();
|
||||||
|
if (config.getJSONObject("advanced-status-custom").getJSONObject("inMainMenu").getBoolean("enable")) {
|
||||||
|
proxy.rpcupdate(config.getJSONObject("advanced-status-custom").getJSONObject("inMainMenu").getString("message"), null, false);
|
||||||
|
} else {
|
||||||
|
proxy.rpcupdate("", null, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -1,8 +1,13 @@
|
|||||||
package ch.m4th1eu.richpresence;
|
package ch.m4th1eu.richpresence;
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import ch.m4th1eu.json.JSONObject;
|
||||||
import java.io.File;
|
import net.minecraft.client.Minecraft;
|
||||||
import java.io.FileReader;
|
import net.minecraft.network.INetHandler;
|
||||||
|
|
||||||
|
import java.io.*;
|
||||||
|
import java.net.URL;
|
||||||
|
import java.net.URLConnection;
|
||||||
|
import java.nio.charset.Charset;
|
||||||
|
|
||||||
public class Utils {
|
public class Utils {
|
||||||
|
|
||||||
@ -27,4 +32,91 @@ public class Utils {
|
|||||||
return "ERROR";
|
return "ERROR";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Nathanael
|
||||||
|
*/
|
||||||
|
public static String readTextFromURL(String url) throws IOException {
|
||||||
|
URL urlObject;
|
||||||
|
URLConnection uc;
|
||||||
|
StringBuilder parsedContentFromUrl = new StringBuilder();
|
||||||
|
urlObject = new URL(url);
|
||||||
|
uc = urlObject.openConnection();
|
||||||
|
uc.connect();
|
||||||
|
uc = urlObject.openConnection();
|
||||||
|
uc.addRequestProperty("User-Agent",
|
||||||
|
"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.0)");
|
||||||
|
uc.getInputStream();
|
||||||
|
InputStream is = uc.getInputStream();
|
||||||
|
BufferedReader in = new BufferedReader(new InputStreamReader(is, Charset.forName("UTF-8")));
|
||||||
|
|
||||||
|
int ch;
|
||||||
|
while ((ch = in.read()) != -1) {
|
||||||
|
parsedContentFromUrl.append((char) ch);
|
||||||
|
}
|
||||||
|
return parsedContentFromUrl.toString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author M4TH1EU_
|
||||||
|
*/
|
||||||
|
public static String replaceArgsString(String variable) {
|
||||||
|
File config_file = new File(Minecraft.getMinecraft().mcDataDir, "\\config\\" + Main.MODID + ".json");
|
||||||
|
JSONObject config = new JSONObject(Utils.readFileToString(config_file));
|
||||||
|
|
||||||
|
String serverip = config.getString("server-ip");
|
||||||
|
String serverport = config.getString("server-port");
|
||||||
|
|
||||||
|
try {
|
||||||
|
variable = variable.replaceAll("%player-name%", Minecraft.getMinecraft().getSession().getUsername());
|
||||||
|
variable = variable.replaceAll("%server-connected-player%", readTextFromURL("https://minecraft-api.com/api/ping/playeronline.php?ip=" + serverip + "&port=" + serverport));
|
||||||
|
variable = variable.replaceAll("%server-max-slot%", readTextFromURL("https://minecraft-api.com/api/ping/maxplayer.php?ip=" + serverip + "&port=" + serverport));
|
||||||
|
} catch (Exception e) {
|
||||||
|
}
|
||||||
|
|
||||||
|
return variable;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void updateStatus(int id) {
|
||||||
|
Thread t = new Thread(() -> {
|
||||||
|
JSONObject config = new JSONObject(Utils.readFileToString(new File(Minecraft.getMinecraft().mcDataDir, "\\config\\" + Main.MODID + ".json")));
|
||||||
|
JSONObject onQuitServer = config.getJSONObject("advanced-status-custom").getJSONObject("onQuitServer");
|
||||||
|
JSONObject onJoinServer = config.getJSONObject("advanced-status-custom").getJSONObject("onJoinServer");
|
||||||
|
JSONObject inPauseMenu = config.getJSONObject("advanced-status-custom").getJSONObject("inPauseMenu");
|
||||||
|
JSONObject inMainMenu = config.getJSONObject("advanced-status-custom").getJSONObject("inMainMenu");
|
||||||
|
JSONObject inInventory = config.getJSONObject("advanced-status-custom").getJSONObject("inInventory");
|
||||||
|
|
||||||
|
switch (id) {
|
||||||
|
case 0:
|
||||||
|
Main.proxy.rpcupdate(Utils.replaceArgsString(config.getJSONObject("advanced-status-custom").getJSONObject("inMainMenu").getString("message")), null, false);
|
||||||
|
break;
|
||||||
|
case 1:
|
||||||
|
Main.proxy.rpcupdate(Utils.replaceArgsString(onJoinServer.getString("message")), null, false);
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
Main.proxy.rpcupdate(Utils.replaceArgsString(onQuitServer.getString("message")), null, false);
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
Main.proxy.rpcupdate(Utils.replaceArgsString(inPauseMenu.getString("message")), null, false);
|
||||||
|
break;
|
||||||
|
case 4:
|
||||||
|
Main.proxy.rpcupdate(Utils.replaceArgsString(inMainMenu.getString("message")), null, false);
|
||||||
|
break;
|
||||||
|
case 5:
|
||||||
|
Main.proxy.rpcupdate(Utils.replaceArgsString(inInventory.getString("message")), null, false);
|
||||||
|
break;
|
||||||
|
case 6:
|
||||||
|
Main.proxy.rpcupdate(Utils.replaceArgsString(config.getJSONObject("advanced-status-custom").getJSONObject("onJoinServer").getString("message")), null, false);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
t.start();
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -5,7 +5,9 @@ import ch.m4th1eu.richpresence.Main;
|
|||||||
import ch.m4th1eu.richpresence.Utils;
|
import ch.m4th1eu.richpresence.Utils;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.gui.GuiIngameMenu;
|
import net.minecraft.client.gui.GuiIngameMenu;
|
||||||
import net.minecraft.server.MinecraftServer;
|
import net.minecraft.client.gui.GuiMainMenu;
|
||||||
|
import net.minecraft.client.gui.inventory.GuiInventory;
|
||||||
|
import net.minecraft.entity.player.EntityPlayerMP;
|
||||||
import net.minecraftforge.client.event.GuiOpenEvent;
|
import net.minecraftforge.client.event.GuiOpenEvent;
|
||||||
import net.minecraftforge.fml.client.FMLClientHandler;
|
import net.minecraftforge.fml.client.FMLClientHandler;
|
||||||
import net.minecraftforge.fml.common.Mod;
|
import net.minecraftforge.fml.common.Mod;
|
||||||
@ -24,28 +26,52 @@ public class AdvancedStatusEvent {
|
|||||||
JSONObject config = new JSONObject(Utils.readFileToString(config_file));
|
JSONObject config = new JSONObject(Utils.readFileToString(config_file));
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void onServerJoin(FMLNetworkEvent.ClientConnectedToServerEvent event) {
|
public void onJoinServer(FMLNetworkEvent.ClientConnectedToServerEvent event) {
|
||||||
if (Main.advancedstatus) {
|
JSONObject onJoinServer = config.getJSONObject("advanced-status-custom").getJSONObject("onJoinServer");
|
||||||
Main.proxy.rpcupdate(config.getJSONArray("advanced-status-custom").getJSONObject(0).getString("message"), null);
|
|
||||||
|
if (onJoinServer.getBoolean("enable")) {
|
||||||
|
Utils.updateStatus(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void onQuitServer(FMLNetworkEvent.ClientDisconnectionFromServerEvent event) {
|
public void onQuitServer(FMLNetworkEvent.ClientDisconnectionFromServerEvent event) {
|
||||||
if (Main.advancedstatus) {
|
JSONObject onQuitServer = config.getJSONObject("advanced-status-custom").getJSONObject("onQuitServer");
|
||||||
|
|
||||||
Main.proxy.rpcupdate(config.getJSONArray("advanced-status-custom").getJSONObject(1).getString("message"), null);
|
if (onQuitServer.getBoolean("enable")) {
|
||||||
|
Utils.updateStatus(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SubscribeEvent
|
@SubscribeEvent
|
||||||
public void onGuiOpen(GuiOpenEvent event) {
|
public void onGuiOpen(GuiOpenEvent event) {
|
||||||
if (Main.advancedstatus) {
|
|
||||||
|
JSONObject inPauseMenu = config.getJSONObject("advanced-status-custom").getJSONObject("inPauseMenu");
|
||||||
|
JSONObject inMainMenu = config.getJSONObject("advanced-status-custom").getJSONObject("inMainMenu");
|
||||||
|
JSONObject inInventory = config.getJSONObject("advanced-status-custom").getJSONObject("inInventory");
|
||||||
|
|
||||||
|
if (inPauseMenu.getBoolean("enable")) {
|
||||||
if (event.getGui() instanceof GuiIngameMenu) {
|
if (event.getGui() instanceof GuiIngameMenu) {
|
||||||
Main.proxy.rpcupdate(config.getJSONArray("advanced-status-custom").getJSONObject(2).getString("message"), null);
|
Utils.updateStatus(3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inMainMenu.getBoolean("enable")) {
|
||||||
|
if (event.getGui() instanceof GuiMainMenu) {
|
||||||
|
Utils.updateStatus(4);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (inInventory.getBoolean("enable")) {
|
||||||
|
if (event.getGui() instanceof GuiInventory) {
|
||||||
|
Utils.updateStatus(5);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (event.getGui() == null) {
|
||||||
|
if (config.getJSONObject("advanced-status-custom").getJSONObject("onJoinServer").getBoolean("enable")) {
|
||||||
|
Utils.updateStatus(6);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -12,17 +12,13 @@ public class EventPresence {
|
|||||||
|
|
||||||
private static Thread callbackRunner;
|
private static Thread callbackRunner;
|
||||||
|
|
||||||
public synchronized static final void init() {
|
public synchronized static void init() {
|
||||||
DiscordEventHandlers handlers = new DiscordEventHandlers();
|
DiscordEventHandlers handlers = new DiscordEventHandlers();
|
||||||
DiscordRPC.discordInitialize(Main.applicationId, handlers, true, null);
|
DiscordRPC.discordInitialize(Main.applicationId, handlers, true, null);
|
||||||
if (EventPresence.callbackRunner == null) {
|
if (EventPresence.callbackRunner == null) {
|
||||||
(EventPresence.callbackRunner = new Thread(() -> {
|
(EventPresence.callbackRunner = new Thread(() -> {
|
||||||
while (!Thread.currentThread().isInterrupted()) {
|
while (!Thread.currentThread().isInterrupted()) {
|
||||||
DiscordRPC.discordRunCallbacks();
|
DiscordRPC.discordRunCallbacks();
|
||||||
try {
|
|
||||||
Thread.sleep(100L);
|
|
||||||
} catch (InterruptedException ex) {
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}, "RPC-Callback-Handler")).start();
|
}, "RPC-Callback-Handler")).start();
|
||||||
@ -30,14 +26,16 @@ public class EventPresence {
|
|||||||
Main.logger.info("EventPresence has been started.");
|
Main.logger.info("EventPresence has been started.");
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final void updatePresence(String details, String action) {
|
public synchronized static void updatePresence(String details, String action, Boolean changeTime) {
|
||||||
DiscordRichPresence presence = new DiscordRichPresence();
|
DiscordRichPresence presence = new DiscordRichPresence();
|
||||||
presence.largeImageKey = Main.largeimage;
|
presence.largeImageKey = Main.largeimage;
|
||||||
presence.largeImageText = Main.largeimagetext;
|
presence.largeImageText = Main.largeimagetext;
|
||||||
if (details != null) {
|
if (details != null) {
|
||||||
presence.details = details;
|
presence.details = details;
|
||||||
|
|
||||||
presence.startTimestamp = System.currentTimeMillis() / 1000L;
|
if (changeTime) {
|
||||||
|
presence.startTimestamp = System.currentTimeMillis() / 1000L;
|
||||||
|
}
|
||||||
} else if (action != null) {
|
} else if (action != null) {
|
||||||
presence.state = action;
|
presence.state = action;
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,7 @@ public class ClientProxy extends CommonProxy {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void rpcupdate(String details, String action) {
|
public void rpcupdate(String details, String action, Boolean changeTime) {
|
||||||
EventPresence.updatePresence(details, action);
|
EventPresence.updatePresence(details, action, changeTime);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,7 @@ public class CommonProxy {
|
|||||||
public void rpcinit() {
|
public void rpcinit() {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void rpcupdate(String details, String action) {
|
public void rpcupdate(String details, String action, Boolean changeTime) {
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user