parent
371cda280a
commit
5f88d87027
|
@ -1290,10 +1290,22 @@ class ParserState<T> {
|
|||
ParseLocation location = ParseLocation.fromElementName(myChildName);
|
||||
myErrorHandler.invalidValue(location, value, "Attribute value must not be empty (\"\")");
|
||||
} else {
|
||||
|
||||
/*
|
||||
* It may be possible to clean this up somewhat once the following PR is hopefully merged:
|
||||
* https://github.com/FasterXML/jackson-core/pull/611
|
||||
*
|
||||
* See TolerantJsonParser
|
||||
*/
|
||||
if ("decimal".equals(myTypeName)) {
|
||||
if (value != null && value.startsWith(".") && NumberUtils.isDigits(value.substring(1))) {
|
||||
value = "0" + value;
|
||||
}
|
||||
if (value != null)
|
||||
if (value.startsWith(".") && NumberUtils.isDigits(value.substring(1))) {
|
||||
value = "0" + value;
|
||||
} else {
|
||||
while (value.startsWith("00")) {
|
||||
value = value.substring(1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
|
@ -1324,17 +1336,6 @@ class ParserState<T> {
|
|||
pop();
|
||||
}
|
||||
|
||||
// @Override
|
||||
// public void enteringNewElementExtension(StartElement theElement,
|
||||
// String theUrlAttr) {
|
||||
// if (myInstance instanceof ISupportsUndeclaredExtensions) {
|
||||
// UndeclaredExtension ext = new UndeclaredExtension(theUrlAttr);
|
||||
// ((ISupportsUndeclaredExtensions)
|
||||
// myInstance).getUndeclaredExtensions().add(ext);
|
||||
// push(new ExtensionState(ext));
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void enteringNewElement(String theNamespaceUri, String theLocalPart) throws DataFormatException {
|
||||
super.enteringNewElement(theNamespaceUri, theLocalPart);
|
||||
|
|
|
@ -2,5 +2,6 @@
|
|||
type: fix
|
||||
issue: 1801
|
||||
title: "In previous versions of HAPI FHIR, the server incorrectly silently accepted decimal numbers in JSON with no
|
||||
leading numbers (e.g. `.123`). These will now be rejected by the JSON parser. Any values with this string that
|
||||
have previously been stored in the JPA server database will now automatically convert the value to `0.123`."
|
||||
leading numbers (e.g. `.123`), as well as decimal numbers with more than one leading zero (e.g. 00.123). These will
|
||||
now be rejected by the JSON parser. Any values with this string that have previously been stored in the JPA server
|
||||
database will now automatically normalize the value to `0.123`."
|
||||
|
|
|
@ -25,17 +25,19 @@ import ca.uhn.fhir.parser.DataFormatException;
|
|||
import ca.uhn.fhir.parser.IParserErrorHandler;
|
||||
import ca.uhn.fhir.parser.JsonParser;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
|
||||
class TolerantJsonParser extends JsonParser {
|
||||
|
||||
private static final Logger ourLog = LoggerFactory.getLogger(TolerantJsonParser.class);
|
||||
|
||||
TolerantJsonParser(FhirContext theContext, IParserErrorHandler theParserErrorHandler) {
|
||||
super(theContext, theParserErrorHandler);
|
||||
}
|
||||
|
@ -45,31 +47,33 @@ class TolerantJsonParser extends JsonParser {
|
|||
try {
|
||||
return super.parseResource(theResourceType, theMessageString);
|
||||
} catch (DataFormatException e) {
|
||||
if (defaultString(e.getMessage()).contains("Unexpected character ('.' (code 46))")) {
|
||||
|
||||
/*
|
||||
* The following is a hacky and gross workaround until the following PR is hopefully merged:
|
||||
* https://github.com/FasterXML/jackson-core/pull/611
|
||||
*
|
||||
* The issue this solves is that under Gson it was possible to store JSON containing
|
||||
* decimal numbers with no leading integer, e.g. .123
|
||||
*
|
||||
* These don't parse in Jackson, meaning we can be stuck with data in the database
|
||||
* that can't be loaded back out.
|
||||
*
|
||||
* Note that if we fix this in the future to rely on Jackson natively handing this
|
||||
* nicely we may or may not be able to remove some code from
|
||||
* ParserState.Primitive state too.
|
||||
*/
|
||||
/*
|
||||
* The following is a hacky and gross workaround until the following PR is hopefully merged:
|
||||
* https://github.com/FasterXML/jackson-core/pull/611
|
||||
*
|
||||
* The issue this solves is that under Gson it was possible to store JSON containing
|
||||
* decimal numbers with no leading integer (e.g. .123) and numbers with double leading
|
||||
* zeros (e.g. 000.123).
|
||||
*
|
||||
* These don't parse in Jackson (which is valid behaviour, these aren't ok according to the
|
||||
* JSON spec), meaning we can be stuck with data in the database that can't be loaded back out.
|
||||
*
|
||||
* Note that if we fix this in the future to rely on Jackson natively handing this
|
||||
* nicely we may or may not be able to remove some code from
|
||||
* ParserState.Primitive state too.
|
||||
*/
|
||||
|
||||
String msg = defaultString(e.getMessage());
|
||||
if (msg.contains("Unexpected character ('.' (code 46))") || msg.contains("Invalid numeric value: Leading zeroes not allowed")) {
|
||||
Gson gson = new Gson();
|
||||
|
||||
JsonObject object = gson.fromJson(theMessageString, JsonObject.class);
|
||||
String corrected = gson.toJson(object);
|
||||
|
||||
return super.parseResource(theResourceType, corrected);
|
||||
|
||||
}
|
||||
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -15,7 +15,7 @@ public class TolerantJsonParserR4Test {
|
|||
private FhirContext myFhirContext = FhirContext.forR4();
|
||||
|
||||
@Test
|
||||
public void testParseInvalidNumeric() {
|
||||
public void testParseInvalidNumeric_LeadingDecimal() {
|
||||
String input = "{\n" +
|
||||
"\"resourceType\": \"Observation\",\n" +
|
||||
"\"valueQuantity\": {\n" +
|
||||
|
@ -30,6 +30,22 @@ public class TolerantJsonParserR4Test {
|
|||
assertEquals("0.5", obs.getValueQuantity().getValueElement().getValueAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseInvalidNumeric_LeadingZeros() {
|
||||
String input = "{\n" +
|
||||
"\"resourceType\": \"Observation\",\n" +
|
||||
"\"valueQuantity\": {\n" +
|
||||
" \"value\": 00.5\n" +
|
||||
" }\n" +
|
||||
"}";
|
||||
|
||||
|
||||
TolerantJsonParser parser = new TolerantJsonParser(myFhirContext, new LenientErrorHandler());
|
||||
Observation obs = parser.parseResource(Observation.class, input);
|
||||
|
||||
assertEquals("0.5", obs.getValueQuantity().getValueElement().getValueAsString());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseInvalidNumeric2() {
|
||||
String input = "{\n" +
|
||||
|
|
Loading…
Reference in New Issue