Skip to content

Commit

Permalink
Merge pull request #543 from johnjaylward/RefactorXmlConfiguration
Browse files Browse the repository at this point in the history
Refactor XMLConfiguration to use Builder Pattern
  • Loading branch information
stleary committed Jul 24, 2020
2 parents 0e34d8d + 4f1c8b2 commit 7852810
Show file tree
Hide file tree
Showing 5 changed files with 179 additions and 38 deletions.
16 changes: 8 additions & 8 deletions src/main/java/org/json/XML.java
Expand Up @@ -286,7 +286,7 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
if (x.next() == '[') {
string = x.nextCDATA();
if (string.length() > 0) {
context.accumulate(config.cDataTagName, string);
context.accumulate(config.getcDataTagName(), string);
}
return false;
}
Expand Down Expand Up @@ -350,13 +350,13 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
throw x.syntaxError("Missing value");
}

if (config.convertNilAttributeToNull
if (config.isConvertNilAttributeToNull()
&& NULL_ATTR.equals(string)
&& Boolean.parseBoolean((String) token)) {
nilAttributeFound = true;
} else if (!nilAttributeFound) {
jsonObject.accumulate(string,
config.keepStrings
config.isKeepStrings()
? ((String) token)
: stringToValue((String) token));
}
Expand Down Expand Up @@ -392,8 +392,8 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
} else if (token instanceof String) {
string = (String) token;
if (string.length() > 0) {
jsonObject.accumulate(config.cDataTagName,
config.keepStrings ? string : stringToValue(string));
jsonObject.accumulate(config.getcDataTagName(),
config.isKeepStrings() ? string : stringToValue(string));
}

} else if (token == LT) {
Expand All @@ -402,8 +402,8 @@ private static boolean parse(XMLTokener x, JSONObject context, String name, XMLP
if (jsonObject.length() == 0) {
context.accumulate(tagName, "");
} else if (jsonObject.length() == 1
&& jsonObject.opt(config.cDataTagName) != null) {
context.accumulate(tagName, jsonObject.opt(config.cDataTagName));
&& jsonObject.opt(config.getcDataTagName()) != null) {
context.accumulate(tagName, jsonObject.opt(config.getcDataTagName()));
} else {
context.accumulate(tagName, jsonObject);
}
Expand Down Expand Up @@ -748,7 +748,7 @@ public static String toString(final Object object, final String tagName, final X
}

// Emit content in body
if (key.equals(config.cDataTagName)) {
if (key.equals(config.getcDataTagName())) {
if (value instanceof JSONArray) {
ja = (JSONArray) value;
int jaLength = ja.length();
Expand Down
143 changes: 132 additions & 11 deletions src/main/java/org/json/XMLParserConfiguration.java
Expand Up @@ -24,44 +24,57 @@ of this software and associated documentation files (the "Software"), to deal
*/

/**
* Configuration object for the XML parser.
* Configuration object for the XML parser. The configuration is immutable.
* @author AylwardJ
*
*/
@SuppressWarnings({""})
public class XMLParserConfiguration {
/** 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. */
public static final XMLParserConfiguration KEEP_STRINGS = new XMLParserConfiguration(true);
public static final XMLParserConfiguration KEEP_STRINGS
= new XMLParserConfiguration().withKeepStrings(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 (<code>true</code>), or if
* they should try to be guessed into JSON values (numeric, boolean, string)
*/
public final boolean keepStrings;
private boolean keepStrings;

/**
* The name of the key in a JSON Object that indicates a CDATA section. Historically this has
* been the value "content" but can be changed. Use <code>null</code> to indicate no CDATA
* processing.
*/
public final String cDataTagName;
private 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)
* should be kept as attribute(<code>false</code>), or they should be converted to
* <code>null</code>(<code>true</code>)
*/
public final boolean convertNilAttributeToNull;
private boolean convertNilAttributeToNull;

/**
* Default parser configuration. Does not keep strings, and the CDATA Tag Name is "content".
* Default parser configuration. Does not keep strings (tries to implicitly convert
* values), and the CDATA Tag Name is "content".
*/
public XMLParserConfiguration () {
this(false, "content", false);
this.keepStrings = false;
this.cDataTagName = "content";
this.convertNilAttributeToNull = false;
}

/**
* 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.
* <code>false</code> to try and convert XML string values into a JSON value.
* @deprecated This constructor has been deprecated in favor of using the new builder
* pattern for the configuration.
* This constructor may be removed in a future release.
*/
@Deprecated
public XMLParserConfiguration (final boolean keepStrings) {
this(keepStrings, "content", false);
}
Expand All @@ -72,7 +85,11 @@ public XMLParserConfiguration (final boolean keepStrings) {
* disable CDATA processing
* @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.
* @deprecated This constructor has been deprecated in favor of using the new builder
* pattern for the configuration.
* This constructor may be removed in a future release.
*/
@Deprecated
public XMLParserConfiguration (final String cDataTagName) {
this(false, cDataTagName, false);
}
Expand All @@ -83,7 +100,11 @@ public XMLParserConfiguration (final String cDataTagName) {
* <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.
* @deprecated This constructor has been deprecated in favor of using the new builder
* pattern for the configuration.
* This constructor may be removed in a future release.
*/
@Deprecated
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName) {
this.keepStrings = keepStrings;
this.cDataTagName = cDataTagName;
Expand All @@ -98,10 +119,110 @@ public XMLParserConfiguration (final boolean keepStrings, final String cDataTagN
* 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}.
* @deprecated This constructor has been deprecated in favor of using the new builder
* pattern for the configuration.
* This constructor may be removed or marked private in a future release.
*/
@Deprecated
public XMLParserConfiguration (final boolean keepStrings, final String cDataTagName, final boolean convertNilAttributeToNull) {
this.keepStrings = keepStrings;
this.cDataTagName = cDataTagName;
this.convertNilAttributeToNull = convertNilAttributeToNull;
}

/**
* Provides a new instance of the same configuration.
*/
@Override
protected XMLParserConfiguration clone() {
// future modifications to this method should always ensure a "deep"
// clone in the case of collections. i.e. if a Map is added as a configuration
// item, a new map instance should be created and if possible each value in the
// map should be cloned as well. If the values of the map are known to also
// be immutable, then a shallow clone of the map is acceptable.
return new XMLParserConfiguration(
this.keepStrings,
this.cDataTagName,
this.convertNilAttributeToNull
);
}

/**
* When parsing the XML into JSON, specifies if values should be kept as strings (<code>true</code>), or if
* they should try to be guessed into JSON values (numeric, boolean, string)
*
* @return The {@link #keepStrings} configuration value.
*/
public boolean isKeepStrings() {
return this.keepStrings;
}

/**
* When parsing the XML into JSON, specifies if values should be kept as strings (<code>true</code>), or if
* they should try to be guessed into JSON values (numeric, boolean, string)
*
* @param newVal
* new value to use for the {@link #keepStrings} configuration option.
*
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public XMLParserConfiguration withKeepStrings(final boolean newVal) {
XMLParserConfiguration newConfig = this.clone();
newConfig.keepStrings = newVal;
return newConfig;
}

/**
* The name of the key in a JSON Object that indicates a CDATA section. Historically this has
* been the value "content" but can be changed. Use <code>null</code> to indicate no CDATA
* processing.
*
* @return The {@link #cDataTagName} configuration value.
*/
public String getcDataTagName() {
return this.cDataTagName;
}

/**
* The name of the key in a JSON Object that indicates a CDATA section. Historically this has
* been the value "content" but can be changed. Use <code>null</code> to indicate no CDATA
* processing.
*
* @param newVal
* new value to use for the {@link #cDataTagName} configuration option.
*
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public XMLParserConfiguration withcDataTagName(final String newVal) {
XMLParserConfiguration newConfig = this.clone();
newConfig.cDataTagName = newVal;
return newConfig;
}

/**
* When parsing the XML into JSON, specifies if values with attribute xsi:nil="true"
* should be kept as attribute(<code>false</code>), or they should be converted to
* <code>null</code>(<code>true</code>)
*
* @return The {@link #convertNilAttributeToNull} configuration value.
*/
public boolean isConvertNilAttributeToNull() {
return this.convertNilAttributeToNull;
}

/**
* When parsing the XML into JSON, specifies if values with attribute xsi:nil="true"
* should be kept as attribute(<code>false</code>), or they should be converted to
* <code>null</code>(<code>true</code>)
*
* @param newVal
* new value to use for the {@link #convertNilAttributeToNull} configuration option.
*
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public XMLParserConfiguration withConvertNilAttributeToNull(final boolean newVal) {
XMLParserConfiguration newConfig = this.clone();
newConfig.convertNilAttributeToNull = newVal;
return newConfig;
}
}
2 changes: 1 addition & 1 deletion src/test/java/org/json/junit/JSONArrayTest.java
Expand Up @@ -1140,7 +1140,7 @@ public void testJSONArrayInt() {
assertNotNull(new JSONArray(5));
// Check Size -> Even though the capacity of the JSONArray can be specified using a positive
// integer but the length of JSONArray always reflects upon the items added into it.
assertEquals(0l, (long)new JSONArray(10).length());
assertEquals(0l, new JSONArray(10).length());
try {
assertNotNull("Should throw an exception", new JSONArray(-1));
} catch (JSONException e) {
Expand Down

0 comments on commit 7852810

Please sign in to comment.