Skip to content

Commit 876d351

Browse files
authored
Fix #3522: support serialization of ByteArrayOutputStream instances (#4886)
1 parent 0e2ab57 commit 876d351

File tree

7 files changed

+66
-27
lines changed

7 files changed

+66
-27
lines changed

release-notes/VERSION

+1
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ Versions: 3.x (for earlier see VERSION-2.x)
6262
#3046: Rename `JsonSerializable` as `JacksonSerializable`
6363
#3047: Rename `Bean[De]SerializerModifier` as `Value[De]SerializerModifier`
6464
#3070: Change default for `SerializationFeature.FAIL_ON_EMPTY_BEANS` to `false`
65+
#3522: Support serializing `ByteArrayOutputStream` as "simple" Binary value
6566
#3536: Create new exception type `JsonNodeException` for use by `JsonNode`-related problems
6667
#3542: Rename "com.fasterxml.jackson" -> "tools.jackson"
6768
#3561: Add `DeserializationContext` as an argument for `SettableBeanProperty.set(...)`

src/main/java/tools/jackson/databind/ser/jdk/ByteArraySerializer.java

+2-12
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,10 @@
44
import tools.jackson.core.JsonGenerator;
55
import tools.jackson.core.JsonToken;
66
import tools.jackson.core.type.WritableTypeId;
7+
78
import tools.jackson.databind.JavaType;
89
import tools.jackson.databind.SerializationContext;
910
import tools.jackson.databind.annotation.JacksonStdImpl;
10-
import tools.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor;
11-
import tools.jackson.databind.jsonFormatVisitors.JsonFormatTypes;
1211
import tools.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
1312
import tools.jackson.databind.jsontype.TypeSerializer;
1413
import tools.jackson.databind.ser.std.StdSerializer;
@@ -66,15 +65,6 @@ public void serializeWithType(byte[] value, JsonGenerator g, SerializationContex
6665
@Override
6766
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
6867
{
69-
// 14-Mar-2016, tatu: while logically (and within JVM) binary, gets encoded as Base64 String,
70-
// let's try to indicate it is array of Bytes... difficult, thanks to JSON Schema's
71-
// lackluster listing of types
72-
//
73-
// TODO: for 2.8, make work either as String/base64, or array of numbers,
74-
// with a qualifier that can be used to determine it's byte[]
75-
JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint);
76-
if (v2 != null) {
77-
v2.itemsFormat(JsonFormatTypes.INTEGER);
78-
}
68+
acceptJsonFormatVisitorForBinary(visitor, typeHint);
7969
}
8070
}

src/main/java/tools/jackson/databind/ser/jdk/ByteBufferSerializer.java

+2-9
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,6 @@
44

55
import tools.jackson.core.*;
66
import tools.jackson.databind.*;
7-
import tools.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor;
8-
import tools.jackson.databind.jsonFormatVisitors.JsonFormatTypes;
97
import tools.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
108
import tools.jackson.databind.ser.std.StdScalarSerializer;
119
import tools.jackson.databind.util.ByteBufferBackedInputStream;
@@ -33,12 +31,7 @@ public void serialize(ByteBuffer bbuf, JsonGenerator gen, SerializationContext p
3331
}
3432

3533
@Override
36-
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
37-
{
38-
// 31-Mar-2017, tatu: Use same type as `ByteArraySerializer`: not optimal but has to do
39-
JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint);
40-
if (v2 != null) {
41-
v2.itemsFormat(JsonFormatTypes.INTEGER);
42-
}
34+
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) {
35+
acceptJsonFormatVisitorForBinary(visitor, typeHint);
4336
}
4437
}

src/main/java/tools/jackson/databind/ser/jdk/JDKMiscSerializers.java

+31
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package tools.jackson.databind.ser.jdk;
22

3+
import java.io.ByteArrayOutputStream;
34
import java.util.*;
45
import java.util.concurrent.atomic.*;
56

