diff --git a/JSONML.java b/JSONML.java
index 9acf21d..7e99aab 100644
--- a/JSONML.java
+++ b/JSONML.java
@@ -36,20 +36,21 @@ import java.util.Iterator;
* @version 2016-01-30
*/
public class JSONML {
-
/**
* Parse XML values and store them in a JSONArray.
* @param x The XMLTokener containing the source string.
* @param arrayForm true if array form, false if object form.
* @param ja The JSONArray that is containing the current tag or null
* if we are at the outermost level.
+ * @param keepStrings Don't type-convert text nodes and attibute values
* @return A JSONArray if the value is the outermost tag, otherwise null.
* @throws JSONException
*/
private static Object parse(
XMLTokener x,
boolean arrayForm,
- JSONArray ja
+ JSONArray ja,
+ boolean keepStrings
) throws JSONException {
String attribute;
char c;
@@ -174,7 +175,7 @@ public class JSONML {
if (!(token instanceof String)) {
throw x.syntaxError("Missing value");
}
- newjo.accumulate(attribute, JSONObject.stringToValue((String)token));
+ newjo.accumulate(attribute, keepStrings ? token :JSONObject.stringToValue((String)token));
token = null;
} else {
newjo.accumulate(attribute, "");
@@ -193,9 +194,8 @@ public class JSONML {
if (ja == null) {
if (arrayForm) {
return newja;
- } else {
- return newjo;
}
+ return newjo;
}
// Content, between <...> and
@@ -204,7 +204,7 @@ public class JSONML {
if (token != XML.GT) {
throw x.syntaxError("Misshaped tag");
}
- closeTag = (String)parse(x, arrayForm, newja);
+ closeTag = (String)parse(x, arrayForm, newja, keepStrings);
if (closeTag != null) {
if (!closeTag.equals(tagName)) {
throw x.syntaxError("Mismatched '" + tagName +
@@ -217,9 +217,8 @@ public class JSONML {
if (ja == null) {
if (arrayForm) {
return newja;
- } else {
- return newjo;
}
+ return newjo;
}
}
}
@@ -227,7 +226,7 @@ public class JSONML {
} else {
if (ja != null) {
ja.put(token instanceof String
- ? JSONObject.stringToValue((String)token)
+ ? keepStrings ? token :JSONObject.stringToValue((String)token)
: token);
}
}
@@ -245,10 +244,54 @@ public class JSONML {
* Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
* @param string The source string.
* @return A JSONArray containing the structured data from the XML string.
- * @throws JSONException
+ * @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(String string) throws JSONException {
- return toJSONArray(new XMLTokener(string));
+ return (JSONArray)parse(new XMLTokener(string), true, null, false);
+ }
+
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML string into a
+ * JSONArray using the JsonML transform. Each XML tag is represented as
+ * a JSONArray in which the first element is the tag name. If the tag has
+ * attributes, then the second element will be JSONObject containing the
+ * name/value pairs. If the tag contains children, then strings and
+ * JSONArrays will represent the child tags.
+ * As opposed to toJSONArray this method does not attempt to convert
+ * any text node or attribute value to any type
+ * but just leaves it as a string.
+ * Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
+ * @param string The source string.
+ * @param keepStrings If true, then values will not be coerced into boolean
+ * or numeric values and will instead be left as strings
+ * @return A JSONArray containing the structured data from the XML string.
+ * @throws JSONException Thrown on error converting to a JSONArray
+ */
+ public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException {
+ return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings);
+ }
+
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML string into a
+ * JSONArray using the JsonML transform. Each XML tag is represented as
+ * a JSONArray in which the first element is the tag name. If the tag has
+ * attributes, then the second element will be JSONObject containing the
+ * name/value pairs. If the tag contains children, then strings and
+ * JSONArrays will represent the child content and tags.
+ * As opposed to toJSONArray this method does not attempt to convert
+ * any text node or attribute value to any type
+ * but just leaves it as a string.
+ * Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
+ * @param x An XMLTokener.
+ * @param keepStrings If true, then values will not be coerced into boolean
+ * or numeric values and will instead be left as strings
+ * @return A JSONArray containing the structured data from the XML string.
+ * @throws JSONException Thrown on error converting to a JSONArray
+ */
+ public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException {
+ return (JSONArray)parse(x, true, null, keepStrings);
}
@@ -262,28 +305,10 @@ public class JSONML {
* Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
* @param x An XMLTokener.
* @return A JSONArray containing the structured data from the XML string.
- * @throws JSONException
+ * @throws JSONException Thrown on error converting to a JSONArray
*/
public static JSONArray toJSONArray(XMLTokener x) throws JSONException {
- return (JSONArray)parse(x, true, null);
- }
-
-
- /**
- * Convert a well-formed (but not necessarily valid) XML string into a
- * JSONObject using the JsonML transform. Each XML tag is represented as
- * a JSONObject with a "tagName" property. If the tag has attributes, then
- * the attributes will be in the JSONObject as properties. If the tag
- * contains children, the object will have a "childNodes" property which
- * will be an array of strings and JsonML JSONObjects.
-
- * Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
- * @param x An XMLTokener of the XML source text.
- * @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException
- */
- public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
- return (JSONObject)parse(x, false, null);
+ return (JSONArray)parse(x, true, null, false);
}
@@ -298,10 +323,68 @@ public class JSONML {
* Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
* @param string The XML source text.
* @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException
+ * @throws JSONException Thrown on error converting to a JSONObject
*/
public static JSONObject toJSONObject(String string) throws JSONException {
- return toJSONObject(new XMLTokener(string));
+ return (JSONObject)parse(new XMLTokener(string), false, null, false);
+ }
+
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML string into a
+ * JSONObject using the JsonML transform. Each XML tag is represented as
+ * a JSONObject with a "tagName" property. If the tag has attributes, then
+ * the attributes will be in the JSONObject as properties. If the tag
+ * contains children, the object will have a "childNodes" property which
+ * will be an array of strings and JsonML JSONObjects.
+
+ * Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
+ * @param string The XML source text.
+ * @param keepStrings If true, then values will not be coerced into boolean
+ * or numeric values and will instead be left as strings
+ * @return A JSONObject containing the structured data from the XML string.
+ * @throws JSONException Thrown on error converting to a JSONObject
+ */
+ public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
+ return (JSONObject)parse(new XMLTokener(string), false, null, keepStrings);
+ }
+
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML string into a
+ * JSONObject using the JsonML transform. Each XML tag is represented as
+ * a JSONObject with a "tagName" property. If the tag has attributes, then
+ * the attributes will be in the JSONObject as properties. If the tag
+ * contains children, the object will have a "childNodes" property which
+ * will be an array of strings and JsonML JSONObjects.
+
+ * Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
+ * @param x An XMLTokener of the XML source text.
+ * @return A JSONObject containing the structured data from the XML string.
+ * @throws JSONException Thrown on error converting to a JSONObject
+ */
+ public static JSONObject toJSONObject(XMLTokener x) throws JSONException {
+ return (JSONObject)parse(x, false, null, false);
+ }
+
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML string into a
+ * JSONObject using the JsonML transform. Each XML tag is represented as
+ * a JSONObject with a "tagName" property. If the tag has attributes, then
+ * the attributes will be in the JSONObject as properties. If the tag
+ * contains children, the object will have a "childNodes" property which
+ * will be an array of strings and JsonML JSONObjects.
+
+ * Comments, prologs, DTDs, and <[ [ ]]>
are ignored.
+ * @param x An XMLTokener of the XML source text.
+ * @param keepStrings If true, then values will not be coerced into boolean
+ * or numeric values and will instead be left as strings
+ * @return A JSONObject containing the structured data from the XML string.
+ * @throws JSONException Thrown on error converting to a JSONObject
+ */
+ public static JSONObject toJSONObject(XMLTokener x, boolean keepStrings) throws JSONException {
+ return (JSONObject)parse(x, false, null, keepStrings);
}
@@ -309,7 +392,7 @@ public class JSONML {
* Reverse the JSONML transformation, making an XML text from a JSONArray.
* @param ja A JSONArray.
* @return An XML string.
- * @throws JSONException
+ * @throws JSONException Thrown on error converting to a string
*/
public static String toString(JSONArray ja) throws JSONException {
int i;
@@ -393,7 +476,7 @@ public class JSONML {
* The other properties are attributes with string values.
* @param jo A JSONObject.
* @return An XML string.
- * @throws JSONException
+ * @throws JSONException Thrown on error converting to a string
*/
public static String toString(JSONObject jo) throws JSONException {
StringBuilder sb = new StringBuilder();
diff --git a/JSONTokener.java b/JSONTokener.java
index 7702b19..d0b197d 100644
--- a/JSONTokener.java
+++ b/JSONTokener.java
@@ -71,7 +71,7 @@ public class JSONTokener {
* Construct a JSONTokener from an InputStream.
* @param inputStream The source.
*/
- public JSONTokener(InputStream inputStream) throws JSONException {
+ public JSONTokener(InputStream inputStream) {
this(new InputStreamReader(inputStream));
}
@@ -90,6 +90,8 @@ public class JSONTokener {
* 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) {
@@ -121,6 +123,9 @@ public class JSONTokener {
return -1;
}
+ /**
+ * @return true if at the end of the file and we didn't step back
+ */
public boolean end() {
return this.eof && !this.usePrevious;
}
@@ -130,6 +135,8 @@ public class JSONTokener {
* Determine if the source string still contains characters that next()
* can consume.
* @return true if not yet at the end of the source.
+ * @throws JSONException thrown if there is an error stepping forward
+ * or backward while checking for more data.
*/
public boolean more() throws JSONException {
this.next();
@@ -145,6 +152,7 @@ public class JSONTokener {
* Get the next character in the source string.
*
* @return The next character, or 0 if past the end of the source string.
+ * @throws JSONException Thrown if there is an error reading the source string.
*/
public char next() throws JSONException {
int c;
@@ -225,7 +233,7 @@ public class JSONTokener {
/**
* Get the next char in the string, skipping whitespace.
- * @throws JSONException
+ * @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 {
@@ -309,6 +317,8 @@ public class JSONTokener {
* end of line, whichever comes first.
* @param delimiter A delimiter character.
* @return A string.
+ * @throws JSONException Thrown if there is an error while searching
+ * for the delimiter
*/
public String nextTo(char delimiter) throws JSONException {
StringBuilder sb = new StringBuilder();
@@ -330,6 +340,8 @@ public class JSONTokener {
* characters or the end of line, whichever comes first.
* @param delimiters A set of delimiter characters.
* @return A string, trimmed.
+ * @throws JSONException Thrown if there is an error while searching
+ * for the delimiter
*/
public String nextTo(String delimiters) throws JSONException {
char c;
@@ -401,6 +413,8 @@ public class JSONTokener {
* @param to A character to skip to.
* @return The requested character, or zero if the requested character
* is not found.
+ * @throws JSONException Thrown if there is an error while searching
+ * for the to character
*/
public char skipTo(char to) throws JSONException {
char c;
@@ -453,6 +467,7 @@ public class JSONTokener {
*
* @return " at {index} [character {character} line {line}]"
*/
+ @Override
public String toString() {
return " at " + this.index + " [character " + this.character + " line " +
this.line + "]";
diff --git a/XML.java b/XML.java
index bbcda3b..b76969a 100644
--- a/XML.java
+++ b/XML.java
@@ -110,7 +110,7 @@ public class XML {
*
* @param string
* A string.
- * @throws JSONException
+ * @throws JSONException Thrown if the string contains whitespace or is empty.
*/
public static void noSpace(String string) throws JSONException {
int i, length = string.length();
@@ -137,7 +137,7 @@ public class XML {
* @return true if the close tag is processed.
* @throws JSONException
*/
- private static boolean parse(XMLTokener x, JSONObject context, String name)
+ private static boolean parse(XMLTokener x, JSONObject context, String name, boolean keepStrings)
throws JSONException {
char c;
int i;
@@ -238,7 +238,7 @@ public class XML {
throw x.syntaxError("Missing value");
}
jsonobject.accumulate(string,
- JSONObject.stringToValue((String) token));
+ keepStrings ? token : JSONObject.stringToValue((String) token));
token = null;
} else {
jsonobject.accumulate(string, "");
@@ -270,12 +270,12 @@ public class XML {
string = (String) token;
if (string.length() > 0) {
jsonobject.accumulate("content",
- JSONObject.stringToValue(string));
+ keepStrings ? token : JSONObject.stringToValue(string));
}
} else if (token == LT) {
// Nested element
- if (parse(x, jsonobject, tagName)) {
+ if (parse(x, jsonobject, tagName,keepStrings)) {
if (jsonobject.length() == 0) {
context.accumulate(tagName, "");
} else if (jsonobject.length() == 1
@@ -301,9 +301,10 @@ public class XML {
* {@link JSONObject.stringToValue(String)} method. Use it instead.
*
* @deprecated Use {@link JSONObject#stringToValue(String)} instead.
- * @param string
+ * @param string String to convert
* @return JSON value of this string or the string
*/
+ @Deprecated
public static Object stringToValue(String string) {
return JSONObject.stringToValue(string);
}
@@ -322,24 +323,49 @@ public class XML {
* @param string
* The source string.
* @return A JSONObject containing the structured data from the XML string.
- * @throws JSONException
+ * @throws JSONException Thrown if there is an errors while parsing the string
*/
public static JSONObject toJSONObject(String string) throws JSONException {
+ return toJSONObject(string, false);
+ }
+
+
+ /**
+ * Convert a well-formed (but not necessarily valid) XML string into a
+ * JSONObject. Some information may be lost in this transformation because
+ * JSON is a data format and XML is a document format. XML uses elements,
+ * attributes, and content text, while JSON uses unordered collections of
+ * name/value pairs and arrays of values. JSON does not does not like to
+ * distinguish between elements and attributes. Sequences of similar
+ * elements are represented as JSONArrays. Content text may be placed in a
+ * "content" member. Comments, prologs, DTDs, and <[ [ ]]>
+ * are ignored.
+ *
+ * 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.
+ *
+ * @param string
+ * The source string.
+ * @param keepStrings If true, then values will not be coerced into boolean
+ * or numeric values and will instead be left as strings
+ * @return A JSONObject containing the structured data from the XML string.
+ * @throws JSONException Thrown if there is an errors while parsing the string
+ */
+ public static JSONObject toJSONObject(String string, boolean keepStrings) throws JSONException {
JSONObject jo = new JSONObject();
XMLTokener x = new XMLTokener(string);
while (x.more() && x.skipPast("<")) {
- parse(x, jo, null);
+ parse(x, jo, null, keepStrings);
}
return jo;
}
-
/**
* Convert a JSONObject into a well-formed, element-normal XML string.
*
* @param object
* A JSONObject.
* @return A string.
- * @throws JSONException
+ * @throws JSONException Thrown if there is an error parsing the string
*/
public static String toString(Object object) throws JSONException {
return toString(object, null);
@@ -353,7 +379,7 @@ public class XML {
* @param tagName
* The optional name of the enclosing tag.
* @return A string.
- * @throws JSONException
+ * @throws JSONException Thrown if there is an error parsing the string
*/
public static String toString(Object object, String tagName)
throws JSONException {