Skip to content

Commit af34dd3

Browse files
committed
[Fix #840] Allow overriding of default object mapper
By default, the internal object mapper will call findAndRegisterModules. If this is not the desired behaviour, implementors might replace it by a custom object mapper of their choice, either using ServiceLoader or explicit static call. Signed-off-by: fjtirado <[email protected]>
1 parent 666cdb3 commit af34dd3

File tree

2 files changed

+52
-13
lines changed

2 files changed

+52
-13
lines changed

impl/jackson/src/main/java/io/serverlessworkflow/impl/jackson/JsonUtils.java

Lines changed: 31 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -44,7 +44,9 @@
4444
import java.util.EnumSet;
4545
import java.util.HashMap;
4646
import java.util.Map;
47+
import java.util.Objects;
4748
import java.util.Optional;
49+
import java.util.ServiceLoader;
4850
import java.util.Set;
4951
import java.util.function.BiConsumer;
5052
import java.util.function.BinaryOperator;
@@ -54,10 +56,26 @@
5456

5557
public class JsonUtils {
5658

57-
private static ObjectMapper mapper = new ObjectMapper();
59+
private static class DefaultMapperFactory implements ObjectMapperFactory {
60+
private static ObjectMapper mapper = new ObjectMapper().findAndRegisterModules();
61+
62+
@Override
63+
public ObjectMapper get() {
64+
return mapper;
65+
}
66+
}
67+
68+
private static ObjectMapperFactory mapperFactory =
69+
ServiceLoader.load(ObjectMapperFactory.class)
70+
.findFirst()
71+
.orElseGet(() -> new DefaultMapperFactory());
72+
73+
public static void setMapperFactory(ObjectMapperFactory mapperFactory) {
74+
JsonUtils.mapperFactory = Objects.requireNonNull(mapperFactory);
75+
}
5876

5977
public static ObjectMapper mapper() {
60-
return mapper;
78+
return mapperFactory.get();
6179
}
6280

6381
public static Collector<JsonNode, ArrayNode, ArrayNode> arrayNodeCollector() {
@@ -87,7 +105,7 @@ public Function<ArrayNode, ArrayNode> finisher() {
87105

88106
@Override
89107
public Supplier<ArrayNode> supplier() {
90-
return () -> mapper.createArrayNode();
108+
return () -> mapper().createArrayNode();
91109
}
92110
};
93111
}
@@ -129,7 +147,7 @@ public static JsonNode fromValue(Object value) {
129147
} else if (value instanceof WorkflowModel model) {
130148
return modelToJson(model);
131149
} else {
132-
return mapper.convertValue(value, JsonNode.class);
150+
return mapper().convertValue(value, JsonNode.class);
133151
}
134152
}
135153

@@ -152,7 +170,7 @@ public static JsonNode fromString(String value) {
152170
String trimmedValue = value.trim();
153171
if (trimmedValue.startsWith("{") && trimmedValue.endsWith("}")) {
154172
try {
155-
return mapper.readTree(trimmedValue);
173+
return mapper().readTree(trimmedValue);
156174
} catch (IOException ex) {
157175
// ignore and return test node
158176
}
@@ -186,7 +204,7 @@ public static <T> T convertValue(Object obj, Class<T> returnType) {
186204
} else if (obj instanceof JsonNode) {
187205
return convertValue((JsonNode) obj, returnType);
188206
} else {
189-
return mapper.convertValue(obj, returnType);
207+
return mapper().convertValue(obj, returnType);
190208
}
191209
}
192210

@@ -203,7 +221,7 @@ public static <T> T convertValue(JsonNode jsonNode, Class<T> returnType) {
203221
} else if (String.class.isAssignableFrom(returnType)) {
204222
obj = jsonNode.asText();
205223
} else {
206-
obj = mapper.convertValue(jsonNode, returnType);
224+
obj = mapper().convertValue(jsonNode, returnType);
207225
}
208226
return returnType.cast(obj);
209227
}
@@ -233,28 +251,28 @@ private static Object internalToJavaValue(
233251
} else if (jsonNode.isObject()) {
234252
return objectFunction.apply((ObjectNode) jsonNode);
235253
} else {
236-
return mapper.convertValue(jsonNode, Object.class);
254+
return mapper().convertValue(jsonNode, Object.class);
237255
}
238256
}
239257

240258
public static String toString(JsonNode node) throws JsonProcessingException {
241-
return mapper.writeValueAsString(node);
259+
return mapper().writeValueAsString(node);
242260
}
243261

244262
public static void addToNode(String name, Object value, ObjectNode dest) {
245263
dest.set(name, fromValue(value));
246264
}
247265

248266
private static ObjectNode mapToNode(Map<String, Object> value) {
249-
ObjectNode objectNode = mapper.createObjectNode();
267+
ObjectNode objectNode = mapper().createObjectNode();
250268
for (Map.Entry<String, Object> entry : value.entrySet()) {
251269
addToNode(entry.getKey(), entry.getValue(), objectNode);
252270
}
253271
return objectNode;
254272
}
255273

256274
private static ArrayNode mapToArray(Collection<?> collection) {
257-
return mapToArray(collection, mapper.createArrayNode());
275+
return mapToArray(collection, mapper().createArrayNode());
258276
}
259277

260278
private static ArrayNode mapToArray(Collection<?> collection, ArrayNode arrayNode) {
@@ -265,11 +283,11 @@ private static ArrayNode mapToArray(Collection<?> collection, ArrayNode arrayNod
265283
}
266284

267285
public static ObjectNode object() {
268-
return mapper.createObjectNode();
286+
return mapper().createObjectNode();
269287
}
270288

271289
public static ArrayNode array() {
272-
return mapper.createArrayNode();
290+
return mapper().createArrayNode();
273291
}
274292

275293
public static Optional<OffsetDateTime> toDate(JsonNode node) {
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright 2020-Present The Serverless Workflow Specification Authors
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
package io.serverlessworkflow.impl.jackson;
17+
18+
import com.fasterxml.jackson.databind.ObjectMapper;
19+
import java.util.function.Supplier;
20+
21+
public interface ObjectMapperFactory extends Supplier<ObjectMapper> {}

0 commit comments

Comments
 (0)