http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonJsonb.java ---------------------------------------------------------------------- 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 new file mode 100644 index 0000000..9894228 --- /dev/null +++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonJsonb.java @@ -0,0 +1,368 @@ +/* + * 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.apache.johnzon.mapper.Mapper; +import org.apache.johnzon.mapper.MapperException; +import org.apache.johnzon.mapper.reflection.JohnzonParameterizedType; + +import javax.json.bind.Jsonb; +import javax.json.bind.JsonbException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.StringReader; +import java.io.Writer; +import java.lang.reflect.Array; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Collection; +import java.util.Optional; +import java.util.OptionalDouble; +import java.util.OptionalInt; +import java.util.OptionalLong; + +// TODO: Optional handling for lists (and arrays)? +public class JohnzonJsonb implements Jsonb, AutoCloseable { + private final Mapper delegate; + + public JohnzonJsonb(final Mapper build) { + this.delegate = build; + } + + @Override + public <T> T fromJson(final String str, final Class<T> type) throws JsonbException { + try { + if (isArray(type)) { + return delegate.readTypedArray(new StringReader(str), type.getComponentType(), type); + } else if (Collection.class.isAssignableFrom(type)) { + return (T) delegate.readCollection(new StringReader(str), new JohnzonParameterizedType(type, Object.class)); + } + final Type mappingType = unwrapPrimitiveOptional(type); + final Object object = delegate.readObject(str, mappingType); + if (mappingType != type) { + return wrapPrimitiveOptional(object, type); + } + return (T) object; + } catch (final MapperException me) { + throw new JsonbException(me.getMessage(), me); + } + } + + private <T> T wrapPrimitiveOptional(final Object object, final Type type) { + if (OptionalDouble.class == type) { + if (object == null) { + return (T) OptionalDouble.empty(); + } + return (T) OptionalDouble.of(Number.class.cast(object).doubleValue()); + } else if (OptionalInt.class == type) { + if (object == null) { + return (T) OptionalInt.empty(); + } + return (T) OptionalInt.of(Number.class.cast(object).intValue()); + } else if (OptionalLong.class == type) { + if (object == null) { + return (T) OptionalLong.empty(); + } + return (T) OptionalLong.of(Number.class.cast(object).longValue()); + } + // Optional + return (T) Optional.ofNullable(object); + } + + private Type unwrapPrimitiveOptional(final Type type) { + if (OptionalDouble.class == type) { + return double.class; + } else if (OptionalInt.class == type) { + return int.class; + } else if (OptionalLong.class == type) { + return long.class; + } else if (ParameterizedType.class.isInstance(type)) { + final ParameterizedType pt = ParameterizedType.class.cast(type); + if (Optional.class == pt.getRawType()) { + return pt.getActualTypeArguments()[0]; + } + } + return type; + } + + @Override + public <T> T fromJson(final String str, final Type runtimeType) throws JsonbException { + try { + if (isArray(runtimeType)) { + final Class cast = Class.class.cast(runtimeType); + return (T) delegate.readTypedArray(new StringReader(str), cast.getComponentType(), cast); + } else if (isCollection(runtimeType)) { + return (T) delegate.readCollection(new StringReader(str), ParameterizedType.class.cast(runtimeType)); + } + final Type mappingType = unwrapPrimitiveOptional(runtimeType); + final Object object = delegate.readObject(str, mappingType); + if (mappingType != runtimeType) { + return wrapPrimitiveOptional(object, runtimeType); + } + return (T) object; + } catch (final MapperException me) { + throw new JsonbException(me.getMessage(), me); + } + } + + @Override + public <T> T fromJson(final Reader reader, final Class<T> type) throws JsonbException { + try { + if (isArray(type)) { + return delegate.readTypedArray(reader, type.getComponentType(), type); + } else if (Collection.class.isAssignableFrom(type)) { + return (T) delegate.readCollection(reader, new JohnzonParameterizedType(type, Object.class)); + } + final Type mappingType = unwrapPrimitiveOptional(type); + final Object object = delegate.readObject(reader, mappingType); + if (mappingType != type) { + return wrapPrimitiveOptional(object, type); + } + return (T) object; + } catch (final MapperException me) { + throw new JsonbException(me.getMessage(), me); + } + } + + @Override + public <T> T fromJson(final Reader reader, final Type runtimeType) throws JsonbException { + try { + if (isArray(runtimeType)) { + final Class<T> type = Class.class.cast(runtimeType); + return delegate.readTypedArray(reader, type.getComponentType(), type); + } else if (isCollection(runtimeType)) { + return (T) delegate.readCollection(reader, ParameterizedType.class.cast(runtimeType)); + } + final Type mappingType = unwrapPrimitiveOptional(runtimeType); + final Object object = delegate.readObject(reader, mappingType); + if (mappingType != runtimeType) { + return wrapPrimitiveOptional(object, runtimeType); + } + return (T) object; + } catch (final MapperException me) { + throw new JsonbException(me.getMessage(), me); + } + } + + @Override + public <T> T fromJson(final InputStream stream, final Class<T> type) throws JsonbException { + try { + if (isArray(type)) { + return delegate.readTypedArray(stream, type.getComponentType(), type); + } else if (Collection.class.isAssignableFrom(type)) { + return (T) delegate.readCollection(stream, new JohnzonParameterizedType(type, Object.class)); + } + final Type mappingType = unwrapPrimitiveOptional(type); + final Object object = delegate.readObject(stream, mappingType); + if (mappingType != type) { + return wrapPrimitiveOptional(object, type); + } + return (T) object; + } catch (final MapperException me) { + throw new JsonbException(me.getMessage(), me); + } + } + + @Override + public <T> T fromJson(final InputStream stream, final Type runtimeType) throws JsonbException { + try { + if (isArray(runtimeType)) { + final Class<T> type = Class.class.cast(runtimeType); + return delegate.readTypedArray(stream, type.getComponentType(), type); + } else if (isCollection(runtimeType)) { + return (T) delegate.readCollection(stream, ParameterizedType.class.cast(runtimeType)); + } + + final Type mappingType = unwrapPrimitiveOptional(runtimeType); + final Object object = delegate.readObject(stream, mappingType); + if (mappingType != runtimeType) { + return wrapPrimitiveOptional(object, runtimeType); + } + return (T) object; + } catch (final MapperException me) { + throw new JsonbException(me.getMessage(), me); + } + } + + @Override + public String toJson(final Object inObject) throws JsonbException { + try { + final Object object = unwrapOptional(inObject); + if (object == null) { + return "null"; + } + if (isArray(object.getClass())) { + return delegate.writeArrayAsString(toArray(object)); + } else if (Collection.class.isInstance(object)) { + return delegate.writeArrayAsString(Collection.class.cast(object)); + } + return delegate.writeObjectAsString(object); + + } catch (final MapperException me) { + throw new JsonbException(me.getMessage(), me); + } + } + + private Object[] toArray(final Object object) { + final Class<?> componentType = object.getClass().getComponentType(); + Object[] array; + if (int.class == componentType) { + final int length = Array.getLength(object); + array = new Integer[length]; + for (int i = 0; i < length; i++) { + array[i] = Array.getInt(object, i); + } + } else if (double.class == componentType) { + final int length = Array.getLength(object); + array = new Integer[length]; + for (int i = 0; i < length; i++) { + array[i] = Array.getDouble(object, i); + } + } else if (byte.class == componentType) { + final int length = Array.getLength(object); + array = new Integer[length]; + for (int i = 0; i < length; i++) { + array[i] = Array.getByte(object, i); + } + } else if (char.class == componentType) { + final int length = Array.getLength(object); + array = new Integer[length]; + for (int i = 0; i < length; i++) { + array[i] = Array.getChar(object, i); + } + } else if (float.class == componentType) { + final int length = Array.getLength(object); + array = new Integer[length]; + for (int i = 0; i < length; i++) { + array[i] = Array.getFloat(object, i); + } + } else if (long.class == componentType) { + final int length = Array.getLength(object); + array = new Integer[length]; + for (int i = 0; i < length; i++) { + array[i] = Array.getLong(object, i); + } + } else if (short.class == componentType) { + final int length = Array.getLength(object); + array = new Integer[length]; + for (int i = 0; i < length; i++) { + array[i] = Array.getShort(object, i); + } + } else { + array = (Object[]) object; + } + return array; + } + + @Override + public String toJson(final Object inObject, final Type runtimeType) throws JsonbException { + final Object object = unwrapOptional(inObject); + if (object != null && isArray(runtimeType)) { + return delegate.writeArrayAsString((Object[]) object); + } else if (isCollection(runtimeType)) { + return delegate.writeArrayAsString(Collection.class.cast(object)); + } + return delegate.writeObjectAsString(object); + } + + @Override + public void toJson(final Object inObject, final Writer writer) throws JsonbException { + final Object object = unwrapOptional(inObject); + if (object != null && isArray(object.getClass())) { + delegate.writeArray((Object[]) object, writer); + } else if (Collection.class.isInstance(object)) { + delegate.writeArray(Collection.class.cast(object), writer); + } else { + delegate.writeObject(object, writer); + } + } + + @Override + public void toJson(final Object inObject, final Type runtimeType, final Writer writer) throws JsonbException { + final Object object = unwrapOptional(inObject); + if (object != null && isArray(runtimeType)) { + delegate.writeArray((Object[]) object, writer); + } else if (isCollection(runtimeType)) { + delegate.writeArray(Collection.class.cast(object), writer); + } else { + delegate.writeObject(object, writer); + } + } + + @Override + public void toJson(final Object inObject, final OutputStream stream) throws JsonbException { + final Object object = unwrapOptional(inObject); + if (object != null && isArray(object.getClass())) { + delegate.writeArray((Object[]) object, stream); + } else if (Collection.class.isInstance(object)) { + delegate.writeArray(Collection.class.cast(object), stream); + } else { + delegate.writeObject(object, stream); + } + } + + @Override + public void toJson(final Object inObject, final Type runtimeType, final OutputStream stream) throws JsonbException { + final Object object = unwrapOptional(inObject); + if (object != null && isArray(runtimeType)) { + delegate.writeArray((Object[]) object, stream); + } else if (isCollection(runtimeType)) { + delegate.writeArray(Collection.class.cast(object), stream); + } else { + delegate.writeObject(object, stream); + } + } + + private Object unwrapOptional(final Object inObject) { + if (Optional.class.isInstance(inObject)) { + return Optional.class.cast(inObject).orElse(null); + } + if (OptionalInt.class.isInstance(inObject)) { + final OptionalInt optionalInt = OptionalInt.class.cast(inObject); + return optionalInt.isPresent() ? optionalInt.getAsInt() : null; + } + if (OptionalLong.class.isInstance(inObject)) { + final OptionalLong optionalLong = OptionalLong.class.cast(inObject); + return optionalLong.isPresent() ? optionalLong.getAsLong() : null; + } + if (OptionalDouble.class.isInstance(inObject)) { + final OptionalDouble optionalDouble = OptionalDouble.class.cast(inObject); + return optionalDouble.isPresent() ? optionalDouble.getAsDouble() : null; + } + return inObject; + } + + private boolean isArray(final Type runtimeType) { + return Class.class.isInstance(runtimeType) && Class.class.cast(runtimeType).isArray(); + } + + private boolean isCollection(final Type runtimeType) { + if (!ParameterizedType.class.isInstance(runtimeType)) { + return false; + } + final Type rawType = ParameterizedType.class.cast(runtimeType).getRawType(); + return Class.class.isInstance(rawType) && Collection.class.isAssignableFrom(Class.class.cast(rawType)); + } + + @Override + public void close() { + delegate.close(); + } +}
http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/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 28c7211..4526c72 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 @@ -29,7 +29,10 @@ 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.JohnzonAny; +import org.apache.johnzon.mapper.JohnzonConverter; +import org.apache.johnzon.mapper.MapperConverter; import org.apache.johnzon.mapper.ObjectConverter; import org.apache.johnzon.mapper.TypeAwareAdapter; import org.apache.johnzon.mapper.access.AccessMode; @@ -100,7 +103,7 @@ public class JsonbAccessMode implements AccessMode, Closeable { private final PropertyNamingStrategy naming; private final String order; private final PropertyVisibilityStrategy visibility; - private final FieldAndMethodAccessMode delegate; + private final AccessMode delegate; private final boolean caseSensitive; private final Map<AdapterKey, Adapter<?, ?>> defaultConverters; private final JohnzonAdapterFactory factory; @@ -122,12 +125,12 @@ public class JsonbAccessMode implements AccessMode, Closeable { public JsonbAccessMode(final PropertyNamingStrategy propertyNamingStrategy, final String orderValue, final PropertyVisibilityStrategy visibilityStrategy, final boolean caseSensitive, final Map<AdapterKey, Adapter<?, ?>> defaultConverters, final JohnzonAdapterFactory factory, - final Supplier<JsonParserFactory> parserFactory) { + final Supplier<JsonParserFactory> parserFactory, final AccessMode delegate) { this.naming = propertyNamingStrategy; this.order = orderValue; this.visibility = visibilityStrategy; this.caseSensitive = caseSensitive; - this.delegate = new FieldAndMethodAccessMode(true, true, false); + this.delegate = delegate; this.defaultConverters = defaultConverters; this.factory = factory; this.parserFactory = parserFactory; @@ -166,11 +169,14 @@ public class JsonbAccessMode implements AccessMode, Closeable { final String[] params; final Adapter<?, ?>[] converters; final Adapter<?, ?>[] itemConverters; + final ObjectConverter.Codec<?>[] objectConverters; if (finalConstructor != null || finalFactory != null) { types = finalConstructor != null ? finalConstructor.getGenericParameterTypes() : finalFactory.getGenericParameterTypes(); params = new String[types.length]; converters = new Adapter<?, ?>[types.length]; itemConverters = new Adapter<?, ?>[types.length]; + objectConverters = new ObjectConverter.Codec<?>[types.length]; + int i = 0; for (final Parameter parameter : (finalConstructor == null ? finalFactory : finalConstructor).getParameters()) { final JsonbProperty property = getAnnotation(parameter, JsonbProperty.class); @@ -179,20 +185,25 @@ public class JsonbAccessMode implements AccessMode, Closeable { final JsonbTypeAdapter adapter = getAnnotation(parameter, JsonbTypeAdapter.class); final JsonbDateFormat dateFormat = getAnnotation(parameter, JsonbDateFormat.class); final JsonbNumberFormat numberFormat = getAnnotation(parameter, JsonbNumberFormat.class); - if (adapter == null && dateFormat == null && numberFormat == null) { + final JohnzonConverter johnzonConverter = getAnnotation(parameter, JohnzonConverter.class); + if (adapter == null && dateFormat == null && numberFormat == null && johnzonConverter == null) { converters[i] = defaultConverters.get(parameter.getType()); itemConverters[i] = null; } else { - validateAnnotations(parameter, adapter, dateFormat, numberFormat); + validateAnnotations(parameter, adapter, dateFormat, numberFormat, johnzonConverter); try { - final Adapter converter = toConverter(parameter.getType(), adapter, dateFormat, numberFormat); - if (matches(parameter.getParameterizedType(), converter)) { - converters[i] = converter; - itemConverters[i] = null; - } else { - converters[i] = null; - itemConverters[i] = converter; + if (adapter != null) { + final Adapter converter = toConverter(parameter.getType(), adapter, dateFormat, numberFormat); + if (matches(parameter.getParameterizedType(), converter)) { + converters[i] = converter; + itemConverters[i] = null; + } else { + converters[i] = null; + itemConverters[i] = converter; + } + } else if (johnzonConverter != null) { + objectConverters[i] = (ObjectConverter.Codec<?>) johnzonConverter.value().newInstance(); } } catch (final InstantiationException | IllegalAccessException e) { throw new IllegalArgumentException(e); @@ -206,6 +217,7 @@ public class JsonbAccessMode implements AccessMode, Closeable { params = null; converters = null; itemConverters = null; + objectConverters = null; } return constructor == null && factory == null ? delegate.findFactory(clazz) : ( @@ -241,6 +253,11 @@ public class JsonbAccessMode implements AccessMode, Closeable { public Adapter<?, ?>[] getParameterItemConverter() { return itemConverters; } + + @Override + public ObjectConverter.Codec<?>[] getObjectConverter() { + return objectConverters; + } } : new Factory() { @Override @@ -277,17 +294,24 @@ public class JsonbAccessMode implements AccessMode, Closeable { public Adapter<?, ?>[] getParameterItemConverter() { return itemConverters; } + + @Override + public ObjectConverter.Codec<?>[] getObjectConverter() { + return objectConverters; + } }); } private void validateAnnotations(final Object parameter, final JsonbTypeAdapter adapter, final JsonbDateFormat dateFormat, - final JsonbNumberFormat numberFormat) { + final JsonbNumberFormat numberFormat, + final JohnzonConverter johnzonConverter) { int notNull = adapter != null ? 1 : 0; notNull += dateFormat != null ? 1 : 0; notNull += numberFormat != null ? 1 : 0; + notNull += johnzonConverter != null ? 1 : 0; if (notNull > 1) { - throw new IllegalArgumentException("Conflicting @JsonbXXX on " + parameter); + throw new IllegalArgumentException("Conflicting @JsonbXXX/@JohnzonConverter on " + parameter); } } @@ -612,10 +636,28 @@ public class JsonbAccessMode implements AccessMode, Closeable { final JsonbPropertyOrder orderAnnotation = Meta.getAnnotation(clazz, JsonbPropertyOrder.class); if (orderAnnotation != null) { final List<String> indexed = new ArrayList<>(asList(orderAnnotation.value())); + if (naming != null) { // JsonbPropertyOrder applies on java names + for (int i = 0; i < indexed.size(); i++) { + indexed.set(i, naming.translateName(indexed.get(i))); + } + } keyComparator = (o1, o2) -> { final int i1 = indexed.indexOf(o1); final int i2 = indexed.indexOf(o2); if (i1 < 0) { + if (i2 < 0) { + if (order != null) { + switch (order) { + case PropertyOrderStrategy.LEXICOGRAPHICAL: + return o1.compareTo(o2); + case PropertyOrderStrategy.REVERSE: + return o2.compareTo(o1); + case PropertyOrderStrategy.ANY: + default: + return 1; + } + } + } return 1; } return i1 - i2; @@ -629,7 +671,7 @@ public class JsonbAccessMode implements AccessMode, Closeable { keyComparator = String::compareTo; break; case PropertyOrderStrategy.REVERSE: - keyComparator = (o1, o2) -> o2.compareTo(o1); + keyComparator = Comparator.reverseOrder(); break; default: keyComparator = null; @@ -643,6 +685,9 @@ public class JsonbAccessMode implements AccessMode, Closeable { @Override public void close() throws IOException { toRelease.forEach(JohnzonAdapterFactory.Instance::release); + if (Closeable.class.isInstance(delegate)) { + Closeable.class.cast(delegate).close(); + } toRelease.clear(); } @@ -664,10 +709,11 @@ public class JsonbAccessMode implements AccessMode, Closeable { final JsonbTypeAdapter adapter = annotationHolder.getAnnotation(JsonbTypeAdapter.class); final JsonbDateFormat dateFormat = annotationHolder.getAnnotation(JsonbDateFormat.class); final JsonbNumberFormat numberFormat = annotationHolder.getAnnotation(JsonbNumberFormat.class); - validateAnnotations(annotationHolder, adapter, dateFormat, numberFormat); + final JohnzonConverter johnzonConverter = annotationHolder.getAnnotation(JohnzonConverter.class); + validateAnnotations(annotationHolder, adapter, dateFormat, numberFormat, johnzonConverter); try { - converter = adapter == null && dateFormat == null && numberFormat == null ? + converter = adapter == null && dateFormat == null && numberFormat == null && johnzonConverter == null ? defaultConverters.get(new AdapterKey(annotationHolder.getType(), String.class)) : toConverter(annotationHolder.getType(), adapter, dateFormat, numberFormat); } catch (final InstantiationException | IllegalAccessException e) { @@ -684,8 +730,17 @@ public class JsonbAccessMode implements AccessMode, Closeable { toRelease.add(instance); reader = (jsonObject, targetType, parser) -> instance.getValue().deserialize(parserFactory.get().createParser(jsonObject), new JohnzonDeserializationContext(parser), targetType); - } else { - reader = null; + } else if (johnzonConverter != null) { + try { + MapperConverter mapperConverter = johnzonConverter.value().newInstance(); + if (mapperConverter instanceof Converter) { + converter = new ConverterAdapter<>((Converter) mapperConverter); + } else if (mapperConverter instanceof ObjectConverter.Reader) { + reader = (ObjectConverter.Reader) mapperConverter; + } + } catch (final InstantiationException | IllegalAccessException e) { + throw new IllegalArgumentException(e); + } } } } @@ -699,10 +754,11 @@ public class JsonbAccessMode implements AccessMode, Closeable { final JsonbTypeAdapter adapter = initialReader.getAnnotation(JsonbTypeAdapter.class); final JsonbDateFormat dateFormat = initialReader.getAnnotation(JsonbDateFormat.class); final JsonbNumberFormat numberFormat = initialReader.getAnnotation(JsonbNumberFormat.class); - validateAnnotations(initialReader, adapter, dateFormat, numberFormat); + final JohnzonConverter johnzonConverter = initialReader.getAnnotation(JohnzonConverter.class); + validateAnnotations(initialReader, adapter, dateFormat, numberFormat, johnzonConverter); try { - converter = adapter == null && dateFormat == null && numberFormat == null ? + converter = adapter == null && dateFormat == null && numberFormat == null && johnzonConverter == null ? defaultConverters.get(new AdapterKey(initialReader.getType(), String.class)) : toConverter(initialReader.getType(), adapter, dateFormat, numberFormat); } catch (final InstantiationException | IllegalAccessException e) { @@ -719,8 +775,17 @@ public class JsonbAccessMode implements AccessMode, Closeable { toRelease.add(instance); writer = (instance1, jsonbGenerator) -> instance.getValue().serialize(instance1, jsonbGenerator.getJsonGenerator(), new JohnzonSerializationContext(jsonbGenerator)); - } else { - writer = null; + } else if (johnzonConverter != null) { + try { + MapperConverter mapperConverter = johnzonConverter.value().newInstance(); + if (mapperConverter instanceof Converter) { + converter = new ConverterAdapter<>((Converter) mapperConverter) ; + } else if (mapperConverter instanceof ObjectConverter.Writer) { + writer = (ObjectConverter.Writer) mapperConverter; + } + } catch (final InstantiationException | IllegalAccessException e) { + throw new IllegalArgumentException(e); + } } } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java index 9f92c9a..e119fd8 100644 --- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java +++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/CDIs.java @@ -18,7 +18,7 @@ */ package org.apache.johnzon.jsonb.cdi; -import org.apache.johnzon.jsonb.JohnsonJsonb; +import org.apache.johnzon.jsonb.JohnzonJsonb; // helper class to lazy trigger CDI deps public final class CDIs { @@ -28,12 +28,12 @@ public final class CDIs { this.tracker = Lazy.load(beanManager); } - public void track(final JohnsonJsonb johnsonJsonb) { - tracker.track(johnsonJsonb); + public void track(final JohnzonJsonb johnzonJsonb) { + tracker.track(johnzonJsonb); } - public void untrack(final JohnsonJsonb johnsonJsonb) { - tracker.untrack(johnsonJsonb); + public void untrack(final JohnzonJsonb johnzonJsonb) { + tracker.untrack(johnzonJsonb); } public boolean isCanWrite() { http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java index 17dae3c..ee42c9a 100644 --- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java +++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/cdi/JohnzonCdiExtension.java @@ -18,7 +18,7 @@ */ package org.apache.johnzon.jsonb.cdi; -import org.apache.johnzon.jsonb.JohnsonJsonb; +import org.apache.johnzon.jsonb.JohnzonJsonb; import javax.enterprise.event.Observes; import javax.enterprise.inject.spi.BeforeBeanDiscovery; @@ -29,7 +29,7 @@ import java.util.Collection; import java.util.concurrent.locks.ReentrantLock; public class JohnzonCdiExtension implements Extension { - private final Collection<JohnsonJsonb> jsonbs = new ArrayList<>(); + private final Collection<JohnzonJsonb> jsonbs = new ArrayList<>(); private final ReentrantLock lock = new ReentrantLock(); private volatile boolean canWrite = false; @@ -37,7 +37,7 @@ public class JohnzonCdiExtension implements Extension { return canWrite; } - public void track(final JohnsonJsonb jsonb) { + public void track(final JohnzonJsonb jsonb) { if (!canWrite) { throw new IllegalStateException("CDI context already shutdown"); } @@ -49,7 +49,7 @@ public class JohnzonCdiExtension implements Extension { } } - public void untrack(final JohnsonJsonb jsonb) { + public void untrack(final JohnzonJsonb jsonb) { synchronized (this) { lock.lock(); try { http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JohnzonJsonbAdapter.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JohnzonJsonbAdapter.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JohnzonJsonbAdapter.java index c9992b2..7fc505f 100644 --- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JohnzonJsonbAdapter.java +++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/converter/JohnzonJsonbAdapter.java @@ -24,36 +24,36 @@ import javax.json.bind.JsonbException; import javax.json.bind.adapter.JsonbAdapter; import java.lang.reflect.Type; -public class JohnzonJsonbAdapter<A, B> implements TypeAwareAdapter<A, B> { - private final JsonbAdapter<A, B> delegate; +public class JohnzonJsonbAdapter<JsonType, OriginalType> implements TypeAwareAdapter<OriginalType, JsonType> { + private final JsonbAdapter<OriginalType, JsonType> delegate; private final Type from; private final Type to; - public JohnzonJsonbAdapter(final JsonbAdapter<A, B> delegate, final Type from, final Type to) { + public JohnzonJsonbAdapter(final JsonbAdapter<OriginalType, JsonType> delegate, final Type from, final Type to) { this.delegate = delegate; this.from = from; this.to = to; } @Override - public A to(final B obj) { + public OriginalType to(final JsonType obj) { if (obj == null) { return null; } try { - return delegate.adaptToJson(obj); + return delegate.adaptFromJson(obj); } catch (final Exception e) { throw new JsonbException(e.getMessage(), e); } } @Override - public B from(final A obj) { + public JsonType from(final OriginalType obj) { if (obj == null) { return null; } try { - return delegate.adaptFromJson(obj); + return delegate.adaptToJson(obj); } catch (final Exception e) { throw new JsonbException(e.getMessage(), e); } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java index 05b80da..775442e 100644 --- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AdapterTest.java @@ -132,12 +132,12 @@ public class AdapterTest { public static class PolyBarAdapter implements JsonbAdapter<Bar, TypeInstance> { @Override - public Bar adaptToJson(final TypeInstance obj) throws Exception { + public Bar adaptFromJson(final TypeInstance obj) throws Exception { return obj.value; } @Override - public TypeInstance adaptFromJson(final Bar obj) throws Exception { + public TypeInstance adaptToJson(final Bar obj) throws Exception { final TypeInstance typeInstance = new TypeInstance(); typeInstance.type = obj.getClass().getName(); typeInstance.value = obj; @@ -151,29 +151,29 @@ public class AdapterTest { public static class DummyAdapter implements JsonbAdapter<Dummy, String> { @Override - public Dummy adaptToJson(final String obj) throws Exception { + public Dummy adaptFromJson(final String obj) throws Exception { final Dummy bar = new Dummy(); bar.value = Long.parseLong(obj); return bar; } @Override - public String adaptFromJson(final Dummy obj) throws Exception { + public String adaptToJson(final Dummy obj) throws Exception { return Long.toString(obj.value); } } public static class BarAdapter implements JsonbAdapter<Bar, String> { @Override - public Bar adaptToJson(final String obj) throws Exception { - final Bar bar = new Bar(); - bar.value = Integer.parseInt(obj); - return bar; + public String adaptToJson(final Bar obj) throws Exception { + return Integer.toString(obj.value); } @Override - public String adaptFromJson(final Bar obj) throws Exception { - return Integer.toString(obj.value); + public Bar adaptFromJson(final String obj) throws Exception { + final Bar bar = new Bar(); + bar.value = Integer.parseInt(obj); + return bar; } } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AnnotationOrderTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AnnotationOrderTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AnnotationOrderTest.java new file mode 100644 index 0000000..3c75869 --- /dev/null +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/AnnotationOrderTest.java @@ -0,0 +1,77 @@ +/* + * 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.JsonbBuilder; +import javax.json.bind.JsonbConfig; +import javax.json.bind.annotation.JsonbPropertyOrder; +import javax.json.bind.config.PropertyNamingStrategy; + +import static org.junit.Assert.assertEquals; + +public class AnnotationOrderTest { + /** + * Test that @JsonbPropertyOrder takes java names and pushes at the end not mentionned properties. + */ + @Test + public void run() { + final Person p = new Person(); + p.setPersonAge(12); + p.setPersonName("David"); + p.setPersonGender("Male"); + assertEquals( + "{\"person_gender\":\"Male\",\"person_name\":\"David\",\"person_age\":12}", + JsonbBuilder.create(new JsonbConfig().withPropertyNamingStrategy(PropertyNamingStrategy.LOWER_CASE_WITH_UNDERSCORES)) + .toJson(p)); + } + + @JsonbPropertyOrder({"personGender", "personName"}) + public class Person { + private String personName; + private int personAge; + private String personGender; + + public String getPersonName() { + return personName; + } + + public void setPersonName(String name) { + this.personName = name; + } + + public int getPersonAge() { + return personAge; + } + + public void setPersonAge(int age) { + this.personAge = age; + } + + public String getPersonGender() { + return personGender; + } + + public void setPersonGender(String personGender) { + this.personGender = personGender; + } + } + +} http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java index 322325f..79685bb 100644 --- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CdiAdapterTest.java @@ -90,12 +90,12 @@ public class CdiAdapterTest { private Service service; @Override - public Model adaptToJson(final String obj) throws Exception { + public Model adaptFromJson(final String obj) throws Exception { throw new UnsupportedOperationException(); } @Override - public String adaptFromJson(final Model obj) throws Exception { + public String adaptToJson(final Model obj) throws Exception { assertTrue(OwbNormalScopeProxy.class.isInstance(service)); // additional test return service.toString(obj); } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ClassConverterTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ClassConverterTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ClassConverterTest.java index 63a66c6..940404a 100644 --- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ClassConverterTest.java +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ClassConverterTest.java @@ -93,7 +93,7 @@ public class ClassConverterTest { } } - public static class MyAdapter implements JsonbAdapter<Whole, Switch> { + public static class MyAdapter implements JsonbAdapter<Switch, Whole> { @Override public Whole adaptToJson(final Switch obj) throws Exception { final Whole whole = new Whole(); http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CustomParameterizedTypeTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CustomParameterizedTypeTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CustomParameterizedTypeTest.java new file mode 100644 index 0000000..7b5e2cc --- /dev/null +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/CustomParameterizedTypeTest.java @@ -0,0 +1,104 @@ +/* + * 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.spi.JsonbProvider; +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.util.Map; +import java.util.Objects; + +import static org.hamcrest.CoreMatchers.instanceOf; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; + +public class CustomParameterizedTypeTest { + @Test + public void run() { + final String value = "{\"val1\":{\"name\":\"the name\",\"age\":1234}}"; + final Object map = JsonbProvider.provider().create().build().fromJson(value, new ParameterizedType() { + @Override + public Type[] getActualTypeArguments() { + return new Type[]{String.class, Value.class}; + } + + @Override + public Type getRawType() { + return Map.class; + } + + @Override + public Type getOwnerType() { + return null; + } + }); + assertThat(map, instanceOf(Map.class)); + final Map<String, Value> asMap = Map.class.cast(map); + assertTrue(asMap.containsKey("val1")); + assertEquals(1, asMap.size()); + assertEquals(1234, asMap.get("val1").age); + assertEquals("the name", asMap.get("val1").name); + } + + public static class Value { + private String name; + private int age; + + public String getName() { + return this.name; + } + + public void setName(String name) { + this.name = name; + } + + public int getAge() { + return this.age; + } + + public void setAge(int age) { + this.age = age; + } + + @Override + public int hashCode() { + return 0; + } + + @Override + public boolean equals(Object obj) { + if (obj == null || obj.getClass() != getClass()) { + return false; + } + Value other = (Value) obj; + return Objects.equals(this.name, other.name) + && Objects.equals(this.age, other.age); + } + + @Override + public String toString() { + return this.name + " " + this.age; + } + + } + +} http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DefaultMappingTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DefaultMappingTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DefaultMappingTest.java index 5c99371..d638d5a 100644 --- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DefaultMappingTest.java +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DefaultMappingTest.java @@ -340,11 +340,11 @@ public class DefaultMappingTest { //Map Map<String, Object> map = (Map<String, Object>) JSONB.fromJson("{\"name\":\"unknown object\"}", Object.class); - //mapping for number -> Integer, Long, BigDecimal - Map<String, Object> mapWithBigDecimal = (Map<String, Object>) JSONB.fromJson("{\"intValue\":5,\"longValue\":17179869184,\"otherValue\":1.2}", Object.class); + //mapping for number -> Integer, Long, Double + Map<String, Object> mapWithBigDecimal = (Map<String, Object>) JSONB.fromJson("{\"intValue\":5,\"longValue\":17179869184,\"doubleValue\":1.2}", Object.class); assertTrue(mapWithBigDecimal.get("intValue") instanceof Integer); assertTrue(mapWithBigDecimal.get("longValue") instanceof Long); - assertTrue(mapWithBigDecimal.get("otherValue") instanceof BigDecimal); + assertTrue(mapWithBigDecimal.get("doubleValue") instanceof Double); //Collection /* why collection and not array or sthg else? http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DynamicBufferResizingTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DynamicBufferResizingTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DynamicBufferResizingTest.java new file mode 100644 index 0000000..6345a9b --- /dev/null +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/DynamicBufferResizingTest.java @@ -0,0 +1,93 @@ +/* + * 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 javax.json.bind.Jsonb; +import javax.json.bind.JsonbBuilder; +import javax.json.bind.JsonbConfig; +import javax.json.bind.annotation.JsonbCreator; +import javax.json.bind.annotation.JsonbProperty; +import javax.json.bind.annotation.JsonbPropertyOrder; +import javax.json.bind.config.BinaryDataStrategy; + +import org.junit.Test; + +public class DynamicBufferResizingTest { + @Test + public void main() { + final JsonbConfig config = new JsonbConfig() + .withFormatting(Boolean.TRUE) + .withBinaryDataStrategy(BinaryDataStrategy.BASE_64); + Jsonb jsonb = JsonbBuilder.create(config); + + final Request request = new Request("Screenshot.png", "image/png", new byte[558140]); + String json = jsonb.toJson(request); + + // the first call works + for (int i = 0; i < 10; i++) { // originally the second call was failling + final Request fromJson = jsonb.fromJson(json, Request.class); + assertEquals("Screenshot.png", fromJson.name); + assertEquals("image/png", fromJson.mimeType); + assertEquals(558140, fromJson.body.length); + } + } + + @JsonbPropertyOrder(value = {"name", "mimeType"}) + public static class Request { + private String name; + private String mimeType; + private byte[] body; + + @JsonbCreator + public Request( + final @JsonbProperty("name") String name, + final @JsonbProperty("mimeType") String mimeType, + final @JsonbProperty("body") byte[] body) { + this.name = name; + this.mimeType = mimeType; + this.body = body; + } + + public String getName() { + return name; + } + + public void setName(String name) { + this.name = name; + } + + public String getMimeType() { + return mimeType; + } + + public void setMimeType(String mimeType) { + this.mimeType = mimeType; + } + + public byte[] getBody() { + return body; + } + + public void setBody(byte[] body) { + this.body = body; + } + } +} http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/FailOnUnknownPropertiesTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/FailOnUnknownPropertiesTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/FailOnUnknownPropertiesTest.java new file mode 100644 index 0000000..90f3bf1 --- /dev/null +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/FailOnUnknownPropertiesTest.java @@ -0,0 +1,56 @@ +/* + * 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.JsonbConfig; +import javax.json.bind.JsonbException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +public class FailOnUnknownPropertiesTest { + @Test + public void failOnUnknownProperties() { + final Jsonb jsonb = JsonbBuilder.create(new JsonbConfig().setProperty("johnzon.fail-on-unknown-properties", true)); + + // valid + assertEquals("ok", jsonb.fromJson("{\"known\":\"ok\"}", Model.class).known); + + try { // invalid + assertEquals("ok", jsonb.fromJson("{\"known\":\"ok\",\"unknown\":\"whatever\"}", Model.class).known); + fail(); + } catch (final JsonbException jsone) { + assertEquals("(fail on unknown properties): [unknown]", jsone.getMessage()); + } + try { // invalid but a missing key from the model + assertEquals("ok", jsonb.fromJson("{\"unknown\":\"whatever\"}", Model.class).known); + fail(); + } catch (final JsonbException jsone) { + assertEquals("(fail on unknown properties): [unknown]", jsone.getMessage()); + } + } + + public static class Model { + public String known; + } +} http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonConverterInJsonbTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonConverterInJsonbTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonConverterInJsonbTest.java new file mode 100644 index 0000000..f9de06a --- /dev/null +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonConverterInJsonbTest.java @@ -0,0 +1,134 @@ +/* + * 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 java.lang.reflect.Type; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; + +import javax.json.JsonObject; +import javax.json.bind.Jsonb; +import javax.json.bind.spi.JsonbProvider; + +import org.apache.johnzon.mapper.Converter; +import org.apache.johnzon.mapper.JohnzonConverter; +import org.apache.johnzon.mapper.MappingGenerator; +import org.apache.johnzon.mapper.MappingParser; +import org.apache.johnzon.mapper.ObjectConverter; +import org.junit.Test; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +/** + * Test that a Johnzon Converter works even in JsonB mode + */ +public class JohnzonConverterInJsonbTest { + + @Test + public void testJohnzonConverter() { + TestDTO dto = new TestDTO(); + dto.setInstant(Instant.now()); + + Jsonb jsonb = JsonbProvider.provider().create().build(); + String json = jsonb.toJson(dto); + assertNotNull(json); + + TestDTO deserialized = jsonb.fromJson(json, TestDTO.class); + assertEquals(dto.instant, deserialized.instant); + } + + @Test + public void testObjectConverter() { + TestDTOWithOC dto = new TestDTOWithOC(); + dto.dto = new TestDTO(); + dto.dto.instant = Instant.now(); + + Jsonb jsonb = JsonbProvider.provider().create().build(); + String json = jsonb.toJson(dto); + assertNotNull(json); + + TestDTOWithOC deserialized = jsonb.fromJson(json, TestDTOWithOC.class); + assertEquals(deserialized.dto.instant, dto.dto.instant); + } + + public static class TestDTOWithOC { + @JohnzonConverter(TestDTOConverter.class) + private TestDTO dto; + + public TestDTO getDto() { + return dto; + } + + public void setDto(TestDTO dto) { + this.dto = dto; + } + } + + public static class TestDTOConverter implements ObjectConverter.Codec<TestDTO> { + + private static final String TIMESTAMP_JSON_KEY = "timestamp"; + + @Override + public void writeJson(TestDTO instance, MappingGenerator jsonbGenerator) { + jsonbGenerator.getJsonGenerator().write(TIMESTAMP_JSON_KEY, instance.instant.atZone(ZoneId.of("UTC")).toString()); + } + + @Override + public TestDTO fromJson(JsonObject jsonObject, Type targetType, MappingParser parser) { + TestDTO dto = new TestDTO(); + dto.instant = ZonedDateTime.parse(jsonObject.getString(TIMESTAMP_JSON_KEY)).toInstant(); + return dto; + } + } + + public static class TestDTO { + @JohnzonConverter(TestInstantConverter.class) + private Instant instant; + + public Instant getInstant() { + return instant; + } + + public void setInstant(Instant instant) { + this.instant = instant; + } + } + + + public static class TestInstantConverter implements Converter<Instant> { + public static final DateTimeFormatter FORMAT = DateTimeFormatter.ofPattern( + "yyyy-MM-dd HH:mm:ss.SSS"); + + @Override + public String toString(Instant date) { + return FORMAT.withZone(ZoneId.of("UTC")).format(date); + } + + @Override + public Instant fromString(String dateStr) { + return LocalDateTime.parse(dateStr, FORMAT) + .atZone(ZoneId.of("UTC")) + .toInstant(); + } + + } + +} http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonIgnoreNestedTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonIgnoreNestedTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonIgnoreNestedTest.java new file mode 100644 index 0000000..2bf3815 --- /dev/null +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JohnzonIgnoreNestedTest.java @@ -0,0 +1,65 @@ +/* + * 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.apache.johnzon.mapper.JohnzonIgnoreNested; +import org.junit.Test; + +import javax.json.bind.Jsonb; +import javax.json.bind.spi.JsonbProvider; +import java.util.Collection; + +import static java.util.Collections.singletonList; +import static org.junit.Assert.assertEquals; + +public class JohnzonIgnoreNestedTest { + @Test + public void ignoreNested() { + final To to = new To(); + to.name = "to"; + + final Person from = new Person(); + from.name = "myname"; + from.street = "blastreet 1"; + from.description = "gets ignored"; + + to.person = from; + to.persons = singletonList(from); + + + final Jsonb jsonb = JsonbProvider.provider().create().build(); + assertEquals("{\"name\":\"to\",\"person\":{\"name\":\"myname\"},\"persons\":[{\"name\":\"myname\"}]}", jsonb.toJson(to)); + } + + public static class To { + public String name; + + @JohnzonIgnoreNested(properties = {"street", "description"}) + public Person person; + + @JohnzonIgnoreNested(properties = {"street", "description"}) + public Collection<Person> persons; + } + + public static class Person { + public String name; + public String street; + public String description; + } +} http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java index 4b19cff..bd63127 100644 --- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbReadTest.java @@ -20,16 +20,40 @@ package org.apache.johnzon.jsonb; import org.junit.Test; +import javax.json.bind.JsonbConfig; +import javax.json.bind.JsonbException; import javax.json.bind.annotation.JsonbDateFormat; import javax.json.bind.annotation.JsonbProperty; +import javax.json.bind.config.BinaryDataStrategy; import javax.json.bind.spi.JsonbProvider; + +import java.io.ByteArrayInputStream; import java.io.StringReader; +import java.nio.charset.StandardCharsets; import java.time.LocalDate; import java.time.format.DateTimeFormatter; +import java.util.Base64; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertTrue; public class JsonbReadTest { + + @Test + public void boolFromString() { + assertTrue(JsonbProvider.provider().create().build().fromJson("true", Boolean.class)); + } + + @Test + public void boolFromReader() { + assertTrue(JsonbProvider.provider().create().build().fromJson(new StringReader("true"), Boolean.class)); + } + + @Test + public void boolFromStream() { + assertTrue(JsonbProvider.provider().create().build().fromJson(new ByteArrayInputStream("true".getBytes()), Boolean.class)); + } + @Test public void simple() { assertEquals("test", JsonbProvider.provider().create().build().fromJson(new StringReader("{\"value\":\"test\"}"), Simple.class).value); @@ -48,6 +72,51 @@ public class JsonbReadTest { JsonbProvider.provider().create().build().fromJson(new StringReader("{\"date\":\"" + date + "\"}"), DateFormatting.class).date.getYear()); } + @Test + public void propertyMappingNewLine() { + String json = "{\n" + + " \"simple\":\"test\"\n" + + "}\n"; + + assertEquals("test", JsonbProvider.provider().create().build().fromJson(new StringReader(json), SimpleProperty.class).value); + } + + @Test + public void propertyMappingNewLineCr() { + String json = "{\r\n" + + " \"simple\":\"test\"\r\n" + + "}\r\n"; + + assertEquals("test", JsonbProvider.provider().create().build().fromJson(new StringReader(json), SimpleProperty.class).value); + } + + @Test + public void propertyMappingNewLineTabs() { + String json = "{\n" + + "\t\"simple\":\"test\"\n" + + "}\n"; + + assertEquals("test", JsonbProvider.provider().create().build().fromJson(new StringReader(json), SimpleProperty.class).value); + } + + @Test + public void testValidBase64() { + String json = "{\"blob\":\"" + Base64.getEncoder().encodeToString("test".getBytes(StandardCharsets.UTF_8)) + "\"}"; + JsonbConfig cfg = new JsonbConfig() + .withBinaryDataStrategy(BinaryDataStrategy.BASE_64); + SimpleBinaryDto simpleBinaryDto = JsonbProvider.provider().create().withConfig(cfg).build().fromJson(new StringReader(json), SimpleBinaryDto.class); + assertEquals("test", new String(simpleBinaryDto.getBlob(), StandardCharsets.UTF_8)); + } + + @Test(expected = JsonbException.class) + public void testInvalidBase64() { + String jsonWithIllegalBase64 = "{\"blob\":\"dGVXz@dA==\"}"; + JsonbConfig cfg = new JsonbConfig() + .withBinaryDataStrategy(BinaryDataStrategy.BASE_64); + SimpleBinaryDto simpleBinaryDto = JsonbProvider.provider().create().withConfig(cfg).build().fromJson(new StringReader(jsonWithIllegalBase64), SimpleBinaryDto.class); + } + + public static class Simple { private String value; @@ -99,4 +168,16 @@ public class JsonbReadTest { this.date = value; } } + + public static class SimpleBinaryDto { + private byte[] blob; + + public byte[] getBlob() { + return blob; + } + + public void setBlob(byte[] blob) { + this.blob = blob; + } + } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java index 0f792df..ad5b6d2 100644 --- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbTypesTest.java @@ -36,11 +36,13 @@ import java.time.Period; import java.time.ZoneId; import java.time.ZoneOffset; import java.time.ZonedDateTime; +import java.time.format.DateTimeFormatter; import java.time.temporal.ChronoUnit; import java.util.Calendar; import java.util.Comparator; import java.util.Date; import java.util.GregorianCalendar; +import java.util.Locale; import java.util.Objects; import java.util.Optional; import java.util.OptionalDouble; @@ -49,6 +51,7 @@ import java.util.OptionalLong; import java.util.SimpleTimeZone; import java.util.TimeZone; import java.util.concurrent.TimeUnit; +import org.apache.cxf.common.util.StringUtils; import static org.junit.Assert.assertEquals; @@ -109,8 +112,44 @@ public class JsonbTypesTest { assertEquals(expected, jsonb.toJson(types)); } + @Test + public void readAndWriteWithDateFormats() { + readAndWriteWithDateFormat(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"), "yyyy-MM-dd'T'HH:mm:ss.SSSZ"); + readAndWriteWithDateFormat(DateTimeFormatter.ofPattern("yyyyMMdd+HHmmssZ"), "yyyyMMdd+HHmmssZ"); + readAndWriteWithDateFormat(DateTimeFormatter.ofPattern("yyyy-MM-dd"), "yyyy-MM-dd"); + } + + private void readAndWriteWithDateFormat(DateTimeFormatter dateTimeFormatter, String dateFormat) { + final LocalDate localDate = LocalDate.of(2015, 1, 1); + final LocalDateTime localDateTime = LocalDateTime.of(2015, 1, 1, 1, 1); + final ZonedDateTime zonedDateTime = ZonedDateTime.of(localDateTime, ZoneId.of("UTC")); + final String expected = "{" + + "\"calendar\":\"" + dateTimeFormatter.format(zonedDateTime) + "\"," + + "\"date\":\"" + dateTimeFormatter.format(ZonedDateTime.ofInstant(localDateTime.toInstant(ZoneOffset.UTC), ZoneId.of("UTC"))) + "\"," + + "\"gregorianCalendar\":\"" + dateTimeFormatter.format(zonedDateTime) + "\"," + + "\"instant\":\"" + dateTimeFormatter.format(ZonedDateTime.ofInstant(Instant.ofEpochMilli(TimeUnit.DAYS.toMillis(localDate.toEpochDay())), ZoneId.of("UTC"))) + "\"," + + "\"localDate\":\"" + dateTimeFormatter.format(ZonedDateTime.ofInstant(Instant.ofEpochMilli(TimeUnit.DAYS.toMillis(localDate.toEpochDay())), ZoneId.of("UTC"))) + "\"," + + "\"localDateTime\":\"" + dateTimeFormatter.format(ZonedDateTime.ofInstant(localDateTime.toInstant(ZoneOffset.UTC), ZoneId.of("UTC"))) + "\"," + + "\"offsetDateTime\":\"" + dateTimeFormatter.format(ZonedDateTime.ofInstant(OffsetDateTime.of(localDateTime, ZoneOffset.UTC).toInstant(), ZoneId.of("UTC"))) + "\"" + + "}"; + + final Jsonb jsonb = newJsonb(dateFormat); + + final DateTypes types = jsonb.fromJson(new StringReader(expected), DateTypes.class); + assertEquals(localDate, types.localDate); + assertEquals(expected, jsonb.toJson(types)); + } + private static Jsonb newJsonb() { - return JsonbProvider.provider().create().withConfig(new JsonbConfig().setProperty("johnzon.attributeOrder", new Comparator<String>() { + return newJsonb(null); + } + + private static Jsonb newJsonb(String dateFormat) { + JsonbConfig jsonbConfig = new JsonbConfig(); + if (!StringUtils.isEmpty(dateFormat)){ + jsonbConfig.withDateFormat(dateFormat, Locale.getDefault()); + } + return JsonbProvider.provider().create().withConfig(jsonbConfig.setProperty("johnzon.attributeOrder", new Comparator<String>() { @Override public int compare(final String o1, final String o2) { return o1.compareTo(o2); @@ -339,4 +378,97 @@ public class JsonbTypesTest { period, localDateTime, localDate, offsetDateTime, offsetTime); } } + + public static class DateTypes { + private Date date; + private Calendar calendar; + private GregorianCalendar gregorianCalendar; + private Instant instant; + private LocalDateTime localDateTime; + private LocalDate localDate; + private OffsetDateTime offsetDateTime; + + + public Date getDate() { + return date; + } + + public void setDate(Date date) { + this.date = date; + } + + public Calendar getCalendar() { + return calendar; + } + + public void setCalendar(Calendar calendar) { + this.calendar = calendar; + } + + public GregorianCalendar getGregorianCalendar() { + return gregorianCalendar; + } + + public void setGregorianCalendar(GregorianCalendar gregorianCalendar) { + this.gregorianCalendar = gregorianCalendar; + } + + public Instant getInstant() { + return instant; + } + + public void setInstant(Instant instant) { + this.instant = instant; + } + + public LocalDateTime getLocalDateTime() { + return localDateTime; + } + + public void setLocalDateTime(LocalDateTime localDateTime) { + this.localDateTime = localDateTime; + } + + public LocalDate getLocalDate() { + return localDate; + } + + public void setLocalDate(LocalDate localDate) { + this.localDate = localDate; + } + + public OffsetDateTime getOffsetDateTime() { + return offsetDateTime; + } + + public void setOffsetDateTime(OffsetDateTime offsetDateTime) { + this.offsetDateTime = offsetDateTime; + } + + + @Override + public boolean equals(final Object o) { + if (this == o) { + return true; + } + if (o == null || getClass() != o.getClass()) { + return false; + } + final Types types = Types.class.cast(o); + return + Objects.equals(date, types.date) && + Objects.equals(calendar, types.calendar) && + Objects.equals(gregorianCalendar, types.gregorianCalendar) && + Objects.equals(instant, types.instant) && + Objects.equals(localDateTime, types.localDateTime) && + Objects.equals(localDate, types.localDate) && + Objects.equals(offsetDateTime, types.offsetDateTime); + } + + @Override + public int hashCode() { + return Objects.hash( + date, calendar, gregorianCalendar, instant, localDateTime, localDate, offsetDateTime); + } + } } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java index 7ec37c1..f16e2c4 100644 --- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/JsonbWriteTest.java @@ -24,6 +24,9 @@ import javax.json.bind.Jsonb; import javax.json.bind.annotation.JsonbDateFormat; import javax.json.bind.annotation.JsonbProperty; import javax.json.bind.spi.JsonbProvider; + +import java.io.ByteArrayOutputStream; +import java.io.StringWriter; import java.time.LocalDateTime; import java.util.Collection; import java.util.HashMap; @@ -34,6 +37,35 @@ import static org.junit.Assert.assertEquals; public class JsonbWriteTest { @Test + public void boolAsString() { + assertEquals("true", JsonbProvider.provider().create().build().toJson(Boolean.TRUE)); + } + + @Test + public void boolAsStringWriter() { + StringWriter sw = new StringWriter(); + JsonbProvider.provider().create().build().toJson(Boolean.TRUE,sw); + assertEquals("true", sw.toString()); + } + + @Test + public void boolAsStream() { + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonbProvider.provider().create().build().toJson(Boolean.TRUE, baos); + assertEquals("true", baos.toString()); + } + + @Test + public void boolAsStreamInObject() { + SimpleBool simple = new SimpleBool(); + simple.setBool(Boolean.TRUE); + + ByteArrayOutputStream baos = new ByteArrayOutputStream(); + JsonbProvider.provider().create().build().toJson(simple, baos); + assertEquals("{\"bool\":true}", baos.toString()); + } + + @Test public void simple() { final Simple simple = new Simple(); simple.setValue("test"); @@ -93,6 +125,19 @@ public class JsonbWriteTest { } } + public static class SimpleBool { + private Boolean bool; + + public Boolean getBool() { + return bool; + } + + public SimpleBool setBool(Boolean bool) { + this.bool = bool; + return this; + } + } + public static class SimpleProperty { @JsonbProperty("simple") private String value; http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ObjectSerializationTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ObjectSerializationTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ObjectSerializationTest.java new file mode 100644 index 0000000..7ad703c --- /dev/null +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/ObjectSerializationTest.java @@ -0,0 +1,77 @@ +/* + * 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 java.util.Arrays.asList; +import static org.junit.Assert.assertEquals; + +import javax.json.bind.Jsonb; +import javax.json.bind.JsonbBuilder; + +import org.junit.Test; + +public class ObjectSerializationTest { + private final Jsonb mapper = JsonbBuilder.create(); + + @Test + public void primitiveBoolean() { + assertEquals("{\"data\":true}", toJson(new Wrapper(true))); + } + + @Test + public void numberBoolean() { + assertEquals("{\"data\":1}", toJson(new Wrapper(1))); + } + + @Test + public void stringBoolean() { + assertEquals("{\"data\":\"ok\"}", toJson(new Wrapper("ok"))); + } + + @Test + public void objectBoolean() { + assertEquals("{\"data\":{\"data\":\"ok\"}}", toJson(new Wrapper(new Wrapper("ok")))); + } + + @Test + public void arrayString() { + assertEquals("{\"data\":[\"10\",\"2\"]}", toJson(new Wrapper(asList("10", "2")))); + } + + @Test + public void nestedArrayString() { + assertEquals("{\"data\":{\"data\":[\"10\",\"2\"]}}", toJson(new Wrapper(new Wrapper(asList("10", "2"))))); + } + + private String toJson(final Wrapper wrapper) { + return mapper.toJson(wrapper); + } + + public static class Wrapper { + private final Object data; + + private Wrapper(final Object data) { + this.data = data; + } + + public Object getData() { + return data; + } + } +} http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/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 index 475fbcc..a6771ef 100644 --- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/SerializerTest.java @@ -31,6 +31,8 @@ import javax.json.bind.serializer.SerializationContext; import javax.json.stream.JsonGenerator; import javax.json.stream.JsonParser; import java.lang.reflect.Type; +import java.util.ArrayList; +import java.util.List; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; @@ -41,19 +43,31 @@ public class SerializerTest { public void roundTrip() { final Jsonb jsonb = JsonbBuilder.create(); - final String json = "{\"foo\":{\"full\":true,\"name\":\"SerializerTest\"}}"; + final String expectedJson = "{\"foo\":{\"full\":true,\"name\":\"SerializerTest\"},\"moreFoos\":[{\"full\":true,\"name\":\"foo2\"},{\"full\":true,\"name\":\"foo3\"}]}"; final Foo foo = new Foo(); foo.name = "SerializerTest"; final Wrapper wrapper = new Wrapper(); wrapper.foo = foo; - assertEquals(json, jsonb.toJson(wrapper)); + Foo foo2 = new Foo(); + foo2.name = "foo2"; + Foo foo3 = new Foo(); + foo3.name = "foo3"; + wrapper.moreFoos.add(foo2); + wrapper.moreFoos.add(foo3); - final Wrapper deser = jsonb.fromJson(json, Wrapper.class); + assertEquals(expectedJson, jsonb.toJson(wrapper)); + + final Wrapper deser = jsonb.fromJson(expectedJson, Wrapper.class); assertEquals(foo.name, deser.foo.name); assertEquals(foo.name.length(), deser.foo.value); assertTrue(deser.foo.flag); + + assertEquals(2, deser.moreFoos.size()); + assertEquals("foo2", deser.moreFoos.get(0).name); + assertEquals(4, deser.moreFoos.get(0).value); + assertEquals(4, deser.moreFoos.get(1).value); } public static class Foo { @@ -66,6 +80,10 @@ public class SerializerTest { @JsonbTypeSerializer(FooSer.class) @JsonbTypeDeserializer(FooDeser.class) public Foo foo; + + @JsonbTypeSerializer(FooSer.class) + @JsonbTypeDeserializer(FooDeser.class) + public List<Foo> moreFoos = new ArrayList<>(); } public static class FooDeser implements JsonbDeserializer<Foo> { http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/jaxrs/JsonbJaxRsTest.java ---------------------------------------------------------------------- diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/jaxrs/JsonbJaxRsTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/jaxrs/JsonbJaxRsTest.java index d733447..91fca7d 100644 --- a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/jaxrs/JsonbJaxRsTest.java +++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/jaxrs/JsonbJaxRsTest.java @@ -41,31 +41,58 @@ import java.io.IOException; import java.io.OutputStream; import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; +import java.util.Arrays; import java.util.List; import static java.util.Arrays.asList; import static java.util.Collections.singletonList; +import javax.json.bind.Jsonb; +import javax.json.bind.JsonbBuilder; +import javax.ws.rs.ext.ContextResolver; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertTrue; public class JsonbJaxRsTest { private final static String ENDPOINT_ADDRESS = "local://johnzon"; + private final static String ENDPOINT_ADDRESS_JSONB_CONFIG = "local://johnzonjsonbconfig"; private static Server server; + private static Server serverJsonbConfig; + public static class JsonBindingProvider implements ContextResolver<Jsonb> { + + private final Jsonb jsonb = JsonbBuilder.create(); + public static Boolean called = Boolean.FALSE; + + @Override + public Jsonb getContext(Class<?> type) { + called = Boolean.TRUE; + return jsonb; + } + + } + @BeforeClass public static void bindEndpoint() throws Exception { - final JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean(); + JAXRSServerFactoryBean sf = new JAXRSServerFactoryBean(); sf.setResourceClasses(JohnzonResource.class); sf.setProviders(singletonList(new JsonbJaxrsProvider<>())); sf.setResourceProvider(JohnzonResource.class, new SingletonResourceProvider(new JohnzonResource(), false)); sf.setAddress(ENDPOINT_ADDRESS); server = sf.create(); + sf = new JAXRSServerFactoryBean(); + sf.setResourceClasses(JohnzonResource.class); + sf.setProviders(Arrays.asList(new JsonbJaxrsProvider<>(), new JsonBindingProvider())); + sf.setResourceProvider(JohnzonResource.class, new SingletonResourceProvider(new JohnzonResource(), false)); + sf.setAddress(ENDPOINT_ADDRESS_JSONB_CONFIG); + serverJsonbConfig = sf.create(); } @AfterClass public static void unbind() throws Exception { server.stop(); server.destroy(); + serverJsonbConfig.stop(); + serverJsonbConfig.destroy(); } @Test @@ -75,6 +102,12 @@ public class JsonbJaxRsTest { } @Test + public void jsonbconfigProvider() { + client(ENDPOINT_ADDRESS_JSONB_CONFIG, MediaType.APPLICATION_JSON_TYPE).path("johnzon").get(String.class); + assertEquals(JsonBindingProvider.called, Boolean.TRUE); + } + + @Test public void object() { final String output = client().path("johnzon").get(String.class); assertEquals("{\"name\":\"johnzon\"}", output); @@ -149,7 +182,11 @@ public class JsonbJaxRsTest { } private static WebClient client(final MediaType mediaType) { - final WebClient client = WebClient.create(ENDPOINT_ADDRESS, singletonList(new JsonbJaxrsProvider<>())).accept(mediaType); + return client(ENDPOINT_ADDRESS, mediaType); + } + + private static WebClient client(final String endpoint, final MediaType mediaType) { + final WebClient client = WebClient.create(endpoint, singletonList(new JsonbJaxrsProvider<>())).accept(mediaType); WebClient.getConfig(client).getRequestContext().put(LocalConduit.DIRECT_DISPATCH, Boolean.TRUE); return client; } http://git-wip-us.apache.org/repos/asf/johnzon/blob/76fe13de/johnzon-mapper/pom.xml ---------------------------------------------------------------------- diff --git a/johnzon-mapper/pom.xml b/johnzon-mapper/pom.xml index d28502a..cf16061 100644 --- a/johnzon-mapper/pom.xml +++ b/johnzon-mapper/pom.xml @@ -71,4 +71,18 @@ <staging.directory>${project.parent.reporting.outputDirectory}</staging.directory> </properties> <packaging>bundle</packaging> + + <build> + <plugins> + <plugin> + <groupId>org.apache.felix</groupId> + <artifactId>maven-bundle-plugin</artifactId> + <configuration> + <instructions> + <Export-Package>{local-packages};-split-package:=error,org.apache.johnzon.mapper.internal</Export-Package> + </instructions> + </configuration> + </plugin> + </plugins> + </build> </project>
