mirror of
https://github.com/stleary/JSON-java.git
synced 2025-08-02 11:05:28 -04:00
Refs #541
Updates XML configuration to use a builder pattern instead of constructors with many parameters
This commit is contained in:
parent
6ddaa13c1e
commit
5a31f9ef5f
@ -286,7 +286,7 @@ public class XML {
|
||||
if (x.next() == '[') {
|
||||
string = x.nextCDATA();
|
||||
if (string.length() > 0) {
|
||||
context.accumulate(config.cDataTagName, string);
|
||||
context.accumulate(config.getcDataTagName(), string);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
@ -350,13 +350,13 @@ public class XML {
|
||||
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));
|
||||
}
|
||||
@ -392,8 +392,8 @@ public class XML {
|
||||
} 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) {
|
||||
@ -402,8 +402,8 @@ public class XML {
|
||||
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);
|
||||
}
|
||||
@ -748,7 +748,7 @@ public class XML {
|
||||
}
|
||||
|
||||
// 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();
|
||||
|
@ -24,44 +24,57 @@ SOFTWARE.
|
||||
*/
|
||||
|
||||
/**
|
||||
* 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);
|
||||
}
|
||||
@ -72,7 +85,11 @@ public class XMLParserConfiguration {
|
||||
* 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);
|
||||
}
|
||||
@ -83,7 +100,11 @@ public class XMLParserConfiguration {
|
||||
* <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;
|
||||
@ -98,10 +119,110 @@ public class XMLParserConfiguration {
|
||||
* 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;
|
||||
}
|
||||
}
|
||||
|
@ -1131,7 +1131,7 @@ public class JSONArrayTest {
|
||||
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) {
|
||||
|
@ -209,7 +209,7 @@ public class XMLConfigurationTest {
|
||||
"</addresses>";
|
||||
try {
|
||||
XMLParserConfiguration config =
|
||||
new XMLParserConfiguration("altContent");
|
||||
new XMLParserConfiguration().withcDataTagName("altContent");
|
||||
XML.toJSONObject(xmlStr, config);
|
||||
fail("Expecting a JSONException");
|
||||
} catch (JSONException e) {
|
||||
@ -300,7 +300,7 @@ public class XMLConfigurationTest {
|
||||
"XMLSchema-instance\"}}";
|
||||
|
||||
XMLParserConfiguration config =
|
||||
new XMLParserConfiguration("altContent");
|
||||
new XMLParserConfiguration().withcDataTagName("altContent");
|
||||
compareStringToJSONObject(xmlStr, expectedStr, config);
|
||||
compareReaderToJSONObject(xmlStr, expectedStr, config);
|
||||
compareFileToJSONObject(xmlStr, expectedStr);
|
||||
@ -325,7 +325,7 @@ public class XMLConfigurationTest {
|
||||
" </address>\n"+
|
||||
"</addresses>";
|
||||
XMLParserConfiguration config =
|
||||
new XMLParserConfiguration("altContent");
|
||||
new XMLParserConfiguration().withcDataTagName("altContent");
|
||||
JSONObject jsonObject = XML.toJSONObject(xmlStr, config);
|
||||
String expectedStr = "{\"addresses\":{\"address\":{\"street\":\"Baker "+
|
||||
"street 5\",\"name\":\"Joe Tester\",\"altContent\":\" this is -- "+
|
||||
@ -378,7 +378,7 @@ public class XMLConfigurationTest {
|
||||
String expectedStr =
|
||||
"{\"addresses\":{\"altContent\":\">\"}}";
|
||||
JSONObject expectedJsonObject = new JSONObject(expectedStr);
|
||||
XMLParserConfiguration config = new XMLParserConfiguration("altContent");
|
||||
XMLParserConfiguration config = new XMLParserConfiguration().withcDataTagName("altContent");
|
||||
String finalStr = XML.toString(expectedJsonObject, null, config);
|
||||
String expectedFinalStr = "<addresses>></addresses>";
|
||||
assertTrue("Should handle expectedFinal: ["+expectedStr+"] final: ["+
|
||||
@ -395,7 +395,7 @@ public class XMLConfigurationTest {
|
||||
String expectedStr =
|
||||
"{\"addresses\":{\"altContent\":[1, 2, 3]}}";
|
||||
JSONObject expectedJsonObject = new JSONObject(expectedStr);
|
||||
XMLParserConfiguration config = new XMLParserConfiguration("altContent");
|
||||
XMLParserConfiguration config = new XMLParserConfiguration().withcDataTagName("altContent");
|
||||
String finalStr = XML.toString(expectedJsonObject, null, config);
|
||||
String expectedFinalStr = "<addresses>"+
|
||||
"1\n2\n3"+
|
||||
@ -595,7 +595,9 @@ public class XMLConfigurationTest {
|
||||
// multiple consecutive standalone cdatas are accumulated into an array
|
||||
xmlStr = "<tag1></tag1><![CDATA[if (a < b && a > 0) then return]]><tag2></tag2><![CDATA[here is another cdata]]>";
|
||||
jsonObject = XML.toJSONObject(xmlStr,
|
||||
new XMLParserConfiguration(true, "altContent"));
|
||||
new XMLParserConfiguration()
|
||||
.withKeepStrings(true)
|
||||
.withcDataTagName("altContent"));
|
||||
assertTrue("2. 3 items", 3 == jsonObject.length());
|
||||
assertTrue("2. empty tag1", "".equals(jsonObject.get("tag1")));
|
||||
assertTrue("2. empty tag2", "".equals(jsonObject.get("tag2")));
|
||||
@ -612,7 +614,9 @@ public class XMLConfigurationTest {
|
||||
*/
|
||||
xmlStr = "<tag1>value 1</tag1>";
|
||||
jsonObject = XML.toJSONObject(xmlStr,
|
||||
new XMLParserConfiguration(true, "altContent"));
|
||||
new XMLParserConfiguration()
|
||||
.withKeepStrings(true)
|
||||
.withcDataTagName("altContent"));
|
||||
assertTrue("3. 2 items", 1 == jsonObject.length());
|
||||
assertTrue("3. value tag1", "value 1".equals(jsonObject.get("tag1")));
|
||||
|
||||
@ -623,7 +627,9 @@ public class XMLConfigurationTest {
|
||||
*/
|
||||
xmlStr = "<tag1>value 1</tag1><tag1>2</tag1><tag1>true</tag1>";
|
||||
jsonObject = XML.toJSONObject(xmlStr,
|
||||
new XMLParserConfiguration(true, "altContent"));
|
||||
new XMLParserConfiguration()
|
||||
.withKeepStrings(true)
|
||||
.withcDataTagName("altContent"));
|
||||
assertTrue("4. 1 item", 1 == jsonObject.length());
|
||||
assertTrue("4. content array found", jsonObject.get("tag1") instanceof JSONArray);
|
||||
jsonArray = jsonObject.getJSONArray("tag1");
|
||||
@ -639,7 +645,9 @@ public class XMLConfigurationTest {
|
||||
*/
|
||||
xmlStr = "<tag1>val1<tag2/>val2</tag1>";
|
||||
jsonObject = XML.toJSONObject(xmlStr,
|
||||
new XMLParserConfiguration(true, "altContent"));
|
||||
new XMLParserConfiguration()
|
||||
.withKeepStrings(true)
|
||||
.withcDataTagName("altContent"));
|
||||
assertTrue("5. 1 item", 1 == jsonObject.length());
|
||||
assertTrue("5. jsonObject found", jsonObject.get("tag1")
|
||||
instanceof JSONObject);
|
||||
@ -659,7 +667,9 @@ public class XMLConfigurationTest {
|
||||
*/
|
||||
xmlStr = "<tag1>val1<tag2/></tag1>";
|
||||
jsonObject = XML.toJSONObject(xmlStr,
|
||||
new XMLParserConfiguration(true, "altContent"));
|
||||
new XMLParserConfiguration()
|
||||
.withKeepStrings(true)
|
||||
.withcDataTagName("altContent"));
|
||||
assertTrue("6. 1 item", 1 == jsonObject.length());
|
||||
assertTrue("6. jsonObject found", jsonObject.get("tag1") instanceof JSONObject);
|
||||
jsonObject = jsonObject.getJSONObject("tag1");
|
||||
@ -674,7 +684,9 @@ public class XMLConfigurationTest {
|
||||
*/
|
||||
xmlStr = "<tag1>val1<altContent/></tag1>";
|
||||
jsonObject = XML.toJSONObject(xmlStr,
|
||||
new XMLParserConfiguration(true, "altContent"));
|
||||
new XMLParserConfiguration()
|
||||
.withKeepStrings(true)
|
||||
.withcDataTagName("altContent"));
|
||||
assertTrue("7. 1 item", 1 == jsonObject.length());
|
||||
assertTrue("7. jsonArray found",
|
||||
jsonObject.get("tag1") instanceof JSONArray);
|
||||
@ -713,7 +725,9 @@ public class XMLConfigurationTest {
|
||||
"}";
|
||||
jsonObject = new JSONObject(jsonStr);
|
||||
xmlStr = XML.toString(jsonObject, null,
|
||||
new XMLParserConfiguration(true, "altContent"));
|
||||
new XMLParserConfiguration()
|
||||
.withKeepStrings(true)
|
||||
.withcDataTagName("altContent"));
|
||||
/*
|
||||
* This is the created XML. Looks like content was mistaken for
|
||||
* complex (child node + text) XML.
|
||||
@ -739,7 +753,7 @@ public class XMLConfigurationTest {
|
||||
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
|
||||
final JSONObject expected = new JSONObject("{\"root\":{\"item\":{\"id\":\"01\"},\"id\":[\"01\",1,\"00\",0],\"title\":true}}");
|
||||
final JSONObject actualJsonOutput = XML.toJSONObject(originalXml,
|
||||
new XMLParserConfiguration(false));
|
||||
new XMLParserConfiguration().withKeepStrings(false));
|
||||
Util.compareActualVsExpectedJsonObjects(actualJsonOutput,expected);
|
||||
}
|
||||
|
||||
@ -749,7 +763,7 @@ public class XMLConfigurationTest {
|
||||
@Test
|
||||
public void testToJSONArray_reversibility() {
|
||||
final String originalXml = "<root><id>01</id><id>1</id><id>00</id><id>0</id><item id=\"01\"/><title>True</title></root>";
|
||||
XMLParserConfiguration config = new XMLParserConfiguration(false);
|
||||
XMLParserConfiguration config = new XMLParserConfiguration().withKeepStrings(false);
|
||||
final String revertedXml =
|
||||
XML.toString(XML.toJSONObject(originalXml, config),
|
||||
null, config);
|
||||
@ -765,7 +779,7 @@ public class XMLConfigurationTest {
|
||||
final JSONObject expected = new JSONObject("{\"root\":{\"item\":{\"id\":\"01\"},\"id\":[\"01\",\"1\",\"00\",\"0\"],\"title\":\"True\"}}");
|
||||
|
||||
final JSONObject json = XML.toJSONObject(originalXml,
|
||||
new XMLParserConfiguration(true));
|
||||
new XMLParserConfiguration().withKeepStrings(true));
|
||||
Util.compareActualVsExpectedJsonObjects(json, expected);
|
||||
|
||||
final String reverseXml = XML.toString(json);
|
||||
@ -850,7 +864,9 @@ public class XMLConfigurationTest {
|
||||
|
||||
// keep strings, use the altContent tag
|
||||
XMLParserConfiguration config =
|
||||
new XMLParserConfiguration(true, "altContent");
|
||||
new XMLParserConfiguration()
|
||||
.withKeepStrings(true)
|
||||
.withcDataTagName("altContent");
|
||||
JSONObject jsonObject = XML.toJSONObject(xmlStr, config);
|
||||
// num is parsed as a string
|
||||
assertEquals(jsonObject.getJSONObject("addresses").
|
||||
@ -875,7 +891,7 @@ public class XMLConfigurationTest {
|
||||
Util.compareActualVsExpectedJsonArrays(jsonArray, expectedJsonArray);
|
||||
|
||||
// use alternate content name
|
||||
config = new XMLParserConfiguration("altContent");
|
||||
config = new XMLParserConfiguration().withcDataTagName("altContent");
|
||||
jsonObject = XML.toJSONObject(xmlStr, config);
|
||||
// num is parsed as a number
|
||||
assertEquals(jsonObject.getJSONObject("addresses").
|
||||
|
@ -883,7 +883,10 @@ public class XMLTest {
|
||||
final String originalXml = "<root><id xsi:nil=\"true\"/></root>";
|
||||
final String expectedJsonString = "{\"root\":{\"id\":null}}";
|
||||
|
||||
final JSONObject json = XML.toJSONObject(originalXml, new XMLParserConfiguration(false, "content", true));
|
||||
final JSONObject json = XML.toJSONObject(originalXml,
|
||||
new XMLParserConfiguration()
|
||||
.withKeepStrings(false).withcDataTagName("content")
|
||||
.withConvertNilAttributeToNull(true));
|
||||
assertEquals(expectedJsonString, json.toString());
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user