This is an automated email from the ASF dual-hosted git repository. jlmonteiro pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/johnzon.git
The following commit(s) were added to refs/heads/master by this push: new aef76ee8 feat: add support for JsonbTypeDeserializer with factories (JsonbCreator) aef76ee8 is described below commit aef76ee8b6ab4f76e2ffc709cd9f61abc61c435c Author: Jean-Louis Monteiro <jlmonte...@tomitribe.com> AuthorDate: Wed Oct 11 16:39:44 2023 +0200 feat: add support for JsonbTypeDeserializer with factories (JsonbCreator) Signed-off-by: Jean-Louis Monteiro <jlmonte...@tomitribe.com> --- .../org/apache/johnzon/jsonb/JsonbAccessMode.java | 60 +++++++++++++++++++++- 1 file changed, 59 insertions(+), 1 deletion(-) 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 fb3f3fc7..a18b3481 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 @@ -264,7 +264,8 @@ public class JsonbAccessMode implements AccessMode, Closeable, Cleanable<Class<? final JsonbDateFormat dateFormat = getAnnotation(parameter, JsonbDateFormat.class); final JsonbNumberFormat numberFormat = getAnnotation(parameter, JsonbNumberFormat.class); final JohnzonConverter johnzonConverter = getAnnotation(parameter, JohnzonConverter.class); - if (adapter == null && dateFormat == null && numberFormat == null && johnzonConverter == null) { + final JsonbTypeDeserializer deserializer = getAnnotation(parameter, JsonbTypeDeserializer.class); + if (adapter == null && dateFormat == null && numberFormat == null && johnzonConverter == null && deserializer == null) { converters[i] = defaultConverters.get(parameter.getType()); itemConverters[i] = null; } else { @@ -283,6 +284,63 @@ public class JsonbAccessMode implements AccessMode, Closeable, Cleanable<Class<? } } else if (johnzonConverter != null) { objectConverters[i] = (ObjectConverter.Codec<?>) johnzonConverter.value().newInstance(); + + } else if (deserializer != null) { + final Class<? extends JsonbDeserializer> value = deserializer.value(); + final JohnzonAdapterFactory.Instance<? extends JsonbDeserializer> instance = newInstance(value); + final ParameterizedType pt = this.types.findParameterizedType(value, JsonbDeserializer.class); + final Class<?> mappedType = this.types.findParamType(pt, JsonbDeserializer.class); + toRelease.add(instance); + final JsonBuilderFactory builderFactoryInstance = builderFactory.get(); + final Type[] arguments = this.types.findParameterizedType(value, JsonbDeserializer.class).getActualTypeArguments(); + final boolean global = arguments.length == 1 && arguments[0] != null && arguments[0].equals(parameter.getType()); + objectConverters[i] = new ObjectConverter.Codec() { + private final ConcurrentMap<Type, BiFunction<JsonValue, MappingParser, Object>> impl = + new ConcurrentHashMap<>(); + @Override + public Object fromJson(final JsonValue value, final Type targetType, final MappingParser parser) { + final JsonbDeserializer jsonbDeserializer = instance.getValue(); + if (global || targetType == mappedType) { // fast test and matches most cases + return mapItem(value, targetType, parser, jsonbDeserializer); + } + + BiFunction<JsonValue, MappingParser, Object> fn = impl.get(targetType); + if (fn == null) { + if (value.getValueType() == JsonValue.ValueType.ARRAY) { + if (ParameterizedType.class.isInstance(targetType)) { + final ParameterizedType parameterizedType = ParameterizedType.class.cast(targetType); + final Class<?> paramType = JsonbAccessMode.this.types.findParamType(parameterizedType, Collection.class); + if (paramType != null && (mappedType == null /*Object*/ || mappedType.isAssignableFrom(paramType))) { + final Collector<Object, ?, ? extends Collection<Object>> collector = + Set.class.isAssignableFrom( + JsonbAccessMode.this.types.asClass(parameterizedType.getRawType())) ? toSet() : toList(); + fn = (json, mp) -> json.asJsonArray().stream() + .map(i -> mapItem(i, paramType, mp, jsonbDeserializer)) + .collect(collector); + } + } + } + if (fn == null) { + fn = (json, mp) -> mapItem(json, targetType, mp, jsonbDeserializer); + } + impl.putIfAbsent(targetType, fn); + } + return fn.apply(value, parser); + } + + private Object mapItem(final JsonValue jsonValue, final Type targetType, + final MappingParser parser, final JsonbDeserializer jsonbDeserializer) { + return jsonbDeserializer.deserialize( + JsonValueParserAdapter.createFor(jsonValue, parserFactory), + new JohnzonDeserializationContext(parser, builderFactoryInstance, jsonProvider), + targetType); + } + + @Override + public void writeJson(final Object instance, final MappingGenerator jsonbGenerator) { + // no-op, it's for factories only + } + }; } } catch (final InstantiationException | IllegalAccessException e) { throw new IllegalArgumentException(e);