Ether Framework
Unified API docs for Ether modules
Loading...
Searching...
No Matches
JacksonJsonCodec.java
Go to the documentation of this file.
1/*-
2 * #%L
3 * ether-json
4 * %%
5 * Copyright (C) 2025 Raúl Eduardo González Argote
6 * %%
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in
15 * all copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 * THE SOFTWARE.
24 * #L%
25 */
26
27package dev.rafex.ether.json;
28
29import java.io.IOException;
30import java.io.InputStream;
31import java.io.OutputStream;
32import java.util.Objects;
33
34import com.fasterxml.jackson.core.JsonProcessingException;
35import com.fasterxml.jackson.core.type.TypeReference;
36import com.fasterxml.jackson.databind.JavaType;
37import com.fasterxml.jackson.databind.JsonNode;
38import com.fasterxml.jackson.databind.ObjectMapper;
39import com.fasterxml.jackson.databind.SerializationFeature;
40import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
41
42/**
43 * Implementación de {@link JsonCodec} basada en Jackson {@link ObjectMapper}.
44 *
45 * <p>Esta clase delega toda la serialización y deserialización JSON al
46 * {@code ObjectMapper} proporcionado, envolviendo las excepciones de Jackson
47 * en {@link JsonCodecException} para mantener una API unificada.</p>
48 */
49public final class JacksonJsonCodec implements JsonCodec {
50
51 private final ObjectMapper mapper;
52
53 /**
54 * Crea un codec que utiliza el {@link ObjectMapper} proporcionado.
55 *
56 * @param mapper instancia de Jackson para serializar y deserializar; no puede ser {@code null}
57 * @throws NullPointerException si {@code mapper} es {@code null}
58 */
59 public JacksonJsonCodec(final ObjectMapper mapper) {
60 this.mapper = Objects.requireNonNull(mapper, "mapper");
61 }
62
63 /**
64 * Devuelve una instancia de codec con la configuración por defecto
65 * (módulo JavaTime habilitado, fechas como texto ISO-8601).
66 *
67 * @return codec configurado por defecto
68 */
70 return JsonCodecBuilder.create().build();
71 }
72
73 /**
74 * Devuelve el {@link ObjectMapper} interno utilizado por este codec.
75 *
76 * @return instancia del mapper de Jackson
77 */
78 public ObjectMapper mapper() {
79 return mapper;
80 }
81
82 /**
83 * Crea un {@link ObjectMapper} con la configuración por defecto del módulo:
84 * registra {@link JavaTimeModule} y deshabilita la escritura de fechas como timestamps.
85 *
86 * @return ObjectMapper configurado por defecto
87 */
88 public static ObjectMapper defaultMapper() {
89 final var mapper = new ObjectMapper();
90 mapper.registerModule(new JavaTimeModule());
91 mapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
92 return mapper;
93 }
94
95 /**
96 * {@inheritDoc}
97 *
98 * @throws JsonCodecException si ocurre un error durante la serialización
99 */
100 @Override
101 public String toJson(final Object value) {
102 try {
103 return mapper.writeValueAsString(value);
104 } catch (final JsonProcessingException e) {
105 throw new JsonCodecException("Error serializando a JSON", e);
106 }
107 }
108
109 /**
110 * {@inheritDoc}
111 *
112 * @throws JsonCodecException si ocurre un error durante la serialización formateada
113 */
114 @Override
115 public String toPrettyJson(final Object value) {
116 try {
117 return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(value);
118 } catch (final JsonProcessingException e) {
119 throw new JsonCodecException("Error serializando a JSON formateado", e);
120 }
121 }
122
123 /**
124 * {@inheritDoc}
125 *
126 * @throws JsonCodecException si ocurre un error durante la serialización
127 */
128 @Override
129 public byte[] toJsonBytes(final Object value) {
130 try {
131 return mapper.writeValueAsBytes(value);
132 } catch (final JsonProcessingException e) {
133 throw new JsonCodecException("Error serializando a bytes JSON", e);
134 }
135 }
136
137 /**
138 * {@inheritDoc}
139 *
140 * @throws JsonCodecException si ocurre un error al escribir en el stream
141 */
142 @Override
143 public void writeValue(final OutputStream output, final Object value) {
144 try {
145 mapper.writeValue(output, value);
146 } catch (final IOException e) {
147 throw new JsonCodecException("Error escribiendo JSON al stream", e);
148 }
149 }
150
151 @Override
152 public <T> T readValue(final InputStream input, final Class<T> type) {
153 try {
154 return mapper.readValue(input, type);
155 } catch (final IOException e) {
156 throw new JsonCodecException("Error deserializando stream JSON", e);
157 }
158 }
159
160 @Override
161 public <T> T readValue(final InputStream input, final TypeReference<T> typeRef) {
162 try {
163 return mapper.readValue(input, typeRef);
164 } catch (final IOException e) {
165 throw new JsonCodecException("Error deserializando stream JSON", e);
166 }
167 }
168
169 @SuppressWarnings("unchecked")
170 @Override
171 public <T> T readValue(final InputStream input, final JavaType type) {
172 try {
173 return (T) mapper.readValue(input, type);
174 } catch (final IOException e) {
175 throw new JsonCodecException("Error deserializando stream JSON", e);
176 }
177 }
178
179 @Override
180 public <T> T readValue(final String content, final Class<T> type) {
181 try {
182 return mapper.readValue(content, type);
183 } catch (final IOException e) {
184 throw new JsonCodecException("Error deserializando JSON", e);
185 }
186 }
187
188 @Override
189 public <T> T readValue(final String content, final TypeReference<T> typeRef) {
190 try {
191 return mapper.readValue(content, typeRef);
192 } catch (final IOException e) {
193 throw new JsonCodecException("Error deserializando JSON", e);
194 }
195 }
196
197 @SuppressWarnings("unchecked")
198 @Override
199 public <T> T readValue(final String content, final JavaType type) {
200 try {
201 return (T) mapper.readValue(content, type);
202 } catch (final IOException e) {
203 throw new JsonCodecException("Error deserializando JSON", e);
204 }
205 }
206
207 @Override
208 public <T> T readValue(final byte[] content, final Class<T> type) {
209 try {
210 return mapper.readValue(content, type);
211 } catch (final IOException e) {
212 throw new JsonCodecException("Error deserializando bytes JSON", e);
213 }
214 }
215
216 @Override
217 public <T> T readValue(final byte[] content, final TypeReference<T> typeRef) {
218 try {
219 return mapper.readValue(content, typeRef);
220 } catch (final IOException e) {
221 throw new JsonCodecException("Error deserializando bytes JSON", e);
222 }
223 }
224
225 @SuppressWarnings("unchecked")
226 @Override
227 public <T> T readValue(final byte[] content, final JavaType type) {
228 try {
229 return (T) mapper.readValue(content, type);
230 } catch (final IOException e) {
231 throw new JsonCodecException("Error deserializando bytes JSON", e);
232 }
233 }
234
235 @Override
236 public JsonNode readTree(final String content) {
237 try {
238 return mapper.readTree(content);
239 } catch (final IOException e) {
240 throw new JsonCodecException("Error parseando JSON a JsonNode", e);
241 }
242 }
243
244 @Override
245 public JsonNode readTree(final InputStream input) {
246 try {
247 return mapper.readTree(input);
248 } catch (final IOException e) {
249 throw new JsonCodecException("Error parseando stream JSON a JsonNode", e);
250 }
251 }
252
253 @Override
254 public JsonNode readTree(final byte[] input) {
255 try {
256 return mapper.readTree(input);
257 } catch (final IOException e) {
258 throw new JsonCodecException("Error parseando bytes JSON a JsonNode", e);
259 }
260 }
261
262 @Override
263 public JsonNode valueToTree(final Object value) {
264 return mapper.valueToTree(value);
265 }
266
267 @Override
268 public <T> T treeToValue(final JsonNode node, final Class<T> type) {
269 try {
270 return mapper.treeToValue(node, type);
271 } catch (final JsonProcessingException e) {
272 throw new JsonCodecException("Error convirtiendo JsonNode a POJO", e);
273 }
274 }
275
276 @Override
277 public <T> T treeToValue(final JsonNode node, final TypeReference<T> typeRef) {
278 return mapper.convertValue(node, typeRef);
279 }
280
281 @Override
282 public JsonNode at(final JsonNode node, final String pointer) {
283 Objects.requireNonNull(node, "node");
284 Objects.requireNonNull(pointer, "pointer");
285 return node.at(pointer);
286 }
287}
static JacksonJsonCodec defaultCodec()
Devuelve una instancia de codec con la configuración por defecto (módulo JavaTime habilitado,...
String toPrettyJson(final Object value)
ObjectMapper mapper()
Devuelve el ObjectMapper interno utilizado por este codec.
static ObjectMapper defaultMapper()
Crea un ObjectMapper con la configuración por defecto del módulo: registra JavaTimeModule y deshabili...
JsonNode readTree(final String content)
void writeValue(final OutputStream output, final Object value)
JsonNode readTree(final byte[] input)
JsonNode at(final JsonNode node, final String pointer)
JsonNode readTree(final InputStream input)
JacksonJsonCodec(final ObjectMapper mapper)
Crea un codec que utiliza el ObjectMapper proporcionado.
JsonNode valueToTree(final Object value)