diff --git a/impl/jackson/src/main/java/io/serverlessworkflow/impl/jackson/JsonUtils.java b/impl/jackson/src/main/java/io/serverlessworkflow/impl/jackson/JsonUtils.java index 146df093..649242a5 100644 --- a/impl/jackson/src/main/java/io/serverlessworkflow/impl/jackson/JsonUtils.java +++ b/impl/jackson/src/main/java/io/serverlessworkflow/impl/jackson/JsonUtils.java @@ -44,7 +44,9 @@ import java.util.EnumSet; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.Optional; +import java.util.ServiceLoader; import java.util.Set; import java.util.function.BiConsumer; import java.util.function.BinaryOperator; @@ -54,10 +56,26 @@ public class JsonUtils { - private static ObjectMapper mapper = new ObjectMapper(); + private static class DefaultMapperFactory implements ObjectMapperFactory { + private static ObjectMapper mapper = new ObjectMapper().findAndRegisterModules(); + + @Override + public ObjectMapper get() { + return mapper; + } + } + + private static ObjectMapperFactory mapperFactory = + ServiceLoader.load(ObjectMapperFactory.class) + .findFirst() + .orElseGet(() -> new DefaultMapperFactory()); + + public static void setMapperFactory(ObjectMapperFactory mapperFactory) { + JsonUtils.mapperFactory = Objects.requireNonNull(mapperFactory); + } public static ObjectMapper mapper() { - return mapper; + return mapperFactory.get(); } public static Collector arrayNodeCollector() { @@ -87,7 +105,7 @@ public Function finisher() { @Override public Supplier supplier() { - return () -> mapper.createArrayNode(); + return () -> mapper().createArrayNode(); } }; } @@ -129,7 +147,7 @@ public static JsonNode fromValue(Object value) { } else if (value instanceof WorkflowModel model) { return modelToJson(model); } else { - return mapper.convertValue(value, JsonNode.class); + return mapper().convertValue(value, JsonNode.class); } } @@ -152,7 +170,7 @@ public static JsonNode fromString(String value) { String trimmedValue = value.trim(); if (trimmedValue.startsWith("{") && trimmedValue.endsWith("}")) { try { - return mapper.readTree(trimmedValue); + return mapper().readTree(trimmedValue); } catch (IOException ex) { // ignore and return test node } @@ -186,7 +204,7 @@ public static T convertValue(Object obj, Class returnType) { } else if (obj instanceof JsonNode) { return convertValue((JsonNode) obj, returnType); } else { - return mapper.convertValue(obj, returnType); + return mapper().convertValue(obj, returnType); } } @@ -203,7 +221,7 @@ public static T convertValue(JsonNode jsonNode, Class returnType) { } else if (String.class.isAssignableFrom(returnType)) { obj = jsonNode.asText(); } else { - obj = mapper.convertValue(jsonNode, returnType); + obj = mapper().convertValue(jsonNode, returnType); } return returnType.cast(obj); } @@ -233,12 +251,12 @@ private static Object internalToJavaValue( } else if (jsonNode.isObject()) { return objectFunction.apply((ObjectNode) jsonNode); } else { - return mapper.convertValue(jsonNode, Object.class); + return mapper().convertValue(jsonNode, Object.class); } } public static String toString(JsonNode node) throws JsonProcessingException { - return mapper.writeValueAsString(node); + return mapper().writeValueAsString(node); } public static void addToNode(String name, Object value, ObjectNode dest) { @@ -246,7 +264,7 @@ public static void addToNode(String name, Object value, ObjectNode dest) { } private static ObjectNode mapToNode(Map value) { - ObjectNode objectNode = mapper.createObjectNode(); + ObjectNode objectNode = mapper().createObjectNode(); for (Map.Entry entry : value.entrySet()) { addToNode(entry.getKey(), entry.getValue(), objectNode); } @@ -254,7 +272,7 @@ private static ObjectNode mapToNode(Map value) { } private static ArrayNode mapToArray(Collection collection) { - return mapToArray(collection, mapper.createArrayNode()); + return mapToArray(collection, mapper().createArrayNode()); } private static ArrayNode mapToArray(Collection collection, ArrayNode arrayNode) { @@ -265,11 +283,11 @@ private static ArrayNode mapToArray(Collection collection, ArrayNode arrayNod } public static ObjectNode object() { - return mapper.createObjectNode(); + return mapper().createObjectNode(); } public static ArrayNode array() { - return mapper.createArrayNode(); + return mapper().createArrayNode(); } public static Optional toDate(JsonNode node) { diff --git a/impl/jackson/src/main/java/io/serverlessworkflow/impl/jackson/ObjectMapperFactory.java b/impl/jackson/src/main/java/io/serverlessworkflow/impl/jackson/ObjectMapperFactory.java new file mode 100644 index 00000000..684a60a6 --- /dev/null +++ b/impl/jackson/src/main/java/io/serverlessworkflow/impl/jackson/ObjectMapperFactory.java @@ -0,0 +1,21 @@ +/* + * Copyright 2020-Present The Serverless Workflow Specification Authors + * + * 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 io.serverlessworkflow.impl.jackson; + +import com.fasterxml.jackson.databind.ObjectMapper; +import java.util.function.Supplier; + +public interface ObjectMapperFactory extends Supplier {}