You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by jl...@apache.org on 2023/10/11 15:05:16 UTC
[johnzon] branch master updated: feat: add support for JsonbTypeDeserializer with factories (JsonbCreator)
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 <jl...@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 <jl...@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);