You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@johnzon.apache.org by rm...@apache.org on 2019/10/18 08:01:12 UTC

[johnzon] branch master updated: JOHNZON-290 PolumorphicConfig support

This is an automated email from the ASF dual-hosted git repository.

rmannibucau 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 56cd895  JOHNZON-290 PolumorphicConfig support
56cd895 is described below

commit 56cd8957a2a9d36483eacc97911ff990403a5220
Author: Romain Manni-Bucau <rm...@gmail.com>
AuthorDate: Fri Oct 18 10:01:08 2019 +0200

    JOHNZON-290 PolumorphicConfig support
---
 .../org/apache/johnzon/jsonb/JohnzonBuilder.java   |  10 ++
 .../jsonb/api/experimental/PolymorphicConfig.java  |  80 ++++++++++++
 .../johnzon/jsonb/PolymorphicConfigTest.java       | 140 +++++++++++++++++++++
 .../org/apache/johnzon/mapper/MapperBuilder.java   |  38 +++++-
 .../org/apache/johnzon/mapper/MapperConfig.java    |  46 ++++++-
 .../johnzon/mapper/MappingGeneratorImpl.java       |   7 +-
 .../apache/johnzon/mapper/MappingParserImpl.java   |  13 +-
 .../apache/johnzon/mapper/MapperConfigTest.java    |  10 +-
 .../test/java/org/superbiz/ExtendMappingTest.java  |  14 +--
 9 files changed, 337 insertions(+), 21 deletions(-)

diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
index d33f229..427e493 100644
--- a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/JohnzonBuilder.java
@@ -88,6 +88,7 @@ import org.apache.johnzon.core.AbstractJsonFactory;
 import org.apache.johnzon.core.JsonGeneratorFactoryImpl;
 import org.apache.johnzon.core.JsonParserFactoryImpl;
 import org.apache.johnzon.core.Types;
+import org.apache.johnzon.jsonb.api.experimental.PolymorphicConfig;
 import org.apache.johnzon.jsonb.cdi.CDIs;
 import org.apache.johnzon.jsonb.converter.JohnzonJsonbAdapter;
 import org.apache.johnzon.jsonb.factory.SimpleJohnzonAdapterFactory;
@@ -167,6 +168,15 @@ public class JohnzonBuilder implements JsonbBuilder {
             builder.setPretty(true);
         }
 
+        config.getProperty(PolymorphicConfig.class.getName())
+                .map(PolymorphicConfig.class::cast)
+                .ifPresent(pc -> {
+                    builder.setPolymorphicDiscriminator(pc.getDiscriminator());
+                    builder.setPolymorphicDeserializationPredicate(pc.getDeserializationPredicate());
+                    builder.setPolymorphicSerializationPredicate(pc.getSerializationPredicate());
+                    builder.setPolymorphicDiscriminatorMapper(pc.getDiscriminatorMapper());
+                    builder.setPolymorphicTypeLoader(pc.getTypeLoader());
+                });
         config.getProperty(JsonbConfig.ENCODING).ifPresent(encoding -> builder.setEncoding(String.valueOf(encoding)));
         final boolean isNillable = config.getProperty(JsonbConfig.NULL_VALUES)
                 .map(it -> String.class.isInstance(it) ? Boolean.parseBoolean(it.toString()) : Boolean.class.cast(it))
