diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java index 10b8609356a..4dea1260aca 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/JsonParser.java @@ -317,19 +317,14 @@ public class JsonParser extends BaseParser implements IJsonLikeParser { } case CONTAINED_RESOURCE_LIST: case CONTAINED_RESOURCES: { - /* - * Disabled per #103 ContainedDt value = (ContainedDt) theNextValue; for (IResource next : - * value.getContainedResources()) { if (getContainedResources().getResourceId(next) != null) { continue; } - * encodeResourceToJsonStreamWriter(theResDef, next, theWriter, null, true, - * fixContainedResourceId(next.getId().getValue())); } - */ List containedResources = getContainedResources().getContainedResources(); if (containedResources.size() > 0) { beginArray(theEventWriter, theChildName); for (IBaseResource next : containedResources) { IIdType resourceId = getContainedResources().getResourceId(next); - encodeResourceToJsonStreamWriter(theResDef, next, theEventWriter, null, true, fixContainedResourceId(resourceId.getValue()), theEncodeContext); + String value = resourceId.getValue(); + encodeResourceToJsonStreamWriter(theResDef, next, theEventWriter, null, true, fixContainedResourceId(value), theEncodeContext); } theEventWriter.endArray(); @@ -359,7 +354,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser { RuntimeResourceDefinition def = myContext.getResourceDefinition(resource); theEncodeContext.pushPath(def.getName(), true); - encodeResourceToJsonStreamWriter(def, resource, theEventWriter, theChildName, false, theEncodeContext); + encodeResourceToJsonStreamWriter(def, resource, theEventWriter, theChildName, theContainedResource, theEncodeContext); theEncodeContext.popPath(); break; diff --git a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java index 2ed7221cc16..a09ad1208be 100644 --- a/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java +++ b/hapi-fhir-base/src/main/java/ca/uhn/fhir/parser/XmlParser.java @@ -287,7 +287,8 @@ public class XmlParser extends BaseParser { for (IBaseResource next : getContainedResources().getContainedResources()) { IIdType resourceId = getContainedResources().getResourceId(next); theEventWriter.writeStartElement("contained"); - encodeResourceToXmlStreamWriter(next, theEventWriter, true, fixContainedResourceId(resourceId.getValue()), theEncodeContext); + String value = resourceId.getValue(); + encodeResourceToXmlStreamWriter(next, theEventWriter, true, fixContainedResourceId(value), theEncodeContext); theEventWriter.writeEndElement(); } break; @@ -300,7 +301,7 @@ public class XmlParser extends BaseParser { } theEventWriter.writeStartElement(theChildName); theEncodeContext.pushPath(resourceName, true); - encodeResourceToXmlStreamWriter(resource, theEventWriter, false, theEncodeContext); + encodeResourceToXmlStreamWriter(resource, theEventWriter, theIncludedResource, theEncodeContext); theEncodeContext.popPath(); theEventWriter.writeEndElement(); break; diff --git a/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/4_3_0/1778-avoid-crash-encoding-contained-bundle.yaml b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/4_3_0/1778-avoid-crash-encoding-contained-bundle.yaml new file mode 100644 index 00000000000..d7c698890e9 --- /dev/null +++ b/hapi-fhir-docs/src/main/resources/ca/uhn/hapi/fhir/changelog/4_3_0/1778-avoid-crash-encoding-contained-bundle.yaml @@ -0,0 +1,5 @@ +--- +type: fix +issue: 1778 +title: "When encoding a resource, a crash could occur if the resource had a contained Bundle resource. This + is not commonly done, but there are valid scenarios for doing so." diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java index 3b30dfb70b9..350746625aa 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/JsonParserR4Test.java @@ -789,6 +789,40 @@ public class JsonParserR4Test extends BaseTest { return b; } + /** + * Ensure that a contained bundle doesn't cause a crash + */ + @Test + public void testEncodeContainedBundle() { + String auditEvent = "{\n" + + " \"resourceType\": \"AuditEvent\",\n" + + " \"contained\": [ {\n" + + " \"resourceType\": \"Bundle\",\n" + + " \"id\": \"REASONS\",\n" + + " \"entry\": [ {\n" + + " \"resource\": {\n" + + " \"resourceType\": \"Condition\",\n" + + " \"id\": \"123\"\n" + + " }\n" + + " } ]\n" + + " }, {\n" + + " \"resourceType\": \"MeasureReport\",\n" + + " \"id\": \"MRPT5000602611RD\",\n" + + " \"evaluatedResource\": [ {\n" + + " \"reference\": \"#REASONS\"\n" + + " } ]\n" + + " } ],\n" + + " \"entity\": [ {\n" + + " \"what\": {\n" + + " \"reference\": \"#MRPT5000602611RD\"\n" + + " }\n" + + " } ]\n" + + "}"; + AuditEvent ae = ourCtx.newJsonParser().parseResource(AuditEvent.class, auditEvent); + String auditEventAsString = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(ae); + assertEquals(auditEvent, auditEventAsString); + } + @AfterClass public static void afterClassClearContext() { diff --git a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/XmlParserR4Test.java b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/XmlParserR4Test.java index e109aa84490..536dce99b7e 100644 --- a/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/XmlParserR4Test.java +++ b/hapi-fhir-structures-r4/src/test/java/ca/uhn/fhir/parser/XmlParserR4Test.java @@ -9,6 +9,7 @@ import static org.junit.Assert.assertThat; import ca.uhn.fhir.test.BaseTest; import org.hl7.fhir.instance.model.api.IBaseResource; +import org.hl7.fhir.r4.model.AuditEvent; import org.hl7.fhir.r4.model.Bundle; import org.hl7.fhir.r4.model.Composition; import org.hl7.fhir.r4.model.DocumentReference; @@ -115,5 +116,43 @@ public class XmlParserR4Test extends BaseTest { ourLog.info(encoded); } + /** + * Ensure that a contained bundle doesn't cause a crash + */ + @Test + public void testEncodeContainedBundle() { + String auditEvent = "\n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + " \n" + + ""; + AuditEvent ae = ourCtx.newXmlParser().parseResource(AuditEvent.class, auditEvent); + String auditEventAsString = ourCtx.newXmlParser().setPrettyPrint(true).encodeResourceToString(ae); + assertEquals(auditEvent, auditEventAsString); + } + + }