diff --git a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonDeserializer.java b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonDeserializer.java index bfefb16e2..ab6275d9e 100644 --- a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonDeserializer.java +++ b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonDeserializer.java @@ -16,20 +16,6 @@ */ package org.eclipse.digitaltwin.aas4j.v3.dataformat.json; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.core.type.TypeReference; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.json.JsonMapper; -import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; -import com.fasterxml.jackson.databind.module.SimpleModule; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.deserialization.EnumDeserializer; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.internal.ReflectionAnnotationIntrospector; -import org.eclipse.digitaltwin.aas4j.v3.model.Environment; -import org.eclipse.digitaltwin.aas4j.v3.model.Referable; - import java.io.BufferedReader; import java.io.File; import java.io.FileInputStream; @@ -41,6 +27,16 @@ import java.util.List; import java.util.stream.Collectors; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.DeserializationException; +import org.eclipse.digitaltwin.aas4j.v3.model.Environment; +import org.eclipse.digitaltwin.aas4j.v3.model.Referable; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.core.type.TypeReference; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; + /** * Class for deserializing/parsing AAS JSON documents. @@ -49,43 +45,14 @@ public class JsonDeserializer { protected JsonMapper mapper; protected SimpleAbstractTypeResolver typeResolver; + private JsonMapperFactory jsonMapperFactory; private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; public JsonDeserializer() { - initTypeResolver(); - buildMapper(); - } - - protected void buildMapper() { - mapper = JsonMapper.builder() - .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) - .disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) - .annotationIntrospector(new ReflectionAnnotationIntrospector()) - .addModule(buildEnumModule()) - .addModule(buildImplementationModule()) - .build(); - ReflectionHelper.JSON_MIXINS.entrySet().forEach(x -> mapper.addMixIn(x.getKey(), x.getValue())); - } - - @SuppressWarnings("unchecked") - private void initTypeResolver() { - typeResolver = new SimpleAbstractTypeResolver(); - ReflectionHelper.DEFAULT_IMPLEMENTATIONS - .stream() - .forEach(x -> typeResolver.addMapping(x.getInterfaceType(), x.getImplementationType())); - } - - protected SimpleModule buildEnumModule() { - SimpleModule module = new SimpleModule(); - ReflectionHelper.ENUMS.forEach(x -> module.addDeserializer(x, new EnumDeserializer<>(x))); - return module; - } - - protected SimpleModule buildImplementationModule() { - SimpleModule module = new SimpleModule(); - module.setAbstractTypes(typeResolver); - return module; + typeResolver = new SimpleAbstractTypeResolverFactory().create(); + jsonMapperFactory = new JsonMapperFactory(); + mapper = jsonMapperFactory.create(typeResolver); } /** @@ -185,7 +152,7 @@ public Environment read(java.io.File file) throws FileNotFoundException, Deseria */ public void useImplementation(Class aasInterface, Class implementation) { typeResolver.addMapping(aasInterface, implementation); - buildMapper(); + mapper = jsonMapperFactory.create(typeResolver); } /** diff --git a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java new file mode 100644 index 000000000..a849c7370 --- /dev/null +++ b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonMapperFactory.java @@ -0,0 +1,73 @@ +/* + * Copyright (c) 2023 Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e. V. + * + * Licensed 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.eclipse.digitaltwin.aas4j.v3.dataformat.json; + +import java.util.Arrays; +import java.util.List; + +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.deserialization.EnumDeserializer; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.serialization.EnumSerializer; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.internal.ReflectionAnnotationIntrospector; + +import com.fasterxml.jackson.annotation.JsonInclude; +import com.fasterxml.jackson.databind.DeserializationFeature; +import com.fasterxml.jackson.databind.SerializationFeature; +import com.fasterxml.jackson.databind.json.JsonMapper; +import com.fasterxml.jackson.databind.json.JsonMapper.Builder; +import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; +import com.fasterxml.jackson.databind.module.SimpleModule; + +/** + * Factory for creating a {@link JsonMapper} configured to produce and consume AAS Version 3 conformant JSON serializations + * + * @author schnicke + * + */ +public class JsonMapperFactory { + + public JsonMapper create(SimpleAbstractTypeResolver typeResolver) { + Builder builder = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT).disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES) + .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) + .annotationIntrospector(new ReflectionAnnotationIntrospector()) + .serializationInclusion(JsonInclude.Include.NON_NULL); + + getModulesToInstall(typeResolver).stream().forEach(m -> builder.addModule(m)); + + JsonMapper mapper = builder.build(); + ReflectionHelper.JSON_MIXINS.entrySet().forEach(x -> mapper.addMixIn(x.getKey(), x.getValue())); + + return mapper; + } + + protected List getModulesToInstall(SimpleAbstractTypeResolver typeResolver) { + return Arrays.asList(buildEnumModule(), buildImplementationModule(typeResolver)); + } + + protected SimpleModule buildImplementationModule(SimpleAbstractTypeResolver typeResolver) { + SimpleModule module = new SimpleModule(); + module.setAbstractTypes(typeResolver); + return module; + } + + protected SimpleModule buildEnumModule() { + SimpleModule module = new SimpleModule(); + ReflectionHelper.ENUMS.forEach(x -> module.addSerializer(x, new EnumSerializer())); + ReflectionHelper.ENUMS.forEach(x -> module.addDeserializer(x, new EnumDeserializer<>(x))); + return module; + } +} diff --git a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonSerializer.java b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonSerializer.java index f370de8c0..993ee925d 100644 --- a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonSerializer.java +++ b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/JsonSerializer.java @@ -16,21 +16,6 @@ */ package org.eclipse.digitaltwin.aas4j.v3.dataformat.json; -import com.fasterxml.jackson.annotation.JsonInclude; -import com.fasterxml.jackson.core.JsonProcessingException; -import com.fasterxml.jackson.databind.DeserializationFeature; -import com.fasterxml.jackson.databind.JsonNode; -import com.fasterxml.jackson.databind.ObjectWriter; -import com.fasterxml.jackson.databind.SerializationFeature; -import com.fasterxml.jackson.databind.json.JsonMapper; -import com.fasterxml.jackson.databind.module.SimpleModule; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.SerializationException; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.serialization.EnumSerializer; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; -import org.eclipse.digitaltwin.aas4j.v3.dataformat.json.internal.ReflectionAnnotationIntrospector; -import org.eclipse.digitaltwin.aas4j.v3.model.Environment; -import org.eclipse.digitaltwin.aas4j.v3.model.Referable; - import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; @@ -41,6 +26,15 @@ import java.util.Collection; import java.util.List; +import org.eclipse.digitaltwin.aas4j.v3.dataformat.SerializationException; +import org.eclipse.digitaltwin.aas4j.v3.model.Environment; +import org.eclipse.digitaltwin.aas4j.v3.model.Referable; + +import com.fasterxml.jackson.core.JsonProcessingException; +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectWriter; +import com.fasterxml.jackson.databind.json.JsonMapper; + /** * Class for serializing an instance of AssetAdministrationShellEnvironment or Referables to * JSON. @@ -52,29 +46,7 @@ public class JsonSerializer { private static final Charset DEFAULT_CHARSET = StandardCharsets.UTF_8; public JsonSerializer() { - buildMapper(); - } - - protected void buildMapper() { - mapper = JsonMapper.builder().enable(SerializationFeature.INDENT_OUTPUT) - .enable(DeserializationFeature.ACCEPT_SINGLE_VALUE_AS_ARRAY) - .serializationInclusion(JsonInclude.Include.NON_NULL) - .addModule(buildEnumModule()) - .addModule(buildCustomSerializerModule()) - .annotationIntrospector(new ReflectionAnnotationIntrospector()) - .build(); - ReflectionHelper.JSON_MIXINS.entrySet().forEach(x -> mapper.addMixIn(x.getKey(), x.getValue())); - } - - protected SimpleModule buildCustomSerializerModule() { - SimpleModule module = new SimpleModule(); - return module; - } - - protected SimpleModule buildEnumModule() { - SimpleModule module = new SimpleModule(); - module.addSerializer(Enum.class, new EnumSerializer()); - return module; + mapper = new JsonMapperFactory().create(new SimpleAbstractTypeResolverFactory().create()); } /** diff --git a/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/SimpleAbstractTypeResolverFactory.java b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/SimpleAbstractTypeResolverFactory.java new file mode 100644 index 000000000..742af85ab --- /dev/null +++ b/dataformat-json/src/main/java/org/eclipse/digitaltwin/aas4j/v3/dataformat/json/SimpleAbstractTypeResolverFactory.java @@ -0,0 +1,37 @@ +/* + * Copyright (c) 2023 Fraunhofer-Gesellschaft zur Foerderung der angewandten Forschung e. V. + * + * Licensed 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.eclipse.digitaltwin.aas4j.v3.dataformat.json; + +import org.eclipse.digitaltwin.aas4j.v3.dataformat.core.util.ReflectionHelper; + +import com.fasterxml.jackson.databind.module.SimpleAbstractTypeResolver; + +/** + * Factory for creating a {@link SimpleAbstractTypeResolver} configured with the + * Default Implementations of AAS4J + * + * @author schnicke + * + */ +public class SimpleAbstractTypeResolverFactory { + @SuppressWarnings("unchecked") + public SimpleAbstractTypeResolver create() { + SimpleAbstractTypeResolver typeResolver = new SimpleAbstractTypeResolver(); + ReflectionHelper.DEFAULT_IMPLEMENTATIONS.stream().forEach(x -> typeResolver.addMapping(x.getInterfaceType(), x.getImplementationType())); + return typeResolver; + } +}