This is an automated email from the ASF dual-hosted git repository. rmannibucau pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/johnzon.git
The following commit(s) were added to refs/heads/master by this push: new 165fb6c JOHNZON-302 enable from/to parser/generator in jsonb impl 165fb6c is described below commit 165fb6c39a6fa675fd51478b0d3f8834d2bfea17 Author: Romain Manni-Bucau <rmannibu...@apache.org> AuthorDate: Fri Feb 21 07:26:31 2020 +0100 JOHNZON-302 enable from/to parser/generator in jsonb impl --- .../apache/johnzon/core/JsonParserFactoryImpl.java | 4 ++ .../apache/johnzon/core/JsonReaderFactoryImpl.java | 15 +++--- .../org/apache/johnzon/jsonb/JohnzonJsonb.java | 40 ++++++++++++++ .../jsonb/api/experimental/JsonbExtension.java | 19 ++++++- .../johnzon/jsonb/ParserGeneratorMappingTest.java | 60 +++++++++++++++++++++ .../org/apache/johnzon/jsonb/test/JsonbRule.java | 22 ++++++++ .../org/apache/johnzon/mapper/JohnzonCores.java | 62 ++++++++++++++++++++++ .../johnzon/mapper/JohnzonReaderHandler.java | 41 -------------- .../java/org/apache/johnzon/mapper/Mapper.java | 27 +++++++++- .../org/apache/johnzon/mapper/MapperBuilder.java | 42 ++++++++------- .../org/apache/johnzon/mapper/ReaderHandler.java | 53 ------------------ 11 files changed, 260 insertions(+), 125 deletions(-) diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonParserFactoryImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonParserFactoryImpl.java index a1651df..b1ef5c6 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonParserFactoryImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonParserFactoryImpl.java @@ -71,6 +71,10 @@ public class JsonParserFactoryImpl extends AbstractJsonFactory implements JsonPa this.defaultEncoding = ofNullable(getString(ENCODING, null)).map(Charset::forName).orElse(null); } + public BufferStrategy.BufferProvider<char[]> getValueBufferProvider() { + return valueBufferProvider; + } + private JsonStreamParserImpl getDefaultJsonParserImpl(final InputStream in) { if (defaultEncoding != null) { return getDefaultJsonParserImpl(in, defaultEncoding); diff --git a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderFactoryImpl.java b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderFactoryImpl.java index 106de0a..4f98812 100644 --- a/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderFactoryImpl.java +++ b/johnzon-core/src/main/java/org/apache/johnzon/core/JsonReaderFactoryImpl.java @@ -29,6 +29,7 @@ import java.util.Map; import javax.json.JsonReader; import javax.json.JsonReaderFactory; +import javax.json.stream.JsonParser; class JsonReaderFactoryImpl extends AbstractJsonFactory implements JsonReaderFactory { static final Collection<String> SUPPORTED_CONFIG_KEYS = asList( @@ -43,25 +44,25 @@ class JsonReaderFactoryImpl extends AbstractJsonFactory implements JsonReaderFac @Override public JsonReader createReader(final Reader reader) { - return new JsonReaderImpl(parserFactory.createInternalParser(reader), getCharArrayProvider()); + return new JsonReaderImpl(parserFactory.createInternalParser(reader), parserFactory.getValueBufferProvider()); } @Override public JsonReader createReader(final InputStream in) { - return new JsonReaderImpl(parserFactory.createInternalParser(in), getCharArrayProvider()); + return new JsonReaderImpl(parserFactory.createInternalParser(in), parserFactory.getValueBufferProvider()); } @Override public JsonReader createReader(final InputStream in, final Charset charset) { - return new JsonReaderImpl(parserFactory.createInternalParser(in, charset), getCharArrayProvider()); + return new JsonReaderImpl(parserFactory.createInternalParser(in, charset), parserFactory.getValueBufferProvider()); + } + + public JsonReader createReader(final JsonParser parser) { + return new JsonReaderImpl(parser, parserFactory.getValueBufferProvider()); } @Override public Map<String, ?> getConfigInUse() { return Collections.unmodifiableMap(internalConfig); } - - private BufferStrategy.BufferProvider<char[]> getCharArrayProvider() { - return getBufferProvider().newCharProvider(1024); - } } diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonJsonb.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonJsonb.java index ba2d8b2..c3aa979 100644 --- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonJsonb.java +++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonJsonb.java @@ -32,6 +32,9 @@ import javax.json.JsonStructure; import javax.json.JsonValue; import javax.json.bind.Jsonb; import javax.json.bind.JsonbException; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonParser; + import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; @@ -533,6 +536,43 @@ public class JohnzonJsonb implements Jsonb, AutoCloseable, JsonbExtension { } } + @Override + public <T> T fromJson(final JsonParser json, final Class<T> type) { + return type.cast(fromJson(json, Type.class.cast(type))); + } + + @Override + public <T> T fromJson(final JsonParser parser, final Type runtimeType) { + try { + if (isArray(runtimeType)) { + final Class<T> type = Class.class.cast(runtimeType); + return delegate.readTypedArray(parser, type.getComponentType(), type); + } else if (JsonArray.class == runtimeType) { + return (T) delegate.readJsonArray(parser); + } else if (isCollection(runtimeType)) { + return (T) delegate.readCollection(parser, ParameterizedType.class.cast(runtimeType)); + } + final Type mappingType = unwrapPrimitiveOptional(runtimeType); + final Object object = delegate.readObject(parser, mappingType); + if (mappingType != runtimeType) { + return wrapPrimitiveOptional(object, runtimeType); + } + return (T) object; + } catch (final MapperException me) { + throw new JsonbException(me.getMessage(), me); + } + } + + @Override + public void toJson(final Object object, final JsonGenerator jsonGenerator) { + delegate.writeObjectWithGenerator(unwrapOptional(object), jsonGenerator); + } + + @Override + public void toJson(final Object object, final Type runtimeType, final JsonGenerator jsonGenerator) { + toJson(object, jsonGenerator); + } + private boolean isValueProvider(final Reader reader) { final Class<? extends Reader> key = reader.getClass(); Boolean exists = structureAwareIo.get(key); diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/api/experimental/JsonbExtension.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/api/experimental/JsonbExtension.java index aa8c342..d32e68c 100644 --- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/api/experimental/JsonbExtension.java +++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/api/experimental/JsonbExtension.java @@ -21,14 +21,29 @@ package org.apache.johnzon.jsonb.api.experimental; import java.lang.reflect.Type; import javax.json.JsonValue; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonParser; -// https://github.com/eclipse-ee4j/jsonb-api/issues/111 public interface JsonbExtension { + // https://github.com/eclipse-ee4j/jsonb-api/issues/111 + <T> T fromJsonValue(JsonValue json, Class<T> type); <T> T fromJsonValue(JsonValue json, Type runtimeType); JsonValue toJsonValue(Object object); - JsonValue toJsonValue (Object object, Type runtimeType); + JsonValue toJsonValue(Object object, Type runtimeType); + + // https://github.com/eclipse-ee4j/jsonb-api/issues/224 + + + + <T> T fromJson(JsonParser json, Class<T> type); + + <T> T fromJson(JsonParser json, Type runtimeType); + + void toJson(Object object, JsonGenerator jsonGenerator); + + void toJson(Object object, Type runtimeType, JsonGenerator jsonGenerator); } diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ParserGeneratorMappingTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ParserGeneratorMappingTest.java new file mode 100644 index 0000000..e414e81 --- /dev/null +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ParserGeneratorMappingTest.java @@ -0,0 +1,60 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.johnzon.jsonb; + +import static org.junit.Assert.assertEquals; + +import java.io.StringReader; +import java.io.StringWriter; + +import javax.json.Json; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonParser; + +import org.apache.johnzon.jsonb.test.JsonbRule; +import org.junit.Rule; +import org.junit.Test; + +public class ParserGeneratorMappingTest { + @Rule + public final JsonbRule rule = new JsonbRule(); + + @Test + public void parser() { + try (final JsonParser parser = Json.createParser(new StringReader("{\"name\":\"bar\"}"))) { + final Foo foo = rule.fromJson(parser, Foo.class); + assertEquals("bar", foo.name); + } + } + + @Test + public void generator() { + final StringWriter writer = new StringWriter(); + try (final JsonGenerator generator = Json.createGenerator(writer)) { + final Foo foo = new Foo(); + foo.name = "bar"; + rule.toJson(foo, generator); + } + assertEquals("{\"name\":\"bar\"}", writer.toString()); + } + + public static class Foo { + public String name; + } +} diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/test/JsonbRule.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/test/JsonbRule.java index bd164fa..b62d689 100644 --- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/test/JsonbRule.java +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/test/JsonbRule.java @@ -29,6 +29,8 @@ import javax.json.bind.Jsonb; import javax.json.bind.JsonbBuilder; import javax.json.bind.JsonbConfig; import javax.json.bind.JsonbException; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonParser; import org.apache.johnzon.jsonb.api.experimental.JsonbExtension; import org.junit.rules.TestRule; @@ -144,4 +146,24 @@ public class JsonbRule implements TestRule, Jsonb, JsonbExtension { public JsonValue toJsonValue(final Object object, final Type runtimeType) { return JsonbExtension.class.cast(jsonb).toJsonValue(object, runtimeType); } + + @Override + public <T> T fromJson(final JsonParser json, final Class<T> type) { + return JsonbExtension.class.cast(jsonb).fromJson(json, type); + } + + @Override + public <T> T fromJson(final JsonParser json, final Type runtimeType) { + return JsonbExtension.class.cast(jsonb).fromJson(json, runtimeType); + } + + @Override + public void toJson(final Object object, final JsonGenerator jsonGenerator) { + JsonbExtension.class.cast(jsonb).toJson(object, jsonGenerator); + } + + @Override + public void toJson(final Object object, final Type runtimeType, final JsonGenerator jsonGenerator) { + JsonbExtension.class.cast(jsonb).toJson(object, runtimeType, jsonGenerator); + } } diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonCores.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonCores.java new file mode 100644 index 0000000..91e0e2d --- /dev/null +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonCores.java @@ -0,0 +1,62 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you 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. + */ +package org.apache.johnzon.mapper; + +import static java.util.Optional.ofNullable; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; + +import javax.json.JsonReader; +import javax.json.JsonReaderFactory; +import javax.json.stream.JsonParser; + +public final class JohnzonCores { + private static final Method CREATE_READER; + + static { + Method m = null; + try { + final Class<?> jrfi = ofNullable(JohnzonCores.class.getClassLoader()) + .orElseGet(ClassLoader::getSystemClassLoader) + .loadClass("org.apache.johnzon.core.JsonReaderFactoryImpl"); + m = jrfi.getDeclaredMethod("createReader", JsonParser.class); + if (!m.isAccessible()) { + m.setAccessible(true); + } + } catch (final Exception e) { + // no-op + } + CREATE_READER = m; + } + + private JohnzonCores() { + // no-op + } + + public static JsonReader map(final JsonParser parser, final JsonReaderFactory readerFactory) { + try { + return JsonReader.class.cast(CREATE_READER.invoke(readerFactory, parser)); + } catch (final IllegalAccessException e) { + throw new IllegalStateException(e); + } catch (final InvocationTargetException e) { + throw new IllegalStateException(e.getTargetException()); + } + } +} diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonReaderHandler.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonReaderHandler.java deleted file mode 100644 index a89a354..0000000 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/JohnzonReaderHandler.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -package org.apache.johnzon.mapper; - -import org.apache.johnzon.core.JsonLongImpl; -import org.apache.johnzon.core.JsonReaderImpl; - -import javax.json.JsonNumber; -import javax.json.JsonReader; -import javax.json.JsonValue; - -// just for classloading -public class JohnzonReaderHandler { - private JohnzonReaderHandler() { - // no-op - } - - public static JsonValue read(final JsonReader reader) { - return JsonReaderImpl.class.cast(reader).readValue(); - } - - public static boolean isLong(final JsonNumber number) { - return JsonLongImpl.class.isInstance(number); - } -} diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java index 4a9639c..3616bf7 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java @@ -49,6 +49,7 @@ import javax.json.JsonValue; import javax.json.spi.JsonProvider; import javax.json.stream.JsonGenerator; import javax.json.stream.JsonGeneratorFactory; +import javax.json.stream.JsonParser; import org.apache.johnzon.mapper.internal.JsonPointerTracker; import org.apache.johnzon.mapper.reflection.JohnzonCollectionType; @@ -62,7 +63,6 @@ public class Mapper implements Closeable { protected final JsonGeneratorFactory generatorFactory; protected final JsonBuilderFactory builderFactory; protected final JsonProvider provider; - protected final ReaderHandler readerHandler; protected final Collection<Closeable> closeables; protected final Charset charset; @@ -75,7 +75,6 @@ public class Mapper implements Closeable { this.provider = provider; this.config = config; this.mappings = new Mappings(config); - this.readerHandler = ReaderHandler.create(readerFactory); this.closeables = closeables; this.charset = config.getEncoding(); } @@ -298,6 +297,12 @@ public class Mapper implements Closeable { } } + public <T> T readObject(final JsonParser stream, final Type clazz) { + try (final JsonReader reader = JohnzonCores.map(stream, readerFactory)) { + return mapObject(clazz, reader); + } + } + public <T> T readObject(final InputStream stream, final Type clazz) { try (final JsonReader reader = charset == null ? readerFactory.createReader(stream(stream)) : readerFactory.createReader( stream(stream), charset)) { @@ -325,6 +330,12 @@ public class Mapper implements Closeable { } } + public <T> Collection<T> readCollection(final JsonParser stream, final ParameterizedType genericType) { + try (final JsonReader reader = JohnzonCores.map(stream, readerFactory)) { + return mapObject(genericType, reader); + } + } + public <T> T[] readArray(final Reader stream, final Class<T> clazz) { try (final JsonReader reader = readerFactory.createReader(stream(stream))) { return (T[]) mapArray(clazz, reader); @@ -343,12 +354,24 @@ public class Mapper implements Closeable { } } + public <T> T readTypedArray(final JsonParser parser, final Class<?> elementType, final Class<T> arrayType) { + try (final JsonReader reader = JohnzonCores.map(parser, readerFactory)) { + return arrayType.cast(mapArray(elementType, reader)); + } + } + public JsonArray readJsonArray(final Reader stream) { try (final JsonReader reader = readerFactory.createReader(stream(stream))) { return reader.readArray(); } } + public JsonArray readJsonArray(final JsonParser stream) { + try (final JsonReader reader = JohnzonCores.map(stream, readerFactory)) { + return reader.readArray(); + } + } + public <T> T[] readArray(final InputStream stream, final Class<T> clazz) { try (final JsonReader reader = charset == null ? readerFactory.createReader(stream(stream)): readerFactory.createReader(stream(stream), charset)) { return (T[]) mapArray(clazz, reader); diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java index 0de82c4..81cc049 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java @@ -169,32 +169,34 @@ public class MapperBuilder { if (bufferStrategy != null) { config.put("org.apache.johnzon.buffer-strategy", bufferStrategy); } - if (pretty) { - config.put(JsonGenerator.PRETTY_PRINTING, true); - } if (generatorFactory == null) { + if (pretty) { + config.put(JsonGenerator.PRETTY_PRINTING, true); + } generatorFactory = provider.createGeneratorFactory(config); } - config.remove(JsonGenerator.PRETTY_PRINTING); // doesnt mean anything anymore for reader - if (supportsComments) { - config.put("org.apache.johnzon.supports-comments", "true"); - } - if (maxSize > 0) { - config.put("org.apache.johnzon.max-string-length", maxSize); - } - if (bufferSize > 0) { - config.put("org.apache.johnzon.default-char-buffer", bufferSize); - } - if (autoAdjustStringBuffers) { - config.put("org.apache.johnzon.auto-adjust-buffer", true); - } - if (encoding != null) { - config.put("org.apache.johnzon.encoding", encoding.name()); + if (readerFactory == null) { + config.remove(JsonGenerator.PRETTY_PRINTING); // doesnt mean anything anymore for reader + if (supportsComments) { + config.put("org.apache.johnzon.supports-comments", "true"); + } + if (maxSize > 0) { + config.put("org.apache.johnzon.max-string-length", maxSize); + } + if (bufferSize > 0) { + config.put("org.apache.johnzon.default-char-buffer", bufferSize); + } + if (autoAdjustStringBuffers) { + config.put("org.apache.johnzon.auto-adjust-buffer", true); + } + if (encoding != null) { + config.put("org.apache.johnzon.encoding", encoding.name()); + } + readerFactory = provider.createReaderFactory(config); } - } - if (this.provider == null) { + } else if (this.provider == null) { this.provider = JsonProvider.provider(); } if (builderFactory == null) { diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ReaderHandler.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ReaderHandler.java deleted file mode 100644 index c317cab..0000000 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ReaderHandler.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you 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. - */ -package org.apache.johnzon.mapper; - -import javax.json.JsonNumber; -import javax.json.JsonReader; -import javax.json.JsonReaderFactory; -import javax.json.JsonValue; - -public class ReaderHandler { - private final boolean johnzon; - - private ReaderHandler(final boolean johnzon) { - this.johnzon = johnzon; - } - - public static ReaderHandler create(final JsonReaderFactory readerFactory) { - if (readerFactory.getClass().getName().equals("org.apache.johnzon.core.JsonReaderFactoryImpl")) { - return new ReaderHandler(true); - } - return new ReaderHandler(false); - } - - public JsonValue read(final JsonReader reader) { - if (johnzon) { - return JohnzonReaderHandler.read(reader); - } - return reader.read(); - } - - public boolean isJsonLong(final JsonNumber number) { - if (johnzon) { - return JohnzonReaderHandler.isLong(number); - } - return false; // will be slower but not a big deal - } -}