2

I am using Jackson 2.2.3. When I serialize an object to JSON, all the byte[] properties are encoded to base64 in generated json.

How do I disable that?

Here is my code.

DataHolder.java

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "", propOrder = {
    "expectedData"
})
@XmlRootElement(name = "dataHolder")
public class DataHolder {

    private final static long serialVersionUID = 1L;
    @XmlElement(required = true, type = String.class)
    @XmlJavaTypeAdapter(HexBinaryAdapter.class)
    @XmlSchemaType(name = "hexBinary")
    protected byte[] expectedData;

    ...

}

JSON output:

{
...
"dataHolder": {
    "expectedData": "c29tZXRleHQ=",
}
...
}
Kishor Prakash
  • 8,011
  • 12
  • 61
  • 92

1 Answers1

2

Here I am creating custom Serializer :

public class BytesToStringSerializer extends StdSerializer<byte[]> {

    public BytesToStringSerializer() {
        super(byte[].class);
    }

    protected BytesToStringSerializer(Class<byte[]> t) {
        super(t);
    }

    @Override
    public void serialize(byte[] value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        String yourReadableString = new String(value, StandardCharsets.UTF_8);
        gen.writeString(yourReadableString);
    }
}

Your DataHolder class :

public class DataHolder {
    @JsonSerialize(using = BytesToStringSerializer.class)
    byte[] expectedData;

    public DataHolder(byte[] expectedData) {
        this.expectedData = expectedData;
    }
}

And Main class for testing :

public class Main {
    public static void main(String[] args) throws JsonProcessingException {

        byte[] someBytes = "Hello world".getBytes(StandardCharsets.UTF_8);
        DataHolder dataHolder = new DataHolder(someBytes);
        ObjectMapper objectMapper = new ObjectMapper();
        String output = objectMapper.writeValueAsString(dataHolder);
        System.out.println(output);
    }
}

The output is :

{"expectedData":"Hello world"}

Please keep in mind that you should use encoding thats is suitable for you. If your byte[] array does not represent anything readable you should keep it in base64 format.

EDIT :

To configure ObjectMapper globally register module with Serializer for it :

public class Main {
    public static void main(String[] args) throws JsonProcessingException {
        byte[] someBytes = "Hello world".getBytes(StandardCharsets.UTF_8);
        DataHolder dataHolder = new DataHolder(someBytes);

        ObjectMapper objectMapper = new ObjectMapper();
        SimpleModule module = new SimpleModule();
        module.addSerializer(byte[].class, new BytesToStringSerializer());
        objectMapper.registerModule(module);

        String output = objectMapper.writeValueAsString(dataHolder);
        System.out.println(output);
    }
}

Remember to provide getters and setters for your data. If you dont want getters and setters configure objectMapper and set field visibility :

objectMapper.setVisibility(PropertyAccessor.FIELD, JsonAutoDetect.Visibility.ANY);
Michał Krzywański
  • 15,659
  • 4
  • 36
  • 63
  • Thanks for the answer. Data holder is just a poc. The project which I am working on has hundreds of classes and at least half of them have properties of type `byte[]`. So looking for a generic solution. – Kishor Prakash May 08 '19 at 16:36
  • 1
    Are you using Spring maybe? Are you able to configure your ObjectMapper globally? One option is to annotate your `byte[]` arrays in every class with `@JsonSerialize(using = BytesToStringSerializer.class)` annotation or configure object mapper globally. – Michał Krzywański May 08 '19 at 16:38
  • No not using spring. But I do have access to ObjectMapper globally. How do I configure it globally? – Kishor Prakash May 09 '19 at 06:41