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 cb177b737d1..f3a3a6a3612 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 @@ -9,9 +9,9 @@ package ca.uhn.fhir.parser; * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at - * + * * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -33,7 +33,6 @@ import ca.uhn.fhir.parser.json.*; import ca.uhn.fhir.parser.json.JsonLikeValue.ScalarType; import ca.uhn.fhir.parser.json.JsonLikeValue.ValueType; import ca.uhn.fhir.rest.api.EncodingEnum; -import ca.uhn.fhir.util.BinaryUtil; import ca.uhn.fhir.util.ElementUtil; import com.google.gson.Gson; import com.google.gson.GsonBuilder; @@ -275,12 +274,12 @@ 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())); } - */ + /* + * 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); @@ -982,7 +981,7 @@ public class JsonParser extends BaseParser implements IJsonLikeParser { for (int i = 0; i < nextArray.size(); i++) { JsonLikeValue nextObject = nextArray.get(i); JsonLikeValue nextAlternate = null; - if (nextAlternateArray != null) { + if (nextAlternateArray != null && nextAlternateArray.size() >= (i + 1)) { nextAlternate = nextAlternateArray.get(i); } parseChildren(theState, theName, nextObject, nextAlternate, theAlternateName, true); @@ -1066,12 +1065,12 @@ public class JsonParser extends BaseParser implements IJsonLikeParser { } } - /* - * This happens if an element has an extension but no actual value. I.e. - * if a resource has a "_status" element but no corresponding "status" - * element. This could be used to handle a null value with an extension - * for example. - */ + /* + * This happens if an element has an extension but no actual value. I.e. + * if a resource has a "_status" element but no corresponding "status" + * element. This could be used to handle a null value with an extension + * for example. + */ if (allUnderscoreNames > handledUnderscoreNames) { for (String alternateName : nextExtObj.keySet()) { if (alternateName.startsWith("_") && alternateName.length() > 1) { 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 64f379f9160..ff91cf607b4 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 @@ -3,13 +3,17 @@ package ca.uhn.fhir.parser; import ca.uhn.fhir.context.FhirContext; import ca.uhn.fhir.util.TestUtil; import com.google.common.collect.Sets; +import org.apache.commons.io.IOUtils; import org.hl7.fhir.r4.model.Bundle; +import org.hl7.fhir.r4.model.Extension; import org.hl7.fhir.r4.model.Patient; +import org.hl7.fhir.r4.model.StringType; import org.junit.AfterClass; import org.junit.Test; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import java.io.IOException; import java.util.HashSet; import java.util.Set; @@ -21,6 +25,19 @@ public class JsonParserR4Test { private static final Logger ourLog = LoggerFactory.getLogger(JsonParserR4Test.class); private static FhirContext ourCtx = FhirContext.forR4(); + @Test + public void testParseExtensionOnPrimitive() throws IOException { + String input = IOUtils.toString(JsonParserR4Test.class.getResourceAsStream("/extension-on-line.txt")); + IParser parser = ourCtx.newJsonParser().setPrettyPrint(true); + Patient pt = parser.parseResource(Patient.class, input); + + StringType line0 = pt.getAddressFirstRep().getLine().get(0); + assertEquals("535 Sheppard Avenue West, Unit 1907", line0.getValue()); + Extension houseNumberExt = line0.getExtensionByUrl("http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-houseNumber"); + assertEquals("535", ((StringType)houseNumberExt.getValue()).getValue()); + + } + @Test public void testExcludeNothing() { IParser parser = ourCtx.newJsonParser().setPrettyPrint(true); diff --git a/hapi-fhir-structures-r4/src/test/resources/extension-on-line.txt b/hapi-fhir-structures-r4/src/test/resources/extension-on-line.txt new file mode 100644 index 00000000000..13c6990b92f --- /dev/null +++ b/hapi-fhir-structures-r4/src/test/resources/extension-on-line.txt @@ -0,0 +1,58 @@ +{ + "resourceType": "Patient", + "name": [ + { + "family": "Doe", + "given": [ + "John", + "W." + ] + } + ], + "gender": "male", + "birthDate": "2012-02-14", + "address": [ + { + "use": "home", + "line": [ + "535 Sheppard Avenue West, Unit 1907", + "RR 66, Station A, RPO 123" + ], + "_line": [ + { + "extension": [ + { + "url": "http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-houseNumber", + "valueString": "535" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-streetName", + "valueString": "Sheppard" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-streetNameType", + "valueString": "Avenue" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-direction", + "valueString": "West" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-unitID", + "valueString": "1907" + }, + { + "url": "http://hl7.org/fhir/StructureDefinition/iso21090-ADXP-postBox", + "valueString": "1234" + } + ] + } + ], + "city": "Toronto", + "state": "ON", + "postalCode": "M3H4X8" + } + ] +} + + diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 63e2a47fe9f..90b87f2abdd 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -6,6 +6,15 @@ HAPI FHIR Changelog + + + Fix a crash in the JSON parser when parsing extensions on repeatable + elements (e.g. Patient.address.line) where there is an extension on the + first repetion but not on subsequent repetitions of the + repeatable primitive. Thanks to Igor Sirkovich for providing a + test case! + + Support for custom search parameters has been backported in the JPA server