If you are using Jackson for JSON parsing, it can automatically convert byte[] to/from Base64 encoded Strings via data-binding.

Or, if you want low-level access, both JsonParser and JsonGenerator have binary access methods (writeBinary, readBinary) to do the same at level of JSON token stream.

For automatic approach, consider POJO like:

public class Message {
  public String mimetype;
  public byte[] value;
}

and to create JSON, you could do:

Message msg = ...;
String jsonStr = new ObjectMapper().writeValueAsString(msg);

or, more commonly would write it out with:

OutputStream out = ...;
new ObjectMapper().writeValue(out, msg);
Answer from StaxMan on Stack Overflow
Top answer
1 of 3
48

If you are using Jackson for JSON parsing, it can automatically convert byte[] to/from Base64 encoded Strings via data-binding.

Or, if you want low-level access, both JsonParser and JsonGenerator have binary access methods (writeBinary, readBinary) to do the same at level of JSON token stream.

For automatic approach, consider POJO like:

public class Message {
  public String mimetype;
  public byte[] value;
}

and to create JSON, you could do:

Message msg = ...;
String jsonStr = new ObjectMapper().writeValueAsString(msg);

or, more commonly would write it out with:

OutputStream out = ...;
new ObjectMapper().writeValue(out, msg);
2 of 3
20

You can write your own CustomSerializer like this one:

public class ByteArraySerializer extends JsonSerializer<byte[]> {

@Override
public void serialize(byte[] bytes, JsonGenerator jgen,
        SerializerProvider provider) throws IOException,
        JsonProcessingException {
    jgen.writeStartArray();

    for (byte b : bytes) {
        jgen.writeNumber(unsignedToBytes(b));
    }

    jgen.writeEndArray();

}

private static int unsignedToBytes(byte b) {
    return b & 0xFF;
  }

}

This one returns an unsigned byte array representation instead of a Base64 string.

How to use it with your POJO:

public class YourPojo {

    @JsonProperty("mimetype")
    private String mimetype;
    @JsonProperty("value")
    private byte[] value;



    public String getMimetype() { return this.mimetype; }
    public void setMimetype(String mimetype) { this.mimetype = mimetype; }

    @JsonSerialize(using= com.example.yourapp.ByteArraySerializer.class)
    public byte[] getValue() { return this.value; }
    public void setValue(String value) { this.value = value; }


}

And here is an example of it's output:

{
    "mimetype": "text/plain",
    "value": [
        81,
        109,
        70,
        122,
        90,
        83,
        65,
        50,
        78,
        67,
        66,
        84,
        100,
        72,
        74,
        108,
        89,
        87,
        48,
        61
    ]
}

P.S.: This serializer is a mix of some answers that I found on StackOverflow.

🌐
Baeldung
baeldung.com › home › java › java array › convert byte array to json and vice versa in java
Convert Byte Array to JSON and Vice Versa in Java | Baeldung
April 19, 2024 - Next, we’ll explore several approaches to achieve the conversion between byte array and JSON string. Convеrting a bytе array to JSON is a crucial opеration whеn dеaling with data intеrchangе in Java. Furthermore, there are multiple approaches to achiеvе this convеrsion. We can utilize the Jackson as a standard library.
Discussions

java - Current recommended way to convert byte[] to JsonNode and back - Stack Overflow
I'd like to read a JSON "tree" from a java byte array and write a JSON "tree" back out as java byte array using Jackson. One way to do it is shown below: ObjectMapper om = new ObjectMapper(); Json... More on stackoverflow.com
🌐 stackoverflow.com
convert JSON Type to Byte array format in java - Stack Overflow
I have a problem when I want to sending data using byte format in UDP protocol, the problem is when I try to create a data with type json object, I can't get the byte format of my data this is my s... More on stackoverflow.com
🌐 stackoverflow.com
java - Put byte array to JSON and vice versa - Stack Overflow
Is it possible to put a byte[] (byte array) to JSON? if so, how can I do that in java? then read that JSON and convert that field again to byte[]? More on stackoverflow.com
🌐 stackoverflow.com
java - how to deserialize / serialize byte array using Jackson and wrapper object - Stack Overflow
5 Jackson serialize Object to JSON to base64 (without endless loop) 0 Jackson serializing and deserializing Map More on stackoverflow.com
🌐 stackoverflow.com
🌐
DZone
dzone.com › coding › java › converting java objects to byte array, json and xml
Converting Java Objects to Byte Array, JSON and XML
July 22, 2013 - /** * Convert object to byte array * @param object * @return */ public static byte[] fromJavaToByteArray(Serializable object) { return SerializationUtils.serialize(object); } /** * Convert byte array to object * @param bytes * @return */ public static Object fromByteArrayToJava(byte[] bytes) { return SerializationUtils.deserialize(bytes); } Next, we will convert a java object to JSON and back to java. We will use the Jackson library for this.
🌐
javathinking
javathinking.com › blog › convert-byte-array-to-json-java
Converting Byte Array to JSON in Java — javathinking.com
You need to ensure that the data in the byte array is valid JSON before attempting to convert it. A: Yes, both Gson and Jackson support deserializing a byte array directly into a Java object.
🌐
javathinking
javathinking.com › blog › put-byte-array-to-json-and-vice-versa
Can You Put a Byte Array in JSON? How to Convert & Read It Back in Java — javathinking.com
Encode the byte array to a Base64 string with java.util.Base64. Embed the Base64 string into JSON using Jackson (or another JSON library).
🌐
CodingTechRoom
codingtechroom.com › question › convert-byte-array-json-java
How to Convert a Byte Array to JSON and Vice Versa in Java? - CodingTechRoom
Yes, it is possible to store a byte array in JSON format by encoding it as a base64 string. Java libraries like Jackson or Gson can be used for this purpose, enabling easy conversion between byte arrays and JSON.
Top answer
1 of 1
14