@@ -50,6 +51,9 @@ public static final ValueSerializer<?> find(Class<?> raw)
5051
if ((raw == Void.class) || (raw == Void.TYPE)) {
5152
return NullSerializer.instance;
5253
}
54+
if (ByteArrayOutputStream.class.isAssignableFrom(raw)) {
55+
return new ByteArrayOutputStreamSerializer();
56+
}
5357
return null;
5458
}
5559

@@ -108,4 +112,31 @@ public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType t
108112
visitIntFormat(visitor, typeHint, JsonParser.NumberType.LONG);
109113
}
110114
}
115+
116+
/*
117+
/**********************************************************************
118+
/* Serializers, other
119+
/**********************************************************************
120+
*/
121+
122+
/**
123+
* @since 3.0
124+
*/
125+
public static class ByteArrayOutputStreamSerializer
126+
extends StdScalarSerializer<ByteArrayOutputStream>
127+
{
128+
public ByteArrayOutputStreamSerializer() { super(ByteArrayOutputStream.class, false); }
129+
130+
@Override
131+
public void serialize(ByteArrayOutputStream value, JsonGenerator gen,
132+
SerializationContext ctxt) throws JacksonException {
133+
gen.writeBinary(value.toByteArray());
134+
}
135+
136+
@Override
137+
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
138+
{
139+
acceptJsonFormatVisitorForBinary(visitor, typeHint);
140+
}
141+
}
111142
}

src/main/java/tools/jackson/databind/ser/std/StdSerializer.java

+19
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,25 @@ public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType t
106106
visitor.expectAnyFormat(typeHint);
107107
}
108108

109+
/**
110+
* Helper method for handling Binary values: typically serialized as Base64-encoded
111+
* data (in textual formats) or native binary (binary formats).
112+
*/
113+
protected void acceptJsonFormatVisitorForBinary(JsonFormatVisitorWrapper visitor, JavaType typeHint)
114+
{
115+
// 14-Mar-2016, tatu: while logically (and within JVM) binary, gets often encoded
116+
// as Base64 String, let's try to indicate it is array of Bytes... difficult,
117+
// thanks to JSON Schema's lackluster set of types available
118+
//
119+
// TODO: make work either as String/base64, or array of numbers,
120+
// with a qualifier that can be used to determine it's byte[]
121+
122+
JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint);
123+
if (v2 != null) {
124+
v2.itemsFormat(JsonFormatTypes.INTEGER);
125+
}
126+
}
127+
109128
/*
110129
/**********************************************************************
111130
/* Helper methods for JSON Schema generation

src/test/java/tools/jackson/databind/ser/jdk/JDKTypeSerializationTest.java

+11
Original file line numberDiff line numberDiff line change
@@ -258,4 +258,15 @@ public void testThreadSerialization() throws Exception
258258
assertNotNull(cl);
259259
assertEquals(0, cl.size());
260260
}
261+
262+
// [databind#3522]: ByteArrayOutputStream
263+
@Test
264+
public void testByteArrayOutputStreamSerialization() throws Exception
265+
{
266+
byte[] bytes = new byte[] { 1, 11, 111 };
267+
final String exp = MAPPER.writeValueAsString(bytes);
268+
ByteArrayOutputStream baos = new ByteArrayOutputStream();
269+
baos.write(bytes);
270+
assertEquals(exp, MAPPER.writeValueAsString(baos));
271+
}
261272
}

src/test/java/tools/jackson/databind/ser/jdk/JavaUtilDateSerializationTest.java

-6
Original file line numberDiff line numberDiff line change
@@ -433,10 +433,4 @@ private void serialize(ObjectWriter w, Object date, List<String> expected) throw
433433
String result = w.writeValueAsString(date);
434434
assertTrue(expected.contains(result), "unexpected result: " + result);
435435
}
436-
437-
private String zoneOffset(String raw) {
438-
// Add colon or not -- difference between 2.10 and earlier, 2.11 and later
439-
return raw.substring(0, 2) + ":" + raw.substring(2); // 2.11 and later
440-
// return raw; // 2.10 and earlier
441-
}
442436
}

0 commit comments

Comments
 (0)