Merge pull request #646 from Zetmas/feature/issue#595

XMLParserConfiguration support for xml to json arrays
This commit is contained in:
Sean Leary
2021-12-03 19:37:00 -06:00
committed by GitHub
3 changed files with 239 additions and 14 deletions

View File

@@ -380,12 +380,23 @@ public class XML {
if (x.nextToken() != GT) {
throw x.syntaxError("Misshaped tag");
}
if (nilAttributeFound) {
context.accumulate(tagName, JSONObject.NULL);
} else if (jsonObject.length() > 0) {
context.accumulate(tagName, jsonObject);
if (config.getForceList().contains(tagName)) {
// Force the value to be an array
if (nilAttributeFound) {
context.append(tagName, JSONObject.NULL);
} else if (jsonObject.length() > 0) {
context.append(tagName, jsonObject);
} else {
context.put(tagName, new JSONArray());
}
} else {
context.accumulate(tagName, "");
if (nilAttributeFound) {
context.accumulate(tagName, JSONObject.NULL);
} else if (jsonObject.length() > 0) {
context.accumulate(tagName, jsonObject);
} else {
context.accumulate(tagName, "");
}
}
return false;
@@ -413,14 +424,27 @@ public class XML {
} else if (token == LT) {
// Nested element
if (parse(x, jsonObject, tagName, config)) {
if (jsonObject.length() == 0) {
context.accumulate(tagName, "");
} else if (jsonObject.length() == 1
&& jsonObject.opt(config.getcDataTagName()) != null) {
context.accumulate(tagName, jsonObject.opt(config.getcDataTagName()));
if (config.getForceList().contains(tagName)) {
// Force the value to be an array
if (jsonObject.length() == 0) {
context.put(tagName, new JSONArray());
} else if (jsonObject.length() == 1
&& jsonObject.opt(config.getcDataTagName()) != null) {
context.append(tagName, jsonObject.opt(config.getcDataTagName()));
} else {
context.append(tagName, jsonObject);
}
} else {
context.accumulate(tagName, jsonObject);
if (jsonObject.length() == 0) {
context.accumulate(tagName, "");
} else if (jsonObject.length() == 1
&& jsonObject.opt(config.getcDataTagName()) != null) {
context.accumulate(tagName, jsonObject.opt(config.getcDataTagName()));
} else {
context.accumulate(tagName, jsonObject);
}
}
return false;
}
}

View File

@@ -25,7 +25,9 @@ SOFTWARE.
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;
/**
@@ -66,6 +68,12 @@ public class XMLParserConfiguration {
*/
private Map<String, XMLXsiTypeConverter<?>> xsiTypeMap;
/**
* When parsing the XML into JSON, specifies the tags whose values should be converted
* to arrays
*/
private Set<String> forceList;
/**
* Default parser configuration. Does not keep strings (tries to implicitly convert
* values), and the CDATA Tag Name is "content".
@@ -75,6 +83,7 @@ public class XMLParserConfiguration {
this.cDataTagName = "content";
this.convertNilAttributeToNull = false;
this.xsiTypeMap = Collections.emptyMap();
this.forceList = Collections.emptySet();
}
/**
@@ -151,13 +160,15 @@ public class XMLParserConfiguration {
* <code>false</code> to parse values with attribute xsi:nil="true" as {"xsi:nil":true}.
* @param xsiTypeMap <code>new HashMap<String, XMLXsiTypeConverter<?>>()</code> to parse values with attribute
* xsi:type="integer" as integer, xsi:type="string" as string
* @param forceList <code>new HashSet<String>()</code> to parse the provided tags' values as arrays
*/
private XMLParserConfiguration (final boolean keepStrings, final String cDataTagName,
final boolean convertNilAttributeToNull, final Map<String, XMLXsiTypeConverter<?>> xsiTypeMap ) {
final boolean convertNilAttributeToNull, final Map<String, XMLXsiTypeConverter<?>> xsiTypeMap, final Set<String> forceList ) {
this.keepStrings = keepStrings;
this.cDataTagName = cDataTagName;
this.convertNilAttributeToNull = convertNilAttributeToNull;
this.xsiTypeMap = Collections.unmodifiableMap(xsiTypeMap);
this.forceList = Collections.unmodifiableSet(forceList);
}
/**
@@ -174,7 +185,8 @@ public class XMLParserConfiguration {
this.keepStrings,
this.cDataTagName,
this.convertNilAttributeToNull,
this.xsiTypeMap
this.xsiTypeMap,
this.forceList
);
}
@@ -283,4 +295,26 @@ public class XMLParserConfiguration {
newConfig.xsiTypeMap = Collections.unmodifiableMap(cloneXsiTypeMap);
return newConfig;
}
/**
* When parsing the XML into JSON, specifies that tags that will be converted to arrays
* in this configuration {@code Set<String>} to parse the provided tags' values as arrays
* @return <code>forceList</code> unmodifiable configuration set.
*/
public Set<String> getForceList() {
return this.forceList;
}
/**
* When parsing the XML into JSON, specifies that tags that will be converted to arrays
* in this configuration {@code Set<String>} to parse the provided tags' values as arrays
* @param forceList {@code new HashSet<String>()} to parse the provided tags' values as arrays
* @return The existing configuration will not be modified. A new configuration is returned.
*/
public XMLParserConfiguration withForceList(final Set<String> forceList) {
XMLParserConfiguration newConfig = this.clone();
Set<String> cloneForceList = new HashSet<String>(forceList);
newConfig.forceList = Collections.unmodifiableSet(cloneForceList);
return newConfig;
}
}