From 42e0944708570b5bb34fa4c9a3fa461279520d34 Mon Sep 17 00:00:00 2001 From: Jakob Stemberger Date: Wed, 14 Nov 2012 20:37:36 +0100 Subject: [PATCH 1/3] Brings in changes from PR #70 to be updated to HEAD --- JSONML.java | 65 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 62 insertions(+), 3 deletions(-) diff --git a/JSONML.java b/JSONML.java index 9acf21d..c10ea34 100644 --- a/JSONML.java +++ b/JSONML.java @@ -50,6 +50,25 @@ public class JSONML { XMLTokener x, boolean arrayForm, JSONArray ja + ) throws JSONException { + return parse(x, arrayForm, ja, false); + } + + /** + * 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, + boolean keepStrings ) throws JSONException { String attribute; char c; @@ -174,7 +193,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, ""); @@ -204,7 +223,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 + @@ -227,7 +246,7 @@ public class JSONML { } else { if (ja != null) { ja.put(token instanceof String - ? JSONObject.stringToValue((String)token) + ? keepStrings ? token :JSONObject.stringToValue((String)token) : token); } } @@ -252,6 +271,46 @@ public class JSONML { } + /** + * 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. + * @return A JSONArray containing the structured data from the XML string. + * @throws JSONException + */ + public static JSONArray toJsonML(String string) throws JSONException { + return toJsonML(new XMLTokener(string)); + } + + + /** + * 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. + * @return A JSONArray containing the structured data from the XML string. + * @throws JSONException + */ + public static JSONArray toJsonML(XMLTokener x) throws JSONException { + return (JSONArray)parse(x, true, null, true); + } + + /** * Convert a well-formed (but not necessarily valid) XML string into a * JSONArray using the JsonML transform. Each XML tag is represented as From 93704371bb3dca6ebe1a057a148b19c140615392 Mon Sep 17 00:00:00 2001 From: "John J. Aylward" Date: Mon, 18 Jul 2016 14:12:06 -0400 Subject: [PATCH 2/3] Updates to the Javadoc for exceptions --- JSONTokener.java | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) 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 + "]"; From 09d37e59b8620234d0fbb07dc71216b96692346b Mon Sep 17 00:00:00 2001 From: "John J. Aylward" Date: Mon, 18 Jul 2016 14:42:21 -0400 Subject: [PATCH 3/3] Cleans up the JSONML changes and adds similar changes to the XML class --- JSONML.java | 132 +++++++++++++++++++++++++++++++--------------------- XML.java | 48 ++++++++++++++----- 2 files changed, 115 insertions(+), 65 deletions(-) diff --git a/JSONML.java b/JSONML.java index c10ea34..7e99aab 100644 --- a/JSONML.java +++ b/JSONML.java @@ -36,24 +36,6 @@ 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. - * @return A JSONArray if the value is the outermost tag, otherwise null. - * @throws JSONException - */ - private static Object parse( - XMLTokener x, - boolean arrayForm, - JSONArray ja - ) throws JSONException { - return parse(x, arrayForm, ja, false); - } - /** * Parse XML values and store them in a JSONArray. * @param x The XMLTokener containing the source string. @@ -212,9 +194,8 @@ public class JSONML { if (ja == null) { if (arrayForm) { return newja; - } else { - return newjo; } + return newjo; } // Content, between <...> and @@ -236,9 +217,8 @@ public class JSONML { if (ja == null) { if (arrayForm) { return newja; - } else { - return newjo; } + return newjo; } } } @@ -264,10 +244,10 @@ 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); } @@ -283,11 +263,13 @@ public class JSONML { * 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 + * @throws JSONException Thrown on error converting to a JSONArray */ - public static JSONArray toJsonML(String string) throws JSONException { - return toJsonML(new XMLTokener(string)); + public static JSONArray toJSONArray(String string, boolean keepStrings) throws JSONException { + return (JSONArray)parse(new XMLTokener(string), true, null, keepStrings); } @@ -303,11 +285,13 @@ public class JSONML { * 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 + * @throws JSONException Thrown on error converting to a JSONArray */ - public static JSONArray toJsonML(XMLTokener x) throws JSONException { - return (JSONArray)parse(x, true, null, true); + public static JSONArray toJSONArray(XMLTokener x, boolean keepStrings) throws JSONException { + return (JSONArray)parse(x, true, null, keepStrings); } @@ -321,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); } @@ -357,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); } @@ -368,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; @@ -452,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/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 {