Implement Jackson parser/serializer (#1733)
* [dev] Integration of a Jackson serializer and deserializer - first stage * [fix] Fixed some serializing issues [improve] Improved the processing, removed the loggers * [clean] Removed the JacksonSerializer class, replaced all the Gson classes with Jackson classes * [clean] Small cleanup * [improve] Throw a ConfigurationException if the JsonGenerator cannot be created * [improve] Use the ObjectMapper's `readTree` instead of `readValue` * [dev] Latest fixes and improvements * [dev] Use the Jackson serializer * [clean] Removed the ObjectMapper configuration, for now * [fix] Use the GsonStructure also for the parsing of a FHIR resource * [clean] Removed the LinkedList usage * Work on preparing for merge of #1673 * Resolve build errors * Work on parser integration * Tests passing * Resolve fixme * CLeanup * Fix dependency Co-authored-by: Bogdan Solga <bogdan.solga@gmail.com>
This commit is contained in:
parent
4583cb9939
commit
bde7c356fe
|
@ -20,8 +20,8 @@
|
|||
|
||||
<!-- JSON -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<groupId>com.fasterxml.jackson.core</groupId>
|
||||
<artifactId>jackson-databind</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!-- XML -->
|
||||
|
|
|
@ -22,20 +22,29 @@ package ca.uhn.fhir.parser;
|
|||
|
||||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum;
|
||||
import ca.uhn.fhir.model.api.*;
|
||||
import ca.uhn.fhir.model.api.ExtensionDt;
|
||||
import ca.uhn.fhir.model.api.IPrimitiveDatatype;
|
||||
import ca.uhn.fhir.model.api.IResource;
|
||||
import ca.uhn.fhir.model.api.ISupportsUndeclaredExtensions;
|
||||
import ca.uhn.fhir.model.api.ResourceMetadataKeyEnum;
|
||||
import ca.uhn.fhir.model.api.Tag;
|
||||
import ca.uhn.fhir.model.api.TagList;
|
||||
import ca.uhn.fhir.model.api.annotation.Child;
|
||||
import ca.uhn.fhir.model.base.composite.BaseCodingDt;
|
||||
import ca.uhn.fhir.model.base.composite.BaseContainedDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.InstantDt;
|
||||
import ca.uhn.fhir.narrative.INarrativeGenerator;
|
||||
import ca.uhn.fhir.parser.json.*;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeArray;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeObject;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeStructure;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeValue;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeValue.ScalarType;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeValue.ValueType;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeWriter;
|
||||
import ca.uhn.fhir.parser.json.jackson.JacksonStructure;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.util.ElementUtil;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
import org.apache.commons.text.WordUtils;
|
||||
|
@ -45,11 +54,17 @@ import java.io.IOException;
|
|||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum.ID_DATATYPE;
|
||||
import static ca.uhn.fhir.context.BaseRuntimeElementDefinition.ChildTypeEnum.PRIMITIVE_DATATYPE;
|
||||
import static org.apache.commons.lang3.StringUtils.*;
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
/**
|
||||
* This class is the FHIR JSON parser/encoder. Users should not interact with this class directly, but should use
|
||||
|
@ -147,10 +162,9 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
|||
theEventWriter.beginObject(arrayName);
|
||||
}
|
||||
|
||||
private JsonLikeWriter createJsonWriter(Writer theWriter) {
|
||||
JsonLikeStructure jsonStructure = new GsonStructure();
|
||||
JsonLikeWriter retVal = jsonStructure.getJsonLikeWriter(theWriter);
|
||||
return retVal;
|
||||
private JsonLikeWriter createJsonWriter(Writer theWriter) throws IOException {
|
||||
JsonLikeStructure jsonStructure = new JacksonStructure();
|
||||
return jsonStructure.getJsonLikeWriter(theWriter);
|
||||
}
|
||||
|
||||
public void doEncodeResourceToJsonLikeWriter(IBaseResource theResource, JsonLikeWriter theEventWriter, EncodeContext theEncodeContext) throws IOException {
|
||||
|
@ -168,11 +182,12 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
|||
protected void doEncodeResourceToWriter(IBaseResource theResource, Writer theWriter, EncodeContext theEncodeContext) throws IOException {
|
||||
JsonLikeWriter eventWriter = createJsonWriter(theWriter);
|
||||
doEncodeResourceToJsonLikeWriter(theResource, eventWriter, theEncodeContext);
|
||||
eventWriter.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T extends IBaseResource> T doParseResource(Class<T> theResourceType, Reader theReader) {
|
||||
JsonLikeStructure jsonStructure = new GsonStructure();
|
||||
JsonLikeStructure jsonStructure = new JacksonStructure();
|
||||
jsonStructure.load(theReader);
|
||||
|
||||
T retVal = doParseResource(theResourceType, jsonStructure);
|
||||
|
@ -418,10 +433,10 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
|||
String currentChildName = null;
|
||||
boolean inArray = false;
|
||||
|
||||
ArrayList<ArrayList<HeldExtension>> extensions = new ArrayList<ArrayList<HeldExtension>>(0);
|
||||
ArrayList<ArrayList<HeldExtension>> modifierExtensions = new ArrayList<ArrayList<HeldExtension>>(0);
|
||||
ArrayList<ArrayList<String>> comments = new ArrayList<ArrayList<String>>(0);
|
||||
ArrayList<String> ids = new ArrayList<String>(0);
|
||||
ArrayList<ArrayList<HeldExtension>> extensions = new ArrayList<>(0);
|
||||
ArrayList<ArrayList<HeldExtension>> modifierExtensions = new ArrayList<>(0);
|
||||
ArrayList<ArrayList<String>> comments = new ArrayList<>(0);
|
||||
ArrayList<String> ids = new ArrayList<>(0);
|
||||
|
||||
int valueIdx = 0;
|
||||
for (IBase nextValue : values) {
|
||||
|
@ -1107,7 +1122,8 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
|||
} else {
|
||||
// must be a SCALAR
|
||||
theState.enteringNewElement(null, theName);
|
||||
theState.attributeValue("value", theJsonVal.getAsString());
|
||||
String asString = theJsonVal.getAsString();
|
||||
theState.attributeValue("value", asString);
|
||||
parseAlternates(theAlternateVal, theState, theAlternateName, theAlternateName);
|
||||
theState.endingElement();
|
||||
}
|
||||
|
@ -1376,11 +1392,6 @@ public class JsonParser extends BaseParser implements IJsonLikeParser {
|
|||
}
|
||||
}
|
||||
|
||||
public static Gson newGson() {
|
||||
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
return gson;
|
||||
}
|
||||
|
||||
private static void write(JsonLikeWriter theWriter, String theName, String theValue) throws IOException {
|
||||
theWriter.write(theName, theValue);
|
||||
}
|
||||
|
|
|
@ -1,379 +0,0 @@
|
|||
package ca.uhn.fhir.parser.json;
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2020 University Health Network
|
||||
* %%
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.PushbackReader;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
public class GsonStructure implements JsonLikeStructure {
|
||||
|
||||
private enum ROOT_TYPE {OBJECT, ARRAY};
|
||||
private ROOT_TYPE rootType = null;
|
||||
private JsonElement nativeRoot = null;
|
||||
private JsonLikeValue jsonLikeRoot = null;
|
||||
private GsonWriter jsonLikeWriter = null;
|
||||
|
||||
public GsonStructure() {
|
||||
super();
|
||||
}
|
||||
|
||||
public void setNativeObject (JsonObject json) {
|
||||
this.rootType = ROOT_TYPE.OBJECT;
|
||||
this.nativeRoot = json;
|
||||
}
|
||||
public void setNativeArray (JsonArray json) {
|
||||
this.rootType = ROOT_TYPE.ARRAY;
|
||||
this.nativeRoot = json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeStructure getInstance() {
|
||||
return new GsonStructure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Reader theReader) throws DataFormatException {
|
||||
this.load(theReader, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Reader theReader, boolean allowArray) throws DataFormatException {
|
||||
PushbackReader pbr = new PushbackReader(theReader);
|
||||
int nextInt;
|
||||
try {
|
||||
while(true) {
|
||||
nextInt = pbr.read();
|
||||
if (nextInt == -1) {
|
||||
throw new DataFormatException("Did not find any content to parse");
|
||||
}
|
||||
if (nextInt == '{') {
|
||||
pbr.unread(nextInt);
|
||||
break;
|
||||
}
|
||||
if (Character.isWhitespace(nextInt)) {
|
||||
continue;
|
||||
}
|
||||
if (allowArray) {
|
||||
if (nextInt == '[') {
|
||||
pbr.unread(nextInt);
|
||||
break;
|
||||
}
|
||||
throw new DataFormatException("Content does not appear to be FHIR JSON, first non-whitespace character was: '" + (char)nextInt + "' (must be '{' or '[')");
|
||||
}
|
||||
throw new DataFormatException("Content does not appear to be FHIR JSON, first non-whitespace character was: '" + (char)nextInt + "' (must be '{')");
|
||||
}
|
||||
|
||||
Gson gson = new GsonBuilder().disableHtmlEscaping().create();
|
||||
if (nextInt == '{') {
|
||||
JsonObject root = gson.fromJson(pbr, JsonObject.class);
|
||||
setNativeObject(root);
|
||||
} else if (nextInt == '[') {
|
||||
JsonArray root = gson.fromJson(pbr, JsonArray.class);
|
||||
setNativeArray(root);
|
||||
}
|
||||
} catch (JsonSyntaxException e) {
|
||||
if (e.getMessage().startsWith("Unexpected char 39")) {
|
||||
throw new DataFormatException("Failed to parse JSON encoded FHIR content: " + e.getMessage() + " - This may indicate that single quotes are being used as JSON escapes where double quotes are required", e);
|
||||
}
|
||||
throw new DataFormatException("Failed to parse JSON encoded FHIR content: " + e.getMessage(), e);
|
||||
} catch (Exception e) {
|
||||
throw new DataFormatException("Failed to parse JSON content, error was: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter getJsonLikeWriter (Writer writer) {
|
||||
if (null == jsonLikeWriter) {
|
||||
jsonLikeWriter = new GsonWriter(writer);
|
||||
}
|
||||
return jsonLikeWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter getJsonLikeWriter () {
|
||||
if (null == jsonLikeWriter) {
|
||||
jsonLikeWriter = new GsonWriter();
|
||||
}
|
||||
return jsonLikeWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeObject getRootObject() throws DataFormatException {
|
||||
if (rootType == ROOT_TYPE.OBJECT) {
|
||||
if (null == jsonLikeRoot) {
|
||||
jsonLikeRoot = new GsonJsonObject((JsonObject)nativeRoot);
|
||||
}
|
||||
return jsonLikeRoot.getAsObject();
|
||||
}
|
||||
throw new DataFormatException("Content must be a valid JSON Object. It must start with '{'.");
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeArray getRootArray() throws DataFormatException {
|
||||
if (rootType == ROOT_TYPE.ARRAY) {
|
||||
if (null == jsonLikeRoot) {
|
||||
jsonLikeRoot = new GsonJsonArray((JsonArray)nativeRoot);
|
||||
}
|
||||
return jsonLikeRoot.getAsArray();
|
||||
}
|
||||
throw new DataFormatException("Content must be a valid JSON Array. It must start with '['.");
|
||||
}
|
||||
|
||||
private static class GsonJsonObject extends JsonLikeObject {
|
||||
private JsonObject nativeObject;
|
||||
private Set<String> keySet = null;
|
||||
private Map<String,JsonLikeValue> jsonLikeMap = new LinkedHashMap<String,JsonLikeValue>();
|
||||
|
||||
public GsonJsonObject (JsonObject json) {
|
||||
this.nativeObject = json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> keySet() {
|
||||
if (null == keySet) {
|
||||
Set<Entry<String, JsonElement>> entrySet = nativeObject.entrySet();
|
||||
keySet = new EntryOrderedSet<String>(entrySet.size());
|
||||
for (Entry<String,?> entry : entrySet) {
|
||||
keySet.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
return keySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeValue get(String key) {
|
||||
JsonLikeValue result = null;
|
||||
if (jsonLikeMap.containsKey(key)) {
|
||||
result = jsonLikeMap.get(key);
|
||||
} else {
|
||||
JsonElement child = nativeObject.get(key);
|
||||
if (child != null) {
|
||||
result = new GsonJsonValue(child);
|
||||
}
|
||||
jsonLikeMap.put(key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static class GsonJsonArray extends JsonLikeArray {
|
||||
private JsonArray nativeArray;
|
||||
private Map<Integer,JsonLikeValue> jsonLikeMap = new LinkedHashMap<Integer,JsonLikeValue>();
|
||||
|
||||
public GsonJsonArray (JsonArray json) {
|
||||
this.nativeArray = json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return nativeArray.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeValue get(int index) {
|
||||
Integer key = Integer.valueOf(index);
|
||||
JsonLikeValue result = null;
|
||||
if (jsonLikeMap.containsKey(key)) {
|
||||
result = jsonLikeMap.get(key);
|
||||
} else {
|
||||
JsonElement child = nativeArray.get(index);
|
||||
if (child != null) {
|
||||
result = new GsonJsonValue(child);
|
||||
}
|
||||
jsonLikeMap.put(key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static class GsonJsonValue extends JsonLikeValue {
|
||||
private JsonElement nativeValue;
|
||||
private JsonLikeObject jsonLikeObject = null;
|
||||
private JsonLikeArray jsonLikeArray = null;
|
||||
|
||||
public GsonJsonValue (JsonElement json) {
|
||||
this.nativeValue = json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
if (nativeValue != null && nativeValue.isJsonPrimitive()) {
|
||||
if (((JsonPrimitive)nativeValue).isNumber()) {
|
||||
return nativeValue.getAsNumber();
|
||||
}
|
||||
if (((JsonPrimitive)nativeValue).isBoolean()) {
|
||||
return Boolean.valueOf(nativeValue.getAsBoolean());
|
||||
}
|
||||
return nativeValue.getAsString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueType getJsonType() {
|
||||
if (null == nativeValue || nativeValue.isJsonNull()) {
|
||||
return ValueType.NULL;
|
||||
}
|
||||
if (nativeValue.isJsonObject()) {
|
||||
return ValueType.OBJECT;
|
||||
}
|
||||
if (nativeValue.isJsonArray()) {
|
||||
return ValueType.ARRAY;
|
||||
}
|
||||
if (nativeValue.isJsonPrimitive()) {
|
||||
return ValueType.SCALAR;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType getDataType() {
|
||||
if (nativeValue != null && nativeValue.isJsonPrimitive()) {
|
||||
if (((JsonPrimitive)nativeValue).isNumber()) {
|
||||
return ScalarType.NUMBER;
|
||||
}
|
||||
if (((JsonPrimitive)nativeValue).isString()) {
|
||||
return ScalarType.STRING;
|
||||
}
|
||||
if (((JsonPrimitive)nativeValue).isBoolean()) {
|
||||
return ScalarType.BOOLEAN;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeArray getAsArray() {
|
||||
if (nativeValue != null && nativeValue.isJsonArray()) {
|
||||
if (null == jsonLikeArray) {
|
||||
jsonLikeArray = new GsonJsonArray((JsonArray)nativeValue);
|
||||
}
|
||||
}
|
||||
return jsonLikeArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeObject getAsObject() {
|
||||
if (nativeValue != null && nativeValue.isJsonObject()) {
|
||||
if (null == jsonLikeObject) {
|
||||
jsonLikeObject = new GsonJsonObject((JsonObject)nativeValue);
|
||||
}
|
||||
}
|
||||
return jsonLikeObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number getAsNumber() {
|
||||
return nativeValue != null ? nativeValue.getAsNumber() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString() {
|
||||
return nativeValue != null ? nativeValue.getAsString() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAsBoolean() {
|
||||
if (nativeValue != null && nativeValue.isJsonPrimitive() && ((JsonPrimitive)nativeValue).isBoolean()) {
|
||||
return nativeValue.getAsBoolean();
|
||||
}
|
||||
return super.getAsBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
private static class EntryOrderedSet<T> extends AbstractSet<T> {
|
||||
private transient ArrayList<T> data = null;
|
||||
|
||||
public EntryOrderedSet (int initialCapacity) {
|
||||
data = new ArrayList<T>(initialCapacity);
|
||||
}
|
||||
@SuppressWarnings("unused")
|
||||
public EntryOrderedSet () {
|
||||
data = new ArrayList<T>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return data.contains(o);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused") // not really.. just not here
|
||||
public T get(int index) {
|
||||
return data.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T element) {
|
||||
if (data.contains(element)) {
|
||||
return false;
|
||||
}
|
||||
return data.add(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return data.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
data.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return data.iterator();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -1,263 +0,0 @@
|
|||
package ca.uhn.fhir.parser.json;
|
||||
|
||||
/*
|
||||
* #%L
|
||||
* HAPI FHIR - Core Library
|
||||
* %%
|
||||
* Copyright (C) 2014 - 2020 University Health Network
|
||||
* %%
|
||||
* 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.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* #L%
|
||||
*/
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
public class GsonWriter extends JsonLikeWriter {
|
||||
private static final Logger log = LoggerFactory.getLogger(GsonWriter.class);
|
||||
|
||||
private JsonWriter eventWriter;
|
||||
private enum BlockType {
|
||||
NONE, OBJECT, ARRAY
|
||||
}
|
||||
private BlockType blockType = BlockType.NONE;
|
||||
private Stack<BlockType> blockStack = new Stack<BlockType>();
|
||||
|
||||
public GsonWriter () {
|
||||
super();
|
||||
}
|
||||
public GsonWriter (Writer writer) {
|
||||
setWriter(writer);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter init() throws IOException {
|
||||
eventWriter = new JsonWriter(getWriter());
|
||||
eventWriter.setSerializeNulls(true);
|
||||
if (isPrettyPrint()) {
|
||||
eventWriter.setIndent(" ");
|
||||
}
|
||||
blockType = BlockType.NONE;
|
||||
blockStack.clear();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter flush() throws IOException {
|
||||
if (blockType != BlockType.NONE) {
|
||||
log.error("JsonLikeStreamWriter.flush() called but JSON document is not finished");
|
||||
}
|
||||
eventWriter.flush();
|
||||
getWriter().flush();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
eventWriter.close();
|
||||
getWriter().close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter beginObject() throws IOException {
|
||||
blockStack.push(blockType);
|
||||
blockType = BlockType.OBJECT;
|
||||
eventWriter.beginObject();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter beginArray() throws IOException {
|
||||
blockStack.push(blockType);
|
||||
blockType = BlockType.ARRAY;
|
||||
eventWriter.beginArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter beginObject(String name) throws IOException {
|
||||
blockStack.push(blockType);
|
||||
blockType = BlockType.OBJECT;
|
||||
eventWriter.name(name);
|
||||
eventWriter.beginObject();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter beginArray(String name) throws IOException {
|
||||
blockStack.push(blockType);
|
||||
blockType = BlockType.ARRAY;
|
||||
eventWriter.name(name);
|
||||
eventWriter.beginArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String value) throws IOException {
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(BigInteger value) throws IOException {
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(BigDecimal value) throws IOException {
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(long value) throws IOException {
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(double value) throws IOException {
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(Boolean value) throws IOException {
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(boolean value) throws IOException {
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter writeNull() throws IOException {
|
||||
eventWriter.nullValue();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, String value) throws IOException {
|
||||
eventWriter.name(name);
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, BigInteger value) throws IOException {
|
||||
eventWriter.name(name);
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, BigDecimal value) throws IOException {
|
||||
eventWriter.name(name);
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, long value) throws IOException {
|
||||
eventWriter.name(name);
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, double value) throws IOException {
|
||||
eventWriter.name(name);
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, Boolean value) throws IOException {
|
||||
eventWriter.name(name);
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, boolean value) throws IOException {
|
||||
eventWriter.name(name);
|
||||
eventWriter.value(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter writeNull(String name) throws IOException {
|
||||
eventWriter.name(name);
|
||||
eventWriter.nullValue();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter endObject() throws IOException {
|
||||
if (blockType == BlockType.NONE) {
|
||||
log.error("JsonLikeStreamWriter.endObject(); called with no active JSON document");
|
||||
} else {
|
||||
if (blockType != BlockType.OBJECT) {
|
||||
log.error("JsonLikeStreamWriter.endObject(); called outside a JSON object. (Use endArray() instead?)");
|
||||
eventWriter.endArray();
|
||||
} else {
|
||||
eventWriter.endObject();
|
||||
}
|
||||
blockType = blockStack.pop();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter endArray() throws IOException {
|
||||
if (blockType == BlockType.NONE) {
|
||||
log.error("JsonLikeStreamWriter.endArray(); called with no active JSON document");
|
||||
} else {
|
||||
if (blockType != BlockType.ARRAY) {
|
||||
log.error("JsonLikeStreamWriter.endArray(); called outside a JSON array. (Use endObject() instead?)");
|
||||
eventWriter.endObject();
|
||||
} else {
|
||||
eventWriter.endArray();
|
||||
}
|
||||
blockType = blockStack.pop();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter endBlock() throws IOException {
|
||||
if (blockType == BlockType.NONE) {
|
||||
log.error("JsonLikeStreamWriter.endBlock(); called with no active JSON document");
|
||||
} else {
|
||||
if (blockType == BlockType.ARRAY) {
|
||||
eventWriter.endArray();
|
||||
} else {
|
||||
eventWriter.endObject();
|
||||
}
|
||||
blockType = blockStack.pop();
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
|
@ -53,20 +53,4 @@ public abstract class JsonLikeObject extends JsonLikeValue {
|
|||
|
||||
public abstract JsonLikeValue get (String key);
|
||||
|
||||
public String getString (String key) {
|
||||
JsonLikeValue value = this.get(key);
|
||||
if (null == value) {
|
||||
throw new NullPointerException("Json object missing element named \""+key+"\"");
|
||||
}
|
||||
return value.getAsString();
|
||||
}
|
||||
|
||||
public String getString (String key, String defaultValue) {
|
||||
String result = defaultValue;
|
||||
JsonLikeValue value = this.get(key);
|
||||
if (value != null) {
|
||||
result = value.getAsString();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -19,11 +19,12 @@
|
|||
*/
|
||||
package ca.uhn.fhir.parser.json;
|
||||
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
|
||||
/**
|
||||
* This interface is the generic representation of any sort of data
|
||||
* structure that looks and smells like JSON. These data structures
|
||||
|
@ -33,7 +34,7 @@ import ca.uhn.fhir.parser.DataFormatException;
|
|||
* @author Bill.Denton
|
||||
*/
|
||||
public interface JsonLikeStructure {
|
||||
public JsonLikeStructure getInstance();
|
||||
JsonLikeStructure getInstance();
|
||||
|
||||
/**
|
||||
* Parse the JSON document into the Json-like structure
|
||||
|
@ -43,10 +44,13 @@ public interface JsonLikeStructure {
|
|||
* process the JSON input stream
|
||||
* @throws DataFormatException when invalid JSON is received
|
||||
*/
|
||||
public void load (Reader theReader) throws DataFormatException;
|
||||
public void load (Reader theReader, boolean allowArray) throws DataFormatException;
|
||||
public JsonLikeObject getRootObject () throws DataFormatException;
|
||||
public JsonLikeArray getRootArray () throws DataFormatException;
|
||||
public JsonLikeWriter getJsonLikeWriter ();
|
||||
public JsonLikeWriter getJsonLikeWriter (Writer writer);
|
||||
void load(Reader theReader) throws DataFormatException;
|
||||
|
||||
void load(Reader theReader, boolean allowArray) throws DataFormatException;
|
||||
|
||||
JsonLikeObject getRootObject() throws DataFormatException;
|
||||
|
||||
JsonLikeWriter getJsonLikeWriter();
|
||||
|
||||
JsonLikeWriter getJsonLikeWriter(Writer writer) throws IOException;
|
||||
}
|
||||
|
|
|
@ -30,54 +30,72 @@ public abstract class JsonLikeWriter {
|
|||
private boolean prettyPrint;
|
||||
private Writer writer;
|
||||
|
||||
public JsonLikeWriter() {
|
||||
super();
|
||||
}
|
||||
|
||||
public boolean isPrettyPrint() {
|
||||
return prettyPrint;
|
||||
}
|
||||
|
||||
public void setPrettyPrint(boolean tf) {
|
||||
prettyPrint = tf;
|
||||
}
|
||||
public boolean isPrettyPrint () {
|
||||
return prettyPrint;
|
||||
|
||||
public Writer getWriter() {
|
||||
return writer;
|
||||
}
|
||||
|
||||
public void setWriter(Writer writer) {
|
||||
this.writer = writer;
|
||||
}
|
||||
public Writer getWriter () {
|
||||
return writer;
|
||||
}
|
||||
|
||||
public abstract JsonLikeWriter init() throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter flush() throws IOException;
|
||||
|
||||
public abstract void close() throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter beginObject() throws IOException;
|
||||
public abstract JsonLikeWriter beginArray () throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter beginObject(String name) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter beginArray(String name) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(String value) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(BigInteger value) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(BigDecimal value) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(long value) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(double value) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(Boolean value) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(boolean value) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter writeNull() throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(String name, String value) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(String name, BigInteger value) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(String name, BigDecimal value) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(String name, long value) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(String name, double value) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(String name, Boolean value) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter write(String name, boolean value) throws IOException;
|
||||
public abstract JsonLikeWriter writeNull (String name) throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter endObject() throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter endArray() throws IOException;
|
||||
|
||||
public abstract JsonLikeWriter endBlock() throws IOException;
|
||||
|
||||
public JsonLikeWriter() {
|
||||
super();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,372 @@
|
|||
package ca.uhn.fhir.parser.json.jackson;
|
||||
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeArray;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeObject;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeStructure;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeValue;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeWriter;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.databind.DeserializationFeature;
|
||||
import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.node.ArrayNode;
|
||||
import com.fasterxml.jackson.databind.node.DecimalNode;
|
||||
import com.fasterxml.jackson.databind.node.JsonNodeFactory;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import org.apache.jena.tdb.setup.BuilderStdDB;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.PushbackReader;
|
||||
import java.io.Reader;
|
||||
import java.io.Writer;
|
||||
import java.math.BigDecimal;
|
||||
import java.util.AbstractSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.StreamSupport;
|
||||
|
||||
public class JacksonStructure implements JsonLikeStructure {
|
||||
|
||||
private static final ObjectMapper OBJECT_MAPPER = createObjectMapper();
|
||||
private JacksonWriter jacksonWriter;
|
||||
private ROOT_TYPE rootType = null;
|
||||
private JsonNode nativeRoot = null;
|
||||
private JsonNode jsonLikeRoot = null;
|
||||
|
||||
public void setNativeObject(ObjectNode objectNode) {
|
||||
this.rootType = ROOT_TYPE.OBJECT;
|
||||
this.nativeRoot = objectNode;
|
||||
}
|
||||
|
||||
public void setNativeArray(ArrayNode arrayNode) {
|
||||
this.rootType = ROOT_TYPE.ARRAY;
|
||||
this.nativeRoot = arrayNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeStructure getInstance() {
|
||||
return new JacksonStructure();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Reader theReader) throws DataFormatException {
|
||||
this.load(theReader, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(Reader theReader, boolean allowArray) throws DataFormatException {
|
||||
PushbackReader pbr = new PushbackReader(theReader);
|
||||
int nextInt;
|
||||
try {
|
||||
while (true) {
|
||||
nextInt = pbr.read();
|
||||
if (nextInt == -1) {
|
||||
throw new DataFormatException("Did not find any content to parse");
|
||||
}
|
||||
if (nextInt == '{') {
|
||||
pbr.unread(nextInt);
|
||||
break;
|
||||
}
|
||||
if (Character.isWhitespace(nextInt)) {
|
||||
continue;
|
||||
}
|
||||
if (allowArray) {
|
||||
if (nextInt == '[') {
|
||||
pbr.unread(nextInt);
|
||||
break;
|
||||
}
|
||||
throw new DataFormatException("Content does not appear to be FHIR JSON, first non-whitespace character was: '" + (char) nextInt + "' (must be '{' or '[')");
|
||||
}
|
||||
throw new DataFormatException("Content does not appear to be FHIR JSON, first non-whitespace character was: '" + (char) nextInt + "' (must be '{')");
|
||||
}
|
||||
|
||||
if (nextInt == '{') {
|
||||
setNativeObject((ObjectNode) OBJECT_MAPPER.readTree(pbr));
|
||||
} else {
|
||||
setNativeArray((ArrayNode) OBJECT_MAPPER.readTree(pbr));
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if (e.getMessage().startsWith("Unexpected char 39")) {
|
||||
throw new DataFormatException("Failed to parse JSON encoded FHIR content: " + e.getMessage() + " - " +
|
||||
"This may indicate that single quotes are being used as JSON escapes where double quotes are required", e);
|
||||
}
|
||||
throw new DataFormatException("Failed to parse JSON encoded FHIR content: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter getJsonLikeWriter(Writer writer) throws IOException {
|
||||
if (null == jacksonWriter) {
|
||||
jacksonWriter = new JacksonWriter(OBJECT_MAPPER.getFactory(), writer);
|
||||
}
|
||||
|
||||
return jacksonWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter getJsonLikeWriter() {
|
||||
if (null == jacksonWriter) {
|
||||
jacksonWriter = new JacksonWriter();
|
||||
}
|
||||
return jacksonWriter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeObject getRootObject() throws DataFormatException {
|
||||
if (rootType == ROOT_TYPE.OBJECT) {
|
||||
if (null == jsonLikeRoot) {
|
||||
jsonLikeRoot = nativeRoot;
|
||||
}
|
||||
|
||||
return new JacksonJsonObject((ObjectNode) jsonLikeRoot);
|
||||
}
|
||||
|
||||
throw new DataFormatException("Content must be a valid JSON Object. It must start with '{'.");
|
||||
}
|
||||
|
||||
private enum ROOT_TYPE {OBJECT, ARRAY}
|
||||
|
||||
private static class JacksonJsonObject extends JsonLikeObject {
|
||||
private final ObjectNode nativeObject;
|
||||
private final Map<String, JsonLikeValue> jsonLikeMap = new LinkedHashMap<>();
|
||||
private Set<String> keySet = null;
|
||||
|
||||
public JacksonJsonObject(ObjectNode json) {
|
||||
this.nativeObject = json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> keySet() {
|
||||
if (null == keySet) {
|
||||
final Iterable<Map.Entry<String, JsonNode>> iterable = nativeObject::fields;
|
||||
keySet = StreamSupport.stream(iterable.spliterator(), false)
|
||||
.map(Map.Entry::getKey)
|
||||
.collect(Collectors.toCollection(EntryOrderedSet::new));
|
||||
}
|
||||
|
||||
return keySet;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeValue get(String key) {
|
||||
JsonLikeValue result = null;
|
||||
if (jsonLikeMap.containsKey(key)) {
|
||||
result = jsonLikeMap.get(key);
|
||||
} else {
|
||||
JsonNode child = nativeObject.get(key);
|
||||
if (child != null) {
|
||||
result = new JacksonJsonValue(child);
|
||||
}
|
||||
jsonLikeMap.put(key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static class EntryOrderedSet<T> extends AbstractSet<T> {
|
||||
private final transient ArrayList<T> data;
|
||||
|
||||
public EntryOrderedSet() {
|
||||
data = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return data.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean contains(Object o) {
|
||||
return data.contains(o);
|
||||
}
|
||||
|
||||
public T get(int index) {
|
||||
return data.get(index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean add(T element) {
|
||||
if (data.contains(element)) {
|
||||
return false;
|
||||
}
|
||||
return data.add(element);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean remove(Object o) {
|
||||
return data.remove(o);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void clear() {
|
||||
data.clear();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Iterator<T> iterator() {
|
||||
return data.iterator();
|
||||
}
|
||||
}
|
||||
|
||||
private static class JacksonJsonArray extends JsonLikeArray {
|
||||
private final ArrayNode nativeArray;
|
||||
private final Map<Integer, JsonLikeValue> jsonLikeMap = new LinkedHashMap<Integer, JsonLikeValue>();
|
||||
|
||||
public JacksonJsonArray(ArrayNode json) {
|
||||
this.nativeArray = json;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int size() {
|
||||
return nativeArray.size();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeValue get(int index) {
|
||||
Integer key = index;
|
||||
JsonLikeValue result = null;
|
||||
if (jsonLikeMap.containsKey(key)) {
|
||||
result = jsonLikeMap.get(key);
|
||||
} else {
|
||||
JsonNode child = nativeArray.get(index);
|
||||
if (child != null) {
|
||||
result = new JacksonJsonValue(child);
|
||||
}
|
||||
jsonLikeMap.put(key, result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
private static class JacksonJsonValue extends JsonLikeValue {
|
||||
private final JsonNode nativeValue;
|
||||
private JsonLikeObject jsonLikeObject = null;
|
||||
private JsonLikeArray jsonLikeArray = null;
|
||||
|
||||
public JacksonJsonValue(JsonNode jsonNode) {
|
||||
this.nativeValue = jsonNode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getValue() {
|
||||
if (nativeValue != null && nativeValue.isValueNode()) {
|
||||
if (nativeValue.isNumber()) {
|
||||
return nativeValue.numberValue();
|
||||
}
|
||||
|
||||
if (nativeValue.isBoolean()) {
|
||||
return nativeValue.booleanValue();
|
||||
}
|
||||
|
||||
return nativeValue.asText();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ValueType getJsonType() {
|
||||
if (null == nativeValue || nativeValue.isNull()) {
|
||||
return ValueType.NULL;
|
||||
}
|
||||
if (nativeValue.isObject()) {
|
||||
return ValueType.OBJECT;
|
||||
}
|
||||
if (nativeValue.isArray()) {
|
||||
return ValueType.ARRAY;
|
||||
}
|
||||
if (nativeValue.isValueNode()) {
|
||||
return ValueType.SCALAR;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScalarType getDataType() {
|
||||
if (nativeValue != null && nativeValue.isValueNode()) {
|
||||
if (nativeValue.isNumber()) {
|
||||
return ScalarType.NUMBER;
|
||||
}
|
||||
if (nativeValue.isTextual()) {
|
||||
return ScalarType.STRING;
|
||||
}
|
||||
if (nativeValue.isBoolean()) {
|
||||
return ScalarType.BOOLEAN;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeArray getAsArray() {
|
||||
if (nativeValue != null && nativeValue.isArray()) {
|
||||
if (null == jsonLikeArray) {
|
||||
jsonLikeArray = new JacksonJsonArray((ArrayNode) nativeValue);
|
||||
}
|
||||
}
|
||||
return jsonLikeArray;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeObject getAsObject() {
|
||||
if (nativeValue != null && nativeValue.isObject()) {
|
||||
if (null == jsonLikeObject) {
|
||||
jsonLikeObject = new JacksonJsonObject((ObjectNode) nativeValue);
|
||||
}
|
||||
}
|
||||
return jsonLikeObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Number getAsNumber() {
|
||||
return nativeValue != null ? nativeValue.numberValue() : null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getAsString() {
|
||||
if (nativeValue != null) {
|
||||
if (nativeValue instanceof DecimalNode) {
|
||||
BigDecimal value = nativeValue.decimalValue();
|
||||
return value.toPlainString();
|
||||
}
|
||||
return nativeValue.asText();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean getAsBoolean() {
|
||||
if (nativeValue != null && nativeValue.isValueNode() && nativeValue.isBoolean()) {
|
||||
return nativeValue.asBoolean();
|
||||
}
|
||||
return super.getAsBoolean();
|
||||
}
|
||||
}
|
||||
|
||||
private static ObjectMapper createObjectMapper() {
|
||||
ObjectMapper retVal = new ObjectMapper();
|
||||
retVal = retVal.setNodeFactory(new JsonNodeFactory(true));
|
||||
retVal = retVal.enable(DeserializationFeature.USE_BIG_DECIMAL_FOR_FLOATS);
|
||||
retVal = retVal.enable(DeserializationFeature.FAIL_ON_TRAILING_TOKENS);
|
||||
retVal = retVal.disable(JsonParser.Feature.INCLUDE_SOURCE_IN_LOCATION);
|
||||
retVal = retVal.disable(JsonGenerator.Feature.AUTO_CLOSE_TARGET);
|
||||
retVal = retVal.disable(JsonParser.Feature.AUTO_CLOSE_SOURCE);
|
||||
retVal = retVal.configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true);
|
||||
return retVal;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,197 @@
|
|||
package ca.uhn.fhir.parser.json.jackson;
|
||||
|
||||
import ca.uhn.fhir.parser.json.JsonLikeWriter;
|
||||
import com.fasterxml.jackson.core.JsonFactory;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.PrettyPrinter;
|
||||
import com.fasterxml.jackson.core.util.DefaultIndenter;
|
||||
import com.fasterxml.jackson.core.util.DefaultPrettyPrinter;
|
||||
import com.fasterxml.jackson.core.util.Separators;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
|
||||
public class JacksonWriter extends JsonLikeWriter {
|
||||
|
||||
private JsonGenerator myJsonGenerator;
|
||||
|
||||
public JacksonWriter(JsonFactory theJsonFactory, Writer theWriter) throws IOException {
|
||||
myJsonGenerator = theJsonFactory.createGenerator(theWriter);
|
||||
setWriter(theWriter);
|
||||
}
|
||||
|
||||
public JacksonWriter() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter init() {
|
||||
if (isPrettyPrint()) {
|
||||
DefaultPrettyPrinter prettyPrinter = new DefaultPrettyPrinter() {
|
||||
|
||||
/**
|
||||
* Objects should serialize as
|
||||
* <pre>
|
||||
* {
|
||||
* "key": "value"
|
||||
* }
|
||||
* </pre>
|
||||
* in order to be consistent with Gson behaviour, instead of the jackson default
|
||||
* <pre>
|
||||
* {
|
||||
* "key" : "value"
|
||||
* }
|
||||
* </pre>
|
||||
*/
|
||||
@Override
|
||||
public DefaultPrettyPrinter withSeparators(Separators separators) {
|
||||
_separators = separators;
|
||||
_objectFieldValueSeparatorWithSpaces = separators.getObjectFieldValueSeparator() + " ";
|
||||
return this;
|
||||
}
|
||||
|
||||
};
|
||||
prettyPrinter = prettyPrinter.withObjectIndenter(new DefaultIndenter(" ", "\n"));
|
||||
|
||||
myJsonGenerator.setPrettyPrinter(prettyPrinter);
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter flush() {
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
myJsonGenerator.close();
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter beginObject() throws IOException {
|
||||
myJsonGenerator.writeStartObject();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter beginObject(String name) throws IOException {
|
||||
myJsonGenerator.writeObjectFieldStart(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter beginArray(String name) throws IOException {
|
||||
myJsonGenerator.writeArrayFieldStart(name);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String value) throws IOException {
|
||||
myJsonGenerator.writeObject(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(BigInteger value) throws IOException {
|
||||
myJsonGenerator.writeObject(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(BigDecimal value) throws IOException {
|
||||
myJsonGenerator.writeObject(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(long value) throws IOException {
|
||||
myJsonGenerator.writeObject(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(double value) throws IOException {
|
||||
myJsonGenerator.writeObject(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(Boolean value) throws IOException {
|
||||
myJsonGenerator.writeObject(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(boolean value) throws IOException {
|
||||
myJsonGenerator.writeObject(value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter writeNull() throws IOException {
|
||||
myJsonGenerator.writeNull();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, String value) throws IOException {
|
||||
myJsonGenerator.writeObjectField(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, BigInteger value) throws IOException {
|
||||
myJsonGenerator.writeObjectField(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, BigDecimal value) throws IOException {
|
||||
myJsonGenerator.writeObjectField(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, long value) throws IOException {
|
||||
myJsonGenerator.writeObjectField(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, double value) throws IOException {
|
||||
myJsonGenerator.writeObjectField(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, Boolean value) throws IOException {
|
||||
myJsonGenerator.writeObjectField(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter write(String name, boolean value) throws IOException {
|
||||
myJsonGenerator.writeObjectField(name, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter endObject() throws IOException {
|
||||
myJsonGenerator.writeEndObject();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter endArray() throws IOException {
|
||||
myJsonGenerator.writeEndArray();
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter endBlock() throws IOException {
|
||||
myJsonGenerator.writeEndObject();
|
||||
return this;
|
||||
}
|
||||
}
|
|
@ -5,6 +5,7 @@ import static org.junit.Assert.assertNotNull;
|
|||
|
||||
import java.io.StringReader;
|
||||
|
||||
import ca.uhn.fhir.parser.json.jackson.JacksonStructure;
|
||||
import org.junit.Test;
|
||||
|
||||
public class JsonLikeStructureTest {
|
||||
|
@ -39,7 +40,7 @@ public class JsonLikeStructureTest {
|
|||
@Test
|
||||
public void testStructureLoading() {
|
||||
StringReader reader = new StringReader(TEST_STRUCTURELOADING_DATA);
|
||||
JsonLikeStructure jsonStructure = new GsonStructure();
|
||||
JsonLikeStructure jsonStructure = new JacksonStructure();
|
||||
jsonStructure.load(reader);
|
||||
|
||||
JsonLikeObject rootObject = jsonStructure.getRootObject();
|
||||
|
@ -70,7 +71,7 @@ public class JsonLikeStructureTest {
|
|||
@Test
|
||||
public void testJsonAndDataTypes() {
|
||||
StringReader reader = new StringReader(TEST_JSONTYPES_DATA);
|
||||
JsonLikeStructure jsonStructure = new GsonStructure();
|
||||
JsonLikeStructure jsonStructure = new JacksonStructure();
|
||||
jsonStructure.load(reader);
|
||||
|
||||
JsonLikeObject rootObject = jsonStructure.getRootObject();
|
||||
|
|
|
@ -5368,7 +5368,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
@Test
|
||||
public void testValidateJsonWithDuplicateKey() throws IOException {
|
||||
|
||||
String inputStr = "{\"resourceType\":\"Patient\", \"name\":[{\"text\":foo\"}], name:[{\"text\":\"foo\"}] }";
|
||||
String inputStr = "{\"resourceType\":\"Patient\", \"name\":[{\"text\":\"foo\"}], \"name\":[{\"text\":\"foo\"}] }";
|
||||
HttpPost post = new HttpPost(ourServerBase + "/Patient/$validate");
|
||||
post.setEntity(new StringEntity(inputStr, ContentType.create(Constants.CT_FHIR_JSON_NEW, "UTF-8")));
|
||||
|
||||
|
@ -5378,7 +5378,7 @@ public class ResourceProviderR4Test extends BaseResourceProviderR4Test {
|
|||
ourLog.info(resp);
|
||||
assertEquals(412, response.getStatusLine().getStatusCode());
|
||||
|
||||
assertThat(resp, stringContainsInOrder("Error parsing JSON source: Syntax error in json reading special word false at Line 1"));
|
||||
assertThat(resp, stringContainsInOrder("Duplicated property name: name"));
|
||||
} finally {
|
||||
response.getEntity().getContent().close();
|
||||
response.close();
|
||||
|
|
|
@ -1518,13 +1518,13 @@ public class JsonParserDstu2_1Test {
|
|||
ourCtx.newJsonParser().parseResource("FOO");
|
||||
fail();
|
||||
} catch (DataFormatException e) {
|
||||
assertEquals("Failed to parse JSON content, error was: Content does not appear to be FHIR JSON, first non-whitespace character was: 'F' (must be '{')", e.getMessage());
|
||||
assertEquals("Failed to parse JSON encoded FHIR content: Content does not appear to be FHIR JSON, first non-whitespace character was: 'F' (must be '{')", e.getMessage());
|
||||
}
|
||||
try {
|
||||
ourCtx.newJsonParser().parseResource("[\"aaa\"]");
|
||||
fail();
|
||||
} catch (DataFormatException e) {
|
||||
assertEquals("Failed to parse JSON content, error was: Content does not appear to be FHIR JSON, first non-whitespace character was: '[' (must be '{')", e.getMessage());
|
||||
assertEquals("Failed to parse JSON encoded FHIR content: Content does not appear to be FHIR JSON, first non-whitespace character was: '[' (must be '{')", e.getMessage());
|
||||
}
|
||||
|
||||
assertEquals(Bundle.class, ourCtx.newJsonParser().parseResource(" {\"resourceType\" : \"Bundle\"}").getClass());
|
||||
|
|
|
@ -1999,37 +1999,23 @@ public class XmlParserDstu2_1Test {
|
|||
" \"resourceType\": \"Patient\",",
|
||||
" \"id\": \"someid\",",
|
||||
" \"_id\": {",
|
||||
" \"fhir_comments\": [",
|
||||
" \" comment 1 \"",
|
||||
" ]",
|
||||
" \"fhir_comments\": [ \" comment 1 \" ]",
|
||||
" },",
|
||||
" \"extension\": [",
|
||||
" {",
|
||||
" \"fhir_comments\": [",
|
||||
" \" comment 2 \",",
|
||||
" \" comment 7 \"",
|
||||
" ],",
|
||||
" \"extension\": [ {",
|
||||
" \"fhir_comments\": [ \" comment 2 \", \" comment 7 \" ],",
|
||||
" \"url\": \"urn:patientext:att\",",
|
||||
" \"valueAttachment\": {",
|
||||
" \"fhir_comments\": [",
|
||||
" \" comment 3 \",",
|
||||
" \" comment 6 \"",
|
||||
" ],",
|
||||
" \"fhir_comments\": [ \" comment 3 \", \" comment 6 \" ],",
|
||||
" \"contentType\": \"aaaa\",",
|
||||
" \"_contentType\": {",
|
||||
" \"fhir_comments\": [",
|
||||
" \" comment 4 \"",
|
||||
" ]",
|
||||
" \"fhir_comments\": [ \" comment 4 \" ]",
|
||||
" },",
|
||||
" \"data\": \"AAAA\",",
|
||||
" \"_data\": {",
|
||||
" \"fhir_comments\": [",
|
||||
" \" comment 5 \"",
|
||||
" ]",
|
||||
" \"fhir_comments\": [ \" comment 5 \" ]",
|
||||
" }",
|
||||
" }",
|
||||
" }",
|
||||
" ]",
|
||||
" } ]",
|
||||
"}"
|
||||
));
|
||||
|
||||
|
|
|
@ -498,37 +498,28 @@ public class JsonParserDstu2Test {
|
|||
String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
|
||||
ourLog.info(enc);
|
||||
|
||||
//@formatter:off
|
||||
String actual = enc.trim();
|
||||
ourLog.info("Actual:\n{}", actual);
|
||||
|
||||
assertEquals("{\n" +
|
||||
" \"resourceType\": \"Patient\",\n" +
|
||||
" \"meta\": {\n" +
|
||||
" \"security\": [\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"SYSTEM1\",\n" +
|
||||
" \"version\": \"VERSION1\",\n" +
|
||||
" \"code\": \"CODE1\",\n" +
|
||||
" \"display\": \"DISPLAY1\"\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"SYSTEM2\",\n" +
|
||||
" \"version\": \"VERSION2\",\n" +
|
||||
" \"code\": \"CODE2\",\n" +
|
||||
" \"display\": \"DISPLAY2\"\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
" },\n" +
|
||||
" \"name\": [\n" +
|
||||
" {\n" +
|
||||
" \"family\": [\n" +
|
||||
" \"FAMILY\"\n" +
|
||||
" ]\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
"}", actual);
|
||||
//@formatter:on
|
||||
assertThat(actual, stringContainsInOrder("{",
|
||||
" \"resourceType\": \"Patient\",",
|
||||
" \"meta\": {",
|
||||
" \"security\": [ {",
|
||||
" \"system\": \"SYSTEM1\",",
|
||||
" \"version\": \"VERSION1\",",
|
||||
" \"code\": \"CODE1\",",
|
||||
" \"display\": \"DISPLAY1\"",
|
||||
" }, {",
|
||||
" \"system\": \"SYSTEM2\",",
|
||||
" \"version\": \"VERSION2\",",
|
||||
" \"code\": \"CODE2\",",
|
||||
" \"display\": \"DISPLAY2\"",
|
||||
" } ]",
|
||||
" },",
|
||||
" \"name\": [ {",
|
||||
" \"family\": [ \"FAMILY\" ]",
|
||||
" } ]",
|
||||
"}"));
|
||||
|
||||
Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, enc);
|
||||
List<BaseCodingDt> gotLabels = ResourceMetadataKeyEnum.SECURITY_LABELS.get(parsed);
|
||||
|
|
|
@ -1,16 +1,15 @@
|
|||
package ca.uhn.fhir.parser.jsonlike;
|
||||
|
||||
import java.io.StringReader;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.parser.IJsonLikeParser;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeStructure;
|
||||
import ca.uhn.fhir.parser.json.jackson.JacksonStructure;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.parser.IJsonLikeParser;
|
||||
import ca.uhn.fhir.parser.json.GsonStructure;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeStructure;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import java.io.StringReader;
|
||||
|
||||
public class JsonLikeParserDstu2Test {
|
||||
private static FhirContext ourCtx = FhirContext.forDstu2();
|
||||
|
@ -28,7 +27,7 @@ public class JsonLikeParserDstu2Test {
|
|||
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed);
|
||||
ourLog.info(encoded);
|
||||
|
||||
JsonLikeStructure jsonLikeStructure = new GsonStructure();
|
||||
JsonLikeStructure jsonLikeStructure = new JacksonStructure();
|
||||
jsonLikeStructure.load(new StringReader(encoded));
|
||||
|
||||
IJsonLikeParser jsonLikeparser = (IJsonLikeParser)ourCtx.newJsonParser();
|
||||
|
|
|
@ -72,7 +72,8 @@ public class JsonParserDstu3Test {
|
|||
p.parseResource(input);
|
||||
fail();
|
||||
} catch (DataFormatException e) {
|
||||
assertEquals("Found incorrect type for element subject - Expected OBJECT and found SCALAR (STRING)", e.getMessage());
|
||||
assertEquals("Failed to parse JSON encoded FHIR content: Unexpected character ('=' (code 61)): was expecting a colon to separate field name and value\n" +
|
||||
" at [Source: UNKNOWN; line: 4, column: 18]", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -488,32 +489,25 @@ public class JsonParserDstu3Test {
|
|||
String enc = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
|
||||
ourLog.info(enc);
|
||||
|
||||
//@formatter:off
|
||||
assertEquals("{\n" +
|
||||
" \"resourceType\": \"Patient\",\n" +
|
||||
" \"meta\": {\n" +
|
||||
" \"security\": [\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"SYSTEM1\",\n" +
|
||||
" \"version\": \"VERSION1\",\n" +
|
||||
" \"code\": \"CODE1\",\n" +
|
||||
" \"display\": \"DISPLAY1\"\n" +
|
||||
" },\n" +
|
||||
" {\n" +
|
||||
" \"system\": \"SYSTEM2\",\n" +
|
||||
" \"version\": \"VERSION2\",\n" +
|
||||
" \"code\": \"CODE2\",\n" +
|
||||
" \"display\": \"DISPLAY2\"\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
" },\n" +
|
||||
" \"name\": [\n" +
|
||||
" {\n" +
|
||||
" \"family\": \"FAMILY\"\n" +
|
||||
" }\n" +
|
||||
" ]\n" +
|
||||
"}", enc.trim());
|
||||
//@formatter:on
|
||||
assertThat(enc.trim(), stringContainsInOrder("{",
|
||||
" \"resourceType\": \"Patient\",",
|
||||
" \"meta\": {",
|
||||
" \"security\": [ {",
|
||||
" \"system\": \"SYSTEM1\",",
|
||||
" \"version\": \"VERSION1\",",
|
||||
" \"code\": \"CODE1\",",
|
||||
" \"display\": \"DISPLAY1\"",
|
||||
" }, {",
|
||||
" \"system\": \"SYSTEM2\",",
|
||||
" \"version\": \"VERSION2\",",
|
||||
" \"code\": \"CODE2\",",
|
||||
" \"display\": \"DISPLAY2\"",
|
||||
" } ]",
|
||||
" },",
|
||||
" \"name\": [ {",
|
||||
" \"family\": \"FAMILY\"",
|
||||
" } ]",
|
||||
"}"));
|
||||
|
||||
Patient parsed = ourCtx.newJsonParser().parseResource(Patient.class, enc);
|
||||
List<Coding> gotLabels = parsed.getMeta().getSecurity();
|
||||
|
@ -1401,7 +1395,8 @@ public class JsonParserDstu3Test {
|
|||
String input = "{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.0000000000000001}}";
|
||||
Observation obs = ourCtx.newJsonParser().parseResource(Observation.class, input);
|
||||
|
||||
assertEquals("0.0000000000000001", ((Quantity) obs.getValue()).getValueElement().getValueAsString());
|
||||
DecimalType valueElement = ((Quantity) obs.getValue()).getValueElement();
|
||||
assertEquals("0.0000000000000001", valueElement.getValueAsString());
|
||||
|
||||
String str = ourCtx.newJsonParser().encodeResourceToString(obs);
|
||||
ourLog.info(str);
|
||||
|
@ -1993,13 +1988,13 @@ public class JsonParserDstu3Test {
|
|||
ourCtx.newJsonParser().parseResource("FOO");
|
||||
fail();
|
||||
} catch (DataFormatException e) {
|
||||
assertEquals("Failed to parse JSON content, error was: Content does not appear to be FHIR JSON, first non-whitespace character was: 'F' (must be '{')", e.getMessage());
|
||||
assertEquals("Failed to parse JSON encoded FHIR content: Content does not appear to be FHIR JSON, first non-whitespace character was: 'F' (must be '{')", e.getMessage());
|
||||
}
|
||||
try {
|
||||
ourCtx.newJsonParser().parseResource("[\"aaa\"]");
|
||||
fail();
|
||||
} catch (DataFormatException e) {
|
||||
assertEquals("Failed to parse JSON content, error was: Content does not appear to be FHIR JSON, first non-whitespace character was: '[' (must be '{')", e.getMessage());
|
||||
assertEquals("Failed to parse JSON encoded FHIR content: Content does not appear to be FHIR JSON, first non-whitespace character was: '[' (must be '{')", e.getMessage());
|
||||
}
|
||||
|
||||
assertEquals(Bundle.class, ourCtx.newJsonParser().parseResource(" {\"resourceType\" : \"Bundle\"}").getClass());
|
||||
|
@ -2221,25 +2216,47 @@ public class JsonParserDstu3Test {
|
|||
|
||||
@Test
|
||||
public void testParseWithPrecision() {
|
||||
|
||||
// BigDecimal d0 = new BigDecimal("0.1");
|
||||
// BigDecimal d1 = new BigDecimal("0.1000");
|
||||
//
|
||||
// ourLog.info("Value: {}", d0);
|
||||
// ourLog.info("Value: {}", d1);
|
||||
|
||||
{
|
||||
String input = "{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.0100}}";
|
||||
Observation obs = ourCtx.newJsonParser().parseResource(Observation.class, input);
|
||||
DecimalType valueElement = ((Quantity) obs.getValue()).getValueElement();
|
||||
assertEquals("0.0100", valueElement.getValueAsString());
|
||||
String str = ourCtx.newJsonParser().encodeResourceToString(obs);
|
||||
ourLog.info(str);
|
||||
assertEquals("{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.0100}}", str);
|
||||
}
|
||||
{
|
||||
String input = "{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.000000000000000100}}";
|
||||
Observation obs = ourCtx.newJsonParser().parseResource(Observation.class, input);
|
||||
|
||||
DecimalType valueElement = ((Quantity) obs.getValue()).getValueElement();
|
||||
assertEquals("0.000000000000000100", valueElement.getValueAsString());
|
||||
|
||||
String str = ourCtx.newJsonParser().encodeResourceToString(obs);
|
||||
ourLog.info(str);
|
||||
assertEquals("{\"resourceType\":\"Observation\",\"valueQuantity\":{\"value\":0.000000000000000100}}", str);
|
||||
}
|
||||
}
|
||||
|
||||
@Test(expected = DataFormatException.class)
|
||||
@Test
|
||||
public void testParseWithTrailingContent() {
|
||||
String bundle = "{\n" +
|
||||
" \"resourceType\": \"Bundle\",\n" +
|
||||
" \"total\": 1\n" +
|
||||
"}}";
|
||||
|
||||
try {
|
||||
ourCtx.newJsonParser().parseResource(Bundle.class, bundle);
|
||||
fail();
|
||||
} catch (DataFormatException e) {
|
||||
assertEquals("Failed to parse JSON encoded FHIR content: Unexpected close marker '}': expected ']' (for root starting at [Source: UNKNOWN; line: 1, column: 0])\n" +
|
||||
" at [Source: UNKNOWN; line: 4, column: 3]", e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -2508,42 +2508,27 @@ public class XmlParserDstu3Test {
|
|||
output = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(pat);
|
||||
ourLog.info(output);
|
||||
|
||||
assertThat(output, stringContainsInOrder(
|
||||
"{",
|
||||
assertThat(output, stringContainsInOrder("{",
|
||||
" \"resourceType\": \"Patient\",",
|
||||
" \"id\": \"someid\",",
|
||||
" \"_id\": {",
|
||||
" \"fhir_comments\": [",
|
||||
" \" comment 1 \"",
|
||||
" ]",
|
||||
" \"fhir_comments\": [ \" comment 1 \" ]",
|
||||
" },",
|
||||
" \"extension\": [",
|
||||
" {",
|
||||
" \"fhir_comments\": [",
|
||||
" \" comment 2 \",",
|
||||
" \" comment 7 \"",
|
||||
" ],",
|
||||
" \"extension\": [ {",
|
||||
" \"fhir_comments\": [ \" comment 2 \", \" comment 7 \" ],",
|
||||
" \"url\": \"urn:patientext:att\",",
|
||||
" \"valueAttachment\": {",
|
||||
" \"fhir_comments\": [",
|
||||
" \" comment 3 \",",
|
||||
" \" comment 6 \"",
|
||||
" ],",
|
||||
" \"fhir_comments\": [ \" comment 3 \", \" comment 6 \" ],",
|
||||
" \"contentType\": \"aaaa\",",
|
||||
" \"_contentType\": {",
|
||||
" \"fhir_comments\": [",
|
||||
" \" comment 4 \"",
|
||||
" ]",
|
||||
" \"fhir_comments\": [ \" comment 4 \" ]",
|
||||
" },",
|
||||
" \"data\": \"AAAA\",",
|
||||
" \"_data\": {",
|
||||
" \"fhir_comments\": [",
|
||||
" \" comment 5 \"",
|
||||
" ]",
|
||||
" \"fhir_comments\": [ \" comment 5 \" ]",
|
||||
" }",
|
||||
" }",
|
||||
" }",
|
||||
" ]",
|
||||
" } ]",
|
||||
"}"));
|
||||
|
||||
}
|
||||
|
|
|
@ -1,5 +1,19 @@
|
|||
package ca.uhn.fhir.parser.jsonlike;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.parser.IJsonLikeParser;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeStructure;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeWriter;
|
||||
import ca.uhn.fhir.parser.json.jackson.JacksonStructure;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.dstu3.model.Reference;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.math.BigDecimal;
|
||||
|
@ -10,22 +24,6 @@ import java.util.List;
|
|||
import java.util.Map;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.dstu3.model.Bundle;
|
||||
import org.hl7.fhir.dstu3.model.Extension;
|
||||
import org.hl7.fhir.dstu3.model.Patient;
|
||||
import org.hl7.fhir.dstu3.model.Reference;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.parser.IJsonLikeParser;
|
||||
import ca.uhn.fhir.parser.json.GsonStructure;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeStructure;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeWriter;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class JsonLikeParserDstu3Test {
|
||||
private static FhirContext ourCtx = FhirContext.forDstu3();
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonLikeParserDstu3Test.class);
|
||||
|
@ -42,7 +40,7 @@ public class JsonLikeParserDstu3Test {
|
|||
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed);
|
||||
ourLog.info(encoded);
|
||||
|
||||
JsonLikeStructure jsonLikeStructure = new GsonStructure();
|
||||
JsonLikeStructure jsonLikeStructure = new JacksonStructure();
|
||||
jsonLikeStructure.load(new StringReader(encoded));
|
||||
|
||||
IJsonLikeParser jsonLikeparser = (IJsonLikeParser)ourCtx.newJsonParser();
|
||||
|
@ -192,17 +190,6 @@ public class JsonLikeParserDstu3Test {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter beginArray() throws IOException {
|
||||
if (currentBlock.getType() == BlockType.NONE) {
|
||||
throw new IOException("JsonLikeStreamWriter.beginArray() called but only beginObject() is allowed here.");
|
||||
}
|
||||
blockStack.push(currentBlock);
|
||||
currentBlock = new Block(BlockType.ARRAY);
|
||||
currentBlock.setArray(new ArrayList<Object>());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter beginObject(String name) throws IOException {
|
||||
if (currentBlock.getType() == BlockType.ARRAY) {
|
||||
|
@ -363,15 +350,6 @@ public class JsonLikeParserDstu3Test {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter writeNull(String name) throws IOException {
|
||||
if (currentBlock.getType() == BlockType.ARRAY) {
|
||||
throw new IOException("Named JSON elements can only be created in JSON objects");
|
||||
}
|
||||
currentBlock.getObject().put(name, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter endObject() throws IOException {
|
||||
if (currentBlock.getType() == BlockType.NONE) {
|
||||
|
@ -399,7 +377,7 @@ public class JsonLikeParserDstu3Test {
|
|||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter endBlock() throws IOException {
|
||||
public JsonLikeWriter endBlock() {
|
||||
if (currentBlock.getType() == BlockType.NONE) {
|
||||
ourLog.error("JsonLikeStreamWriter.endBlock(); called with no active JSON document");
|
||||
} else {
|
||||
|
|
|
@ -1097,12 +1097,6 @@ public class JsonParserHl7OrgDstu2Test {
|
|||
assertEquals("idsystem", p.getIdentifier().get(0).getSystem());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseSingleQuotes() {
|
||||
ourCtx.newJsonParser().parseResource(Bundle.class, "{ \"resourceType\": \"Bundle\" }");
|
||||
ourCtx.newJsonParser().parseResource(Bundle.class, "{ 'resourceType': 'Bundle' }");
|
||||
}
|
||||
|
||||
/**
|
||||
* HAPI FHIR < 0.6 incorrectly used "resource" instead of "reference"
|
||||
*/
|
||||
|
|
|
@ -175,6 +175,11 @@
|
|||
<version>${project.version}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.awaitility</groupId>
|
||||
<artifactId>awaitility</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- Dependencies for Schematron -->
|
||||
<dependency>
|
||||
|
@ -215,9 +220,8 @@
|
|||
|
||||
<!-- UNIT TEST DEPENDENCIES -->
|
||||
<dependency>
|
||||
<groupId>org.apache.jena</groupId>
|
||||
<artifactId>apache-jena-libs</artifactId>
|
||||
<type>pom</type>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
|
|
|
@ -248,6 +248,12 @@ public class JsonParserR4Test extends BaseTest {
|
|||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testParseSingleQuotes() {
|
||||
Bundle bundle = ourCtx.newJsonParser().parseResource(Bundle.class, "{ 'resourceType': 'Bundle', 'id': '123' }");
|
||||
assertEquals("123", bundle.getIdElement().getIdPart());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testEncodeBinary() {
|
||||
|
@ -260,6 +266,18 @@ public class JsonParserR4Test extends BaseTest {
|
|||
assertEquals("{\"resourceType\":\"Binary\",\"contentType\":\"application/octet-stream\",\"data\":\"AAECAwQ=\"}", output);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testAlwaysUseUnixNewlines() {
|
||||
Patient p = new Patient();
|
||||
p.setId("1");
|
||||
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(p);
|
||||
assertEquals("{\n" +
|
||||
" \"resourceType\": \"Patient\",\n" +
|
||||
" \"id\": \"1\"\n" +
|
||||
"}", encoded);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEncodeWithInvalidExtensionMissingUrl() {
|
||||
|
||||
|
@ -586,6 +604,14 @@ public class JsonParserR4Test extends BaseTest {
|
|||
* 15:20:41.708 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:574] - Encoded 1200 passes - 28ms / pass - 34.5 / second
|
||||
* 15:20:44.722 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:574] - Encoded 1300 passes - 29ms / pass - 34.4 / second
|
||||
* 15:20:47.716 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:574] - Encoded 1400 passes - 29ms / pass - 34.4 / second
|
||||
*
|
||||
* 2020-02-27 - Post #1673
|
||||
* 21:27:25.817 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:609] - Encoded 1100 passes - 28ms / pass - 35.5 / second
|
||||
* 21:27:28.598 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:609] - Encoded 1200 passes - 28ms / pass - 35.5 / second
|
||||
* 21:27:31.436 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:609] - Encoded 1300 passes - 28ms / pass - 35.5 / second
|
||||
* 21:27:34.246 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:609] - Encoded 1400 passes - 28ms / pass - 35.5 / second
|
||||
* 21:27:37.013 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:609] - Encoded 1500 passes - 28ms / pass - 35.6 / second
|
||||
* 21:27:39.874 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:609] - Encoded 1600 passes - 28ms / pass - 35.5 / second
|
||||
*/
|
||||
@Test
|
||||
@Ignore
|
||||
|
@ -655,6 +681,12 @@ public class JsonParserR4Test extends BaseTest {
|
|||
* 15:22:40.699 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:638] - Parsed 2500 passes - 12ms / pass - 79.7 / second
|
||||
* 15:22:42.135 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:638] - Parsed 2600 passes - 12ms / pass - 79.3 / second
|
||||
*
|
||||
* 2020-02-27 - Post #1673
|
||||
* 21:29:38.157 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:687] - Parsed 2200 passes - 11ms / pass - 83.4 / second
|
||||
* 21:29:39.374 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:687] - Parsed 2300 passes - 12ms / pass - 83.3 / second
|
||||
* 21:29:40.576 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:687] - Parsed 2400 passes - 12ms / pass - 83.3 / second
|
||||
* 21:29:41.778 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:687] - Parsed 2500 passes - 12ms / pass - 83.3 / second
|
||||
* 21:29:42.999 [main] INFO ca.uhn.fhir.parser.JsonParserR4Test [JsonParserR4Test.java:687] - Parsed 2600 passes - 12ms / pass - 83.3 / second
|
||||
*
|
||||
*/
|
||||
@Test
|
||||
|
|
|
@ -1,5 +1,26 @@
|
|||
package ca.uhn.fhir.parser.jsonlike;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.parser.IJsonLikeParser;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeArray;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeObject;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeStructure;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeValue;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeWriter;
|
||||
import ca.uhn.fhir.parser.json.jackson.JacksonStructure;
|
||||
import ca.uhn.fhir.parser.view.ExtPatient;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.model.Extension;
|
||||
import org.hl7.fhir.r4.model.IntegerType;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.Reference;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Reader;
|
||||
import java.io.StringReader;
|
||||
|
@ -14,31 +35,6 @@ import java.util.Map;
|
|||
import java.util.Set;
|
||||
import java.util.Stack;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.hl7.fhir.r4.model.IntegerType;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.Reference;
|
||||
import org.hl7.fhir.r4.model.Extension;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Test;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.parser.IJsonLikeParser;
|
||||
import ca.uhn.fhir.parser.IParser;
|
||||
import ca.uhn.fhir.parser.json.GsonStructure;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeArray;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeObject;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeStructure;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeValue;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeWriter;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeValue.ScalarType;
|
||||
import ca.uhn.fhir.parser.json.JsonLikeValue.ValueType;
|
||||
import ca.uhn.fhir.parser.view.ExtPatient;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
|
||||
public class JsonLikeParserTest {
|
||||
private static FhirContext ourCtx = FhirContext.forR4();
|
||||
private static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(JsonLikeParserTest.class);
|
||||
|
@ -55,7 +51,7 @@ public class JsonLikeParserTest {
|
|||
String encoded = ourCtx.newJsonParser().setPrettyPrint(true).encodeResourceToString(parsed);
|
||||
ourLog.info(encoded);
|
||||
|
||||
JsonLikeStructure jsonLikeStructure = new GsonStructure();
|
||||
JsonLikeStructure jsonLikeStructure = new JacksonStructure();
|
||||
jsonLikeStructure.load(new StringReader(encoded));
|
||||
|
||||
IJsonLikeParser jsonLikeparser = (IJsonLikeParser)ourCtx.newJsonParser();
|
||||
|
@ -258,17 +254,6 @@ public class JsonLikeParserTest {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter beginArray() throws IOException {
|
||||
if (currentBlock.getType() == BlockType.NONE) {
|
||||
throw new IOException("JsonLikeStreamWriter.beginArray() called but only beginObject() is allowed here.");
|
||||
}
|
||||
blockStack.push(currentBlock);
|
||||
currentBlock = new Block(BlockType.ARRAY);
|
||||
currentBlock.setArray(new ArrayList<Object>());
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter beginObject(String name) throws IOException {
|
||||
if (currentBlock.getType() == BlockType.ARRAY) {
|
||||
|
@ -429,15 +414,6 @@ public class JsonLikeParserTest {
|
|||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter writeNull(String name) throws IOException {
|
||||
if (currentBlock.getType() == BlockType.ARRAY) {
|
||||
throw new IOException("Named JSON elements can only be created in JSON objects");
|
||||
}
|
||||
currentBlock.getObject().put(name, null);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter endObject() throws IOException {
|
||||
if (currentBlock.getType() == BlockType.NONE) {
|
||||
|
@ -452,7 +428,7 @@ public class JsonLikeParserTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter endArray() throws IOException {
|
||||
public JsonLikeWriter endArray() {
|
||||
if (currentBlock.getType() == BlockType.NONE) {
|
||||
ourLog.error("JsonLikeStreamWriter.endArray(); called with no active JSON document");
|
||||
} else {
|
||||
|
@ -465,11 +441,11 @@ public class JsonLikeParserTest {
|
|||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeWriter endBlock() throws IOException {
|
||||
public JsonLikeWriter endBlock() {
|
||||
if (currentBlock.getType() == BlockType.NONE) {
|
||||
ourLog.error("JsonLikeStreamWriter.endBlock(); called with no active JSON document");
|
||||
} else {
|
||||
Object toPut = null;
|
||||
Object toPut;
|
||||
if (currentBlock.getType() == BlockType.ARRAY) {
|
||||
toPut = currentBlock.getArray();
|
||||
} else {
|
||||
|
@ -544,14 +520,9 @@ public class JsonLikeParserTest {
|
|||
return jsonLikeObject;
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonLikeArray getRootArray() throws DataFormatException {
|
||||
throw new DataFormatException("JSON document must be an object not an array for native Java Map structures");
|
||||
}
|
||||
|
||||
private class JsonMapObject extends JsonLikeObject {
|
||||
private Map<String,Object> nativeObject;
|
||||
private Map<String,JsonLikeValue> jsonLikeMap = new LinkedHashMap<String,JsonLikeValue>();
|
||||
private Map<String,JsonLikeValue> jsonLikeMap = new LinkedHashMap<>();
|
||||
|
||||
public JsonMapObject (Map<String,Object> json) {
|
||||
this.nativeObject = json;
|
||||
|
@ -585,7 +556,7 @@ public class JsonLikeParserTest {
|
|||
|
||||
private class JsonMapArray extends JsonLikeArray {
|
||||
private List<Object> nativeArray;
|
||||
private Map<Integer,JsonLikeValue> jsonLikeMap = new LinkedHashMap<Integer,JsonLikeValue>();
|
||||
private Map<Integer,JsonLikeValue> jsonLikeMap = new LinkedHashMap<>();
|
||||
|
||||
public JsonMapArray (List<Object> json) {
|
||||
this.nativeArray = json;
|
||||
|
@ -603,7 +574,7 @@ public class JsonLikeParserTest {
|
|||
|
||||
@Override
|
||||
public JsonLikeValue get(int index) {
|
||||
Integer key = Integer.valueOf(index);
|
||||
Integer key = index;
|
||||
JsonLikeValue result = null;
|
||||
if (jsonLikeMap.containsKey(key)) {
|
||||
result = jsonLikeMap.get(key);
|
||||
|
@ -694,7 +665,7 @@ public class JsonLikeParserTest {
|
|||
@Override
|
||||
public boolean getAsBoolean() {
|
||||
if (nativeValue != null && isBoolean()) {
|
||||
return ((Boolean)nativeValue).booleanValue();
|
||||
return (Boolean) nativeValue;
|
||||
}
|
||||
return super.getAsBoolean();
|
||||
}
|
||||
|
|
|
@ -91,7 +91,7 @@ public class BlockingContentR4Test {
|
|||
if (myByteCount++ == 10) {
|
||||
ourLog.info("About to block...");
|
||||
try {
|
||||
Thread.sleep(30000);
|
||||
Thread.sleep(3000);
|
||||
} catch (InterruptedException e) {
|
||||
ourLog.warn("Interrupted", e);
|
||||
}
|
||||
|
|
|
@ -35,12 +35,16 @@ import org.junit.runner.RunWith;
|
|||
import org.mockito.ArgumentCaptor;
|
||||
import org.mockito.Captor;
|
||||
import org.mockito.Mock;
|
||||
import org.mockito.Mockito;
|
||||
import org.mockito.invocation.Invocation;
|
||||
import org.mockito.junit.MockitoJUnitRunner;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.Matchers.not;
|
||||
import static org.junit.Assert.*;
|
||||
|
@ -201,12 +205,13 @@ public class ConsentInterceptorTest {
|
|||
assertThat(responseContent, containsString("A DIAG"));
|
||||
}
|
||||
|
||||
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
||||
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
||||
verify(myConsentSvc, times(3)).willSeeResource(any(), any(), any());
|
||||
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
||||
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
||||
verify(myConsentSvc, timeout(10000).times(1)).startOperation(any(), any());
|
||||
verify(myConsentSvc, timeout(10000).times(2)).canSeeResource(any(), any(), any());
|
||||
verify(myConsentSvc, timeout(10000).times(3)).willSeeResource(any(), any(), any());
|
||||
verify(myConsentSvc, timeout(10000).times(1)).completeOperationSuccess(any(), any());
|
||||
verify(myConsentSvc, timeout(10000).times(0)).completeOperationFailure(any(), any(), any());
|
||||
verifyNoMoreInteractions(myConsentSvc);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -241,6 +246,7 @@ public class ConsentInterceptorTest {
|
|||
ourPatientProvider.store((Patient) new Patient().setActive(true).setId("PTA"));
|
||||
ourPatientProvider.store((Patient) new Patient().setActive(false).setId("PTB"));
|
||||
|
||||
reset(myConsentSvc);
|
||||
when(myConsentSvc.startOperation(any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||
when(myConsentSvc.canSeeResource(any(), any(), any())).thenReturn(ConsentOutcome.PROCEED);
|
||||
when(myConsentSvc.willSeeResource(any(RequestDetails.class), any(IBaseResource.class), any())).thenAnswer(t->{
|
||||
|
@ -266,10 +272,10 @@ public class ConsentInterceptorTest {
|
|||
assertEquals("PTB", response.getEntry().get(1).getResource().getIdElement().getIdPart());
|
||||
}
|
||||
|
||||
verify(myConsentSvc, times(1)).startOperation(any(), any());
|
||||
verify(myConsentSvc, times(2)).canSeeResource(any(), any(), any());
|
||||
verify(myConsentSvc, times(3)).willSeeResource(any(), any(), any());
|
||||
verify(myConsentSvc, times(1)).completeOperationSuccess(any(), any());
|
||||
verify(myConsentSvc, timeout(1000).times(1)).startOperation(any(), any());
|
||||
verify(myConsentSvc, timeout(1000).times(2)).canSeeResource(any(), any(), any());
|
||||
verify(myConsentSvc, timeout(1000).times(3)).willSeeResource(any(), any(), any());
|
||||
verify(myConsentSvc, timeout(1000).times(1)).completeOperationSuccess(any(), any());
|
||||
verify(myConsentSvc, times(0)).completeOperationFailure(any(), any(), any());
|
||||
verifyNoMoreInteractions(myConsentSvc);
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import ca.uhn.fhir.rest.annotation.Read;
|
|||
import ca.uhn.fhir.rest.server.IResourceProvider;
|
||||
import ca.uhn.fhir.rest.server.RestfulServer;
|
||||
import ca.uhn.fhir.rest.server.servlet.ServletRequestDetails;
|
||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||
import ca.uhn.fhir.util.TestUtil;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.apache.http.HttpResponse;
|
||||
|
@ -21,7 +22,11 @@ import org.hl7.fhir.instance.model.api.IBaseResource;
|
|||
import org.hl7.fhir.r4.model.IdType;
|
||||
import org.hl7.fhir.r4.model.Patient;
|
||||
import org.hl7.fhir.r4.model.Resource;
|
||||
import org.junit.*;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
|
@ -30,11 +35,12 @@ import java.util.Collections;
|
|||
import java.util.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import static org.awaitility.Awaitility.await;
|
||||
import static org.hamcrest.CoreMatchers.containsString;
|
||||
import static org.hamcrest.Matchers.contains;
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import ca.uhn.fhir.test.utilities.JettyUtil;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
public class InterceptorThrowingExceptionR4Test {
|
||||
|
||||
|
@ -84,26 +90,26 @@ public class InterceptorThrowingExceptionR4Test {
|
|||
|
||||
@Test
|
||||
public void testFailureInProcessingCompletedNormally() throws Exception {
|
||||
final List<Integer> hit = new ArrayList<>();
|
||||
final List<Integer> hit = Collections.synchronizedList(new ArrayList<>());
|
||||
ourServlet.getInterceptorService().registerInterceptor(new InterceptorAdapter() {
|
||||
@Override
|
||||
public void processingCompletedNormally(ServletRequestDetails theRequestDetails) {
|
||||
hit.add(1);
|
||||
throw new NullPointerException();
|
||||
throw new NullPointerException("Hit 1");
|
||||
}
|
||||
});
|
||||
ourServlet.getInterceptorService().registerInterceptor(new InterceptorAdapter() {
|
||||
@Override
|
||||
public void processingCompletedNormally(ServletRequestDetails theRequestDetails) {
|
||||
hit.add(2);
|
||||
throw new NullPointerException();
|
||||
throw new NullPointerException("Hit 2");
|
||||
}
|
||||
});
|
||||
ourServlet.getInterceptorService().registerInterceptor(new InterceptorAdapter() {
|
||||
@Override
|
||||
public void processingCompletedNormally(ServletRequestDetails theRequestDetails) {
|
||||
hit.add(3);
|
||||
throw new NullPointerException();
|
||||
throw new NullPointerException("Hit 3");
|
||||
}
|
||||
});
|
||||
|
||||
|
@ -119,6 +125,9 @@ public class InterceptorThrowingExceptionR4Test {
|
|||
assertEquals(200, status.getStatusLine().getStatusCode());
|
||||
assertThat(response, containsString("FAM"));
|
||||
assertTrue(ourHitMethod);
|
||||
|
||||
await().until(() -> hit.size() == 3);
|
||||
|
||||
ourLog.info("Hit: {}", hit);
|
||||
assertThat("Hits: " + hit.toString(), hit, contains(1, 2, 3));
|
||||
|
||||
|
|
|
@ -66,6 +66,10 @@
|
|||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
<!--<dependency> <groupId>ca.uhn.hapi.fhir</groupId> <artifactId>hapi-fhir-structures-dev</artifactId> <version>0.9</version> </dependency> -->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.thymeleaf</groupId>
|
||||
<artifactId>thymeleaf</artifactId>
|
||||
|
|
|
@ -1,42 +1,59 @@
|
|||
package ca.uhn.fhir.to;
|
||||
|
||||
import ca.uhn.fhir.context.FhirContext;
|
||||
import ca.uhn.fhir.context.RuntimeResourceDefinition;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.BoundCodeDt;
|
||||
import ca.uhn.fhir.model.primitive.DateTimeDt;
|
||||
import ca.uhn.fhir.model.primitive.IdDt;
|
||||
import ca.uhn.fhir.model.primitive.StringDt;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.client.impl.GenericClient;
|
||||
import ca.uhn.fhir.rest.gclient.ICreateTyped;
|
||||
import ca.uhn.fhir.rest.gclient.IHistory;
|
||||
import ca.uhn.fhir.rest.gclient.IHistoryTyped;
|
||||
import ca.uhn.fhir.rest.gclient.IHistoryUntyped;
|
||||
import ca.uhn.fhir.rest.gclient.IQuery;
|
||||
import ca.uhn.fhir.rest.gclient.IUntypedQuery;
|
||||
import ca.uhn.fhir.rest.gclient.NumberClientParam.IMatches;
|
||||
import ca.uhn.fhir.rest.gclient.QuantityClientParam;
|
||||
import ca.uhn.fhir.rest.gclient.QuantityClientParam.IAndUnits;
|
||||
import ca.uhn.fhir.rest.gclient.StringClientParam;
|
||||
import ca.uhn.fhir.rest.gclient.TokenClientParam;
|
||||
import ca.uhn.fhir.to.model.HomeRequest;
|
||||
import ca.uhn.fhir.to.model.ResourceRequest;
|
||||
import ca.uhn.fhir.to.model.TransactionRequest;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.dstu3.model.CapabilityStatement;
|
||||
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestComponent;
|
||||
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceComponent;
|
||||
import org.hl7.fhir.dstu3.model.CapabilityStatement.CapabilityStatementRestResourceSearchParamComponent;
|
||||
import org.hl7.fhir.dstu3.model.StringType;
|
||||
import org.hl7.fhir.instance.model.api.IBaseBundle;
|
||||
import org.hl7.fhir.instance.model.api.IBaseConformance;
|
||||
import org.hl7.fhir.instance.model.api.IBaseResource;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.TreeSet;
|
||||
|
||||
import static org.apache.commons.lang3.StringUtils.defaultIfEmpty;
|
||||
import static org.apache.commons.lang3.StringUtils.defaultString;
|
||||
import static org.apache.commons.lang3.StringUtils.isBlank;
|
||||
import static org.apache.commons.lang3.StringUtils.isNotBlank;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.hl7.fhir.dstu3.model.CapabilityStatement;
|
||||
import org.hl7.fhir.dstu3.model.CapabilityStatement.*;
|
||||
import org.hl7.fhir.dstu3.model.StringType;
|
||||
import org.hl7.fhir.instance.model.api.*;
|
||||
import org.springframework.ui.ModelMap;
|
||||
import org.springframework.validation.BindingResult;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
import ca.uhn.fhir.context.*;
|
||||
import ca.uhn.fhir.model.api.Include;
|
||||
import ca.uhn.fhir.model.dstu2.resource.Conformance;
|
||||
import ca.uhn.fhir.model.dstu2.valueset.ResourceTypeEnum;
|
||||
import ca.uhn.fhir.model.primitive.*;
|
||||
import ca.uhn.fhir.parser.DataFormatException;
|
||||
import ca.uhn.fhir.rest.api.Constants;
|
||||
import ca.uhn.fhir.rest.api.EncodingEnum;
|
||||
import ca.uhn.fhir.rest.client.impl.GenericClient;
|
||||
import ca.uhn.fhir.rest.gclient.*;
|
||||
import ca.uhn.fhir.rest.gclient.NumberClientParam.IMatches;
|
||||
import ca.uhn.fhir.rest.gclient.QuantityClientParam.IAndUnits;
|
||||
import ca.uhn.fhir.to.model.*;
|
||||
|
||||
@org.springframework.stereotype.Controller()
|
||||
public class Controller extends BaseController {
|
||||
static final org.slf4j.Logger ourLog = org.slf4j.LoggerFactory.getLogger(Controller.class);
|
||||
|
|
|
@ -46,6 +46,15 @@
|
|||
<artifactId>jsr305</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
Note: As of HAPI FHIR 5.0.0 we now use Jackson for JSON parsing, but the
|
||||
validator still uses GSON so it is a dependency here
|
||||
-->
|
||||
<dependency>
|
||||
<groupId>com.google.code.gson</groupId>
|
||||
<artifactId>gson</artifactId>
|
||||
</dependency>
|
||||
|
||||
<!--
|
||||
Optional dependencies from RI codebase
|
||||
-->
|
||||
|
|
Loading…
Reference in New Issue