Hello guys, Trying to write quickly a mail about that if you want to join the effort - I'll need to move on something else tomorrow.
Updated jsonb-api. Started to impl some parts but that's really just a first pass to have something and not forget to read some config later. What is not handled is mainly lists (either serialization of an object from a list or a list itself, spec expects Type to be List<T> and the T instance to be passed to the serializer) + root objects (see other thread about ObjectConverter). I needed to split ObjectConverter in two to avoid to redefine other API (Reader/Writer - feel free to extract the 3 classes I created in their own files if you prefer and to rename it if names are misleading). Also since we use reader and not parser we need to reparse the loaded instance for jsonb (de)serializer api. This is not as optimial as it should so I guess we'll need to move to JsonParser at some point (+ it will make our mapper symmetric which is not bad ;)). I probably forget something but at least there is a thread now to shout my way if you need ;). Romain Manni-Bucau @rmannibucau <https://twitter.com/rmannibucau> | Blog <http://rmannibucau.wordpress.com> | Github <https://github.com/rmannibucau> | LinkedIn <https://www.linkedin.com/in/rmannibucau> | Tomitriber <http://www.tomitribe.com> | JavaEE Factory <https://javaeefactory-rmannibucau.rhcloud.com> ---------- Forwarded message ---------- From: <[email protected]> Date: 2016-05-10 20:21 GMT+02:00 Subject: incubator-johnzon git commit: upgrading jsonb-api + filling some TODO but not complete + splitting ObjectConverter in two (read/write) To: [email protected] Repository: incubator-johnzon Updated Branches: refs/heads/master 04fbc250a -> 745668a81 upgrading jsonb-api + filling some TODO but not complete + splitting ObjectConverter in two (read/write) Project: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/commit/745668a8 Tree: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/tree/745668a8 Diff: http://git-wip-us.apache.org/repos/asf/incubator-johnzon/diff/745668a8 Branch: refs/heads/master Commit: 745668a81818ec37aed31dc6db868740191a9806 Parents: 04fbc25 Author: Romain manni-Bucau <[email protected]> Authored: Tue May 10 20:21:03 2016 +0200 Committer: Romain manni-Bucau <[email protected]> Committed: Tue May 10 20:21:03 2016 +0200 ---------------------------------------------------------------------- .../apache/johnzon/jsonb/JohnzonBuilder.java | 70 ++++++++++++- .../apache/johnzon/jsonb/JsonbAccessMode.java | 70 +++++++++++-- .../JohnzonDeserializationContext.java | 48 +++++++++ .../serializer/JohnzonSerializationContext.java | 48 +++++++++ .../apache/johnzon/jsonb/SerializerTest.java | 105 +++++++++++++++++++ .../java/org/apache/johnzon/mapper/Mapper.java | 2 +- .../apache/johnzon/mapper/MapperBuilder.java | 14 ++- .../org/apache/johnzon/mapper/MapperConfig.java | 50 ++++++--- .../apache/johnzon/mapper/MappingGenerator.java | 5 +- .../johnzon/mapper/MappingGeneratorImpl.java | 33 +++--- .../apache/johnzon/mapper/MappingParser.java | 2 + .../johnzon/mapper/MappingParserImpl.java | 13 ++- .../org/apache/johnzon/mapper/Mappings.java | 68 +++++++++--- .../apache/johnzon/mapper/ObjectConverter.java | 18 +++- .../johnzon/mapper/access/AccessMode.java | 3 + .../johnzon/mapper/access/FieldAccessMode.java | 11 ++ .../mapper/access/FieldAndMethodAccessMode.java | 13 +++ .../johnzon/mapper/access/MethodAccessMode.java | 16 +++ .../apache/johnzon/mapper/MapperConfigTest.java | 82 ++++++++------- .../ObjectConverterWithAnnotationTest.java | 2 +- .../apache/johnzon/mapper/ObjectTypeTest.java | 6 +- .../main/java/javax/json/bind/JsonbConfig.java | 12 +++ .../bind/annotation/JsonbTypeDeserializer.java | 35 +++++++ .../bind/annotation/JsonbTypeSerializer.java | 35 +++++++ .../bind/serializer/DeserializationContext.java | 33 ++++++ .../json/bind/serializer/JsonbDeserializer.java | 30 ++++++ .../json/bind/serializer/JsonbSerializer.java | 25 +++++ .../bind/serializer/SerializationContext.java | 29 +++++ 28 files changed, 771 insertions(+), 107 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java index 13661c2..390c2bc 100644 --- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java +++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java @@ -23,11 +23,14 @@ import org.apache.johnzon.core.JsonGeneratorFactoryImpl; import org.apache.johnzon.jsonb.cdi.CDIs; import org.apache.johnzon.jsonb.converter.JohnzonJsonbAdapter; import org.apache.johnzon.jsonb.factory.SimpleJohnzonAdapterFactory; +import org.apache.johnzon.jsonb.serializer.JohnzonDeserializationContext; +import org.apache.johnzon.jsonb.serializer.JohnzonSerializationContext; import org.apache.johnzon.jsonb.spi.JohnzonAdapterFactory; import org.apache.johnzon.mapper.Adapter; import org.apache.johnzon.mapper.Converter; import org.apache.johnzon.mapper.Mapper; import org.apache.johnzon.mapper.MapperBuilder; +import org.apache.johnzon.mapper.ObjectConverter; import org.apache.johnzon.mapper.internal.AdapterKey; import org.apache.johnzon.mapper.internal.ConverterAdapter; @@ -39,8 +42,11 @@ import javax.json.bind.annotation.JsonbVisibility; import javax.json.bind.config.BinaryDataStrategy; import javax.json.bind.config.PropertyNamingStrategy; import javax.json.bind.config.PropertyVisibilityStrategy; +import javax.json.bind.serializer.JsonbDeserializer; +import javax.json.bind.serializer.JsonbSerializer; import javax.json.spi.JsonProvider; import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonParserFactory; import java.lang.reflect.Field; import java.lang.reflect.Method; import java.lang.reflect.Modifier; @@ -72,6 +78,8 @@ import java.util.SimpleTimeZone; import java.util.TimeZone; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.concurrent.atomic.AtomicReference; +import java.util.function.Supplier; import java.util.stream.Stream; import static java.time.format.DateTimeFormatter.ofPattern; @@ -107,6 +115,25 @@ public class JohnzonBuilder implements JsonbBuilder { builder.setGeneratorFactory(jsonp.createGeneratorFactory(generatorConfig())); builder.setReaderFactory(jsonp.createReaderFactory(emptyMap())); } + final Supplier<JsonParserFactory> parserFactoryProvider = new Supplier<JsonParserFactory>() { // thread safety is not mandatory + private final AtomicReference<JsonParserFactory> ref = new AtomicReference<>(); + + @Override + public JsonParserFactory get() { + JsonParserFactory factory = ref.get(); + if (factory == null) { + factory = doCreate(); + if (!ref.compareAndSet(null, factory)) { + factory = ref.get(); + } + } + return factory; + } + + private JsonParserFactory doCreate() { + return (jsonp == null ? JsonProvider.provider() : jsonp).createParserFactory(emptyMap()); + } + }; if (config == null) { config = new JsonbConfig(); @@ -189,7 +216,7 @@ public class JohnzonBuilder implements JsonbBuilder { propertyNamingStrategy, orderValue, visibilityStrategy, !namingStrategyValue.orElse("").equals(PropertyNamingStrategy.CASE_INSENSITIVE), defaultConverters, - factory); + factory, parserFactoryProvider); builder.setAccessMode(accessMode); @@ -240,6 +267,40 @@ public class JohnzonBuilder implements JsonbBuilder { builder.setReadAttributeBeforeWrite( config.getProperty("johnzon.readAttributeBeforeWrite").map(Boolean.class::cast).orElse(false)); + config.getProperty(JsonbConfig.SERIALIZERS).map(JsonbSerializer[].class::cast).ifPresent(serializers -> { + Stream.of(serializers).forEach(s -> { + final ParameterizedType pt = findPT(s, JsonbSerializer.class); + if (pt == null) { + throw new IllegalArgumentException(s + " doesn't implement JsonbSerializer"); + } + final Type[] args = pt.getActualTypeArguments(); + // TODO: support PT in ObjectConverter (list) + if (args.length != 1 || !Class.class.isInstance(args[0])) { + throw new IllegalArgumentException("We only support serializer on Class for now"); + } + builder.addObjectConverter( + Class.class.cast(args[0]), (ObjectConverter.Writer) + (instance, jsonbGenerator) -> s.serialize(instance, jsonbGenerator.getJsonGenerator(), new JohnzonSerializationContext(jsonbGenerator))); + }); + }); + config.getProperty(JsonbConfig.DESERIALIZERS).map(JsonbDeserializer[].class::cast).ifPresent(deserializers -> { + Stream.of(deserializers).forEach(d -> { + final ParameterizedType pt = findPT(d, JsonbDeserializer.class); + if (pt == null) { + throw new IllegalArgumentException(d + " doesn't implement JsonbDeserializer"); + } + final Type[] args = pt.getActualTypeArguments(); + if (args.length != 1 || !Class.class.isInstance(args[0])) { + throw new IllegalArgumentException("We only support deserializer on Class for now"); + } + // TODO: support PT in ObjectConverter (list) + builder.addObjectConverter( + Class.class.cast(args[0]), (ObjectConverter.Reader) + (jsonObject, targetType, parser) -> d.deserialize( + parserFactoryProvider.get().createParser(jsonObject), new JohnzonDeserializationContext(parser), targetType)); + }); + }); + final boolean useCdi = cdiIntegration != null && cdiIntegration.isCanWrite(); final Mapper mapper = builder.addCloseable(accessMode).build(); @@ -261,6 +322,13 @@ public class JohnzonBuilder implements JsonbBuilder { } : new JohnsonJsonb(mapper); } + private ParameterizedType findPT(final Object s, final Class<?> type) { + return ParameterizedType.class.cast( + Stream.of(s.getClass().getGenericInterfaces()) + .filter(i -> ParameterizedType.class.isInstance(i) && ParameterizedType.class.cast(i).getRawType() == type) + .findFirst().orElse(null)); + } + private Object getBeanManager() { if (beanManager == null) { try { // don't trigger CDI is not there http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java index 4a0a340..fa2e536 100644 --- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java +++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JsonbAccessMode.java @@ -25,8 +25,11 @@ import org.apache.johnzon.jsonb.converter.JsonbLocalDateTimeConverter; import org.apache.johnzon.jsonb.converter.JsonbNumberConverter; import org.apache.johnzon.jsonb.converter.JsonbValueConverter; import org.apache.johnzon.jsonb.converter.JsonbZonedDateTimeConverter; +import org.apache.johnzon.jsonb.serializer.JohnzonDeserializationContext; +import org.apache.johnzon.jsonb.serializer.JohnzonSerializationContext; import org.apache.johnzon.jsonb.spi.JohnzonAdapterFactory; import org.apache.johnzon.mapper.Adapter; +import org.apache.johnzon.mapper.ObjectConverter; import org.apache.johnzon.mapper.access.AccessMode; import org.apache.johnzon.mapper.access.FieldAccessMode; import org.apache.johnzon.mapper.access.FieldAndMethodAccessMode; @@ -44,9 +47,14 @@ import javax.json.bind.annotation.JsonbProperty; import javax.json.bind.annotation.JsonbPropertyOrder; import javax.json.bind.annotation.JsonbTransient; import javax.json.bind.annotation.JsonbTypeAdapter; +import javax.json.bind.annotation.JsonbTypeDeserializer; +import javax.json.bind.annotation.JsonbTypeSerializer; import javax.json.bind.config.PropertyNamingStrategy; import javax.json.bind.config.PropertyOrderStrategy; import javax.json.bind.config.PropertyVisibilityStrategy; +import javax.json.bind.serializer.JsonbDeserializer; +import javax.json.bind.serializer.JsonbSerializer; +import javax.json.stream.JsonParserFactory; import java.io.Closeable; import java.io.IOException; import java.lang.annotation.Annotation; @@ -74,6 +82,7 @@ import java.util.OptionalLong; import java.util.TreeMap; import java.util.function.BiConsumer; import java.util.function.Function; +import java.util.function.Supplier; import java.util.stream.Stream; import static java.util.Arrays.asList; @@ -89,10 +98,12 @@ public class JsonbAccessMode implements AccessMode, Closeable { private final Map<AdapterKey, Adapter<?, ?>> defaultConverters; private final JohnzonAdapterFactory factory; private final Collection<JohnzonAdapterFactory.Instance<?>> toRelease = new ArrayList<>(); + private final Supplier<JsonParserFactory> parserFactory; public JsonbAccessMode(final PropertyNamingStrategy propertyNamingStrategy, final String orderValue, final PropertyVisibilityStrategy visibilityStrategy, final boolean caseSensitive, - final Map<AdapterKey, Adapter<?, ?>> defaultConverters, final JohnzonAdapterFactory factory) { + final Map<AdapterKey, Adapter<?, ?>> defaultConverters, final JohnzonAdapterFactory factory, + final Supplier<JsonParserFactory> parserFactory) { this.naming = propertyNamingStrategy; this.order = orderValue; this.visibility = visibilityStrategy; @@ -100,6 +111,7 @@ public class JsonbAccessMode implements AccessMode, Closeable { this.delegate = new FieldAndMethodAccessMode(true, true); this.defaultConverters = defaultConverters; this.factory = factory; + this.parserFactory = parserFactory; } @Override @@ -266,13 +278,11 @@ public class JsonbAccessMode implements AccessMode, Closeable { final Adapter converter; if (adapter != null) { final Class<? extends JsonbAdapter> value = adapter.value(); - final ParameterizedType pt = ParameterizedType.class.cast( - Stream.of(value.getGenericInterfaces()) - .filter(i -> ParameterizedType.class.isInstance(i) && ParameterizedType.class.cast(i).getRawType() == JsonbAdapter.class).findFirst().orElse(null)); + final ParameterizedType pt = findPt(value, JsonbAdapter.class); if (pt == null) { throw new IllegalArgumentException(value + " doesn't implement JsonbAdapter"); } - final JohnzonAdapterFactory.Instance<? extends JsonbAdapter> instance = newAdapter(value); + final JohnzonAdapterFactory.Instance<? extends JsonbAdapter> instance = newInstance(value); toRelease.add(instance); final Type[] actualTypeArguments = pt.getActualTypeArguments(); converter = new JohnzonJsonbAdapter(instance.getValue(), actualTypeArguments[0], actualTypeArguments[1]); @@ -296,7 +306,13 @@ public class JsonbAccessMode implements AccessMode, Closeable { return converter; } - private JohnzonAdapterFactory.Instance<? extends JsonbAdapter> newAdapter(final Class<? extends JsonbAdapter> value) { + private ParameterizedType findPt(final Class<?> value, final Class<?> type) { + return ParameterizedType.class.cast( + Stream.of(value.getGenericInterfaces()) + .filter(i -> ParameterizedType.class.isInstance(i) && ParameterizedType.class.cast(i).getRawType() == type).findFirst().orElse(null)); + } + + private JohnzonAdapterFactory.Instance newInstance(final Class<?> value) { return factory.create(value); } @@ -326,6 +342,7 @@ public class JsonbAccessMode implements AccessMode, Closeable { } // we are visible + final JsonbTypeSerializer serializer = initialReader.getAnnotation(JsonbTypeSerializer.class); final JsonbProperty property = initialReader.getAnnotation(JsonbProperty.class); final JsonbNillable nillable = initialReader.getClassOrPackageAnnotation(JsonbNillable.class); final boolean isNillable = nillable != null || (property != null && property.nillable()); @@ -343,6 +360,21 @@ public class JsonbAccessMode implements AccessMode, Closeable { throw new IllegalArgumentException(e); } + final ObjectConverter.Writer writer; + if (serializer != null) { + final Class<? extends JsonbSerializer> value = serializer.value(); + final ParameterizedType pt = findPt(value, JsonbSerializer.class); + if (pt == null) { + throw new IllegalArgumentException(value + " doesn't implement JsonbSerializer"); + } + final JohnzonAdapterFactory.Instance<? extends JsonbSerializer> instance = newInstance(value); + toRelease.add(instance); + writer = (instance1, jsonbGenerator) -> + instance.getValue().serialize(instance1, jsonbGenerator.getJsonGenerator(), new JohnzonSerializationContext(jsonbGenerator)); + } else { + writer = null; + } + // handle optionals since mapper is still only java 7 final Type type; final Function<Object, Object> reader; @@ -371,6 +403,11 @@ public class JsonbAccessMode implements AccessMode, Closeable { } @Override + public ObjectConverter.Writer<?> findObjectConverterWriter() { + return writer; + } + + @Override public Type getType() { return type; } @@ -427,6 +464,7 @@ public class JsonbAccessMode implements AccessMode, Closeable { } // we are visible + final JsonbTypeDeserializer deserializer = initialWriter.getAnnotation(JsonbTypeDeserializer.class); final JsonbProperty property = initialWriter.getAnnotation(JsonbProperty.class); final JsonbNillable nillable = initialWriter.getClassOrPackageAnnotation(JsonbNillable.class); final boolean isNillable = nillable != null || (property != null && property.nillable()); @@ -444,6 +482,21 @@ public class JsonbAccessMode implements AccessMode, Closeable { throw new IllegalArgumentException(e); } + final ObjectConverter.Reader reader; + if (deserializer != null) { + final Class<? extends JsonbDeserializer> value = deserializer.value(); + final ParameterizedType pt = findPt(value, JsonbDeserializer.class); + if (pt == null) { + throw new IllegalArgumentException(value + " doesn't implement JsonbDeserializer"); + } + final JohnzonAdapterFactory.Instance<? extends JsonbDeserializer> instance = newInstance(value); + toRelease.add(instance); + reader = (jsonObject, targetType, parser) -> + instance.getValue().deserialize(parserFactory.get().createParser(jsonObject), new JohnzonDeserializationContext(parser), targetType); + } else { + reader = null; + } + // handle optionals since mapper is still only java 7 final Type type; final BiConsumer<Object, Object> writer; @@ -472,6 +525,11 @@ public class JsonbAccessMode implements AccessMode, Closeable { } @Override + public ObjectConverter.Reader<?> findObjectConverterReader() { + return reader; + } + + @Override public Type getType() { return type; } http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/serializer/JohnzonDeserializationContext.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/serializer/JohnzonDeserializationContext.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/serializer/JohnzonDeserializationContext.java new file mode 100644 index 0000000..2049603 --- /dev/null +++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/serializer/JohnzonDeserializationContext.java @@ -0,0 +1,48 @@ +/* + * 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.serializer; + +import org.apache.johnzon.mapper.MappingParser; + +import javax.json.bind.serializer.DeserializationContext; +import javax.json.stream.JsonParser; +import java.lang.reflect.Type; + +public class JohnzonDeserializationContext implements DeserializationContext { + private final MappingParser runtime; + + public JohnzonDeserializationContext(final MappingParser runtime) { + this.runtime = runtime; + } + + @Override + public <T> T deserialize(final Class<T> clazz, final JsonParser parser) { + return null; + } + + @Override + public <T> T deserialize(final Type type, final JsonParser parser) { + return null; + } + + @Override + public <T> T convertDefault(final Class<T> clazz, final String value) { + return null; + } +} http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/serializer/JohnzonSerializationContext.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/serializer/JohnzonSerializationContext.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/serializer/JohnzonSerializationContext.java new file mode 100644 index 0000000..d40ca24 --- /dev/null +++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/serializer/JohnzonSerializationContext.java @@ -0,0 +1,48 @@ +/* + * 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.serializer; + +import org.apache.johnzon.mapper.MappingGenerator; + +import javax.json.bind.serializer.SerializationContext; +import javax.json.stream.JsonGenerator; + +// TODO: fix it +public class JohnzonSerializationContext implements SerializationContext { + private final MappingGenerator runtime; + + public JohnzonSerializationContext(final MappingGenerator runtime) { + this.runtime = runtime; + } + + @Override + public <T> void serialize(final String key, final T object, final JsonGenerator generator) { + runtime.writeObject(object, generator); + } + + @Override + public <T> void serialize(final T object, final JsonGenerator generator) { + runtime.writeObject(object, generator); + } + + @Override + public <T> String convertDefault(final T obj, final JsonGenerator generator) { + return runtime.convert(obj); + } +} http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java new file mode 100644 index 0000000..475fbcc --- /dev/null +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java @@ -0,0 +1,105 @@ +/* + * 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 org.junit.Test; + +import javax.json.bind.Jsonb; +import javax.json.bind.JsonbBuilder; +import javax.json.bind.annotation.JsonbTypeDeserializer; +import javax.json.bind.annotation.JsonbTypeSerializer; +import javax.json.bind.serializer.DeserializationContext; +import javax.json.bind.serializer.JsonbDeserializer; +import javax.json.bind.serializer.JsonbSerializer; +import javax.json.bind.serializer.SerializationContext; +import javax.json.stream.JsonGenerator; +import javax.json.stream.JsonParser; +import java.lang.reflect.Type; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; + +// TODO: enhance +public class SerializerTest { + @Test + public void roundTrip() { + final Jsonb jsonb = JsonbBuilder.create(); + + final String json = "{\"foo\":{\"full\":true,\"name\":\"SerializerTest\"}}"; + + final Foo foo = new Foo(); + foo.name = "SerializerTest"; + final Wrapper wrapper = new Wrapper(); + wrapper.foo = foo; + + assertEquals(json, jsonb.toJson(wrapper)); + + final Wrapper deser = jsonb.fromJson(json, Wrapper.class); + assertEquals(foo.name, deser.foo.name); + assertEquals(foo.name.length(), deser.foo.value); + assertTrue(deser.foo.flag); + } + + public static class Foo { + public String name; + public int value; + public boolean flag; + } + + public static class Wrapper { + @JsonbTypeSerializer(FooSer.class) + @JsonbTypeDeserializer(FooDeser.class) + public Foo foo; + } + + public static class FooDeser implements JsonbDeserializer<Foo> { + @Override + public Foo deserialize(final JsonParser parser, final DeserializationContext ctx, final Type rtType) { + final Foo f = new Foo(); + assertTrue(parser.hasNext()); + assertEquals(JsonParser.Event.START_OBJECT, parser.next()); + assertTrue(parser.hasNext()); + assertEquals(JsonParser.Event.KEY_NAME, parser.next()); + assertEquals("full", parser.getString()); + assertTrue(parser.hasNext()); + assertEquals(JsonParser.Event.VALUE_TRUE, parser.next()); + assertTrue(parser.hasNext()); + assertEquals(JsonParser.Event.KEY_NAME, parser.next()); + assertEquals("name", parser.getString()); + assertTrue(parser.hasNext()); + assertEquals(JsonParser.Event.VALUE_STRING, parser.next()); + f.name = parser.getString(); + assertTrue(parser.hasNext()); + assertEquals(JsonParser.Event.END_OBJECT, parser.next()); + + // to be sure we passed there + f.flag = true; + f.value = f.name.length(); + return f; + } + } + + public static class FooSer implements JsonbSerializer<Foo> { + @Override + public void serialize(final Foo obj, final JsonGenerator generator, final SerializationContext ctx) { + generator.write("full", true); + generator.write("name", obj.name); + } + } +} http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mapper.java ---------------------------------------------------------------------- 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 986f4c3..c8a163e 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 @@ -136,7 +136,7 @@ public class Mapper implements Closeable { RuntimeException originalException = null; try { - mappingGenerator.doWriteObject(object, true); + mappingGenerator.doWriteObject(object, generator, true); } catch (RuntimeException e) { originalException = e; } finally { http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java ---------------------------------------------------------------------- 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 d354950..73c32da 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 @@ -122,7 +122,8 @@ public class MapperBuilder { private AccessMode accessMode; private Charset encoding = Charset.forName(System.getProperty("johnzon.mapper.encoding", "UTF-8")); private ConcurrentMap<AdapterKey, Adapter<?, ?>> adapters = new ConcurrentHashMap<AdapterKey, Adapter<?, ?>>(DEFAULT_CONVERTERS); - private Map<Class<?>, ObjectConverter<?>> objectConverters = new HashMap<Class<?>, ObjectConverter<?>>(); + private Map<Class<?>, ObjectConverter.Reader<?>> objectConverterReaders = new HashMap<Class<?>, ObjectConverter.Reader<?>>(); + private Map<Class<?>, ObjectConverter.Writer<?>> objectConverterWriters = new HashMap<Class<?>, ObjectConverter.Writer<?>>(); private Map<Class<?>, String[]> ignoredForFields = new HashMap<Class<?>, String[]>(); public Mapper build() { @@ -187,7 +188,7 @@ public class MapperBuilder { return new Mapper( readerFactory, generatorFactory, new MapperConfig( - adapters, objectConverters, + adapters, objectConverterWriters, objectConverterReaders, version, close, skipNull, skipEmptyArray, treatByteArrayAsBase64, treatByteArrayAsBase64URL, readAttributeBeforeWrite, @@ -342,8 +343,13 @@ public class MapperBuilder { return this; } - public <T> MapperBuilder addObjectConverter(final Class<T> targetType, final ObjectConverter<T> objectConverter) { - this.objectConverters.put(targetType, objectConverter); + public <T> MapperBuilder addObjectConverter(final Class<T> targetType, final MapperConverter objectConverter) { + if (ObjectConverter.Reader.class.isInstance(objectConverter)) { + this.objectConverterReaders.put(targetType, ObjectConverter.Reader.class.cast(objectConverter)); + } + if (ObjectConverter.Writer.class.isInstance(objectConverter)) { + this.objectConverterWriters.put(targetType, ObjectConverter.Writer.class.cast(objectConverter)); + } return this; } http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java index afd40b2..590c238 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java @@ -37,7 +37,7 @@ import java.util.concurrent.ConcurrentMap; */ class MapperConfig implements Cloneable { - private static final ObjectConverter NO_CONVERTER = new ObjectConverter() { + private static final ObjectConverter.Codec NO_CONVERTER = new ObjectConverter.Codec() { @Override public void writeJson(Object instance, MappingGenerator jsonbGenerator) { // just a dummy @@ -59,15 +59,18 @@ class MapperConfig implements Cloneable { private final AccessMode accessMode; private final Charset encoding; private final ConcurrentMap<AdapterKey, Adapter<?, ?>> adapters; - private final Map<Class<?>, ObjectConverter<?>> objectConverters; + private final Map<Class<?>, ObjectConverter.Writer<?>> objectConverterWriters; + private final Map<Class<?>, ObjectConverter.Reader<?>> objectConverterReaders; private final Comparator<String> attributeOrder; - private final Map<Class<?>, ObjectConverter<?>> objectConverterCache; + private final Map<Class<?>, ObjectConverter.Writer<?>> objectConverterWriterCache; + private final Map<Class<?>, ObjectConverter.Reader<?>> objectConverterReaderCache; //disable checkstyle for 10+ parameters //CHECKSTYLE:OFF public MapperConfig(final ConcurrentMap<AdapterKey, Adapter<?, ?>> adapters, - final Map<Class<?>, ObjectConverter<?>> objectConverters, + final Map<Class<?>, ObjectConverter.Writer<?>> objectConverterWriters, + final Map<Class<?>, ObjectConverter.Reader<?>> objectConverterReaders, final int version, final boolean close, final boolean skipNull, final boolean skipEmptyArray, final boolean treatByteArrayAsBase64, final boolean treatByteArrayAsBase64URL, @@ -75,7 +78,8 @@ class MapperConfig implements Cloneable { final AccessMode accessMode, final Charset encoding, final Comparator<String> attributeOrder) { //CHECKSTYLE:ON - this.objectConverters = objectConverters; + this.objectConverterWriters = objectConverterWriters; + this.objectConverterReaders = objectConverterReaders; this.version = version; this.close = close; this.skipNull = skipNull; @@ -88,7 +92,8 @@ class MapperConfig implements Cloneable { this.adapters = adapters; this.attributeOrder = attributeOrder; - this.objectConverterCache = new HashMap<Class<?>, ObjectConverter<?>>(objectConverters.size()); + this.objectConverterWriterCache = new HashMap<Class<?>, ObjectConverter.Writer<?>>(objectConverterWriters.size()); + this.objectConverterReaderCache = new HashMap<Class<?>, ObjectConverter.Reader<?>>(objectConverterReaders.size()); } public Adapter findAdapter(final Type aClass) { @@ -123,13 +128,22 @@ class MapperConfig implements Cloneable { * * @throws IllegalArgumentException if {@code clazz} is {@code null} */ - public ObjectConverter findObjectConverter(Class clazz) { + public ObjectConverter.Reader findObjectConverterReader(Class clazz) { + return findObjectConverter(clazz, objectConverterReaders, objectConverterReaderCache); + } + public ObjectConverter.Writer findObjectConverterWriter(Class clazz) { + return findObjectConverter(clazz, objectConverterWriters, objectConverterWriterCache); + } + + private <T> T findObjectConverter(final Class clazz, + final Map<Class<?>, T> from, + final Map<Class<?>, T> cache) { if (clazz == null) { throw new IllegalArgumentException("clazz must not be null"); } // first lets look in our cache - ObjectConverter<?> converter = objectConverterCache.get(clazz); + T converter = cache.get(clazz); if (converter != null && converter != NO_CONVERTER) { return converter; } @@ -142,9 +156,9 @@ class MapperConfig implements Cloneable { // we get called the first time for this class // lets search... - Map<Class<?>, ObjectConverter<?>> matchingConverters = new HashMap<Class<?>, ObjectConverter<?>>(); + Map<Class<?>, T> matchingConverters = new HashMap<Class<?>, T>(); - for (Map.Entry<Class<?>, ObjectConverter<?>> entry : objectConverters.entrySet()) { + for (Map.Entry<Class<?>, T> entry : from.entrySet()) { if (clazz == entry.getKey()) { converter = entry.getValue(); @@ -157,12 +171,12 @@ class MapperConfig implements Cloneable { } if (converter != null) { - objectConverterCache.put(clazz, converter); + cache.put(clazz, converter); return converter; } if (matchingConverters.isEmpty()) { - objectConverterCache.put(clazz, NO_CONVERTER); + cache.put(clazz, (T) NO_CONVERTER); return null; } @@ -195,9 +209,9 @@ class MapperConfig implements Cloneable { } if (converter == null) { - objectConverterCache.put(clazz, NO_CONVERTER); + cache.put(clazz, (T) NO_CONVERTER); } else { - objectConverterCache.put(clazz, converter); + cache.put(clazz, converter); } return converter; @@ -243,8 +257,12 @@ class MapperConfig implements Cloneable { return adapters; } - public Map<Class<?>, ObjectConverter<?>> getObjectConverters() { - return objectConverters; + public Map<Class<?>, ObjectConverter.Writer<?>> getObjectConverterWriters() { + return objectConverterWriters; + } + + public Map<Class<?>, ObjectConverter.Reader<?>> getObjectConverterReaders() { + return objectConverterReaders; } public Comparator<String> getAttributeOrder() { http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGenerator.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGenerator.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGenerator.java index b3719a2..bd02cfe 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGenerator.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGenerator.java @@ -53,9 +53,12 @@ public interface MappingGenerator { * "firstName":"Karl", "lastName":"SomeName", "address":{"street":"mystreet"} * </pre> * @param o the object to write + * @param generator the jsonp generator to use * @return itself, for easier chaining of commands */ - MappingGenerator writeObject(Object o); + MappingGenerator writeObject(Object o, JsonGenerator generator); + // @Experimental + <T> String convert(T obj); } http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java index 48c999d..f984373 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java @@ -18,6 +18,11 @@ */ package org.apache.johnzon.mapper; +import org.apache.johnzon.mapper.internal.AdapterKey; + +import javax.json.JsonValue; +import javax.json.stream.JsonGenerator; +import javax.xml.bind.DatatypeConverter; import java.lang.reflect.Array; import java.lang.reflect.InvocationTargetException; import java.math.BigDecimal; @@ -25,12 +30,6 @@ import java.math.BigInteger; import java.util.Collection; import java.util.Map; -import javax.json.JsonValue; -import javax.json.stream.JsonGenerator; -import javax.xml.bind.DatatypeConverter; - -import org.apache.johnzon.mapper.internal.AdapterKey; - public class MappingGeneratorImpl implements MappingGenerator { private final MapperConfig config; private final JsonGenerator generator; @@ -49,18 +48,23 @@ public class MappingGeneratorImpl implements MappingGenerator { } @Override - public MappingGenerator writeObject(Object object) { + public MappingGenerator writeObject(Object object, JsonGenerator generator) { if (object == null) { return this; } else if (object instanceof JsonValue) { generator.write((JsonValue) object); } else { - doWriteObject(object, false); + doWriteObject(object, generator, false); } return this; } - public void doWriteObject(Object object, boolean writeBody) { + @Override + public <T> String convert(final T obj) { + return (String) config.findAdapter(obj.getClass()).to(obj); + } + + public void doWriteObject(Object object, JsonGenerator generator, boolean writeBody) { try { if (object instanceof Map) { if (writeBody) { @@ -94,7 +98,7 @@ public class MappingGeneratorImpl implements MappingGenerator { generator.writeStartObject(); } - ObjectConverter objectConverter = config.findObjectConverter(objectClass); + ObjectConverter.Writer objectConverter = config.findObjectConverterWriter(objectClass); if (writeBody && objectConverter != null) { objectConverter.writeJson(object, this); } else { @@ -269,7 +273,8 @@ public class MappingGeneratorImpl implements MappingGenerator { final boolean primitive, final boolean array, final boolean collection, final boolean map, final Adapter itemConverter, - final String key, final Object value, final ObjectConverter objectConverter) throws InvocationTargetException, IllegalAccessException { + final String key, final Object value, + final ObjectConverter.Writer objectConverter) throws InvocationTargetException, IllegalAccessException { if (array) { final int length = Array.getLength(value); if (length == 0 && config.isSkipEmptyArray()) { @@ -319,9 +324,9 @@ public class MappingGeneratorImpl implements MappingGenerator { return; } else { - ObjectConverter objectConverterToUse = objectConverter; + ObjectConverter.Writer objectConverterToUse = objectConverter; if (objectConverterToUse == null) { - objectConverterToUse = config.findObjectConverter(type); + objectConverterToUse = config.findObjectConverterWriter(type); } if (objectConverterToUse != null) { @@ -358,7 +363,7 @@ public class MappingGeneratorImpl implements MappingGenerator { } else if (o == null) { generator.writeNull(); } else { - doWriteObject(o, true); + doWriteObject(o, generator, true); } } } http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParser.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParser.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParser.java index cee68d8..6269884 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParser.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParser.java @@ -31,4 +31,6 @@ public interface MappingParser { <T> T readObject(Type targetType); <T> T readObject(JsonValue jsonValue, Type targetType); + + <T> T convert(Class<T> clazz, String value); } http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java index 87ceb49..812b7a6 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java @@ -115,6 +115,11 @@ public class MappingParserImpl implements MappingParser { return readObject(jsonValue, targetType, targetType instanceof Class || targetType instanceof ParameterizedType); } + @Override + public <T> T convert(final Class<T> clazz, final String value) { + return (T) config.findAdapter(clazz).to(value); + } + private <T> T readObject(JsonValue jsonValue, Type targetType, boolean applyObjectConverter) { if (JsonStructure.class == targetType || JsonObject.class == targetType || JsonValue.class == targetType) { return (T) jsonValue; @@ -186,7 +191,7 @@ public class MappingParserImpl implements MappingParser { throw new MapperException("ObjectConverters are only supported for Classes not Types"); } - ObjectConverter objectConverter = config.findObjectConverter((Class) type); + ObjectConverter.Reader objectConverter = config.findObjectConverterReader((Class) type); if (objectConverter != null) { return objectConverter.fromJson(object, type, new SuppressConversionMappingParser(this, object)); } @@ -535,7 +540,7 @@ public class MappingParserImpl implements MappingParser { } private Object toValue(final Object baseInstance, final JsonValue jsonValue, final Adapter converter, - final Adapter itemConverter, final Type type, final ObjectConverter objectConverter) { + final Adapter itemConverter, final Type type, final ObjectConverter.Reader objectConverter) { if (objectConverter != null) { @@ -627,6 +632,10 @@ public class MappingParserImpl implements MappingParser { return delegate.readObject(jsonValue, targetType); } + @Override + public <T> T convert(final Class<T> clazz, final String value) { + return delegate.convert(clazz, value); + } } } http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mappings.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mappings.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mappings.java index 8c1154b..db0ce1c 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mappings.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/Mappings.java @@ -85,7 +85,7 @@ public class Mappings { final int version; final Adapter converter; final Adapter itemConverter; - final ObjectConverter objectConverter; + final ObjectConverter.Writer objectConverter; final boolean primitive; final boolean array; final boolean map; @@ -95,6 +95,7 @@ public class Mappings { final boolean primitive, final boolean array, final boolean collection, final boolean map, final MapperConverter converter, + final ObjectConverter.Writer providedObjectConverter, final int version) { this.reader = reader; this.version = version; @@ -104,14 +105,14 @@ public class Mappings { Adapter theConverter = null; Adapter theItemConverter = null; - ObjectConverter theObjectConverter = null; + ObjectConverter.Writer theObjectConverter = providedObjectConverter; if (converter != null) { - if (converter instanceof ObjectConverter) { - theObjectConverter = (ObjectConverter) converter; - } else { - + if (converter instanceof ObjectConverter.Writer) { + theObjectConverter = (ObjectConverter.Writer) converter; + } + if (theObjectConverter == null) { Adapter adapter; if (converter instanceof Converter) { adapter = new ConverterAdapter((Converter) converter); @@ -155,12 +156,12 @@ public class Mappings { public final Type paramType; public final Adapter converter; public final Adapter itemConverter; - public final ObjectConverter objectConverter; + public final ObjectConverter.Reader objectConverter; public final boolean primitive; public final boolean array; public Setter(final AccessMode.Writer writer, final boolean primitive, final boolean array, - final Type paramType, final MapperConverter converter, + final Type paramType, final MapperConverter converter, final ObjectConverter.Reader providedObjectConverter, final int version) { this.writer = writer; this.paramType = paramType; @@ -170,14 +171,14 @@ public class Mappings { Adapter theConverter = null; Adapter theItemConverter = null; - ObjectConverter theObjectConverter = null; + ObjectConverter.Reader theObjectConverter = providedObjectConverter; if (converter != null) { - if (converter instanceof ObjectConverter) { - theObjectConverter = (ObjectConverter) converter; - } else { - + if (converter instanceof ObjectConverter.Reader) { + theObjectConverter = (ObjectConverter.Reader) converter; + } + if (theObjectConverter == null){ Adapter adapter; if (converter instanceof Converter) { adapter = new ConverterAdapter((Converter) converter); @@ -398,7 +399,8 @@ public class Mappings { final Class<?> returnType = Class.class.isInstance(param) ? Class.class.cast(param) : null; final Setter setter = new Setter( value, isPrimitive(param), returnType != null && returnType.isArray(), param, - findConverter(copyDate, value), writeIgnore != null ? writeIgnore.minVersion() : -1); + findConverter(copyDate, value), value.findObjectConverterReader(), + writeIgnore != null ? writeIgnore.minVersion() : -1); setters.put(key, setter); } } @@ -417,7 +419,7 @@ public class Mappings { || (returnType != null && Collection.class.isAssignableFrom(returnType)), (pt != null && Map.class.isAssignableFrom(Class.class.cast(pt.getRawType()))) || (returnType != null && Map.class.isAssignableFrom(returnType)), - findConverter(copyDate, value), + findConverter(copyDate, value), value.findObjectConverterWriter(), readIgnore != null ? readIgnore.minVersion() : -1); getters.put(key, getter); } @@ -465,11 +467,11 @@ public class Mappings { final Getter getter = getters.get(key); final MapBuilderReader newReader = new MapBuilderReader(objectGetters, path, config.getVersion()); - getters.put(key, new Getter(getter == null ? newReader : new CompositeReader(getter.reader, newReader), false, false, false, true, null, -1)); + getters.put(key, new Getter(getter == null ? newReader : new CompositeReader(getter.reader, newReader), false, false, false, true, null, null, -1)); final Setter newSetter = setters.get(key); final MapUnwrapperWriter newWriter = new MapUnwrapperWriter(objectSetters, path); - setters.put(key, new Setter(newSetter == null ? newWriter : new CompositeWriter(newSetter.writer, newWriter), false, false, VIRTUAL_TYPE, null, -1)); + setters.put(key, new Setter(newSetter == null ? newWriter : new CompositeWriter(newSetter.writer, newWriter), false, false, VIRTUAL_TYPE, null, null, -1)); } private MapperConverter findConverter(final boolean copyDate, final AccessMode.DecoratedType decoratedType) { @@ -574,6 +576,11 @@ public class Mappings { } @Override + public ObjectConverter.Writer<?> findObjectConverterWriter() { + return null; + } + + @Override public Type getType() { return VIRTUAL_TYPE; } @@ -648,6 +655,11 @@ public class Mappings { } @Override + public ObjectConverter.Reader<?> findObjectConverterReader() { + return null; + } + + @Override public Type getType() { return VIRTUAL_TYPE; } @@ -708,6 +720,17 @@ public class Mappings { } @Override + public ObjectConverter.Writer<?> findObjectConverterWriter() { + for (final AccessMode.Reader w : delegates) { + final ObjectConverter.Writer<?> objectConverter = w.findObjectConverterWriter(); + if (objectConverter != null) { + return objectConverter; + } + } + return null; + } + + @Override public Type getType() { return VIRTUAL_TYPE; } @@ -767,6 +790,17 @@ public class Mappings { } @Override + public ObjectConverter.Reader<?> findObjectConverterReader() { + for (final AccessMode.Writer w : delegates) { + final ObjectConverter.Reader<?> objectConverter = w.findObjectConverterReader(); + if (objectConverter != null) { + return objectConverter; + } + } + return null; + } + + @Override public Type getType() { return VIRTUAL_TYPE; } http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ObjectConverter.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ObjectConverter.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ObjectConverter.java index 5869f4d..03ce47e 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ObjectConverter.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/ObjectConverter.java @@ -28,10 +28,20 @@ import java.lang.reflect.Type; * An example would be to convert a custom Project POJO, like Dog.class * to it's JSON representation * - * @param <T> */ -public interface ObjectConverter<T> extends MapperConverter { - void writeJson(T instance, MappingGenerator jsonbGenerator); +public final class ObjectConverter { + private ObjectConverter() { + // no-op + } - T fromJson(JsonObject jsonObject, Type targetType, MappingParser parser); + public interface Writer<T> extends MapperConverter { + void writeJson(T instance, MappingGenerator jsonbGenerator); + } + + public interface Reader<T> extends MapperConverter { + T fromJson(JsonObject jsonObject, Type targetType, MappingParser parser); + } + + public interface Codec<T> extends ObjectConverter.Writer<T>, ObjectConverter.Reader<T> { + } } http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java index 0e667d4..f47e0d0 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/AccessMode.java @@ -19,6 +19,7 @@ package org.apache.johnzon.mapper.access; import org.apache.johnzon.mapper.Adapter; +import org.apache.johnzon.mapper.ObjectConverter; import java.lang.annotation.Annotation; import java.lang.reflect.Type; @@ -36,10 +37,12 @@ public interface AccessMode { interface Writer extends DecoratedType { void write(Object instance, Object value); + ObjectConverter.Reader<?> findObjectConverterReader(); } interface Reader extends DecoratedType { Object read(Object instance); + ObjectConverter.Writer<?> findObjectConverterWriter(); } interface Factory { http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java index 37d92cc..0bb6a4f 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAccessMode.java @@ -21,6 +21,7 @@ package org.apache.johnzon.mapper.access; import org.apache.johnzon.mapper.Adapter; import org.apache.johnzon.mapper.JohnzonProperty; import org.apache.johnzon.mapper.MapperException; +import org.apache.johnzon.mapper.ObjectConverter; import java.lang.annotation.Annotation; import java.lang.reflect.Field; @@ -149,6 +150,11 @@ public class FieldAccessMode extends BaseAccessMode { throw new MapperException(e); } } + + @Override + public ObjectConverter.Reader<?> findObjectConverterReader() { + return null; + } } public static class FieldReader extends FieldDecoratedType implements Reader { @@ -166,6 +172,11 @@ public class FieldAccessMode extends BaseAccessMode { } @Override + public ObjectConverter.Writer<?> findObjectConverterWriter() { + return null; + } + + @Override public Type getType() { return type; } http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java index 7fc224a..0e4d9e7 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/FieldAndMethodAccessMode.java @@ -19,6 +19,7 @@ package org.apache.johnzon.mapper.access; import org.apache.johnzon.mapper.Adapter; +import org.apache.johnzon.mapper.ObjectConverter; import java.lang.annotation.Annotation; import java.lang.reflect.Type; @@ -122,6 +123,12 @@ public class FieldAndMethodAccessMode extends BaseAccessMode { public Object read(final Object instance) { return reader.read(instance); } + + @Override + public ObjectConverter.Writer<?> findObjectConverterWriter() { + final ObjectConverter.Writer<?> objectConverter = Reader.class.cast(type1).findObjectConverterWriter(); + return objectConverter == null ? reader.findObjectConverterWriter() : objectConverter; + } } public static final class CompositeWriter extends CompositeDecoratedType implements Writer { @@ -136,5 +143,11 @@ public class FieldAndMethodAccessMode extends BaseAccessMode { public void write(final Object instance, final Object value) { writer.write(instance, value); } + + @Override + public ObjectConverter.Reader<?> findObjectConverterReader() { + final ObjectConverter.Reader<?> objectConverter = Writer.class.cast(type1).findObjectConverterReader(); + return objectConverter == null ? writer.findObjectConverterReader() : objectConverter; + } } } http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java index 894d03e..4309c28 100644 --- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java +++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/access/MethodAccessMode.java @@ -21,6 +21,7 @@ package org.apache.johnzon.mapper.access; import org.apache.johnzon.mapper.Adapter; import org.apache.johnzon.mapper.JohnzonProperty; import org.apache.johnzon.mapper.MapperException; +import org.apache.johnzon.mapper.ObjectConverter; import java.beans.IntrospectionException; import java.beans.Introspector; @@ -153,6 +154,11 @@ public class MethodAccessMode extends BaseAccessMode { throw new MapperException(e); } } + + @Override + public ObjectConverter.Reader<?> findObjectConverterReader() { + return null; + } } public static class MethodReader extends MethodDecoratedType implements Reader { @@ -168,6 +174,11 @@ public class MethodAccessMode extends BaseAccessMode { throw new MapperException(e); } } + + @Override + public ObjectConverter.Writer<?> findObjectConverterWriter() { + return null; + } } private class MethodGetterAsWriter extends MethodReader implements Writer { @@ -188,5 +199,10 @@ public class MethodAccessMode extends BaseAccessMode { } } } + + @Override + public ObjectConverter.Reader<?> findObjectConverterReader() { + return null; + } } } http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java index 7f5bac2..52a3eeb 100644 --- a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java +++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java @@ -36,14 +36,14 @@ public class MapperConfigTest { @Test public void testFindObjectConverterConverterForSpecificClass() { - ObjectConverter<ClassWithoutSupertypes> theConverter = new TheConverter<ClassWithoutSupertypes>(); + ObjectConverter.Codec<ClassWithoutSupertypes> theConverter = new TheConverter<ClassWithoutSupertypes>(); - Map<Class<?>, ObjectConverter<?>> converterMap = new HashMap<Class<?>, ObjectConverter<?>>(1); + Map<Class<?>, ObjectConverter.Codec<?>> converterMap = new HashMap<Class<?>, ObjectConverter.Codec<?>>(1); converterMap.put(ClassWithoutSupertypes.class, theConverter); MapperConfig config = createConfig(converterMap); - ObjectConverter converter = config.findObjectConverter(ClassWithoutSupertypes.class); + ObjectConverter.Reader converter = config.findObjectConverterReader(ClassWithoutSupertypes.class); Assert.assertNotNull(converter); Assert.assertEquals(theConverter, converter); } @@ -51,11 +51,11 @@ public class MapperConfigTest { @Test public void testFindObjectConverterConverterForInterface() { - ObjectConverter<TheInterface> theConverter = new TheConverter<TheInterface>(); + ObjectConverter.Codec<TheInterface> theConverter = new TheConverter<TheInterface>(); - MapperConfig config = createConfig(Collections.<Class<?>, ObjectConverter<?>>singletonMap(TheInterface.class, theConverter)); + MapperConfig config = createConfig(Collections.<Class<?>, ObjectConverter.Codec<?>>singletonMap(TheInterface.class, theConverter)); - ObjectConverter converter = config.findObjectConverter(ClassForTheInterface.class); + ObjectConverter.Writer converter = config.findObjectConverterWriter(ClassForTheInterface.class); Assert.assertNotNull(converter); Assert.assertEquals(theConverter, converter); } @@ -63,11 +63,11 @@ public class MapperConfigTest { @Test public void testFindObjectConverterConverterOnlyForSuperclass() { - ObjectConverter<ClassForTheInterface> theConverter = new TheConverter<ClassForTheInterface>(); + ObjectConverter.Codec<ClassForTheInterface> theConverter = new TheConverter<ClassForTheInterface>(); - MapperConfig config = createConfig(Collections.<Class<?>, ObjectConverter<?>>singletonMap(ClassForTheInterface.class, theConverter)); + MapperConfig config = createConfig(Collections.<Class<?>, ObjectConverter.Codec<?>>singletonMap(ClassForTheInterface.class, theConverter)); - ObjectConverter converter = config.findObjectConverter(ExtendingClassForTheInterface.class); + ObjectConverter.Reader converter = config.findObjectConverterReader(ExtendingClassForTheInterface.class); Assert.assertNotNull(converter); Assert.assertEquals(theConverter, converter); } @@ -75,36 +75,40 @@ public class MapperConfigTest { @Test public void testFindObjectConverterConverterForInterfaceAndClass() { - ObjectConverter<TheInterface> interfaceConverter = new TheConverter<TheInterface>(); - ObjectConverter<ClassForTheInterface> theConverter = new TheConverter<ClassForTheInterface>(); + ObjectConverter.Codec<TheInterface> interfaceConverter = new TheConverter<TheInterface>(); + ObjectConverter.Codec<ClassForTheInterface> theConverter = new TheConverter<ClassForTheInterface>(); - Map<Class<?>, ObjectConverter<?>> converterMap = new HashMap<Class<?>, ObjectConverter<?>>(2); + Map<Class<?>, ObjectConverter.Codec<?>> converterMap = new HashMap<Class<?>, ObjectConverter.Codec<?>>(2); converterMap.put(TheInterface.class, interfaceConverter); converterMap.put(ClassForTheInterface.class, theConverter); MapperConfig config = createConfig(converterMap); - ObjectConverter converter = config.findObjectConverter(ClassForTheInterface.class); - Assert.assertNotNull(converter); - Assert.assertEquals(theConverter, converter); + { + ObjectConverter.Reader converter = config.findObjectConverterReader(ClassForTheInterface.class); + Assert.assertNotNull(converter); + Assert.assertEquals(theConverter, converter); + } - converter = config.findObjectConverter(ExtendingClassForTheInterface.class); - Assert.assertNotNull(converter); - Assert.assertEquals(theConverter, converter); + { + ObjectConverter.Writer converter = config.findObjectConverterWriter(ExtendingClassForTheInterface.class); + Assert.assertNotNull(converter); + Assert.assertEquals(theConverter, converter); + } } @Test public void testFindObjectConverterConverterForMoreInterfaces() { - ObjectConverter<TheInterface> firstConverter = new TheConverter<TheInterface>(); - ObjectConverter<TheSecondInterface> secondConverter = new TheConverter<TheSecondInterface>(); + ObjectConverter.Codec<TheInterface> firstConverter = new TheConverter<TheInterface>(); + ObjectConverter.Codec<TheSecondInterface> secondConverter = new TheConverter<TheSecondInterface>(); - Map<Class<?>, ObjectConverter<?>> converterMap = new HashMap<Class<?>, ObjectConverter<?>>(2); + Map<Class<?>, ObjectConverter.Codec<?>> converterMap = new HashMap<Class<?>, ObjectConverter.Codec<?>>(2); converterMap.put(TheInterface.class, firstConverter); converterMap.put(TheSecondInterface.class, secondConverter); MapperConfig config = createConfig(converterMap); - ObjectConverter converter = config.findObjectConverter(ClassWithTwoInterfaces.class); + ObjectConverter.Writer converter = config.findObjectConverterWriter(ClassWithTwoInterfaces.class); Assert.assertNotNull(converter); Assert.assertEquals(converterMap.get(ClassWithTwoInterfaces.class.getInterfaces()[0]), converter); } @@ -114,40 +118,44 @@ public class MapperConfigTest { TheAbstractConverter<ClassForTheInterface> theConverter = new TheAbstractConverter<ClassForTheInterface>() {}; - MapperConfig config = createConfig(Collections.<Class<?>, ObjectConverter<?>>singletonMap(ClassForTheInterface.class, theConverter)); + MapperConfig config = createConfig(Collections.<Class<?>, ObjectConverter.Codec<?>>singletonMap(ClassForTheInterface.class, theConverter)); - ObjectConverter converter = config.findObjectConverter(ClassForTheInterface.class); - Assert.assertNotNull(converter); - Assert.assertEquals(theConverter, converter); + { + ObjectConverter.Writer converter = config.findObjectConverterWriter(ClassForTheInterface.class); + Assert.assertNotNull(converter); + Assert.assertEquals(theConverter, converter); + } - converter = config.findObjectConverter(ExtendingClassForTheInterface.class); - Assert.assertNotNull(converter); - Assert.assertEquals(theConverter, converter); + { + ObjectConverter.Writer converter = config.findObjectConverterWriter(ExtendingClassForTheInterface.class); + Assert.assertNotNull(converter); + Assert.assertEquals(theConverter, converter); + } } @Test public void testfindObjectConverterConverterForObject() { TheConverter<Object> theConverter = new TheConverter<Object>(); - MapperConfig config = createConfig(Collections.<Class<?>, ObjectConverter<?>>singletonMap(Object.class, theConverter)); + MapperConfig config = createConfig(Collections.<Class<?>, ObjectConverter.Codec<?>>singletonMap(Object.class, theConverter)); - ObjectConverter converter = config.findObjectConverter(ClassForTheInterface.class); + ObjectConverter.Reader converter = config.findObjectConverterReader(ClassForTheInterface.class); Assert.assertNotNull(converter); Assert.assertEquals(theConverter, converter); - converter = config.findObjectConverter(TheInterface.class); + converter = config.findObjectConverterReader(TheInterface.class); Assert.assertNotNull(converter); Assert.assertEquals(theConverter, converter); - converter = config.findObjectConverter(InterfaceExtendingTwoInterfaces.class); + converter = config.findObjectConverterReader(InterfaceExtendingTwoInterfaces.class); Assert.assertNotNull(converter); Assert.assertEquals(theConverter, converter); } - private MapperConfig createConfig(Map<Class<?>, ObjectConverter<?>> converter) { + private MapperConfig createConfig(Map<Class<?>, ObjectConverter.Codec<?>> converter) { return new MapperConfig(new ConcurrentHashMap<AdapterKey, Adapter<?, ?>>(0), - converter, + Map.class.cast(converter), Map.class.cast(converter), -1, true, true, @@ -173,7 +181,7 @@ public class MapperConfigTest { private interface InterfaceExtendingTwoInterfaces extends TheInterface, TheSecondInterface {} - private static class TheConverter<T> implements ObjectConverter<T>{ + private static class TheConverter<T> implements ObjectConverter.Codec<T>{ @Override public void writeJson(T instance, MappingGenerator jsonbGenerator) { // dummy @@ -186,7 +194,7 @@ public class MapperConfigTest { } } - private static abstract class TheAbstractConverter<T extends TheInterface> implements ObjectConverter<T> { + private static abstract class TheAbstractConverter<T extends TheInterface> implements ObjectConverter.Codec<T> { @Override public void writeJson(T instance, MappingGenerator jsonbGenerator) { // dummy http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java index c14094e..510672d 100644 --- a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java +++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectConverterWithAnnotationTest.java @@ -348,7 +348,7 @@ public class ObjectConverterWithAnnotationTest { TRIATHLON } - public static class BikeConverter implements ObjectConverter<Bike> { + public static class BikeConverter implements ObjectConverter.Codec<Bike> { public static final List<String> MANUFACTURERS = Arrays.asList("Specialized / S-Works", "Canyon", "Trek", "Scott"); http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java ---------------------------------------------------------------------- diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java index 88b03a8..b003ac2 100644 --- a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java +++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/ObjectTypeTest.java @@ -160,11 +160,11 @@ public class ObjectTypeTest { } - public static class TestWithTypeConverter implements ObjectConverter<Dog> { + public static class TestWithTypeConverter implements ObjectConverter.Codec<Dog> { @Override public void writeJson(Dog instance, MappingGenerator mappingGenerator) { mappingGenerator.getJsonGenerator().write("//javaType", instance.getClass().getName()); - mappingGenerator.writeObject(instance); + mappingGenerator.writeObject(instance, mappingGenerator.getJsonGenerator()); } @Override @@ -287,7 +287,7 @@ public class ObjectTypeTest { } - public static class DBAccessPoodleConverter implements ObjectConverter<Poodle> { + public static class DBAccessPoodleConverter implements ObjectConverter.Codec<Poodle> { public static final String POODLE_1_NAME = "Poodle1"; public static final String POODLE_2_NAME = "Poodle2"; http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/jsonb-api/src/main/java/javax/json/bind/JsonbConfig.java ---------------------------------------------------------------------- diff --git a/jsonb-api/src/main/java/javax/json/bind/JsonbConfig.java b/jsonb-api/src/main/java/javax/json/bind/JsonbConfig.java index 717cb15..597c88c 100644 --- a/jsonb-api/src/main/java/javax/json/bind/JsonbConfig.java +++ b/jsonb-api/src/main/java/javax/json/bind/JsonbConfig.java @@ -21,6 +21,8 @@ package javax.json.bind; import javax.json.bind.adapter.JsonbAdapter; import javax.json.bind.config.PropertyNamingStrategy; import javax.json.bind.config.PropertyVisibilityStrategy; +import javax.json.bind.serializer.JsonbDeserializer; +import javax.json.bind.serializer.JsonbSerializer; import java.util.Collections; import java.util.HashMap; import java.util.Locale; @@ -41,6 +43,8 @@ public class JsonbConfig { public static final String BINARY_DATA_STRATEGY = "jsonb.binary-data-strategy"; public static final String DATE_FORMAT = "jsonb.date-format"; public static final String LOCALE = "jsonb.locale"; + public static final String SERIALIZERS = "jsonb.serializers"; + public static final String DESERIALIZERS = "jsonb.derializers"; public final JsonbConfig withDateFormat(final String dateFormat, final Locale locale) { return setProperty(DATE_FORMAT, dateFormat).setProperty(LOCALE, locale != null ? locale : Locale.getDefault()); @@ -102,4 +106,12 @@ public class JsonbConfig { public final JsonbConfig withBinaryDataStrategy(final String binaryDataStrategy) { return setProperty(BINARY_DATA_STRATEGY, binaryDataStrategy); } + + public final JsonbConfig withSerializers(final JsonbSerializer... serializers) { + return setProperty(SERIALIZERS, serializers); + } + + public final JsonbConfig withDeserializers(final JsonbDeserializer... deserializers) { + return setProperty(DESERIALIZERS, deserializers); + } } http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTypeDeserializer.java ---------------------------------------------------------------------- diff --git a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTypeDeserializer.java b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTypeDeserializer.java new file mode 100644 index 0000000..ad8fba2 --- /dev/null +++ b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTypeDeserializer.java @@ -0,0 +1,35 @@ +/* + * 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 javax.json.bind.annotation; + +import javax.json.bind.serializer.JsonbDeserializer; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; + +@JsonbAnnotation +@Retention(RetentionPolicy.RUNTIME) +@Target({ANNOTATION_TYPE, FIELD, METHOD}) +public @interface JsonbTypeDeserializer { + Class<? extends JsonbDeserializer> value(); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTypeSerializer.java ---------------------------------------------------------------------- diff --git a/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTypeSerializer.java b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTypeSerializer.java new file mode 100644 index 0000000..f2efdda --- /dev/null +++ b/jsonb-api/src/main/java/javax/json/bind/annotation/JsonbTypeSerializer.java @@ -0,0 +1,35 @@ +/* + * 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 javax.json.bind.annotation; + +import javax.json.bind.serializer.JsonbSerializer; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +import static java.lang.annotation.ElementType.ANNOTATION_TYPE; +import static java.lang.annotation.ElementType.FIELD; +import static java.lang.annotation.ElementType.METHOD; + +@JsonbAnnotation +@Retention(RetentionPolicy.RUNTIME) +@Target({ANNOTATION_TYPE, FIELD, METHOD}) +public @interface JsonbTypeSerializer { + Class<? extends JsonbSerializer> value(); +} \ No newline at end of file http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/jsonb-api/src/main/java/javax/json/bind/serializer/DeserializationContext.java ---------------------------------------------------------------------- diff --git a/jsonb-api/src/main/java/javax/json/bind/serializer/DeserializationContext.java b/jsonb-api/src/main/java/javax/json/bind/serializer/DeserializationContext.java new file mode 100644 index 0000000..05952fb --- /dev/null +++ b/jsonb-api/src/main/java/javax/json/bind/serializer/DeserializationContext.java @@ -0,0 +1,33 @@ +/* + * 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 javax.json.bind.serializer; + +import javax.json.stream.JsonParser; +import java.lang.reflect.Type; + +public interface DeserializationContext { + /** + * JsonParser cursor is at KEY_NAME event. + */ + <T> T deserialize(Class<T> clazz, JsonParser parser); + + <T> T deserialize(Type type, JsonParser parser); + + <T> T convertDefault(Class<T> clazz, String value); +} http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/jsonb-api/src/main/java/javax/json/bind/serializer/JsonbDeserializer.java ---------------------------------------------------------------------- diff --git a/jsonb-api/src/main/java/javax/json/bind/serializer/JsonbDeserializer.java b/jsonb-api/src/main/java/javax/json/bind/serializer/JsonbDeserializer.java new file mode 100644 index 0000000..1f4de04 --- /dev/null +++ b/jsonb-api/src/main/java/javax/json/bind/serializer/JsonbDeserializer.java @@ -0,0 +1,30 @@ +/* + * 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 javax.json.bind.serializer; + +import javax.json.stream.JsonParser; +import java.lang.reflect.Type; + +public interface JsonbDeserializer<T> { + /** + * JsonParser is at START_OBJECT event. + */ + T deserialize(JsonParser parser, DeserializationContext ctx, Type rtType); +} + http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/jsonb-api/src/main/java/javax/json/bind/serializer/JsonbSerializer.java ---------------------------------------------------------------------- diff --git a/jsonb-api/src/main/java/javax/json/bind/serializer/JsonbSerializer.java b/jsonb-api/src/main/java/javax/json/bind/serializer/JsonbSerializer.java new file mode 100644 index 0000000..6b487a8 --- /dev/null +++ b/jsonb-api/src/main/java/javax/json/bind/serializer/JsonbSerializer.java @@ -0,0 +1,25 @@ +/* + * 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 javax.json.bind.serializer; + +import javax.json.stream.JsonGenerator; + +public interface JsonbSerializer<T> { + void serialize(T obj, JsonGenerator generator, SerializationContext ctx); +} http://git-wip-us.apache.org/repos/asf/incubator-johnzon/blob/745668a8/jsonb-api/src/main/java/javax/json/bind/serializer/SerializationContext.java ---------------------------------------------------------------------- diff --git a/jsonb-api/src/main/java/javax/json/bind/serializer/SerializationContext.java b/jsonb-api/src/main/java/javax/json/bind/serializer/SerializationContext.java new file mode 100644 index 0000000..f26cd1c --- /dev/null +++ b/jsonb-api/src/main/java/javax/json/bind/serializer/SerializationContext.java @@ -0,0 +1,29 @@ +/* + * 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 javax.json.bind.serializer; + +import javax.json.stream.JsonGenerator; + +public interface SerializationContext { + <T> void serialize(String key, T object, JsonGenerator generator); + + <T> void serialize(T object, JsonGenerator generator); + + <T> String convertDefault(T obj, JsonGenerator generator); +}
