1 package com.fasterxml.jackson.databind.ser.std;
2
3 import java.io.IOException;
4 import java.util.UUID;
5
6 import com.fasterxml.jackson.annotation.JsonFormat;
7 import com.fasterxml.jackson.core.JsonGenerator;
8 import com.fasterxml.jackson.databind.*;
9 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
10 import com.fasterxml.jackson.databind.jsonFormatVisitors.JsonValueFormat;
11 import com.fasterxml.jackson.databind.ser.ContextualSerializer;
12 import com.fasterxml.jackson.databind.util.TokenBuffer;
13
14
21 @SuppressWarnings("serial")
22 public class UUIDSerializer
23 extends StdScalarSerializer<UUID>
24 implements ContextualSerializer
25 {
26 final static char[] HEX_CHARS = "0123456789abcdef".toCharArray();
27
28
35 protected final Boolean _asBinary;
36
37 public UUIDSerializer() { this(null); }
38
39
42 protected UUIDSerializer(Boolean asBinary) {
43 super(UUID.class);
44 _asBinary = asBinary;
45 }
46
47 @Override
48 public boolean isEmpty(SerializerProvider prov, UUID value)
49 {
50
51 if (value.getLeastSignificantBits() == 0L
52 && value.getMostSignificantBits() == 0L) {
53 return true;
54 }
55 return false;
56 }
57
58 @Override
59 public JsonSerializer<?> createContextual(SerializerProvider serializers,
60 BeanProperty property) throws JsonMappingException
61 {
62 JsonFormat.Value format = findFormatOverrides(serializers,
63 property, handledType());
64 Boolean asBinary = null;
65
66 if (format != null) {
67 JsonFormat.Shape shape = format.getShape();
68 if (shape == JsonFormat.Shape.BINARY) {
69 asBinary = true;
70 } else if (shape == JsonFormat.Shape.STRING) {
71 asBinary = false;
72 }
73
74 }
75 if (asBinary != _asBinary) {
76 return new UUIDSerializer(asBinary);
77 }
78 return this;
79 }
80
81 @Override
82 public void serialize(UUID value, JsonGenerator gen, SerializerProvider provider)
83 throws IOException
84 {
85
86 if (_writeAsBinary(gen)) {
87 gen.writeBinary(_asBytes(value));
88 return;
89 }
90
91
92
93
94 final char[] ch = new char[36];
95 final long msb = value.getMostSignificantBits();
96 _appendInt((int) (msb >> 32), ch, 0);
97 ch[8] = '-';
98 int i = (int) msb;
99 _appendShort(i >>> 16, ch, 9);
100 ch[13] = '-';
101 _appendShort(i, ch, 14);
102 ch[18] = '-';
103
104 final long lsb = value.getLeastSignificantBits();
105 _appendShort((int) (lsb >>> 48), ch, 19);
106 ch[23] = '-';
107 _appendShort((int) (lsb >>> 32), ch, 24);
108 _appendInt((int) lsb, ch, 28);
109
110 gen.writeString(ch, 0, 36);
111 }
112
113
114 protected boolean _writeAsBinary(JsonGenerator g)
115 {
116 if (_asBinary != null) {
117 return _asBinary;
118 }
119
120
121
122
123 return !(g instanceof TokenBuffer) && g.canWriteBinaryNatively();
124 }
125
126
127
128 @Override
129 public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
130 throws JsonMappingException
131 {
132 visitStringFormat(visitor, typeHint, JsonValueFormat.UUID);
133 }
134
135 private static void _appendInt(int bits, char[] ch, int offset)
136 {
137 _appendShort(bits >> 16, ch, offset);
138 _appendShort(bits, ch, offset+4);
139 }
140
141 private static void _appendShort(int bits, char[] ch, int offset)
142 {
143 ch[offset] = HEX_CHARS[(bits >> 12) & 0xF];
144 ch[++offset] = HEX_CHARS[(bits >> 8) & 0xF];
145 ch[++offset] = HEX_CHARS[(bits >> 4) & 0xF];
146 ch[++offset] = HEX_CHARS[bits & 0xF];
147 }
148
149 private final static byte[] _asBytes(UUID uuid)
150 {
151 byte[] buffer = new byte[16];
152 long hi = uuid.getMostSignificantBits();
153 long lo = uuid.getLeastSignificantBits();
154 _appendInt((int) (hi >> 32), buffer, 0);
155 _appendInt((int) hi, buffer, 4);
156 _appendInt((int) (lo >> 32), buffer, 8);
157 _appendInt((int) lo, buffer, 12);
158 return buffer;
159 }
160
161 private final static void _appendInt(int value, byte[] buffer, int offset)
162 {
163 buffer[offset] = (byte) (value >> 24);
164 buffer[++offset] = (byte) (value >> 16);
165 buffer[++offset] = (byte) (value >> 8);
166 buffer[++offset] = (byte) value;
167 }
168 }
169