Repository: polygene-java Updated Branches: refs/heads/json-revisited [created] 6b569234b
less memory consumption in json deserializer Project: http://git-wip-us.apache.org/repos/asf/polygene-java/repo Commit: http://git-wip-us.apache.org/repos/asf/polygene-java/commit/6b569234 Tree: http://git-wip-us.apache.org/repos/asf/polygene-java/tree/6b569234 Diff: http://git-wip-us.apache.org/repos/asf/polygene-java/diff/6b569234 Branch: refs/heads/json-revisited Commit: 6b569234b64c06cf624e4ff57f1eed483811d441 Parents: 98b50f2 Author: tbml <[email protected]> Authored: Fri May 4 17:41:32 2018 +0200 Committer: tbml <[email protected]> Committed: Fri May 4 17:41:32 2018 +0200 ---------------------------------------------------------------------- .../javaxjson/JavaxJsonAdapters.java | 8 +- .../javaxjson/JavaxJsonDeserializer.java | 114 ++++++------------- .../javaxjson/JavaxJsonFactories.java | 8 +- dependencies.gradle | 2 +- 4 files changed, 51 insertions(+), 81 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/polygene-java/blob/6b569234/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapters.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapters.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapters.java index dccf388..8f52391 100644 --- a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapters.java +++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonAdapters.java @@ -135,7 +135,13 @@ public interface JavaxJsonAdapters @Override public String deserialize( JsonValue json, BiFunction<JsonValue, ValueType, Object> deserialize ) { - return JavaxJson.asString( json ); + switch (json.getValueType()) { + case NULL: + return null; + default: + return JavaxJson.asString(json); + } + } } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/6b569234/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDeserializer.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDeserializer.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDeserializer.java index ad647a4..3ccc884 100644 --- a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDeserializer.java +++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonDeserializer.java @@ -17,11 +17,7 @@ */ package org.apache.polygene.serialization.javaxjson; -import java.io.BufferedReader; -import java.io.IOException; import java.io.Reader; -import java.io.StringReader; -import java.io.UncheckedIOException; import java.lang.reflect.Array; import java.util.AbstractMap; import java.util.ArrayList; @@ -31,17 +27,15 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Scanner; import java.util.Set; import java.util.function.Function; import java.util.stream.Stream; import javax.json.JsonArray; import javax.json.JsonObject; import javax.json.JsonReader; -import javax.json.JsonString; import javax.json.JsonStructure; import javax.json.JsonValue; -import javax.json.stream.JsonParser; -import javax.json.stream.JsonParsingException; import org.apache.polygene.api.association.AssociationDescriptor; import org.apache.polygene.api.composite.CompositeDescriptor; import org.apache.polygene.api.composite.StatefulAssociationCompositeDescriptor; @@ -68,7 +62,6 @@ import static java.nio.charset.StandardCharsets.UTF_8; import static java.util.Collections.unmodifiableList; import static java.util.Collections.unmodifiableMap; import static java.util.Collections.unmodifiableSet; -import static java.util.stream.Collectors.joining; import static java.util.stream.Collectors.toCollection; import static org.apache.polygene.api.util.Collectors.toMapWithNullValues; import static org.apache.polygene.serialization.javaxjson.JavaxJson.asString; @@ -92,88 +85,35 @@ public class JavaxJsonDeserializer extends AbstractTextDeserializer private ServiceDescriptor descriptor; private JavaxJsonSettings settings; - private JsonString emptyJsonString; @Override public void initialize() throws Exception { settings = JavaxJsonSettings.orDefault( descriptor.metaInfo( JavaxJsonSettings.class ) ); - emptyJsonString = jsonFactories.builderFactory().createObjectBuilder().add( "s", "" ).build() - .getJsonString( "s" ); } - @Override - public <T> T deserialize( ModuleDescriptor module, ValueType valueType, Reader state ) + @SuppressWarnings("unchecked") + public <T> T deserialize(ModuleDescriptor module, ValueType valueType, Reader state) { - // JSR-353 Does not allow reading "out of structure" values - // See https://www.jcp.org/en/jsr/detail?id=353 - // And commented JsonReader#readValue() method in the javax.json API - // BUT, it will be part of the JsonReader contract in the next version - // See https://www.jcp.org/en/jsr/detail?id=374 - // Implementation by provider is optional though, so we'll always need a default implementation here. - // Fortunately, JsonParser has new methods allowing to read structures while parsing so it will be easy to do. - // In the meantime, a poor man's implementation reading the json into memory will do. - // TODO Revisit values out of structure JSON deserialization when JSR-374 is out - String stateString; - try( BufferedReader buffer = new BufferedReader( state ) ) - { - stateString = buffer.lines().collect( joining( "\n" ) ); - } - catch( IOException ex ) - { - throw new UncheckedIOException( ex ); - } - // We want plain Strings, BigDecimals, BigIntegers to be deserialized even when unquoted - Function<String, T> plainValueFunction = string -> - { - String poorMans = "{\"value\":" + string + "}"; - JsonObject poorMansJson = jsonFactories.readerFactory() - .createReader( new StringReader( poorMans ) ) - .readObject(); - JsonValue value = poorMansJson.get( "value" ); - return fromJson( module, valueType, value ); - }; - Function<String, T> outOfStructureFunction = string -> + Converter<Object> converter = converters.converterFor(valueType); + if (converter != null) { - // Is this an unquoted plain value? - try - { - return plainValueFunction.apply( '"' + string + '"' ); - } - catch( JsonParsingException ex ) - { - return plainValueFunction.apply( string ); - } - }; - try( JsonParser parser = jsonFactories.parserFactory().createParser( new StringReader( stateString ) ) ) - { - if( parser.hasNext() ) - { - JsonParser.Event e = parser.next(); - switch( e ) - { - case VALUE_NULL: - return null; - case START_ARRAY: - case START_OBJECT: - // JSON Structure - try( JsonReader reader = jsonFactories.readerFactory() - .createReader( new StringReader( stateString ) ) ) - { - return fromJson( module, valueType, reader.read() ); - } - default: - // JSON Value out of structure - return outOfStructureFunction.apply( stateString ); - } + String stateString = readString(state); + if (isJsonNull(stateString)) { + return null; + } else { + return (T) converter.fromString(stateString); } } - catch( JsonParsingException ex ) - { - return outOfStructureFunction.apply( stateString ); + + JavaxJsonAdapter<?> adapter = adapters.adapterFor(valueType); + if (adapter != null) { + return (T) adapter.deserialize(readJsonString(state), (jsonValue, type) -> doDeserialize(module, type, jsonValue)); + } + + try (JsonReader reader = jsonFactories.readerFactory().createReader(state)) { + return fromJson(module, valueType, reader.readValue()); } - // Empty state string? - return fromJson( module, valueType, emptyJsonString ); } @Override @@ -182,6 +122,24 @@ public class JavaxJsonDeserializer extends AbstractTextDeserializer return doDeserialize( module, valueType, state ); } + private JsonValue readJsonString(Reader reader) { + String str = readString(reader); + if (isJsonNull(str)) { + return JsonValue.NULL; + } else { + return jsonFactories.provider().createValue(str); + } + } + + private boolean isJsonNull(String str) { + return "null".equals(str); + } + + private String readString(Reader reader) { + Scanner scanner = new Scanner(reader).useDelimiter("\\A"); + return scanner.hasNext() ? scanner.next() : ""; + } + @SuppressWarnings( "unchecked" ) private <T> T doDeserialize( ModuleDescriptor module, ValueType valueType, JsonValue json ) { http://git-wip-us.apache.org/repos/asf/polygene-java/blob/6b569234/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonFactories.java ---------------------------------------------------------------------- diff --git a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonFactories.java b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonFactories.java index 0a790f2..eb54c97 100644 --- a/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonFactories.java +++ b/core/spi/src/main/java/org/apache/polygene/serialization/javaxjson/JavaxJsonFactories.java @@ -50,6 +50,7 @@ public interface JavaxJsonFactories JsonWriterFactory writerFactory(); + JsonProvider provider(); /** * Creates a {@link JsonString} with the {@link Object#toString()} result on the given object. * @@ -111,6 +112,7 @@ public interface JavaxJsonFactories private JsonGeneratorFactory generatorFactory; private JsonBuilderFactory builderFactory; private JsonWriterFactory writerFactory; + private JsonProvider jsonProvider; @Override public void initialize() throws Exception @@ -118,7 +120,6 @@ public interface JavaxJsonFactories JavaxJsonSettings settings = JavaxJsonSettings.orDefault( descriptor.metaInfo( JavaxJsonSettings.class ) ); String jsonProviderClassName = settings.getJsonProviderClassName(); - JsonProvider jsonProvider; if( jsonProviderClassName == null ) { jsonProvider = JsonProvider.provider(); @@ -251,5 +252,10 @@ public interface JavaxJsonFactories } return job; } + + @Override + public JsonProvider provider() { + return jsonProvider; + } } } http://git-wip-us.apache.org/repos/asf/polygene-java/blob/6b569234/dependencies.gradle ---------------------------------------------------------------------- diff --git a/dependencies.gradle b/dependencies.gradle index bac7a6e..1b0f73e 100644 --- a/dependencies.gradle +++ b/dependencies.gradle @@ -65,7 +65,7 @@ def jcloudsVersion = '2.0.2' def jdbmVersion = '2.4' def jedisVersion = '2.9.0' def jettyVersion = '9.2.17.v20160517' // 9.3.x Tests fail! -def johnzonVersion = '1.1.1' +def johnzonVersion = '1.1.7' def jooqVersion = '3.10.6' def kotlinVersion = '1.2.31' def leveldbVersion = '0.9'
