Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Current recommended way to convert byte[] to JsonNode and back

Tags:

java

json

jackson

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();
JsonNode old = om.createObjectNode();

byte[] arr = om.writeValueAsBytes(old);
JsonNode new = om.readTree(arr);

However, Jackson these days recommends the use of ObjectReader and ObjectWriter instead of ObjectMapper, because of thread safety in configuration, but also because of optimizations that might be relevant for them only. But, ObjectReader does not support readTree with byte arrays directly, and writeValueAsBytes is more generic than writeTree so there might be a way (and a reason) to skip the type mapping logic somehow.

So, today, with the most recent Jackson (2.5), what is the fastest/best/recommended way to do these two conversions?

like image 597
Nakedible Avatar asked Feb 02 '15 08:02

Nakedible


People also ask

Can I send byte array in JSON?

JSON does not support that. Use Base64. That is your library supporting it, not JSON itself. The byte array wont be stored as byte array in the JSON, JSON is a text format meant to be human readable.

How do you find the value of JsonNode?

We can access a field, array or nested object using the get() method of JsonNode class. We can return a valid string representation using the asText() method and convert the value of the node to a Java int using the asInt() method of JsonNode class.


1 Answers

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.

like image 165
wassgren Avatar answered Sep 28 '22 04:09

wassgren