Skip to content

Commit

Permalink
Fix #3522: support serialization of ByteArrayOutputStream instances (
Browse files Browse the repository at this point in the history
  • Loading branch information
cowtowncoder authored Jan 7, 2025
1 parent 0e2ab57 commit 876d351
Show file tree
Hide file tree
Showing 7 changed files with 66 additions and 27 deletions.
1 change: 1 addition & 0 deletions release-notes/VERSION
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,7 @@ Versions: 3.x (for earlier see VERSION-2.x)
#3046: Rename `JsonSerializable` as `JacksonSerializable`
#3047: Rename `Bean[De]SerializerModifier` as `Value[De]SerializerModifier`
#3070: Change default for `SerializationFeature.FAIL_ON_EMPTY_BEANS` to `false`
#3522: Support serializing `ByteArrayOutputStream` as "simple" Binary value
#3536: Create new exception type `JsonNodeException` for use by `JsonNode`-related problems
#3542: Rename "com.fasterxml.jackson" -> "tools.jackson"
#3561: Add `DeserializationContext` as an argument for `SettableBeanProperty.set(...)`
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,10 @@
import tools.jackson.core.JsonGenerator;
import tools.jackson.core.JsonToken;
import tools.jackson.core.type.WritableTypeId;

import tools.jackson.databind.JavaType;
import tools.jackson.databind.SerializationContext;
import tools.jackson.databind.annotation.JacksonStdImpl;
import tools.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor;
import tools.jackson.databind.jsonFormatVisitors.JsonFormatTypes;
import tools.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import tools.jackson.databind.jsontype.TypeSerializer;
import tools.jackson.databind.ser.std.StdSerializer;
Expand Down Expand Up @@ -66,15 +65,6 @@ public void serializeWithType(byte[] value, JsonGenerator g, SerializationContex
@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
{
// 14-Mar-2016, tatu: while logically (and within JVM) binary, gets encoded as Base64 String,
// let's try to indicate it is array of Bytes... difficult, thanks to JSON Schema's
// lackluster listing of types
//
// TODO: for 2.8, make work either as String/base64, or array of numbers,
// with a qualifier that can be used to determine it's byte[]
JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint);
if (v2 != null) {
v2.itemsFormat(JsonFormatTypes.INTEGER);
}
acceptJsonFormatVisitorForBinary(visitor, typeHint);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@

import tools.jackson.core.*;
import tools.jackson.databind.*;
import tools.jackson.databind.jsonFormatVisitors.JsonArrayFormatVisitor;
import tools.jackson.databind.jsonFormatVisitors.JsonFormatTypes;
import tools.jackson.databind.jsonFormatVisitors.JsonFormatVisitorWrapper;
import tools.jackson.databind.ser.std.StdScalarSerializer;
import tools.jackson.databind.util.ByteBufferBackedInputStream;
Expand Down Expand Up @@ -33,12 +31,7 @@ public void serialize(ByteBuffer bbuf, JsonGenerator gen, SerializationContext p
}

@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
{
// 31-Mar-2017, tatu: Use same type as `ByteArraySerializer`: not optimal but has to do
JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint);
if (v2 != null) {
v2.itemsFormat(JsonFormatTypes.INTEGER);
}
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint) {
acceptJsonFormatVisitorForBinary(visitor, typeHint);
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package tools.jackson.databind.ser.jdk;

import java.io.ByteArrayOutputStream;
import java.util.*;
import java.util.concurrent.atomic.*;

Expand Down Expand Up @@ -50,6 +51,9 @@ public static final ValueSerializer<?> find(Class<?> raw)
if ((raw == Void.class) || (raw == Void.TYPE)) {
return NullSerializer.instance;
}
if (ByteArrayOutputStream.class.isAssignableFrom(raw)) {
return new ByteArrayOutputStreamSerializer();
}
return null;
}

Expand Down Expand Up @@ -108,4 +112,31 @@ public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType t
visitIntFormat(visitor, typeHint, JsonParser.NumberType.LONG);
}
}

/*
/**********************************************************************
/* Serializers, other
/**********************************************************************
*/

/**
* @since 3.0
*/
public static class ByteArrayOutputStreamSerializer
extends StdScalarSerializer<ByteArrayOutputStream>
{
public ByteArrayOutputStreamSerializer() { super(ByteArrayOutputStream.class, false); }

@Override
public void serialize(ByteArrayOutputStream value, JsonGenerator gen,
SerializationContext ctxt) throws JacksonException {
gen.writeBinary(value.toByteArray());
}

@Override
public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType typeHint)
{
acceptJsonFormatVisitorForBinary(visitor, typeHint);
}
}
}
19 changes: 19 additions & 0 deletions src/main/java/tools/jackson/databind/ser/std/StdSerializer.java
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,25 @@ public void acceptJsonFormatVisitor(JsonFormatVisitorWrapper visitor, JavaType t
visitor.expectAnyFormat(typeHint);
}

/**
* Helper method for handling Binary values: typically serialized as Base64-encoded
* data (in textual formats) or native binary (binary formats).
*/
protected void acceptJsonFormatVisitorForBinary(JsonFormatVisitorWrapper visitor, JavaType typeHint)
{
// 14-Mar-2016, tatu: while logically (and within JVM) binary, gets often encoded
// as Base64 String, let's try to indicate it is array of Bytes... difficult,
// thanks to JSON Schema's lackluster set of types available
//
// TODO: make work either as String/base64, or array of numbers,
// with a qualifier that can be used to determine it's byte[]

JsonArrayFormatVisitor v2 = visitor.expectArrayFormat(typeHint);
if (v2 != null) {
v2.itemsFormat(JsonFormatTypes.INTEGER);
}
}

/*
/**********************************************************************
/* Helper methods for JSON Schema generation
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -258,4 +258,15 @@ public void testThreadSerialization() throws Exception
assertNotNull(cl);
assertEquals(0, cl.size());
}

// [databind#3522]: ByteArrayOutputStream
@Test
public void testByteArrayOutputStreamSerialization() throws Exception
{
byte[] bytes = new byte[] { 1, 11, 111 };
final String exp = MAPPER.writeValueAsString(bytes);
ByteArrayOutputStream baos = new ByteArrayOutputStream();
baos.write(bytes);
assertEquals(exp, MAPPER.writeValueAsString(baos));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -433,10 +433,4 @@ private void serialize(ObjectWriter w, Object date, List<String> expected) throw
String result = w.writeValueAsString(date);
assertTrue(expected.contains(result), "unexpected result: " + result);
}

private String zoneOffset(String raw) {
// Add colon or not -- difference between 2.10 and earlier, 2.11 and later
return raw.substring(0, 2) + ":" + raw.substring(2); // 2.11 and later
// return raw; // 2.10 and earlier
}
}

0 comments on commit 876d351

Please sign in to comment.