5738: Skip alternate handling if already handled by previous step (#5971)
* 5738: Skip alternate handling if already handled by previous step * Credit for #5738 --------- Co-authored-by: Stefan Lindström <stefan.lindstrom@ehalsomyndigheten.se> Co-authored-by: James Agnew <jamesagnew@gmail.com>
This commit is contained in:
parent
a9815c8857
commit
4ac65da2ee
|
@ -1359,9 +1359,17 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
||||||
String alternateName = keyIter.next();
|
String alternateName = keyIter.next();
|
||||||
if (alternateName.startsWith("_") && alternateName.length() > 1) {
|
if (alternateName.startsWith("_") && alternateName.length() > 1) {
|
||||||
BaseJsonLikeValue nextValue = theObject.get(alternateName);
|
BaseJsonLikeValue nextValue = theObject.get(alternateName);
|
||||||
if (nextValue != null) {
|
|
||||||
if (nextValue.isObject()) {
|
|
||||||
String nextName = alternateName.substring(1);
|
String nextName = alternateName.substring(1);
|
||||||
|
|
||||||
|
if (nextValue != null) {
|
||||||
|
BaseJsonLikeValue nonAlternativeValue = theObject.get(nextName);
|
||||||
|
|
||||||
|
// Only alternate values with no corresponding "normal" value is unhandled from previous step.
|
||||||
|
if (nonAlternativeValue != null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (nextValue.isObject()) {
|
||||||
if (theObject.get(nextName) == null) {
|
if (theObject.get(nextName) == null) {
|
||||||
theState.enteringNewElement(null, nextName);
|
theState.enteringNewElement(null, nextName);
|
||||||
parseAlternates(nextValue, theState, alternateName, alternateName);
|
parseAlternates(nextValue, theState, alternateName, alternateName);
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
---
|
||||||
|
type: fix
|
||||||
|
issue: 5971
|
||||||
|
title: "The JSON Parser failed to parse alternate names (e.g. `_family`) containing extensions if the
|
||||||
|
corresponding regular named element (e.g. `family`) was not present. Thanks to Stefan Lindström for
|
||||||
|
the pull request!"
|
|
@ -46,6 +46,7 @@ import org.hl7.fhir.dstu2016may.model.Observation;
|
||||||
import org.hl7.fhir.dstu2016may.model.Observation.ObservationStatus;
|
import org.hl7.fhir.dstu2016may.model.Observation.ObservationStatus;
|
||||||
import org.hl7.fhir.dstu2016may.model.Parameters;
|
import org.hl7.fhir.dstu2016may.model.Parameters;
|
||||||
import org.hl7.fhir.dstu2016may.model.Patient;
|
import org.hl7.fhir.dstu2016may.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu2016may.model.Practitioner;
|
||||||
import org.hl7.fhir.dstu2016may.model.PrimitiveType;
|
import org.hl7.fhir.dstu2016may.model.PrimitiveType;
|
||||||
import org.hl7.fhir.dstu2016may.model.Quantity;
|
import org.hl7.fhir.dstu2016may.model.Quantity;
|
||||||
import org.hl7.fhir.dstu2016may.model.QuestionnaireResponse;
|
import org.hl7.fhir.dstu2016may.model.QuestionnaireResponse;
|
||||||
|
@ -55,6 +56,7 @@ import org.hl7.fhir.dstu2016may.model.SimpleQuantity;
|
||||||
import org.hl7.fhir.dstu2016may.model.StringType;
|
import org.hl7.fhir.dstu2016may.model.StringType;
|
||||||
import org.hl7.fhir.dstu2016may.model.UriType;
|
import org.hl7.fhir.dstu2016may.model.UriType;
|
||||||
import org.hl7.fhir.dstu2016may.model.ValueSet;
|
import org.hl7.fhir.dstu2016may.model.ValueSet;
|
||||||
|
import org.hl7.fhir.dstu2016may.model.codesystems.DataAbsentReason;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
@ -63,7 +65,6 @@ import org.junit.jupiter.api.Test;
|
||||||
import org.mockito.ArgumentCaptor;
|
import org.mockito.ArgumentCaptor;
|
||||||
|
|
||||||
import java.math.BigDecimal;
|
import java.math.BigDecimal;
|
||||||
import java.nio.charset.StandardCharsets;
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
|
@ -78,6 +79,7 @@ import static org.hamcrest.Matchers.empty;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
@ -1901,6 +1903,40 @@ public class JsonParserDstu2_1Test {
|
||||||
assertEquals(expectedJson, patientString);
|
assertEquals(expectedJson, patientString);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testObjectWithBothPrimitiverAndArrayAlternatives() {
|
||||||
|
String resource = "{\n" +
|
||||||
|
" \"resourceType\": \"Practitioner\",\n" +
|
||||||
|
" \"id\": \"1\",\n" +
|
||||||
|
" \"name\": [{\n" +
|
||||||
|
" \"_family\": {\n" +
|
||||||
|
" \"extension\": [{\n" +
|
||||||
|
" \"url\": \"http://hl7.org/fhir/StructureDefinition/data-absent-reason\",\n" +
|
||||||
|
" \"valueString\": \"masked\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"given\": [\n" +
|
||||||
|
" null\n" +
|
||||||
|
" ],\n" +
|
||||||
|
" \"_given\": [{\n" +
|
||||||
|
" \"extension\": [{\n" +
|
||||||
|
" \"url\": \"http://hl7.org/fhir/StructureDefinition/data-absent-reason\",\n" +
|
||||||
|
" \"valueString\": \"masked\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
"}\n";
|
||||||
|
Practitioner practitioner = assertDoesNotThrow(() -> ourCtx.newJsonParser().parseResource(Practitioner.class, resource));
|
||||||
|
HumanName humanName = practitioner.getName().get(0);
|
||||||
|
StringType given = humanName.getGiven().get(0);
|
||||||
|
assertTrue(given.getExtension().stream().allMatch(ext -> DataAbsentReason.MASKED.toCode().equals(ext.getValue().primitiveValue())));
|
||||||
|
assertTrue(humanName.getFamily().get(0).getExtension().stream().allMatch(ext -> DataAbsentReason.MASKED.toCode().equals(ext.getValue().primitiveValue())));
|
||||||
|
}
|
||||||
|
|
||||||
@AfterAll
|
@AfterAll
|
||||||
public static void afterClassClearContext() {
|
public static void afterClassClearContext() {
|
||||||
TestUtil.randomizeLocaleAndTimezone();
|
TestUtil.randomizeLocaleAndTimezone();
|
||||||
|
|
|
@ -63,6 +63,7 @@ import org.hl7.fhir.dstu3.model.Observation.ObservationStatus;
|
||||||
import org.hl7.fhir.dstu3.model.Organization;
|
import org.hl7.fhir.dstu3.model.Organization;
|
||||||
import org.hl7.fhir.dstu3.model.Parameters;
|
import org.hl7.fhir.dstu3.model.Parameters;
|
||||||
import org.hl7.fhir.dstu3.model.Patient;
|
import org.hl7.fhir.dstu3.model.Patient;
|
||||||
|
import org.hl7.fhir.dstu3.model.Practitioner;
|
||||||
import org.hl7.fhir.dstu3.model.PrimitiveType;
|
import org.hl7.fhir.dstu3.model.PrimitiveType;
|
||||||
import org.hl7.fhir.dstu3.model.Quantity;
|
import org.hl7.fhir.dstu3.model.Quantity;
|
||||||
import org.hl7.fhir.dstu3.model.QuestionnaireResponse;
|
import org.hl7.fhir.dstu3.model.QuestionnaireResponse;
|
||||||
|
@ -74,6 +75,7 @@ import org.hl7.fhir.dstu3.model.SimpleQuantity;
|
||||||
import org.hl7.fhir.dstu3.model.StringType;
|
import org.hl7.fhir.dstu3.model.StringType;
|
||||||
import org.hl7.fhir.dstu3.model.UriType;
|
import org.hl7.fhir.dstu3.model.UriType;
|
||||||
import org.hl7.fhir.dstu3.model.ValueSet;
|
import org.hl7.fhir.dstu3.model.ValueSet;
|
||||||
|
import org.hl7.fhir.dstu3.model.codesystems.DataAbsentReason;
|
||||||
import org.hl7.fhir.instance.model.api.IIdType;
|
import org.hl7.fhir.instance.model.api.IIdType;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
@ -101,6 +103,7 @@ import static org.hamcrest.Matchers.empty;
|
||||||
import static org.hamcrest.Matchers.is;
|
import static org.hamcrest.Matchers.is;
|
||||||
import static org.hamcrest.Matchers.not;
|
import static org.hamcrest.Matchers.not;
|
||||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
|
@ -2548,6 +2551,41 @@ public class JsonParserDstu3Test {
|
||||||
assertThat(patientString, is(not(containsString("fhir_comment"))));
|
assertThat(patientString, is(not(containsString("fhir_comment"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testObjectWithBothPrimitiverAndArrayAlternatives() {
|
||||||
|
String resource = "{\n" +
|
||||||
|
" \"resourceType\": \"Practitioner\",\n" +
|
||||||
|
" \"id\": \"1\",\n" +
|
||||||
|
" \"name\": [{\n" +
|
||||||
|
" \"_family\": {\n" +
|
||||||
|
" \"extension\": [{\n" +
|
||||||
|
" \"url\": \"http://hl7.org/fhir/StructureDefinition/data-absent-reason\",\n" +
|
||||||
|
" \"valueString\": \"masked\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"given\": [\n" +
|
||||||
|
" null\n" +
|
||||||
|
" ],\n" +
|
||||||
|
" \"_given\": [{\n" +
|
||||||
|
" \"extension\": [{\n" +
|
||||||
|
" \"url\": \"http://hl7.org/fhir/StructureDefinition/data-absent-reason\",\n" +
|
||||||
|
" \"valueString\": \"masked\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
"}\n";
|
||||||
|
Practitioner practitioner = assertDoesNotThrow(() -> ourCtx.newJsonParser().parseResource(Practitioner.class, resource));
|
||||||
|
HumanName humanName = practitioner.getName().get(0);
|
||||||
|
StringType given = humanName.getGiven().get(0);
|
||||||
|
assertTrue(given.getExtension().stream().allMatch(ext -> DataAbsentReason.MASKED.toCode().equals(ext.getValue().primitiveValue())));
|
||||||
|
assertTrue(humanName.getFamilyElement().getExtension().stream().allMatch(ext -> DataAbsentReason.MASKED.toCode().equals(ext.getValue().primitiveValue())));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@AfterAll
|
@AfterAll
|
||||||
public static void afterClassClearContext() {
|
public static void afterClassClearContext() {
|
||||||
TestUtil.randomizeLocaleAndTimezone();
|
TestUtil.randomizeLocaleAndTimezone();
|
||||||
|
|
|
@ -45,6 +45,7 @@ import org.hl7.fhir.r4.model.QuestionnaireResponse;
|
||||||
import org.hl7.fhir.r4.model.Reference;
|
import org.hl7.fhir.r4.model.Reference;
|
||||||
import org.hl7.fhir.r4.model.StringType;
|
import org.hl7.fhir.r4.model.StringType;
|
||||||
import org.hl7.fhir.r4.model.Type;
|
import org.hl7.fhir.r4.model.Type;
|
||||||
|
import org.hl7.fhir.r4.model.codesystems.DataAbsentReason;
|
||||||
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
import org.hl7.fhir.utilities.xhtml.XhtmlNode;
|
||||||
import org.junit.jupiter.api.AfterAll;
|
import org.junit.jupiter.api.AfterAll;
|
||||||
import org.junit.jupiter.api.AfterEach;
|
import org.junit.jupiter.api.AfterEach;
|
||||||
|
@ -73,6 +74,7 @@ import static org.hamcrest.Matchers.is;
|
||||||
import static org.hamcrest.Matchers.notNullValue;
|
import static org.hamcrest.Matchers.notNullValue;
|
||||||
import static org.hamcrest.Matchers.stringContainsInOrder;
|
import static org.hamcrest.Matchers.stringContainsInOrder;
|
||||||
import static org.hamcrest.core.IsNot.not;
|
import static org.hamcrest.core.IsNot.not;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
|
||||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertFalse;
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
|
@ -1190,6 +1192,40 @@ public class JsonParserR4Test extends BaseTest {
|
||||||
assertEquals(expected, actual);
|
assertEquals(expected, actual);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
public void testObjectWithBothPrimitiverAndArrayAlternatives() {
|
||||||
|
String resource = "{\n" +
|
||||||
|
" \"resourceType\": \"Practitioner\",\n" +
|
||||||
|
" \"id\": \"1\",\n" +
|
||||||
|
" \"name\": [{\n" +
|
||||||
|
" \"_family\": {\n" +
|
||||||
|
" \"extension\": [{\n" +
|
||||||
|
" \"url\": \"http://hl7.org/fhir/StructureDefinition/data-absent-reason\",\n" +
|
||||||
|
" \"valueString\": \"masked\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" },\n" +
|
||||||
|
" \"given\": [\n" +
|
||||||
|
" null\n" +
|
||||||
|
" ],\n" +
|
||||||
|
" \"_given\": [{\n" +
|
||||||
|
" \"extension\": [{\n" +
|
||||||
|
" \"url\": \"http://hl7.org/fhir/StructureDefinition/data-absent-reason\",\n" +
|
||||||
|
" \"valueString\": \"masked\"\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
" }\n" +
|
||||||
|
" ]\n" +
|
||||||
|
"}\n";
|
||||||
|
Practitioner practitioner = assertDoesNotThrow(() -> ourCtx.newJsonParser().parseResource(Practitioner.class, resource));
|
||||||
|
HumanName humanName = practitioner.getNameFirstRep();
|
||||||
|
StringType given = humanName.getGiven().get(0);
|
||||||
|
assertTrue(given.getExtension().stream().allMatch(ext -> DataAbsentReason.MASKED.toCode().equals(ext.getValue().primitiveValue())));
|
||||||
|
assertTrue(humanName.getFamilyElement().getExtension().stream().allMatch(ext -> DataAbsentReason.MASKED.toCode().equals(ext.getValue().primitiveValue())));
|
||||||
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testEncodeToString_GeneralPurposeDataType() {
|
public void testEncodeToString_GeneralPurposeDataType() {
|
||||||
HumanName name = new HumanName();
|
HumanName name = new HumanName();
|
||||||
|
|
5
pom.xml
5
pom.xml
|
@ -917,6 +917,11 @@
|
||||||
<id>subigre</id>
|
<id>subigre</id>
|
||||||
<name>Renaud Subiger</name>
|
<name>Renaud Subiger</name>
|
||||||
</developer>
|
</developer>
|
||||||
|
<developer>
|
||||||
|
<id>stefan-lindstrom</id>
|
||||||
|
<name>Stefan Lindström</name>
|
||||||
|
<organization>Softhouse AB</organization>
|
||||||
|
</developer>
|
||||||
</developers>
|
</developers>
|
||||||
|
|
||||||
<licenses>
|
<licenses>
|
||||||
|
|
Loading…
Reference in New Issue