Skip to content

Commit 987707f

Browse files
committed
fix: Honor type hints when deserializing XML to JSON with empty string values
Fixes #66
1 parent 0f11f10 commit 987707f

File tree

3 files changed

+46
-19
lines changed

3 files changed

+46
-19
lines changed

subprojects/json-lib-core/src/main/java/org/kordamp/json/util/JSONUtils.java

+24
Original file line numberDiff line numberDiff line change
@@ -385,6 +385,30 @@ public static boolean isString(Object obj) {
385385
return false;
386386
}
387387

388+
/**
389+
* <p>Determines whether a given string is <code>null</code>, empty,
390+
* or only contains whitespace. If it contains anything other than
391+
* whitespace then the string is not considered to be blank and the
392+
* method returns <code>false</code>.</p>
393+
*
394+
* @param str The string to test.
395+
* @return <code> true</code> if the string is <code>null</code>, or
396+
* blank.
397+
*/
398+
public static boolean isBlank(String str) {
399+
if (null == str || str.length() == 0) {
400+
return true;
401+
}
402+
403+
for (char c : str.toCharArray()) {
404+
if (!Character.isWhitespace(c)) {
405+
return false;
406+
}
407+
}
408+
409+
return true;
410+
}
411+
388412
/**
389413
* Tests if the String possibly represents a valid JSON String.<br>
390414
* Valid JSON strings are:

subprojects/json-lib-core/src/main/java/org/kordamp/json/xml/XMLSerializer.java

+10-15
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,8 @@
5959
import java.util.Map;
6060
import java.util.TreeMap;
6161

62+
import static org.kordamp.json.util.JSONUtils.isBlank;
63+
6264
/**
6365
* Utility class for transforming JSON to XML an back.<br>
6466
* When transforming JSONObject and JSONArray instances to XML, this class will
@@ -560,9 +562,7 @@ public void setForcedArrayElements(Collection<String> forcedArrayElements) {
560562
* Creates a JSON value from a XML string.
561563
*
562564
* @param xml A well-formed xml document in a String
563-
*
564565
* @return a JSONNull, JSONObject or JSONArray
565-
*
566566
* @throws JSONException if the conversion from XML to JSON can't be made for
567567
* I/O or format reasons.
568568
*/
@@ -600,9 +600,7 @@ public JSON read(String xml) {
600600
* Creates a JSON value from a File.
601601
*
602602
* @param file
603-
*
604603
* @return a JSONNull, JSONObject or JSONArray
605-
*
606604
* @throws JSONException if the conversion from XML to JSON can't be made for
607605
* I/O or format reasons.
608606
*/
@@ -627,9 +625,7 @@ public JSON readFromFile(File file) {
627625
* Creates a JSON value from a File.
628626
*
629627
* @param path
630-
*
631628
* @return a JSONNull, JSONObject or JSONArray
632-
*
633629
* @throws JSONException if the conversion from XML to JSON can't be made for
634630
* I/O or format reasons.
635631
*/
@@ -643,9 +639,7 @@ public JSON readFromFile(String path) {
643639
* Creates a JSON value from an input stream.
644640
*
645641
* @param stream
646-
*
647642
* @return a JSONNull, JSONObject or JSONArray
648-
*
649643
* @throws JSONException if the conversion from XML to JSON can't be made for
650644
* I/O or format reasons.
651645
*/
@@ -767,9 +761,7 @@ public void setKeepArrayName(boolean keepName) {
767761
* Writes a JSON value into a XML string with UTF-8 encoding.<br>
768762
*
769763
* @param json The JSON value to transform
770-
*
771764
* @return a String representation of a well-formed xml document.
772-
*
773765
* @throws JSONException if the conversion from JSON to XML can't be made for
774766
* I/O reasons.
775767
*/
@@ -783,9 +775,7 @@ public String write(JSON json) {
783775
*
784776
* @param json The JSON value to transform
785777
* @param encoding The xml encoding to use
786-
*
787778
* @return a String representation of a well-formed xml document.
788-
*
789779
* @throws JSONException if the conversion from JSON to XML can't be made for
790780
* I/O reasons or the encoding is not supported.
791781
*/
@@ -1193,7 +1183,9 @@ private Element processJSONObject(JSONObject jsonObject, Element root,
11931183

11941184
Object[] names = jsonObject.names().toArray();
11951185
List<String> unprocessed = new ArrayList<>();
1196-
if (isSortPropertyNames()) { Arrays.sort(names); }
1186+
if (isSortPropertyNames()) {
1187+
Arrays.sort(names);
1188+
}
11971189
for (Object o : names) {
11981190
String name = (String) o;
11991191
Object value = jsonObject.get(name);
@@ -1275,7 +1267,6 @@ private Element processJSONObject(JSONObject jsonObject, Element root,
12751267
* Only perform auto expansion if all children are objects.
12761268
*
12771269
* @param array The array to check
1278-
*
12791270
* @return True if all children are objects, false otherwise.
12801271
*/
12811272
private boolean canAutoExpand(JSONArray array) {
@@ -1557,7 +1548,11 @@ private void setValue(JSONObject jsonObject, Element element, String defaultType
15571548
params = StringUtils.split(paramsAttribute.getValue(), ",");
15581549
setOrAccumulate(jsonObject, key, new JSONFunction(params, text));
15591550
} else {
1560-
if (isArray(element, false)) {
1551+
Attribute typeAttr = element.getAttribute(addJsonPrefix("type"));
1552+
if (typeAttr != null && isBlank(element.getValue()) &&
1553+
element.getChildCount() == 0 && element.getChildElements().size() == 0) {
1554+
setOrAccumulate(jsonObject, key, "");
1555+
} else if (isArray(element, false)) {
15611556
setOrAccumulate(jsonObject, key, processArrayElement(element, defaultType));
15621557
} else if (isObject(element, false)) {
15631558
setOrAccumulate(jsonObject, key, simplifyValue(jsonObject,

subprojects/json-lib-core/src/test/java/org/kordamp/json/xml/TestUserSubmitted.java

+12-4
Original file line numberDiff line numberDiff line change
@@ -221,16 +221,24 @@ public void testXMLWithoutArray() {
221221
Assertions.assertEquals(expected, actual);
222222
}
223223

224+
public void testEmptyStringWithHints() {
225+
String testXML = "<o><test1 type=\"string\" /></o>";
226+
227+
JSON expected = JSONSerializer.toJSON("{\"o\": {\"test1\": \"\"}}");
228+
229+
JSONObject actual = convertXML(testXML);
230+
assertNotNull(actual);
231+
Assertions.assertEquals(expected, actual);
232+
}
233+
224234
private JSONObject convertXML(String testXML) {
225-
JSON jsonElement = getSerializer().read(testXML);
226-
return (JSONObject) jsonElement;
235+
return (JSONObject) getSerializer().read(testXML);
227236
}
228237

229238
private JSONObject convertXML(String testXML, String arrayName) {
230239
final XMLSerializer xmlSerializer = getSerializer();
231240
xmlSerializer.setArrayName(arrayName);
232-
JSON jsonElement = xmlSerializer.read(testXML);
233-
return (JSONObject) jsonElement;
241+
return (JSONObject) xmlSerializer.read(testXML);
234242
}
235243

236244
private XMLSerializer getSerializer() {

0 commit comments

Comments
 (0)