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?
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.
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.
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)
withjava.io.ByteArrayOutputStream
and getting bytes, but more efficient.
For the reading you can simply use the readTree(InputStream)
version.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With