Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[2201.8.x] Support xsi:nil Attribute in xml to json/record conversion #552

Merged
merged 3 commits into from
Dec 12, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Support xsi:nil Attribute
  • Loading branch information
daneshk committed Dec 11, 2024
commit 7180563d184d92293f42fc8fdfe1272f7871be8c
13 changes: 13 additions & 0 deletions ballerina/tests/xml_to_json_test.bal
Original file line number Diff line number Diff line change
Expand Up @@ -730,3 +730,16 @@ function testToJsonComplexXmlElementWithBackSlash() returns Error? {
};
test:assertEquals(j, expectedOutput, msg = "testToJsonComplexXmlElement result incorrect");
}

@test:Config {
groups: ["toJson"]
}
function testToJsonWithNilElementAndWithoutPreserveNS() returns Error? {
xml x1 = xml `<name>Sherlock Holmes</name>
<details xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
<author xsi:nil="true"/>
<language>English</language>
</details>`;
json j = check toJson(x, {preserveNamespaces: false});
test:assertEquals(j, {"name":"Sherlock Holmes", "details":{"author":null, "language":"English"}}, msg = "testToJsonWithNilElement result incorrect");
}
16 changes: 12 additions & 4 deletions native/src/main/java/io/ballerina/stdlib/xmldata/XmlToJson.java
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ public class XmlToJson {
private static final String EMPTY_STRING = "";
public static final int NS_PREFIX_BEGIN_INDEX = BXmlItem.XMLNS_NS_URI_PREFIX.length();
private static final String COLON = ":";
public static final String XMLSCHEMA_INSTANCE_NIL = "{http://www.w3.org/2001/XMLSchema-instance}nil";
public static final BString BSTRING_XMLSCHEMA_INSTANCE_NIL = fromString(XMLSCHEMA_INSTANCE_NIL);

/**
* Converts an XML to the corresponding JSON representation.
Expand Down Expand Up @@ -190,7 +192,13 @@ private static Object convertElement(BXmlItem xmlItem, String attributePrefix,
children = convertToArray(fieldType, children);
}
fieldDetail.setParentArrayName(fieldName);
return insertDataToMap(childrenData, children, rootNode, fieldName, fieldType, fieldDetail);
boolean nilValue = false;
// If the children is null and has `{http://www.w3.org/2001/XMLSchema-instance}nil` attribute set to true,
// then it is a nil value
if (children == null && attributeMap.containsKey(BSTRING_XMLSCHEMA_INSTANCE_NIL)) {
nilValue = Boolean.parseBoolean(attributeMap.get(BSTRING_XMLSCHEMA_INSTANCE_NIL).getValue());
}
return insertDataToMap(childrenData, children, rootNode, fieldName, fieldType, fieldDetail, nilValue);
}

private static void processAttributeWithAnnotation(BXmlItem xmlItem, String attributePrefix,
Expand Down Expand Up @@ -224,7 +232,7 @@ private static void processAttributeWithAnnotation(BXmlItem xmlItem, String attr
@SuppressWarnings("unchecked")
private static BMap<BString, Object> insertDataToMap(BMap<BString, Object> childrenData, Object children,
BMap<BString, Object> rootNode, String keyValue,
Type fieldType, FieldDetails fieldDetails) throws Exception {
Type fieldType, FieldDetails fieldDetails, boolean nilValue) throws Exception {
if (childrenData.size() > 0) {
if (children instanceof BMap) {
BMap<BString, Object> data = (BMap<BString, Object>) children;
Expand All @@ -248,9 +256,9 @@ private static BMap<BString, Object> insertDataToMap(BMap<BString, Object> child
put(rootNode, keyValue, children);
} else if (children == null) {
if (fieldType instanceof ReferenceType && TypeUtils.getReferredType(fieldType) instanceof RecordType) {
put(rootNode, keyValue, ValueCreator.createMapValue(Constants.JSON_MAP_TYPE));
put(rootNode, keyValue, nilValue ? null : ValueCreator.createMapValue(Constants.JSON_MAP_TYPE));
} else {
putAsFieldTypes(rootNode, keyValue, EMPTY_STRING, fieldType, fieldDetails);
putAsFieldTypes(rootNode, keyValue, nilValue ? null : EMPTY_STRING, fieldType, fieldDetails);
}
} else if (children instanceof BArray) {
put(rootNode, keyValue, children);
Expand Down