Apache johnzon

Apache Johnzon is a project providing an implementation of JsonProcessing (aka jsr-353) and a set of useful extension for this specification like an Object mapper and some JAX-RS providers.

Johnzon comes with three main modules.

<dependency>
  <groupId>org.apache.johnzon</groupId>
  <artifactId>johnzon-core</artifactId>
  <version>0.8-incubating-SNAPSHOT</version>
</dependency>

This is the implementation of the specification. You’ll surely want to add the API as dependency too:

<dependency>
  <groupId>org.apache.geronimo.specs</groupId>
  <artifactId>geronimo-json_1.0_spec</artifactId>
  <version>1.0-alpha-1</version>
  <scope>provided</scope> <!-- or compile if your environment doesn't provide it -->
</dependency>
<dependency>
  <groupId>org.apache.johnzon</groupId>
  <artifactId>johnzon-mapper</artifactId>
  <version>0.8-incubating-SNAPSHOT</version>
</dependency>

The mapper module allows you to use the implementation you want of Json Processing specification to map Json to Object and the opposite.

final MySuperObject object = createObject();

final Mapper mapper = new MapperBuilder().build();
mapper.writeObject(object, outputStream);

final MySuperObject otherObject = mapper.readObject(inputStream, MySuperObject.class);
<dependency>
  <groupId>org.apache.johnzon</groupId>
  <artifactId>johnzon-jaxrs</artifactId>
  <version>0.8-incubating-SNAPSHOT</version>
</dependency>

JAX-RS module provides two providers (and underlying MessageBodyReaders and MessageBodyWriters):

  • org.apache.johnzon.jaxrs.JohnzonProvider: use Johnzon Mapper to map Object to Json and the opposite
  • org.apache.johnzon.jaxrs.ConfigurableJohnzonProvider: same as JohnzonProvider but with setters to ease the configuration of the provider in most servers/containers
  • org.apache.johnzon.jaxrs.JsrProvider: allows you to use JsrArray, JsrObject (more generally JsonStructure)
<dependency>
  <groupId>org.apache.johnzon</groupId>
  <artifactId>johnzon-websocket</artifactId>
  <version>0.8-incubating-SNAPSHOT</version>
</dependency>

WebSocket module provides a basic integration with Java WebSocket API (JSR 356).

Integration is at codec level (encoder/decoder). There are two families of codecs:

  • The ones based on JSON-P (JsonObject, JsonArray, JsonStructure)
  • The ones based on Johnzon Mapper

Encoders:

  •  org.apache.johnzon.websocket.jsr.JsrObjectEncoder
  •  org.apache.johnzon.websocket.jsr.JsrArrayEncoder
  •  org.apache.johnzon.websocket.jsr.JsrStructureEncoder

Decoders:

  •  org.apache.johnzon.websocket.jsr.JsrObjectDecoder
  •  org.apache.johnzon.websocket.jsr.JsrArrayDecoder
  •  org.apache.johnzon.websocket.jsr.JsrStructureDecoder

Encoder:

  •  org.apache.johnzon.websocket.mapper.JohnzonTextEncoder

Decoder:

  •  org.apache.johnzon.websocket.mapper.JohnzonTextDecoder

On server and client side configuration is easy: just provide the encoders and decoders parameters to @[Server|Client]Endpoint (or EndpointConfig if you use programmatic API)):

@ClientEndpoint(encoders = JsrObjectEncoder.class, decoders = JsrObjectDecoder.class)
public class JsrClientEndpointImpl {
    @OnMessage
    public void on(final JsonObject message) {
        // ...
    }
}

@ServerEndpoint(value = "/my-server", encoders = JsrObjectEncoder.class, decoders = JsrObjectDecoder.class)
public class JsrClientEndpointImpl {
    @OnMessage
    public void on(final JsonObject message) {
        // ...
    }
}

Server configuration is as simple as providing encoders and decoders parameters to @ServerEndpoint:

@ServerEndpoint(value = "/server", encoders = JohnzonTextEncoder.class, decoders = JohnzonTextDecoder.class)
public class ServerEndpointImpl {
    @OnMessage
    public void on(final Session session, final Message message) {
        // ...
    }
}

Client configuration is almost the same excepted in this case it is not possible for Johnzon to guess the type you expect so you’ll need to provide it. In next sample it is done just extending JohnzonTextDecoder in MessageDecoder.

@ClientEndpoint(encoders = JohnzonTextEncoder.class, decoders = ClientEndpointImpl.MessageDecoder.class)
public class ClientEndpointImpl {
    @OnMessage
    public void on(final Message message) {
        // ...
    }

    public static class MessageDecoder extends JohnzonTextDecoder {
        public MessageDecoder() {
            super(Message.class);
        }
    }
}

We would like to thank ej-technologies for their Java profiler JProfiler which helped us a lot optimizing memory footprint and speed. JProfiler