Skip to content

Commit 6309213

Browse files
authored
Add Byte Array Overloads to ObjectSerializer (Azure#19261)
Add Byte Array Overloads to ObjectSerializer
1 parent 5ea59a8 commit 6309213

File tree

11 files changed

+259
-34
lines changed

11 files changed

+259
-34
lines changed

sdk/core/azure-core-experimental/src/main/java/com/azure/core/experimental/serializer/AvroSerializer.java

Lines changed: 47 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,19 @@
1414
* Generic interface covering basic Avro serialization and deserialization methods.
1515
*/
1616
public interface AvroSerializer extends ObjectSerializer {
17+
/**
18+
* Reads an Avro byte array into its object representation.
19+
*
20+
* @param data Avro byte array.
21+
* @param typeReference {@link TypeReference} representing the object.
22+
* @param <T> Type of the object.
23+
* @return The object represented by the deserialized Avro byte array.
24+
*/
25+
@Override
26+
default <T> T deserializeFromBytes(byte[] data, TypeReference<T> typeReference) {
27+
return ObjectSerializer.super.deserializeFromBytes(data, typeReference);
28+
}
29+
1730
/**
1831
* Reads an Avro stream into its object representation.
1932
*
@@ -25,17 +38,39 @@ public interface AvroSerializer extends ObjectSerializer {
2538
@Override
2639
<T> T deserialize(InputStream stream, TypeReference<T> typeReference);
2740

41+
/**
42+
* Reads an Avro byte array into its object representation.
43+
*
44+
* @param data Avro byte array.
45+
* @param typeReference {@link TypeReference} representing the object.
46+
* @param <T> Type of the object.
47+
* @return Reactive stream that emits the object represented by the deserialized Avro byte array.
48+
*/
49+
default <T> Mono<T> deserializeFromBytesAsync(byte[] data, TypeReference<T> typeReference) {
50+
return ObjectSerializer.super.deserializeFromBytesAsync(data, typeReference);
51+
}
52+
2853
/**
2954
* Reads an Avro stream into its object representation.
3055
*
3156
* @param stream Avro stream.
3257
* @param typeReference {@link TypeReference} representing the object.
3358
* @param <T> Type of the object.
34-
* @return The object represented by the deserialized Avro stream.
59+
* @return Reactive stream that emits the object represented by the deserialized Avro stream.
3560
*/
3661
@Override
3762
<T> Mono<T> deserializeAsync(InputStream stream, TypeReference<T> typeReference);
3863

64+
/**
65+
* Converts the object into an Avro byte array.
66+
*
67+
* @param value The object.
68+
* @return The Avro binary representation of the serialized object.
69+
*/
70+
default byte[] serializeToBytes(Object value) {
71+
return ObjectSerializer.super.serializeToBytes(value);
72+
}
73+
3974
/**
4075
* Writes an object's Avro representation into a stream.
4176
*
@@ -45,6 +80,17 @@ public interface AvroSerializer extends ObjectSerializer {
4580
@Override
4681
void serialize(OutputStream stream, Object value);
4782

83+
/**
84+
* Converts the object into a Avro byte array.
85+
*
86+
* @param value The object.
87+
* @return Reactive stream that emits the Avro binary representation of the serialized object.
88+
*/
89+
@Override
90+
default Mono<byte[]> serializeToBytesAsync(Object value) {
91+
return ObjectSerializer.super.serializeToBytesAsync(value);
92+
}
93+
4894
/**
4995
* Writes an object's Avro representation into a stream.
5096
*

sdk/core/azure-core-serializer-avro-apache/src/main/java/com/azure/core/serializer/avro/apache/ApacheAvroSerializer.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import org.apache.avro.Schema;
1010
import org.apache.avro.io.DatumReader;
1111
import org.apache.avro.io.DatumWriter;
12+
import org.apache.avro.io.Decoder;
1213
import org.apache.avro.io.DecoderFactory;
1314
import org.apache.avro.io.Encoder;
1415
import org.apache.avro.io.EncoderFactory;
@@ -21,6 +22,7 @@
2122
import java.io.InputStream;
2223
import java.io.OutputStream;
2324
import java.io.UncheckedIOException;
25+
import java.util.function.Supplier;
2426

2527
/**
2628
* Apache Avro based implementation of the {@link AvroSerializer} interface.
@@ -41,21 +43,35 @@ public class ApacheAvroSerializer implements AvroSerializer {
4143
this.specificData = specificData;
4244
}
4345

46+
@Override
47+
public <T> T deserializeFromBytes(byte[] data, TypeReference<T> typeReference) {
48+
return deserialize(data, () -> decoderFactory.binaryDecoder(data, null));
49+
}
50+
4451
@Override
4552
public <T> T deserialize(InputStream stream, TypeReference<T> typeReference) {
46-
if (stream == null) {
53+
return deserialize(stream, () -> decoderFactory.binaryDecoder(stream, null));
54+
}
55+
56+
private <T> T deserialize(Object data, Supplier<Decoder> decoderSupplier) {
57+
if (data == null) {
4758
return null;
4859
}
4960

5061
DatumReader<T> reader = new SpecificDatumReader<>(schema, schema, specificData);
5162

5263
try {
53-
return reader.read(null, decoderFactory.binaryDecoder(stream, null));
64+
return reader.read(null, decoderSupplier.get());
5465
} catch (IOException ex) {
5566
throw logger.logExceptionAsError(new UncheckedIOException(ex));
5667
}
5768
}
5869

70+
@Override
71+
public <T> Mono<T> deserializeFromBytesAsync(byte[] data, TypeReference<T> typeReference) {
72+
return Mono.fromCallable(() -> this.deserializeFromBytes(data, typeReference));
73+
}
74+
5975
@Override
6076
public <T> Mono<T> deserializeAsync(InputStream stream, TypeReference<T> typeReference) {
6177
return Mono.fromCallable(() -> deserialize(stream, typeReference));

sdk/core/azure-core-serializer-avro-apache/src/test/java/com/azure/core/serializer/avro/apache/ApacheAvroSerializerTests.java

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -221,9 +221,16 @@ private static Stream<Arguments> deserializeRecordSupplier() {
221221
}
222222

223223
@Test
224-
public void deserializeNullReturnsNull() {
224+
public void deserializeNullInputStreamReturnsNull() {
225225
StepVerifier.create(getSerializer(schemaCreator("null"))
226-
.deserializeAsync(null, createInstance(void.class)))
226+
.deserializeAsync((InputStream) null, createInstance(void.class)))
227+
.verifyComplete();
228+
}
229+
230+
@Test
231+
public void deserializeNullByteArrayReturnsNull() {
232+
StepVerifier.create(getSerializer(schemaCreator("null"))
233+
.deserializeFromBytesAsync((byte[]) null, createInstance(void.class)))
227234
.verifyComplete();
228235
}
229236

sdk/core/azure-core-serializer-json-gson/src/main/java/com/azure/core/serializer/json/gson/GsonJsonSerializer.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,6 @@
2121
import java.lang.reflect.Field;
2222
import java.lang.reflect.Member;
2323
import java.lang.reflect.Modifier;
24-
import java.nio.charset.StandardCharsets;
2524

2625
import static java.nio.charset.StandardCharsets.UTF_8;
2726

@@ -44,7 +43,11 @@ public final class GsonJsonSerializer implements JsonSerializer, MemberNameConve
4443

4544
@Override
4645
public <T> T deserialize(InputStream stream, TypeReference<T> typeReference) {
47-
return gson.fromJson(new InputStreamReader(stream, StandardCharsets.UTF_8), typeReference.getJavaType());
46+
if (stream == null) {
47+
return null;
48+
}
49+
50+
return gson.fromJson(new InputStreamReader(stream, UTF_8), typeReference.getJavaType());
4851
}
4952

5053
@Override
@@ -64,6 +67,11 @@ public void serialize(OutputStream stream, Object value) {
6467
}
6568
}
6669

70+
@Override
71+
public Mono<byte[]> serializeToBytesAsync(Object value) {
72+
return Mono.fromCallable(() -> serializeToBytes(value));
73+
}
74+
6775
@Override
6876
public Mono<Void> serializeAsync(OutputStream stream, Object value) {
6977
return Mono.fromRunnable(() -> serialize(stream, value));

sdk/core/azure-core-serializer-json-gson/src/test/java/com/azure/core/serializer/json/gson/GsonJsonSerializerTests.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,20 @@ public class GsonJsonSerializerTests {
3333
.serializer(new GsonBuilder().registerTypeAdapter(Person.class, new PersonAdapter()).create())
3434
.build();
3535

36+
@Test
37+
public void deserializeNullInputStreamReturnsNull() {
38+
StepVerifier.create(DEFAULT_SERIALIZER
39+
.deserializeAsync((InputStream) null, TypeReference.createInstance(Person.class)))
40+
.verifyComplete();
41+
}
42+
43+
@Test
44+
public void deserializeNullByteArrayReturnsNull() {
45+
StepVerifier.create(DEFAULT_SERIALIZER
46+
.deserializeFromBytesAsync((byte[]) null, TypeReference.createInstance(Person.class)))
47+
.verifyComplete();
48+
}
49+
3650
@Test
3751
public void deserializeWithDefaultSerializer() {
3852
String json = "{\"name\":null,\"age\":50}";

sdk/core/azure-core-serializer-json-jackson/src/main/java/com/azure/core/serializer/json/jackson/JacksonJsonSerializer.java

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ public final class JacksonJsonSerializer implements JsonSerializer, MemberNameCo
4949
this.typeFactory = mapper.getTypeFactory();
5050
}
5151

52+
@Override
53+
public <T> T deserializeFromBytes(byte[] data, TypeReference<T> typeReference) {
54+
if (data == null) {
55+
return null;
56+
}
57+
58+
try {
59+
return mapper.readValue(data, typeFactory.constructType(typeReference.getJavaType()));
60+
} catch (IOException ex) {
61+
throw logger.logExceptionAsError(new UncheckedIOException(ex));
62+
}
63+
}
64+
5265
@Override
5366
public <T> T deserialize(InputStream stream, TypeReference<T> typeReference) {
5467
if (stream == null) {
@@ -62,11 +75,25 @@ public <T> T deserialize(InputStream stream, TypeReference<T> typeReference) {
6275
}
6376
}
6477

78+
@Override
79+
public <T> Mono<T> deserializeFromBytesAsync(byte[] data, TypeReference<T> typeReference) {
80+
return Mono.fromCallable(() -> deserializeFromBytes(data, typeReference));
81+
}
82+
6583
@Override
6684
public <T> Mono<T> deserializeAsync(InputStream stream, TypeReference<T> typeReference) {
6785
return Mono.fromCallable(() -> deserialize(stream, typeReference));
6886
}
6987

88+
@Override
89+
public byte[] serializeToBytes(Object value) {
90+
try {
91+
return mapper.writeValueAsBytes(value);
92+
} catch (IOException ex) {
93+
throw logger.logExceptionAsError(new UncheckedIOException(ex));
94+
}
95+
}
96+
7097
@Override
7198
public void serialize(OutputStream stream, Object value) {
7299
try {
@@ -76,6 +103,11 @@ public void serialize(OutputStream stream, Object value) {
76103
}
77104
}
78105

106+
@Override
107+
public Mono<byte[]> serializeToBytesAsync(Object value) {
108+
return Mono.fromCallable(() -> this.serializeToBytes(value));
109+
}
110+
79111
@Override
80112
public Mono<Void> serializeAsync(OutputStream stream, Object value) {
81113
return Mono.fromRunnable(() -> serialize(stream, value));

sdk/core/azure-core-serializer-json-jackson/src/test/java/com/azure/core/serializer/json/jackson/JacksonJsonSerializerTests.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,8 +39,16 @@ public class JacksonJsonSerializerTests {
3939
.build();
4040

4141
@Test
42-
public void deserializeNull() {
43-
StepVerifier.create(DEFAULT_SERIALIZER.deserializeAsync(null, TypeReference.createInstance(Person.class)))
42+
public void deserializeNullInputStreamReturnsNull() {
43+
StepVerifier.create(DEFAULT_SERIALIZER
44+
.deserializeAsync((InputStream) null, TypeReference.createInstance(Person.class)))
45+
.verifyComplete();
46+
}
47+
48+
@Test
49+
public void deserializeNullByteArrayReturnsNull() {
50+
StepVerifier.create(DEFAULT_SERIALIZER
51+
.deserializeFromBytesAsync((byte[]) null, TypeReference.createInstance(Person.class)))
4452
.verifyComplete();
4553
}
4654

sdk/core/azure-core/src/main/java/com/azure/core/util/BinaryData.java

Lines changed: 5 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -214,13 +214,7 @@ public static BinaryData fromBytes(byte[] data) {
214214
* @see JsonSerializer
215215
*/
216216
public static BinaryData fromObject(Object data) {
217-
if (Objects.isNull(data)) {
218-
return EMPTY_DATA;
219-
}
220-
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
221-
getDefaultSerializer().serialize(outputStream, data);
222-
223-
return new BinaryData(outputStream.toByteArray());
217+
return fromObject(data, getDefaultSerializer());
224218
}
225219

226220
/**
@@ -241,7 +235,7 @@ public static BinaryData fromObject(Object data) {
241235
* @see JsonSerializer
242236
*/
243237
public static Mono<BinaryData> fromObjectAsync(Object data) {
244-
return Mono.fromCallable(() -> fromObject(data));
238+
return fromObjectAsync(data, getDefaultSerializer());
245239
}
246240

247241
/**
@@ -278,9 +272,7 @@ public static BinaryData fromObject(Object data, ObjectSerializer serializer) {
278272

279273
Objects.requireNonNull(serializer, "'serializer' cannot be null.");
280274

281-
final ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
282-
serializer.serialize(outputStream, data);
283-
return new BinaryData(outputStream.toByteArray());
275+
return new BinaryData(serializer.serializeToBytes(data));
284276
}
285277

286278
/**
@@ -461,8 +453,7 @@ public <T> T toObject(TypeReference<T> typeReference, ObjectSerializer serialize
461453
Objects.requireNonNull(typeReference, "'typeReference' cannot be null.");
462454
Objects.requireNonNull(serializer, "'serializer' cannot be null.");
463455

464-
InputStream jsonStream = new ByteArrayInputStream(this.data);
465-
return serializer.deserialize(jsonStream, typeReference);
456+
return serializer.deserializeFromBytes(this.data, typeReference);
466457
}
467458

468459
/**
@@ -515,7 +506,7 @@ public <T> Mono<T> toObjectAsync(Class<T> clazz) {
515506
* @see JsonSerializer
516507
*/
517508
public <T> Mono<T> toObjectAsync(TypeReference<T> typeReference) {
518-
return Mono.fromCallable(() -> toObject(typeReference));
509+
return toObjectAsync(typeReference, getDefaultSerializer());
519510
}
520511

521512
/**

0 commit comments

Comments
 (0)