diff --git a/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/api/experimental/PolymorphicConfig.java b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/api/experimental/PolymorphicConfig.java
new file mode 100644
index 0000000..e127a43
--- /dev/null
+++ b/johnzon-jsonb/src/main/java/org/apache/johnzon/jsonb/api/experimental/PolymorphicConfig.java
@@ -0,0 +1,80 @@
+/*
+ * 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.api.experimental;
+
+import java.util.function.Function;
+import java.util.function.Predicate;
+
+public class PolymorphicConfig {
+    private Function<String, Class<?>> typeLoader = a -> {
+        throw new IllegalArgumentException("Unknown alias: '" + a + "'");
+    };
+    private Function<Class<?>, String> discriminatorMapper = type -> {
+        throw new IllegalArgumentException("Unknown class '" + type.getName() + "'");
+    };
+    private Predicate<Class<?>> serializationPredicate = c -> false;
+    private Predicate<Class<?>> deserializationPredicate = c -> false;
+    private String discriminator = "@type";
+
+    public PolymorphicConfig withDeserializationPredicate(final Predicate<Class<?>> deserializationPredicate) {
+        this.deserializationPredicate = deserializationPredicate;
+        return this;
+    }
+
+    public PolymorphicConfig withSerializationPredicate(final Predicate<Class<?>> serializationPredicate) {
+        this.serializationPredicate = serializationPredicate;
+        return this;
+    }
+
+    public PolymorphicConfig withDiscriminatorMapper(final Function<Class<?>, String> discriminatorMapper) {
+        this.discriminatorMapper = discriminatorMapper;
+        return this;
+    }
+
+    // note this prevents @JsonbCreator usage but otherwise the user will do its own mapping with a deserializer
+    public PolymorphicConfig withTypeLoader(final Function<String, Class<?>> typeLoader) {
+        this.typeLoader = typeLoader;
+        return this;
+    }
+
+    public PolymorphicConfig withDiscriminator(final String value) {
+        this.discriminator = value;
+        return this;
+    }
+
+    public Predicate<Class<?>> getDeserializationPredicate() {
+        return deserializationPredicate;
+    }
+
+    public Function<String, Class<?>> getTypeLoader() {
+        return typeLoader;
+    }
+
+    public Function<Class<?>, String> getDiscriminatorMapper() {
+        return discriminatorMapper;
+    }
+
+    public Predicate<Class<?>> getSerializationPredicate() {
+        return serializationPredicate;
+    }
+
+    public String getDiscriminator() {
+        return discriminator;
+    }
+}
diff --git a/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/PolymorphicConfigTest.java b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/PolymorphicConfigTest.java
new file mode 100644
index 0000000..de2e5d7
--- /dev/null
+++ b/johnzon-jsonb/src/test/java/org/apache/johnzon/jsonb/PolymorphicConfigTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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 java.util.Locale.ROOT;
+import static org.junit.Assert.assertEquals;
+
+import java.util.List;
+import java.util.Objects;
+
+import javax.json.bind.Jsonb;
+import javax.json.bind.JsonbBuilder;
+import javax.json.bind.JsonbConfig;
+import javax.json.bind.config.PropertyOrderStrategy;
+
+import org.apache.johnzon.jsonb.api.experimental.PolymorphicConfig;
+import org.junit.Test;
+
+public class PolymorphicConfigTest {
+    @Test
+    public void roundTrip() throws Exception {
+        final Dog dog = new Dog();
+        dog.name = "wof";
+
+        final Cat cat = new Cat();
+        cat.otherName = "miaou";
+
+        final Aggregate aggregate = new Aggregate();
+        aggregate.animals = asList(dog, cat);
+
+        final String aggJson =
+                "{\"animals\":[{\"@type\":\"dog\",\"name\":\"wof\"},{\"@type\":\"cat\",\"otherName\":\"miaou\"}]}";
+        final String dogJson = "{\"@type\":\"dog\",\"name\":\"wof\"}";
+        try (final Jsonb jsonb = JsonbBuilder.create(new JsonbConfig()
+            .withPropertyOrderStrategy(PropertyOrderStrategy.LEXICOGRAPHICAL)
+            .setProperty(PolymorphicConfig.class.getName(), new PolymorphicConfig()
+                .withDiscriminator("@type")
+                .withSerializationPredicate(c -> asList(Dog.class, Cat.class).contains(c)) // inline/bad/slow impl ok test
+                .withDeserializationPredicate(c -> Animal.class == c)
+                .withDiscriminatorMapper(c -> c.getSimpleName().toLowerCase(ROOT))
+                .withTypeLoader(c -> {
+                    switch (c) {
+                        case "dog":
+                            return Dog.class;
+                        case "cat":
+                            return Cat.class;
+                        default:
+                            throw new IllegalArgumentException(c);
+                    }
+                })))) {
+            assertEquals(aggJson, jsonb.toJson(aggregate));
+            assertEquals(aggregate, jsonb.fromJson(aggJson, Aggregate.class));
+            assertEquals(dogJson, jsonb.toJson(dog));
+            assertEquals(dog, jsonb.fromJson(dogJson, Dog.class));
+        }
+    }
+
+    public interface Animal {
+    }
+
+    public static class Dog implements Animal {
+        public String name;
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            Dog dog = (Dog) o;
+            return Objects.equals(name, dog.name);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(name);
+        }
+    }
+
+    public static class Cat implements Animal {
+        public String otherName;
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            Cat cat = (Cat) o;
+            return Objects.equals(otherName, cat.otherName);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(otherName);
+        }
+    }
+
+    public static class Aggregate {
+        public List<Animal> animals;
+
+        @Override
+        public boolean equals(Object o) {
+            if (this == o) {
+                return true;
+            }
+            if (o == null || getClass() != o.getClass()) {
+                return false;
+            }
+            Aggregate aggregate = (Aggregate) o;
+            return animals.equals(aggregate.animals);
+        }
+
+        @Override
+        public int hashCode() {
+            return Objects.hash(animals);
+        }
+    }
+}
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
index 6eadc0e..3482e5a 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperBuilder.java
@@ -70,6 +70,8 @@ import java.util.Locale;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
+import java.util.function.Predicate;
 
 // this class is responsible to hold any needed config
 // to build the runtime
@@ -147,6 +149,13 @@ public class MapperBuilder {
     private boolean useBigDecimalForObjectNumbers;
     private boolean supportEnumContainerDeserialization = true;
 
+    // @experimental polymorphic api
+    private Function<String, Class<?>> typeLoader;
+    private Function<Class<?>, String> discriminatorMapper;
+    private Predicate<Class<?>> deserializationPredicate;
+    private Predicate<Class<?>> serializationPredicate;
+    private String discriminator;
+
     public Mapper build() {
         if (readerFactory == null || generatorFactory == null) {
             final JsonProvider provider;
@@ -261,7 +270,9 @@ public class MapperBuilder {
                         accessMode, encoding, attributeOrder, enforceQuoteString, failOnUnknownProperties,
                         serializeValueFilter, useBigDecimalForFloats, deduplicateObjects,
                         interfaceImplementationMapping, useJsRange, useBigDecimalForObjectNumbers,
-                        supportEnumContainerDeserialization),
+                        supportEnumContainerDeserialization,
+                        typeLoader, discriminatorMapper, discriminator,
+                        deserializationPredicate, serializationPredicate),
                 closeables);
     }
 
@@ -538,4 +549,29 @@ public class MapperBuilder {
         this.supportEnumContainerDeserialization = supportEnumContainerDeserialization;
         return this;
     }
+
+    public MapperBuilder setPolymorphicSerializationPredicate(final Predicate<Class<?>> serializationPredicate) {
+        this.serializationPredicate = serializationPredicate;
+        return this;
+    }
+
+    public MapperBuilder setPolymorphicDeserializationPredicate(final Predicate<Class<?>> deserializationPredicate) {
+        this.deserializationPredicate = deserializationPredicate;
+        return this;
+    }
+
+    public MapperBuilder setPolymorphicDiscriminatorMapper(final Function<Class<?>, String> discriminatorMapper) {
+        this.discriminatorMapper = discriminatorMapper;
+        return this;
+    }
+
+    public MapperBuilder setPolymorphicTypeLoader(final Function<String, Class<?>> typeLoader) {
+        this.typeLoader = typeLoader;
+        return this;
+    }
+
+    public MapperBuilder setPolymorphicDiscriminator(final String value) {
+        this.discriminator = value;
+        return this;
+    }
 }
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java
index 1f3eafb..fb9f609 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MapperConfig.java
@@ -31,6 +31,8 @@ import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
 import java.util.concurrent.ConcurrentMap;
+import java.util.function.Function;
+import java.util.function.Predicate;
 
 /**
  * Contains internal configuration for all the mapper stuff.
@@ -75,6 +77,12 @@ public /* DON'T MAKE IT HIDDEN */ class MapperConfig implements Cloneable {
     private final Map<Class<?>, Class<?>> interfaceImplementationMapping;
     private final boolean useBigDecimalForObjectNumbers;
 
+    private final Function<String, Class<?>> typeLoader;
+    private final Function<Class<?>, String> discriminatorMapper;
+    private final Predicate<Class<?>> serializationPredicate;
+    private final Predicate<Class<?>> deserializationPredicate;
+    private final String discriminator;
+
     private final Map<Class<?>, ObjectConverter.Writer<?>> objectConverterWriterCache;
     private final Map<Class<?>, ObjectConverter.Reader<?>> objectConverterReaderCache;
 
@@ -96,7 +104,12 @@ public /* DON'T MAKE IT HIDDEN */ class MapperConfig implements Cloneable {
                         final Map<Class<?>, Class<?>> interfaceImplementationMapping,
                         final boolean useJsRange,
                         final boolean useBigDecimalForObjectNumbers,
-                        final boolean supportEnumMapDeserialization) {
+                        final boolean supportEnumMapDeserialization,
+                        final Function<String, Class<?>> typeLoader,
+                        final Function<Class<?>, String> discriminatorMapper,
+                        final String discriminator,
+                        final Predicate<Class<?>> deserializationPredicate,
+                        final Predicate<Class<?>> serializationPredicate) {
     //CHECKSTYLE:ON
         this.objectConverterWriters = objectConverterWriters;
         this.objectConverterReaders = objectConverterReaders;
@@ -112,11 +125,16 @@ public /* DON'T MAKE IT HIDDEN */ class MapperConfig implements Cloneable {
         this.useJsRange = useJsRange;
         this.useBigDecimalForObjectNumbers = useBigDecimalForObjectNumbers;
         this.supportEnumMapDeserialization = supportEnumMapDeserialization;
+        this.typeLoader = typeLoader;
+        this.discriminatorMapper = discriminatorMapper;
+        this.serializationPredicate = serializationPredicate;
+        this.deserializationPredicate = deserializationPredicate;
+        this.discriminator = discriminator;
 
         // handle Adapters
         this.adapters = adapters;
         this.reverseAdapters = new ConcurrentHashMap<>(adapters.size());
-        adapters.entrySet().forEach(e -> this.reverseAdapters.put(e.getValue(), e.getKey()));
+        adapters.forEach((k, v) -> this.reverseAdapters.put(v, k));
 
 
         this.attributeOrder = attributeOrder;
@@ -125,12 +143,32 @@ public /* DON'T MAKE IT HIDDEN */ class MapperConfig implements Cloneable {
         this.serializeValueFilter = serializeValueFilter == null ? (name, value) -> false : serializeValueFilter;
         this.interfaceImplementationMapping = interfaceImplementationMapping;
 
-        this.objectConverterWriterCache = new HashMap<Class<?>, ObjectConverter.Writer<?>>(objectConverterWriters.size());
-        this.objectConverterReaderCache = new HashMap<Class<?>, ObjectConverter.Reader<?>>(objectConverterReaders.size());
+        this.objectConverterWriterCache = new HashMap<>(objectConverterWriters.size());
+        this.objectConverterReaderCache = new HashMap<>(objectConverterReaders.size());
         this.useBigDecimalForFloats = useBigDecimalForFloats;
         this.deduplicateObjects = deduplicateObjects;
     }
 
+    public Function<String, Class<?>> getTypeLoader() {
+        return typeLoader;
+    }
+
+    public Function<Class<?>, String> getDiscriminatorMapper() {
+        return discriminatorMapper;
+    }
+
+    public Predicate<Class<?>> getDeserializationPredicate() {
+        return deserializationPredicate;
+    }
+
+    public Predicate<Class<?>> getSerializationPredicate() {
+        return serializationPredicate;
+    }
+
+    public String getDiscriminator() {
+        return discriminator;
+    }
+
     public boolean isUseBigDecimalForObjectNumbers() {
         return useBigDecimalForObjectNumbers;
     }
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java
index b60bea5..d2fe205 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingGeneratorImpl.java
@@ -178,7 +178,12 @@ public class MappingGeneratorImpl implements MappingGenerator {
                 if (writeBody) {
                     generator.writeStartObject();
                 }
-                doWriteObjectBody(object, ignoredProperties, jsonPointer, generator);
+                if (config.getSerializationPredicate() != null && config.getSerializationPredicate().test(objectClass)) {
+                    generator.write(config.getDiscriminator(), config.getDiscriminatorMapper().apply(objectClass));
+                    doWriteObjectBody(object, ignoredProperties, jsonPointer, generator);
+                } else {
+                    doWriteObjectBody(object, ignoredProperties, jsonPointer, generator);
+                }
                 if (writeBody) {
                     generator.writeEnd();
                 }
diff --git a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
index 6c16b72..a5ed7b3 100644
--- a/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
+++ b/johnzon-mapper/src/main/java/org/apache/johnzon/mapper/MappingParserImpl.java
@@ -238,7 +238,8 @@ public class MappingParserImpl implements MappingParser {
     }
 
 
-    private Object buildObject(final Type inType, final JsonObject object, final boolean applyObjectConverter, JsonPointerTracker jsonPointer) {
+    private Object buildObject(final Type inType, final JsonObject object, final boolean applyObjectConverter,
+                               final JsonPointerTracker jsonPointer) {
         Type type = inType;
         if (inType == Object.class) {
             type = new JohnzonParameterizedType(Map.class, String.class, Object.class);
@@ -256,6 +257,16 @@ public class MappingParserImpl implements MappingParser {
             }
         }
 
+        if (config.getDeserializationPredicate() != null && Class.class.isInstance(inType)) {
+            final Class<?> clazz = Class.class.cast(inType);
+            if (config.getDeserializationPredicate().test(clazz) && object.containsKey(config.getDiscriminator())) {
+                final String discriminator = object.getString(config.getDiscriminator());
+                final Class<?> nestedType = config.getTypeLoader().apply(discriminator);
+                if (nestedType != null && nestedType != inType) {
+                    return buildObject(nestedType, object, applyObjectConverter, jsonPointer);
+                }
+            }
+        }
         final Mappings.ClassMapping classMapping = mappings.findOrCreateClassMapping(type);
 
         if (classMapping == null) {
diff --git a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java
index 3becb92..f0f4020 100644
--- a/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java
+++ b/johnzon-mapper/src/test/java/org/apache/johnzon/mapper/MapperConfigTest.java
@@ -21,14 +21,13 @@ package org.apache.johnzon.mapper;
 import static java.util.Collections.emptyMap;
 
 import org.apache.johnzon.mapper.access.FieldAccessMode;
-import org.apache.johnzon.mapper.internal.AdapterKey;
 import org.junit.Assert;
 import org.junit.Test;
 
 import javax.json.JsonValue;
 
 import java.lang.reflect.Type;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.Map;
@@ -157,7 +156,7 @@ public class MapperConfigTest {
 
 
     private MapperConfig createConfig(Map<Class<?>, ObjectConverter.Codec<?>> converter) {
-        return new MapperConfig(new ConcurrentHashMap<AdapterKey, Adapter<?, ?>>(0),
+        return new MapperConfig(new ConcurrentHashMap<>(0),
                                 Map.class.cast(converter), Map.class.cast(converter),
                                 -1,
                                 true,
@@ -167,9 +166,10 @@ public class MapperConfigTest {
                                 false,
                                 false,
                                 new FieldAccessMode(true, true),
-                                Charset.forName("UTF-8"),
+                                StandardCharsets.UTF_8,
                                 null,
-                                false, false, null, false, false, emptyMap(), true, false, true);
+                                false, false, null, false, false, emptyMap(), true, false, true,
+                                null, null, null, null, null);
     }
 
 
diff --git a/johnzon-mapper/src/test/java/org/superbiz/ExtendMappingTest.java b/johnzon-mapper/src/test/java/org/superbiz/ExtendMappingTest.java
index 559302a..8e5264c 100644
--- a/johnzon-mapper/src/test/java/org/superbiz/ExtendMappingTest.java
+++ b/johnzon-mapper/src/test/java/org/superbiz/ExtendMappingTest.java
@@ -18,16 +18,13 @@
  */
 package org.superbiz;
 
-import org.apache.johnzon.mapper.Adapter;
 import org.apache.johnzon.mapper.MapperConfig;
 import org.apache.johnzon.mapper.Mappings;
-import org.apache.johnzon.mapper.ObjectConverter;
 import org.apache.johnzon.mapper.access.FieldAccessMode;
-import org.apache.johnzon.mapper.internal.AdapterKey;
 import org.junit.Test;
 
 import java.lang.reflect.Type;
-import java.nio.charset.Charset;
+import java.nio.charset.StandardCharsets;
 import java.util.HashMap;
 import java.util.Map;
 import java.util.concurrent.ConcurrentHashMap;
@@ -60,13 +57,12 @@ public class ExtendMappingTest {
     public static class MyMappings extends Mappings {
         public MyMappings() {
             super(new MapperConfig(
-                    new ConcurrentHashMap<AdapterKey, Adapter<?, ?>>(),
-                    new HashMap<Class<?>, ObjectConverter.Writer<?>>(),
-                    new HashMap<Class<?>, ObjectConverter.Reader<?>>(),
+                    new ConcurrentHashMap<>(), new HashMap<>(), new HashMap<>(),
                     -1, true, true, true, false, false, false,
                     new FieldAccessMode(false, false),
-                    Charset.forName("UTF-8"), String::compareTo, false, false, null, false, false,
-                    emptyMap(), true, false, true));
+                    StandardCharsets.UTF_8, String::compareTo, false, false, null, false, false,
+                    emptyMap(), true, false, true,
+                    null, null, null, null, null));
         }
 
         @Override