mirror of
https://github.com/ethauvin/JSON-java.git
synced 2025-06-17 07:50:52 -07:00
add configuration for xsi:nil="true" conversion to null
This commit is contained in:
parent
12bbe8cd9a
commit
d5b278539e
2 changed files with 72 additions and 34 deletions
73
XML.java
73
XML.java
|
@ -31,7 +31,7 @@ import java.util.Iterator;
|
||||||
/**
|
/**
|
||||||
* This provides static methods to convert an XML text into a JSONObject, and to
|
* This provides static methods to convert an XML text into a JSONObject, and to
|
||||||
* covert a JSONObject into an XML text.
|
* covert a JSONObject into an XML text.
|
||||||
*
|
*
|
||||||
* @author JSON.org
|
* @author JSON.org
|
||||||
* @version 2016-08-10
|
* @version 2016-08-10
|
||||||
*/
|
*/
|
||||||
|
@ -64,7 +64,12 @@ public class XML {
|
||||||
|
|
||||||
/** The Character '/'. */
|
/** The Character '/'. */
|
||||||
public static final Character SLASH = '/';
|
public static final Character SLASH = '/';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Null attrubute name
|
||||||
|
*/
|
||||||
|
public static final String NULL_ATTR = "xsi:nil";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an iterator for navigating Code Points in a string instead of
|
* Creates an iterator for navigating Code Points in a string instead of
|
||||||
* characters. Once Java7 support is dropped, this can be replaced with
|
* characters. Once Java7 support is dropped, this can be replaced with
|
||||||
|
@ -72,7 +77,7 @@ public class XML {
|
||||||
* string.codePoints()
|
* string.codePoints()
|
||||||
* </code>
|
* </code>
|
||||||
* 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>
|
||||||
*/
|
*/
|
||||||
|
@ -107,7 +112,7 @@ public class XML {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace special characters with XML escapes:
|
* Replace special characters with XML escapes:
|
||||||
*
|
*
|
||||||
* <pre>
|
* <pre>
|
||||||
* & <small>(ampersand)</small> is replaced by &amp;
|
* & <small>(ampersand)</small> is replaced by &amp;
|
||||||
* < <small>(less than)</small> is replaced by &lt;
|
* < <small>(less than)</small> is replaced by &lt;
|
||||||
|
@ -115,7 +120,7 @@ public class XML {
|
||||||
* " <small>(double quote)</small> is replaced by &quot;
|
* " <small>(double quote)</small> is replaced by &quot;
|
||||||
* ' <small>(single quote / apostrophe)</small> is replaced by &apos;
|
* ' <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.
|
||||||
|
@ -151,17 +156,17 @@ public class XML {
|
||||||
}
|
}
|
||||||
return sb.toString();
|
return sb.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param cp code point to test
|
* @param cp code point to test
|
||||||
* @return true if the code point is not valid for an XML
|
* @return true if the code point is not valid for an XML
|
||||||
*/
|
*/
|
||||||
private static boolean mustEscape(int cp) {
|
private static boolean mustEscape(int cp) {
|
||||||
/* Valid range from https://www.w3.org/TR/REC-xml/#charsets
|
/* Valid range from https://www.w3.org/TR/REC-xml/#charsets
|
||||||
*
|
*
|
||||||
* #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
|
* #x9 | #xA | #xD | [#x20-#xD7FF] | [#xE000-#xFFFD] | [#x10000-#x10FFFF]
|
||||||
*
|
*
|
||||||
* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
|
* any Unicode character, excluding the surrogate blocks, FFFE, and FFFF.
|
||||||
*/
|
*/
|
||||||
// isISOControl is true when (cp >= 0 && cp <= 0x1F) || (cp >= 0x7F && cp <= 0x9F)
|
// isISOControl is true when (cp >= 0 && cp <= 0x1F) || (cp >= 0x7F && cp <= 0x9F)
|
||||||
// all ISO control characters are out of range except tabs and new lines
|
// all ISO control characters are out of range except tabs and new lines
|
||||||
|
@ -180,7 +185,7 @@ public class XML {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
|
@ -212,7 +217,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.
|
||||||
|
@ -232,7 +237,7 @@ 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
|
* @param context
|
||||||
|
@ -328,6 +333,7 @@ public class XML {
|
||||||
tagName = (String) token;
|
tagName = (String) token;
|
||||||
token = null;
|
token = null;
|
||||||
jsonobject = new JSONObject();
|
jsonobject = new JSONObject();
|
||||||
|
boolean nilAttributeFound = false;
|
||||||
for (;;) {
|
for (;;) {
|
||||||
if (token == null) {
|
if (token == null) {
|
||||||
token = x.nextToken();
|
token = x.nextToken();
|
||||||
|
@ -341,8 +347,17 @@ public class XML {
|
||||||
if (!(token instanceof String)) {
|
if (!(token instanceof String)) {
|
||||||
throw x.syntaxError("Missing value");
|
throw x.syntaxError("Missing value");
|
||||||
}
|
}
|
||||||
jsonobject.accumulate(string,
|
|
||||||
config.keepStrings ? ((String)token) : stringToValue((String) token));
|
if (config.convertNilAttributeToNull
|
||||||
|
&& NULL_ATTR.equals(string)
|
||||||
|
&& Boolean.parseBoolean((String) token)) {
|
||||||
|
nilAttributeFound = true;
|
||||||
|
} else if (!nilAttributeFound) {
|
||||||
|
jsonobject.accumulate(string,
|
||||||
|
config.keepStrings
|
||||||
|
? ((String) token)
|
||||||
|
: stringToValue((String) token));
|
||||||
|
}
|
||||||
token = null;
|
token = null;
|
||||||
} else {
|
} else {
|
||||||
jsonobject.accumulate(string, "");
|
jsonobject.accumulate(string, "");
|
||||||
|
@ -354,7 +369,9 @@ public class XML {
|
||||||
if (x.nextToken() != GT) {
|
if (x.nextToken() != GT) {
|
||||||
throw x.syntaxError("Misshaped tag");
|
throw x.syntaxError("Misshaped tag");
|
||||||
}
|
}
|
||||||
if (jsonobject.length() > 0) {
|
if (nilAttributeFound) {
|
||||||
|
context.accumulate(tagName, JSONObject.NULL);
|
||||||
|
} else if (jsonobject.length() > 0) {
|
||||||
context.accumulate(tagName, jsonobject);
|
context.accumulate(tagName, jsonobject);
|
||||||
} else {
|
} else {
|
||||||
context.accumulate(tagName, "");
|
context.accumulate(tagName, "");
|
||||||
|
@ -399,10 +416,10 @@ public class XML {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This method is the same as {@link JSONObject#stringToValue(String)}.
|
* This method is the same as {@link JSONObject#stringToValue(String)}.
|
||||||
*
|
*
|
||||||
* @param string String to convert
|
* @param string String to convert
|
||||||
* @return JSON value of this string or the string
|
* @return JSON value of this string or the string
|
||||||
*/
|
*/
|
||||||
|
@ -463,7 +480,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.
|
||||||
*
|
*
|
||||||
* @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.
|
||||||
|
@ -518,7 +535,7 @@ public class XML {
|
||||||
}
|
}
|
||||||
return toJSONObject(reader, XMLParserConfiguration.ORIGINAL);
|
return toJSONObject(reader, XMLParserConfiguration.ORIGINAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Convert a well-formed (but not necessarily valid) XML into a
|
* Convert a well-formed (but not necessarily valid) XML into a
|
||||||
* JSONObject. Some information may be lost in this transformation because
|
* JSONObject. Some information may be lost in this transformation because
|
||||||
|
@ -560,10 +577,10 @@ 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.
|
||||||
*
|
*
|
||||||
* 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
|
||||||
|
@ -585,10 +602,10 @@ 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.
|
||||||
*
|
*
|
||||||
* 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.
|
||||||
|
@ -601,7 +618,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.
|
||||||
|
@ -610,10 +627,10 @@ public class XML {
|
||||||
public static String toString(Object object) throws JSONException {
|
public static String toString(Object object) throws JSONException {
|
||||||
return toString(object, null, XMLParserConfiguration.ORIGINAL);
|
return toString(object, null, XMLParserConfiguration.ORIGINAL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
* @param tagName
|
||||||
|
@ -627,7 +644,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.
|
||||||
* @param tagName
|
* @param tagName
|
||||||
|
|
|
@ -32,7 +32,7 @@ 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
|
||||||
* they should try to be guessed into JSON values (numeric, boolean, string)
|
* they should try to be guessed into JSON values (numeric, boolean, string)
|
||||||
|
@ -44,12 +44,17 @@ public class XMLParserConfiguration {
|
||||||
* processing.
|
* processing.
|
||||||
*/
|
*/
|
||||||
public final String cDataTagName;
|
public final String cDataTagName;
|
||||||
|
/**
|
||||||
|
* When parsing the XML into JSON, specifies if values with attribute xsi:nil="true"
|
||||||
|
* should be kept as attribute(false), or they should be converted to null(true)
|
||||||
|
*/
|
||||||
|
public final boolean convertNilAttributeToNull;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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");
|
this(false, "content", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -58,7 +63,7 @@ public class XMLParserConfiguration {
|
||||||
* <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");
|
this(keepStrings, "content", false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -69,7 +74,7 @@ public class XMLParserConfiguration {
|
||||||
* 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);
|
this(false, cDataTagName, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -80,7 +85,23 @@ public class XMLParserConfiguration {
|
||||||
* 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 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.
|
||||||
|
* <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) {
|
||||||
|
this.keepStrings = keepStrings;
|
||||||
|
this.cDataTagName = cDataTagName;
|
||||||
|
this.convertNilAttributeToNull = convertNilAttributeToNull;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue