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);

Reply via email to