The problem with using the ObjectMapper directly is that if you alter the configuration of the mapper it can lead to problems. However, if you do not change the underlying config you should be safe anyway (more reading here).

But if you use the ObjectReader and ObjectWriter you are totally safe, even if you actually do alter the configuration of the mapper. This is possible since the reader/writer are immutable and it is therefore not possible to change the underlying state.

So, to read/write to bytes the following approach works fine:

ObjectMapper om = new ObjectMapper();
JsonNode oldNode = om.createObjectNode();

// Writing...
// Create an immutable writer (in this case using the default settings)
final ObjectWriter writer = om.writer();

// Use the writer for thread safe access.
final byte[] bytes = writer.writeValueAsBytes(oldNode);


// Reading...
// Create an immutable reader
final ObjectReader reader = om.reader();

// Use the reader for thread safe access
final JsonNode newNode = reader.readTree(new ByteArrayInputStream(bytes));

So, basically you can use the same principles (with the byte streams) but if you need to be sure that you are using thread safe access to the mapper you should access the reading/writing via the ObjectReader and ObjectWriter.

The writeValueAsBytes is described like this in the JavaDoc:

Functionally equivalent to calling writeValue(Writer,Object) with java.io.ByteArrayOutputStream and getting bytes, but more efficient.

For the reading you can simply use the readTree(InputStream) version.

🌐
GitHub
gist.github.com › mothman88 › 6051977
Converting Java Objects to Byte Array, JSON and XML · GitHub
Converting Java Objects to Byte Array, JSON and XML · Raw · class.java · This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Find elsewhere
🌐
GeeksforGeeks
geeksforgeeks.org › java › java-program-to-convert-byte-array-to-json
Java Program to Convert Byte Array to JSON - GeeksforGeeks
June 19, 2022 - Any string can be changed to a byte array and any byte array can be converted to a String easily via the below ways. Assume the String that we are going to take is of the pattern with the above basic elements. Because nowadays any REST service is producing the output in the format of JSON.
🌐
Javadoc.io
javadoc.io › doc › com.fasterxml.jackson.core › jackson-databind › 2.8.4 › com › fasterxml › jackson › databind › ser › std › ByteArraySerializer.html
ByteArraySerializer - jackson-databind 2.8.4 javadoc
Bookmarks · Latest version of com.fasterxml.jackson.core:jackson-databind · https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind · Current version 2.8.4 · https://javadoc.io/doc/com.fasterxml.jackson.core/jackson-databind/2.8.4 · package-list path (used for javadoc generation ...
Top answer
1 of 6
94

Here is a good example of base64 encoding byte arrays. It gets more complicated when you throw unicode characters in the mix to send things like PDF documents. After encoding a byte array the encoded string can be used as a JSON property value.

Apache commons offers good utilities:

 byte[] bytes = getByteArr();
 String base64String = Base64.encodeBase64String(bytes);
 byte[] backToBytes = Base64.decodeBase64(base64String);

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Base64_encoding_and_decoding

Java server side example:

public String getUnsecureContentBase64(String url)
        throws ClientProtocolException, IOException {

            //getUnsecureContent will generate some byte[]
    byte[] result = getUnsecureContent(url);

            // use apache org.apache.commons.codec.binary.Base64
            // if you're sending back as a http request result you may have to
            // org.apache.commons.httpclient.util.URIUtil.encodeQuery
    return Base64.encodeBase64String(result);
}

JavaScript decode:

//decode URL encoding if encoded before returning result
var uriEncodedString = decodeURIComponent(response);

var byteArr = base64DecToArr(uriEncodedString);

