1 package com.vladmihalcea.hibernate.type.util;
2
3 import com.fasterxml.jackson.core.JsonGenerator;
4 import com.fasterxml.jackson.core.JsonParser;
5 import com.fasterxml.jackson.core.JsonProcessingException;
6 import com.fasterxml.jackson.databind.*;
7 import com.fasterxml.jackson.databind.module.SimpleModule;
8 import org.hibernate.HibernateException;
9
10 import java.io.IOException;
11 import java.io.Serializable;
12 import java.lang.reflect.Type;
13 import java.time.OffsetDateTime;
14 import java.time.ZoneOffset;
15 import java.time.format.DateTimeParseException;
16 import java.util.Date;
17
18 import static java.time.format.DateTimeFormatter.ISO_OFFSET_DATE_TIME;
19
20
26 public class ObjectMapperWrapper implements Serializable {
27
28 private static final ObjectMapper OBJECT_MAPPER = new ObjectMapper()
29 .findAndRegisterModules()
30 .registerModule(
31 new SimpleModule()
32 .addSerializer(OffsetDateTime.class, OffsetDateTimeSerializer.INSTANCE)
33 .addDeserializer(OffsetDateTime.class, OffsetDateTimeDeserializer.INSTANCE)
34 );
35
36 public static final ObjectMapperWrapper INSTANCE = new ObjectMapperWrapper();
37
38 private ObjectMapper objectMapper;
39
40 private ObjectMapperSupplier objectMapperSupplier;
41
42 private JsonSerializer jsonSerializer;
43
44 public ObjectMapperWrapper() {
45 this(OBJECT_MAPPER);
46 }
47
48 public ObjectMapperWrapper(ObjectMapperSupplier objectMapperSupplier) {
49 this.objectMapperSupplier = objectMapperSupplier;
50 }
51
52 public ObjectMapperWrapper(ObjectMapper objectMapper) {
53 this.objectMapper = objectMapper;
54 this.jsonSerializer = new ObjectMapperJsonSerializer(this);
55 }
56
57 public void setJsonSerializer(JsonSerializer jsonSerializer) {
58 this.jsonSerializer = jsonSerializer;
59 }
60
61 public ObjectMapper getObjectMapper() {
62 if(objectMapper == null && objectMapperSupplier != null) {
63 objectMapper = objectMapperSupplier.get();
64 }
65 if(objectMapper == null) {
66 throw new HibernateException("The provided ObjectMapper is null!");
67 }
68 return objectMapper;
69 }
70
71 public <T> T fromString(String string, Class<T> clazz) {
72 try {
73 return getObjectMapper().readValue(string, clazz);
74 } catch (IOException e) {
75 throw new HibernateException(
76 new IllegalArgumentException("The given string value: " + string + " cannot be transformed to Json object", e)
77 );
78 }
79 }
80
81 public <T> T fromString(String string, Type type) {
82 try {
83 return getObjectMapper().readValue(string, getObjectMapper().getTypeFactory().constructType(type));
84 } catch (IOException e) {
85 throw new HibernateException(
86 new IllegalArgumentException("The given string value: " + string + " cannot be transformed to Json object", e)
87 );
88 }
89 }
90
91 public <T> T fromBytes(byte[] value, Class<T> clazz) {
92 try {
93 return getObjectMapper().readValue(value, clazz);
94 } catch (IOException e) {
95 throw new HibernateException(
96 new IllegalArgumentException("The given byte array cannot be transformed to Json object", e)
97 );
98 }
99 }
100
101 public <T> T fromBytes(byte[] value, Type type) {
102 try {
103 return getObjectMapper().readValue(value, getObjectMapper().getTypeFactory().constructType(type));
104 } catch (IOException e) {
105 throw new HibernateException(
106 new IllegalArgumentException("The given byte array cannot be transformed to Json object", e)
107 );
108 }
109 }
110
111 public String toString(Object value) {
112 try {
113 return getObjectMapper().writeValueAsString(value);
114 } catch (JsonProcessingException e) {
115 throw new HibernateException(
116 new IllegalArgumentException("The given Json object value: " + value + " cannot be transformed to a String", e)
117 );
118 }
119 }
120
121 public byte[] toBytes(Object value) {
122 try {
123 return getObjectMapper().writeValueAsBytes(value);
124 } catch (JsonProcessingException e) {
125 throw new HibernateException(
126 new IllegalArgumentException("The given Json object value: " + value + " cannot be transformed to a byte array", e)
127 );
128 }
129 }
130
131 public JsonNode toJsonNode(String value) {
132 try {
133 return getObjectMapper().readTree(value);
134 } catch (IOException e) {
135 throw new HibernateException(
136 new IllegalArgumentException(e)
137 );
138 }
139 }
140
141 public <T> T clone(T value) {
142 return jsonSerializer.clone(value);
143 }
144
145 public static class OffsetDateTimeSerializer extends com.fasterxml.jackson.databind.JsonSerializer<OffsetDateTime> {
146
147 public static final OffsetDateTimeSerializer INSTANCE = new OffsetDateTimeSerializer();
148
149 @Override
150 public void serialize(OffsetDateTime offsetDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
151 if (offsetDateTime == null) {
152 jsonGenerator.writeNull();
153 } else {
154 jsonGenerator.writeString(offsetDateTime.format(ISO_OFFSET_DATE_TIME));
155 }
156 }
157
158 @Override
159 public Class<OffsetDateTime> handledType() {
160 return OffsetDateTime.class;
161 }
162 }
163
164 public static class OffsetDateTimeDeserializer extends JsonDeserializer<OffsetDateTime> {
165
166 public static final OffsetDateTimeDeserializer INSTANCE = new OffsetDateTimeDeserializer();
167
168 @Override
169 public OffsetDateTime deserialize(JsonParser jsonParser, DeserializationContext deserializationContext) throws IOException {
170 if (jsonParser.getText() != null) {
171 try {
172 return OffsetDateTime.parse(jsonParser.getText(), ISO_OFFSET_DATE_TIME);
173 } catch (DateTimeParseException e) {
174 Date date = new Date((long) jsonParser.getDoubleValue() * 1000);
175 return date.toInstant().atOffset(ZoneOffset.UTC);
176 }
177 }
178 return null;
179 }
180
181 @Override
182 public Class<OffsetDateTime> handledType() {
183 return OffsetDateTime.class;
184 }
185 }
186 }
187