-
Notifications
You must be signed in to change notification settings - Fork 100
Expand file tree
/
Copy pathJsonConfig.java
More file actions
132 lines (112 loc) · 5.09 KB
/
JsonConfig.java
File metadata and controls
132 lines (112 loc) · 5.09 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
/*
* Copyright 2023 Amazon.com, Inc. or its affiliates.
* 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 software.amazon.lambda.powertools.utilities;
import java.lang.reflect.Type;
import java.util.function.Supplier;
import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializationFeature;
import com.fasterxml.jackson.databind.json.JsonMapper;
import com.fasterxml.jackson.datatype.joda.JodaModule;
import io.burt.jmespath.JmesPath;
import io.burt.jmespath.RuntimeConfiguration;
import io.burt.jmespath.function.BaseFunction;
import io.burt.jmespath.function.FunctionRegistry;
import io.burt.jmespath.jackson.JacksonRuntime;
import software.amazon.lambda.powertools.utilities.jmespath.Base64Function;
import software.amazon.lambda.powertools.utilities.jmespath.Base64GZipFunction;
import software.amazon.lambda.powertools.utilities.jmespath.JsonFunction;
public final class JsonConfig {
private static final Supplier<ObjectMapper> objectMapperSupplier = () -> JsonMapper.builder()
// Don't throw an exception when json has extra fields you are not serializing on.
.disable(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES)
// Ignore null values when writing json.
.defaultPropertyInclusion(
JsonInclude.Value.construct(JsonInclude.Include.NON_NULL, JsonInclude.Include.USE_DEFAULTS))
// Write times as a String instead of a Long so its human-readable.
.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS)
// Sort fields in alphabetical order
.configure(MapperFeature.SORT_PROPERTIES_ALPHABETICALLY, true)
.addModule(new JodaModule())
.build();
private static final ThreadLocal<ObjectMapper> om = ThreadLocal.withInitial(objectMapperSupplier);
private final FunctionRegistry defaultFunctions = FunctionRegistry.defaultRegistry();
private final FunctionRegistry customFunctions = defaultFunctions.extend(
new Base64Function(),
new Base64GZipFunction(),
new JsonFunction());
private final RuntimeConfiguration configuration = new RuntimeConfiguration.Builder()
.withSilentTypeErrors(true)
.withFunctionRegistry(customFunctions)
.build();
private JmesPath<JsonNode> jmesPath = new JacksonRuntime(configuration, getObjectMapper());
private JsonConfig() {
}
public static JsonConfig get() {
return ConfigHolder.instance;
}
/**
* Return an Object Mapper. Use this to customize (de)serialization config.
*
* @return the {@link ObjectMapper} to serialize / deserialize JSON
*/
public ObjectMapper getObjectMapper() {
return om.get();
}
/**
* Creates a TypeReference from a Class for use with Jackson deserialization.
* This is useful when you need to convert a Class to a TypeReference for generic type handling.
*
* @param clazz the class to convert to TypeReference
* @param <T> the type parameter
* @return a TypeReference wrapping the provided class
*/
public static <T> TypeReference<T> toTypeReference(Class<T> clazz) {
return new TypeReference<T>() {
@Override
public Type getType() {
return clazz;
}
};
}
/**
* Return the JmesPath used to select sub node of Json
*
* @return the {@link JmesPath}
*/
public JmesPath<JsonNode> getJmesPath() {
return jmesPath;
}
/**
* Add a custom {@link io.burt.jmespath.function.Function} to JMESPath
* {@link Base64Function} and {@link Base64GZipFunction} are already built-in.
*
* @param function the function to add
* @param <T> Must extends {@link BaseFunction}
*/
public <T extends BaseFunction> void addFunction(T function) {
FunctionRegistry functionRegistryWithExtendedFunctions = configuration.functionRegistry().extend(function);
RuntimeConfiguration updatedConfig = new RuntimeConfiguration.Builder()
.withFunctionRegistry(functionRegistryWithExtendedFunctions)
.build();
jmesPath = new JacksonRuntime(updatedConfig, getObjectMapper());
}
private static final class ConfigHolder {
private static final JsonConfig instance = new JsonConfig();
}
}