//from mozilla
function b64ToUint6 (nChr) {

  return nChr > 64 && nChr < 91 ?
      nChr - 65
    : nChr > 96 && nChr < 123 ?
      nChr - 71
    : nChr > 47 && nChr < 58 ?
      nChr + 4
    : nChr === 43 ?
      62
    : nChr === 47 ?
      63
    :
      0;

}

function base64DecToArr (sBase64, nBlocksSize) {

  var
    sB64Enc = sBase64.replace(/[^A-Za-z0-9\+\/]/g, ""), nInLen = sB64Enc.length,
    nOutLen = nBlocksSize ? Math.ceil((nInLen * 3 + 1 >> 2) / nBlocksSize) * nBlocksSize : nInLen * 3 + 1 >> 2, taBytes = new Uint8Array(nOutLen);

  for (var nMod3, nMod4, nUint24 = 0, nOutIdx = 0, nInIdx = 0; nInIdx < nInLen; nInIdx++) {
    nMod4 = nInIdx & 3;
    nUint24 |= b64ToUint6(sB64Enc.charCodeAt(nInIdx)) << 18 - 6 * nMod4;
    if (nMod4 === 3 || nInLen - nInIdx === 1) {
      for (nMod3 = 0; nMod3 < 3 && nOutIdx < nOutLen; nMod3++, nOutIdx++) {
        taBytes[nOutIdx] = nUint24 >>> (16 >>> nMod3 & 24) & 255;
      }
      nUint24 = 0;

    }
  }

  return taBytes;
}
2 of 6
15

The typical way to send binary in json is to base64 encode it.

Java provides different ways to Base64 encode and decode a byte[]. One of these is DatatypeConverter.

Very simply

byte[] originalBytes = new byte[] { 1, 2, 3, 4, 5};
String base64Encoded = DatatypeConverter.printBase64Binary(originalBytes);
byte[] base64Decoded = DatatypeConverter.parseBase64Binary(base64Encoded);

You'll have to make this conversion depending on the json parser/generator library you use.

🌐
Medium
priyarajtt.medium.com › java-program-to-convert-byte-array-to-json-38548b53e27f
Java Program to Convert Byte Array to JSON | by priya raj | Medium
July 12, 2022 - When we need to show the data, we can get the byte array data from DB and parse it like the above sample programs and get either as JSONArray/JSONObject. ... Freelancer, Software Consultant. Having Industrial experience of around 12 + years of experience in the fields of Java, Android,SQL,MongoDB
🌐
javathinking
javathinking.com › blog › convert-byte-to-json-java
Convert Byte to JSON in Java — javathinking.com
Jackson is a feature-rich library with high performance and extensive configuration options. Gson is easy to use and has a simple API. JSON-simple is lightweight and suitable for simple JSON processing. A: You can process the data in chunks instead of loading the entire byte array into memory at once.
🌐
Tabnine
tabnine.com › home › code library
Code Library - Tabnine
July 25, 2024 - Get the answers and suggestions you need from our AI code assistant. Get started in minutes with a free 90 day trial of Tabnine Pro.
Top answer
1 of 2
12

This can be done by writing your own custom serializer and deserializer.

http://www.baeldung.com/jackson-custom-serialization

http://www.baeldung.com/jackson-deserialization

Here's an example similar to what you are doing...

Holder class

public static class Holder {
    private Bytes bytes;
    private String otherStuff;

    public Bytes getBytes() {
        return bytes;
    }

    public void setBytes(Bytes bytes) {
        this.bytes = bytes;
    }

    public String getOtherStuff() {
        return otherStuff;
    }

    public void setOtherStuff(String otherStuff) {
        this.otherStuff = otherStuff;
    }

}

Bytes class

Notice the annotations for the custom serializer...

@JsonSerialize(using = BytesSerializer.class)
@JsonDeserialize(using = BytesDeserializer.class)
public static class Bytes {
    private byte[] bytes;

    public Bytes(byte[] bytes) {
        this.bytes = bytes;
    }

    public byte[] getBytes() {
        return bytes;
    }
}

Serializer

This will serialize a "Bytes" object as a base64 string...

public static class BytesSerializer extends StdSerializer<Bytes> {

    private static final long serialVersionUID = -5510353102817291511L;

    public BytesSerializer() {
        super(Bytes.class);
    }

    @Override
    public void serialize(Bytes value, JsonGenerator gen, SerializerProvider provider) throws IOException {
        gen.writeString(Base64.encode(value.getBytes()));
    }
}

Deserializer

public static class BytesDeserializer extends StdDeserializer<Bytes> {

    private static final long serialVersionUID = 1514703510863497028L;

    public BytesDeserializer() {
        super(Bytes.class);
    }

    @Override
    public Bytes deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonNode node = p.getCodec().readTree(p);
        String base64 = node.asText();
        return new Bytes(Base64.decode(base64));
    }
}

Main method

A simple test method...

