Skip to content

Commit 7210c75

Browse files
authored
Merge pull request #71 from baharclerode/bah.CustomEncoder_Fix
[Avro] Fix custom deserializers not being used
2 parents 3d1a46e + c2c2040 commit 7210c75

File tree

2 files changed

+79
-11
lines changed

2 files changed

+79
-11
lines changed

avro/src/main/java/com/fasterxml/jackson/dataformat/avro/AvroTypeDeserializer.java

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,7 @@
44

55
import com.fasterxml.jackson.annotation.JsonTypeInfo;
66
import com.fasterxml.jackson.core.JsonParser;
7-
import com.fasterxml.jackson.databind.BeanProperty;
8-
import com.fasterxml.jackson.databind.DeserializationContext;
9-
import com.fasterxml.jackson.databind.JavaType;
10-
import com.fasterxml.jackson.databind.JsonDeserializer;
7+
import com.fasterxml.jackson.databind.*;
118
import com.fasterxml.jackson.databind.jsontype.TypeDeserializer;
129
import com.fasterxml.jackson.databind.jsontype.TypeIdResolver;
1310
import com.fasterxml.jackson.databind.jsontype.impl.TypeDeserializerBase;

avro/src/test/java/com/fasterxml/jackson/dataformat/avro/interop/annotations/AvroEncodeTest.java

Lines changed: 78 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
package com.fasterxml.jackson.dataformat.avro.interop.annotations;
22

33
import java.io.IOException;
4-
import java.util.ArrayList;
5-
import java.util.Arrays;
6-
import java.util.HashMap;
7-
import java.util.Map;
4+
import java.nio.ByteBuffer;
5+
import java.util.*;
86

7+
import org.apache.avro.SchemaBuilder;
98
import org.apache.avro.io.Decoder;
109
import org.apache.avro.io.Encoder;
1110
import org.apache.avro.reflect.AvroEncode;
@@ -53,14 +52,17 @@ static class CustomComponent {
5352
@Nullable
5453
public Long longValue;
5554

55+
@AvroEncode(using = UuidAsBytesAvroEncoding.class)
56+
private UUID uuidValue;
57+
5658
protected CustomComponent() { }
5759
}
5860

5961
@SuppressWarnings("unchecked")
6062
public static class ApacheImplEncoding extends CustomEncoding<CustomComponent> {
6163

6264
public ApacheImplEncoding() throws IOException {
63-
schema = ApacheAvroInteropUtil.getJacksonSchema(CustomComponent.class);
65+
schema = ApacheAvroInteropUtil.getApacheSchema(CustomComponent.class);
6466
}
6567

6668
@Override
@@ -75,8 +77,67 @@ protected CustomComponent read(Object reuse, Decoder in) throws IOException {
7577

7678
}
7779

78-
protected Wrapper wrapper;
80+
public static class UuidAsBytesAvroEncoding extends CustomEncoding<UUID> {
81+
public static byte[] asByteArray(UUID uuid) {
82+
long msb = uuid.getMostSignificantBits();
83+
long lsb = uuid.getLeastSignificantBits();
84+
byte[] buffer = new byte[16];
85+
for (int i = 0; i < 8; i++) {
86+
buffer[i] = (byte) (msb >>> 8 * (7 - i));
87+
}
88+
for (int i = 8; i < 16; i++) {
89+
buffer[i] = (byte) (lsb >>> 8 * (7 - i));
90+
}
91+
return buffer;
92+
}
7993

94+
public static UUID toUUID(byte[] byteArray) {
95+
long msb = 0;
96+
long lsb = 0;
97+
for (int i = 0; i < 8; i++) { msb = (msb << 8) | (byteArray[i] & 0xff); }
98+
for (int i = 8; i < 16; i++) { lsb = (lsb << 8) | (byteArray[i] & 0xff); }
99+
return new UUID(msb, lsb);
100+
}
101+
102+
public UuidAsBytesAvroEncoding() {
103+
this.schema = SchemaBuilder.unionOf().nullType().and().bytesBuilder().endBytes().endUnion();
104+
}
105+
106+
@Override
107+
public void write(Object datum, Encoder encoder) throws IOException {
108+
if (datum == null) {
109+
encoder.writeIndex(0);
110+
encoder.writeNull();
111+
return;
112+
}
113+
encoder.writeIndex(1);
114+
encoder.writeBytes(asByteArray((UUID) datum));
115+
}
116+
117+
@Override
118+
public UUID read(Object datum, Decoder decoder) throws IOException {
119+
try {
120+
// get index in union
121+
int index = decoder.readIndex();
122+
if (index == 1) {
123+
// read in 16 bytes of data
124+
ByteBuffer b = ByteBuffer.allocate(16);
125+
decoder.readBytes(b);
126+
// convert
127+
UUID uuid = toUUID(b.array());
128+
return uuid;
129+
} else {
130+
decoder.readNull();
131+
// no uuid present
132+
return null;
133+
}
134+
} catch (Exception exception) {
135+
throw new IllegalStateException("Could not decode bytes into UUID", exception);
136+
}
137+
}
138+
}
139+
140+
protected Wrapper wrapper;
80141
protected Wrapper result;
81142

82143
@Before
@@ -93,6 +154,7 @@ public void setup() throws IOException {
93154
mv.put("cats", new ArrayList<Integer>());
94155
mv.put("dogs", new ArrayList<>(Arrays.asList(-1234, 56, 6767, 54134, 57, 86)));
95156
wrapper.component.stringValue = "Hello World!";
157+
wrapper.component.uuidValue = UUID.randomUUID();
96158

97159
CustomComponent cc = new CustomComponent();
98160
cc.byteValue = (byte) 42;
@@ -101,8 +163,8 @@ public void setup() throws IOException {
101163
cc.doubleValue = Double.POSITIVE_INFINITY;
102164
cc.longValue = Long.MAX_VALUE;
103165
cc.stringValue = "Nested Hello World!";
166+
cc.uuidValue = UUID.randomUUID();
104167
wrapper.component.nestedRecordValue = cc;
105-
106168
//
107169
result = roundTrip(wrapper);
108170
}
@@ -137,4 +199,13 @@ public void testIntegerValue() {
137199
assertThat(result.component.intValue).isEqualTo(wrapper.component.intValue);
138200
}
139201

202+
@Test
203+
public void testNestedUuidValue() {
204+
assertThat(result.component.nestedRecordValue.uuidValue).isEqualTo(wrapper.component.nestedRecordValue.uuidValue);
205+
}
206+
207+
@Test
208+
public void testUuidValue() {
209+
assertThat(result.component.uuidValue).isEqualTo(wrapper.component.uuidValue);
210+
}
140211
}

0 commit comments

Comments
 (0)