Skip to content

Commit 8bad264

Browse files
committed
Merge branch '2.12'
2 parents e26f20f + 0e1cd09 commit 8bad264

File tree

4 files changed

+124
-47
lines changed

4 files changed

+124
-47
lines changed

release-notes/VERSION-2.x

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,7 @@ Project: jackson-databind
6767
(reported by isaki@github)
6868
#2796: `TypeFactory.constructType()` does not take `TypeBindings` correctly
6969
(reported by Daniel H)
70+
#2815: Add `JsonFormat.Shape` awareness for UUID serialization (`UUIDSerializer`)
7071

7172
2.11.1 (25-Jun-2020)
7273

src/main/java/com/fasterxml/jackson/databind/ser/std/UUIDSerializer.java

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,24 @@ public class UUIDSerializer
2424
{
2525
final static char[] HEX_CHARS = "0123456789abcdef".toCharArray();
2626

27-
public UUIDSerializer() { super(UUID.class); }
27+
/**
28+
* Configuration setting that indicates if serialization as binary
29+
* (native or Base64-encoded) has been forced; {@code null} means
30+
* "use default heuristic"
31+
*
32+
* @since 2.11.3
33+
*/
34+
protected final Boolean _asBinary;
35+
36+
public UUIDSerializer() { this(null); }
37+
38+
/**
39+
* @since 2.11.3
40+
*/
41+
protected UUIDSerializer(Boolean asBinary) {
42+
super(UUID.class);
43+
_asBinary = asBinary;
44+
}
2845

2946
@Override
3047
public boolean isEmpty(SerializerProvider prov, UUID value)
@@ -44,6 +61,7 @@ public JsonSerializer<?> createContextual(SerializerProvider serializers,
4461
JsonFormat.Value format = findFormatOverrides(serializers,
4562
property, handledType());
4663
Boolean asBinary = null;
64+
4765
if (format != null) {
4866
JsonFormat.Shape shape = format.getShape();
4967
if (shape == JsonFormat.Shape.BINARY) {
@@ -53,7 +71,9 @@ public JsonSerializer<?> createContextual(SerializerProvider serializers,
5371
}
5472
// otherwise leave as `null` meaning about same as NATURAL
5573
}
56-
// !!! TODO:
74+
if (asBinary != _asBinary) {
75+
return new UUIDSerializer(asBinary);
76+
}
5777
return this;
5878
}
5979

@@ -62,15 +82,9 @@ public void serialize(UUID value, JsonGenerator gen, SerializerProvider provider
6282
throws IOException
6383
{
6484
// First: perhaps we could serialize it as raw binary data?
65-
if (gen.canWriteBinaryNatively()) {
66-
// 07-Dec-2013, tatu: One nasty case; that of TokenBuffer. While it can
67-
// technically retain binary data, we do not want to do use binary
68-
// with it, as that results in UUIDs getting converted to Base64 for
69-
// most conversions.
70-
if (!(gen instanceof TokenBuffer)) {
71-
gen.writeBinary(_asBytes(value));
72-
return;
73-
}
85+
if (_writeAsBinary(gen)) {
86+
gen.writeBinary(_asBytes(value));
87+
return;
7488
}
7589

7690
// UUID.toString() works ok functionally, but we can make it go much faster
@@ -95,6 +109,20 @@ public void serialize(UUID value, JsonGenerator gen, SerializerProvider provider
95109
gen.writeString(ch, 0, 36);
96110
}
97111

112+
// @since 2.11.3
113+
protected boolean _writeAsBinary(JsonGenerator g)
114+
{
115+
if (_asBinary != null) {
116+
return _asBinary;
117+
}
118+
// 07-Dec-2013, tatu: One nasty case; that of TokenBuffer. While it can
119+
// technically retain binary data, we do not want to do use binary
120+
// with it, as that results in UUIDs getting converted to Base64 for
121+
// most conversions.
122+
return !(g instanceof TokenBuffer) && g.canWriteBinaryNatively();
123+
}
124+
125+
98126
// Need to add bit of extra info, format
99127
@Override
100128
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)

src/test/java/com/fasterxml/jackson/databind/ser/jdk/JDKTypeSerializationTest.java

Lines changed: 2 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,9 @@
1919
* that are not Enums, Collections, Maps, or standard Date/Time types)
2020
*/
2121
public class JDKTypeSerializationTest
22-
extends com.fasterxml.jackson.databind.BaseMapTest
22+
extends BaseMapTest
2323
{
24-
private final ObjectMapper MAPPER = objectMapper();
24+
private final ObjectMapper MAPPER = sharedMapper();
2525

2626
static class InetAddressBean {
2727
public InetAddress value;
@@ -185,40 +185,6 @@ public void testDuplicatedByteBufferWithCustomPosition() throws IOException
185185
assertEquals(exp, MAPPER.writeValueAsString(bbuf.duplicate()));
186186
}
187187

188-
// Verify that efficient UUID codec won't mess things up:
189-
public void testUUIDs() throws IOException
190-
{
191-
// first, couple of generated UUIDs:
192-
for (String value : new String[] {
193-
"76e6d183-5f68-4afa-b94a-922c1fdb83f8",
194-
"540a88d1-e2d8-4fb1-9396-9212280d0a7f",
195-
"2c9e441d-1cd0-472d-9bab-69838f877574",
196-
"591b2869-146e-41d7-8048-e8131f1fdec5",
197-
"82994ac2-7b23-49f2-8cc5-e24cf6ed77be",
198-
"00000007-0000-0000-0000-000000000000"
199-
}) {
200-
UUID uuid = UUID.fromString(value);
201-
String json = MAPPER.writeValueAsString(uuid);
202-
assertEquals(quote(uuid.toString()), json);
203-
204-
// Also, wrt [#362], should convert cleanly
205-
String str = MAPPER.convertValue(uuid, String.class);
206-
assertEquals(value, str);
207-
}
208-
209-
// then use templating; note that these are not exactly valid UUIDs
210-
// wrt spec (type bits etc), but JDK UUID should deal ok
211-
final String TEMPL = "00000000-0000-0000-0000-000000000000";
212-
final String chars = "123456789abcdef";
213-
214-
for (int i = 0; i < chars.length(); ++i) {
215-
String value = TEMPL.replace('0', chars.charAt(i));
216-
UUID uuid = UUID.fromString(value);
217-
String json = MAPPER.writeValueAsString(uuid);
218-
assertEquals(quote(uuid.toString()), json);
219-
}
220-
}
221-
222188
// [databind#2197]
223189
public void testVoidSerialization() throws Exception
224190
{
Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
package com.fasterxml.jackson.databind.ser.jdk;
2+
3+
import java.io.IOException;
4+
import java.util.UUID;
5+
6+
import com.fasterxml.jackson.annotation.JsonFormat;
7+
8+
import com.fasterxml.jackson.databind.*;
9+
10+
public class UUIDSerializationTest extends BaseMapTest
11+
{
12+
static class UUIDWrapperVanilla {
13+
public UUID uuid;
14+
15+
public UUIDWrapperVanilla(UUID u) { uuid = u; }
16+
}
17+
18+
static class UUIDWrapperBinary {
19+
// default with JSON is String, for use of (base64-encoded) Binary:
20+
@JsonFormat(shape = JsonFormat.Shape.BINARY)
21+
public UUID uuid;
22+
23+
public UUIDWrapperBinary(UUID u) { uuid = u; }
24+
}
25+
26+
private final ObjectMapper MAPPER = sharedMapper();
27+
28+
// Verify that efficient UUID codec won't mess things up:
29+
public void testBasicUUIDs() throws IOException
30+
{
31+
// first, couple of generated UUIDs:
32+
for (String value : new String[] {
33+
"76e6d183-5f68-4afa-b94a-922c1fdb83f8",
34+
"540a88d1-e2d8-4fb1-9396-9212280d0a7f",
35+
"2c9e441d-1cd0-472d-9bab-69838f877574",
36+
"591b2869-146e-41d7-8048-e8131f1fdec5",
37+
"82994ac2-7b23-49f2-8cc5-e24cf6ed77be",
38+
"00000007-0000-0000-0000-000000000000"
39+
}) {
40+
UUID uuid = UUID.fromString(value);
41+
String json = MAPPER.writeValueAsString(uuid);
42+
assertEquals(quote(uuid.toString()), json);
43+
44+
// Also, wrt [#362], should convert cleanly
45+
String str = MAPPER.convertValue(uuid, String.class);
46+
assertEquals(value, str);
47+
}
48+
49+
// then use templating; note that these are not exactly valid UUIDs
50+
// wrt spec (type bits etc), but JDK UUID should deal ok
51+
final String TEMPL = "00000000-0000-0000-0000-000000000000";
52+
final String chars = "123456789abcdef";
53+
54+
for (int i = 0; i < chars.length(); ++i) {
55+
String value = TEMPL.replace('0', chars.charAt(i));
56+
UUID uuid = UUID.fromString(value);
57+
String json = MAPPER.writeValueAsString(uuid);
58+
assertEquals(quote(uuid.toString()), json);
59+
}
60+
}
61+
62+
public void testShapeOverrides() throws Exception
63+
{
64+
final String nullUUIDStr = "00000000-0000-0000-0000-000000000000";
65+
final UUID nullUUID = UUID.fromString(nullUUIDStr);
66+
67+
// First, see that Binary per-property override works:
68+
assertEquals("{\"uuid\":\"AAAAAAAAAAAAAAAAAAAAAA==\"}",
69+
MAPPER.writeValueAsString(new UUIDWrapperBinary(nullUUID)));
70+
71+
// but that without one we'd get String
72+
assertEquals("{\"uuid\":\""+nullUUIDStr+"\"}",
73+
MAPPER.writeValueAsString(new UUIDWrapperVanilla(nullUUID)));
74+
75+
// but can also override by type
76+
ObjectMapper m = newJsonMapper();
77+
m.configOverride(UUID.class)
78+
.setFormat(JsonFormat.Value.forShape(JsonFormat.Shape.BINARY));
79+
assertEquals("{\"uuid\":\"AAAAAAAAAAAAAAAAAAAAAA==\"}",
80+
m.writeValueAsString(new UUIDWrapperVanilla(nullUUID)));
81+
}
82+
}

0 commit comments

Comments
 (0)