public static void main(String[] args) throws Exception {
    ObjectMapper mapper = new ObjectMapper();

    Holder holder = new Holder();
    holder.setOtherStuff("[OTHER STUFF]");
    holder.setBytes(new Bytes(new byte[] { 1, 2, 3, 4, 5 }));

    String json = mapper.writeValueAsString(holder);

    System.out.println(json);
    Holder deserialised = mapper.readValue(json, Holder.class);

    System.out.println(Arrays.toString(deserialised.getBytes().getBytes()));
}

Output

{"bytes":"AQIDBAU=","otherStuff":"[OTHER STUFF]"}
[1, 2, 3, 4, 5]

Run it yourself

All of the classes above are "static" because I'd wrapped them into one big class called "Stack".

If you want to run this, create a new class (called anything you want) and paste all the code here into it...

2 of 2
4

I could not use a wrapped object, but I was able to figure out it wasn't necessary; the following works for me:

public static class ByteArraySerializer extends StdSerializer<byte[]> {

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

    @Override
    public void serialize(byte[] value, JsonGenerator gen,SerializerProvider provider) throws IOException {
        gen.writeString(Base64.getEncoder().encodeToString(value));
    }

}

public static class ByteArrayDeserializer extends StdDeserializer<byte[]> {

    private static final long serialVersionUID = 1514703510863497028L;

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

    @Override
    public byte[] deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonNode node = p.getCodec().readTree(p);
        String base64 = node.asText();
        return Base64.getDecoder().decode(base64);
    }
}

public ObjectMapper getJsonMapper() {
    ObjectMapper jsonMapper = new ObjectMapper();
    SimpleModule module = new SimpleModule("ByteArraySerializer", new Version(1, 0, 0, ""));
    module.addSerializer(byte[].class, new ByteArraySerializer());
    module.addDeserializer(byte[].class, new ByteArrayDeserializer());
    jsonMapper.registerModule(module);
}
🌐
DevQA
devqa.io › encode-decode-json-byte-array
How to Encode and Decode JSON Byte Array
November 9, 2019 - The typical way to send binary in JSON is to base64 encode it. Java provides different ways to Base64 encode and decode a byte[]. One of these is DatatypeConverter.
Top answer
1 of 4
3

Jackson will convert byte[] into Base64-encoded binary data. This is the safe way to pass binary content. Otherwise there is no way to know which character encoding might be used by contained data, so trying to build a String out of it would be risky and error-prone.

So the simplest way would be to have receiver base64 decode contents back into binary data.

You could alternatively add custom serializer to turn into other representations (hex, base85), but it really depends on what the goal is.

2 of 4
1

Note: I'm the EclipseLink JAXB (MOXy) lead and a member of the JAXB (JSR-222) expert group.

Below is how you could support this use case with MOXy as your JSON-binding provider.

Java Model

By default a JAXB implementation will convert a byte[] to base64Binary. You can use the HexBinaryAdapter to have it represented as hexBinary.

package forum15643723;

import javax.xml.bind.annotation.*;
import javax.xml.bind.annotation.adapters.*;

@XmlAccessorType(XmlAccessType.FIELD)
public class Root {

    private byte[] foo;

    @XmlJavaTypeAdapter(HexBinaryAdapter.class)
    private byte[] bar;

}

Demo

In the demo code below we will read the JSON into objects and then write it back to JSON.

package forum15643723;

import java.util.*;
import javax.xml.bind.*;
import javax.xml.transform.stream.StreamSource;
import org.eclipse.persistence.jaxb.JAXBContextProperties;

public class Demo {

    public static void main(String[] args) throws Exception {
        Map<String, Object> properties = new HashMap<String, Object>();
        properties.put(JAXBContextProperties.MEDIA_TYPE, "application/json");
        properties.put(JAXBContextProperties.JSON_INCLUDE_ROOT, false);
        JAXBContext jc = JAXBContext.newInstance(new Class[] {Root.class}, properties);

        Unmarshaller unmarshaller = jc.createUnmarshaller();
        StreamSource json = new StreamSource("src/forum15643723/input.json");
        Root root = (Root) unmarshaller.unmarshal(json, Root.class).getValue();

        Marshaller marshaller = jc.createMarshaller();
        marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
        marshaller.marshal(root, System.out);
    }

}

jaxb.properties

To specify MOXy as your JAXB provider you need to include a file called jaxb.properties in the same package as your domain model (see: http://blog.bdoughan.com/2011/05/specifying-eclipselink-moxy-as-your.html).

javax.xml.bind.context.factory=org.eclipse.persistence.jaxb.JAXBContextFactory

input.json/Output

The foo and bar properties represent the same data. foo is represented as base64Binary and bar is represented as hexBinary.

{
   "foo" : "3q2+78r+",
   "bar" : "DEADBEEFCAFE"
}

For More Information

  • http://blog.bdoughan.com/2011/08/json-binding-with-eclipselink-moxy.html