All Downloads are FREE. Search and download functionalities are using the official Maven repository.

templates.plugins.spincast-jackson-json.spincast-jackson-json.html Maven / Gradle / Ivy

{#==========================================
Spincast Jackson Json plugin
==========================================#}
{% extends "../../layout.html" %}

{% block sectionClasses %}plugins plugins-spincast-jackson-json{% endblock %}
{% block meta_title %}Plugins - Spincast Jackson Json{% endblock %}
{% block meta_description %}Spincast Jackson Json plugin provides Json functionalities using Jackson.{% endblock %}

{% block scripts %}

{% endblock %}

{% block body %}

Overview

The Spincast Jackson Json plugin provides Json functionalities using Jackson. It contains an implementation of the IJsonManager interface.

Most of the time, the IJsonManager interface is used directly from the request context via the json() method or indirectly via some methods on the response() add-on.

For example:

{% verbatim %}

public class AppController {

    public void myHandler(IDefaultRequestContext context) {

        // Create a Json object, using the "json()" add-on
        IJsonObject jsonObj = context.json().create();

        // Send an object as Json, using the "response()" add-on
        context.response().sendJson(jsonObj);
    }
}
{% endverbatim %}

You can also directly inject the IJsonManager instance where you need it in your application.

Installation

If you use the spincast-default artifact, this plugin is already installed so you have nothing more to do!

If you start from scratch using the spincast-core artifact, you can use the plugin by adding this artifact to your project:

<dependency>
    <groupId>org.spincast</groupId>
    <artifactId>spincast-plugins-jackson-json</artifactId>
    <version>{{spincastCurrrentVersion}}</version>
</dependency>

You then install the plugin's Guice module, by passing it to the Guice.createInjector(...) method:

Injector guice = Guice.createInjector(
        new SpincastCoreGuiceModule(args),
        new SpincastJacksonJsonPluginGuiceModule(IAppRequestContext.class)
        // other modules...
        );

... or by using the install(...) method from your custom Guice module:

public class AppModule extends SpincastCoreGuiceModule {

    @Override
    protected void configure() {
        super.configure();
        install(new SpincastJacksonJsonPluginGuiceModule(getRequestContextType()));
        // other modules...
    }
    
    // ...
}

The IJsonManager interface

Methods :

  • IJsonObject create()
    Creates an empty JsonObject
  • IJsonObject create(String jsonString)
    Creates a JsonObject from a Json
    String.
  • IJsonObject create(InputStream inputStream)
    Creates a JsonObject from an inputStream.
  • IJsonArray createArray()
    Creates an empty JsonArray.
  • IJsonArray createArray(String jsonString)
    Creates a JsonArray from a Json
    String.
  • IJsonArray createArray(InputStream inputStream)
    Creates a JsonArray from an inputStream.
  • String toJsonString(Object obj)
    Gets the Json String representation of the specified object.
  • String toJsonString(Object obj, boolean pretty)
    Gets the Json String representation of the specified object.
    @param pretty if true, the generated String will be formatted.
  • Map<String, Object> fromJsonStringToMap(String jsonString)
    Creates a Map<String, Object> from a Json
    String.
  • Map<String, Object> fromJsonInputStreamToMap(InputStream inputStream)
    Creates a Map<String, Object> from a Json inputStream.
  • <T> T fromJsonString(String jsonString, Class<T> clazz)
    Creates an instance of the specified T type from a Json String.
  • <T> T fromJsonInputStream(InputStream inputStream, Class<T> clazz)
    Creates an instance of the specified T type from a Json inputStream.
  • Date parseDateFromJson(String str)
    Converts a Json date to a Java UTC date.

(de)serialization configurations

Jackson allows some configuration when serializing and deserializing an object.

Most of those configurations are defined using annotations. You can annotate the objects directly, or you can use mix-ins.

Annotating the objects :

If you don't minds annotating your objects with Jackson specific annotations, this is maybe the simplest thing to do. For example, let's say you have a User class that has two fields, name and title, and you don't want to keep the title field when you serialize an instance of this class:

public class User implements IUser {

    private String name;
    private String title;

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String getTitle() {
        return this.title;
    }

    @Override
    public void setTitle(String title) {
        this.title = title;
    }
}

To ignore the title field to be included during the serialization, you can simply annotate the getTitle() method with @JsonIgnore:

public class User implements IUser {

    private String name;
    private String title;

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    @JsonIgnore
    public String getTitle() {
        return this.title;
    }

    @Override
    public void setTitle(String title) {
        this.title = title;
    }
}

If you serialize an instance of this class using the Json Manager, only the name property would be kept:

IUser user = new User();
user.setName("Stromgol");
user.setTitle("alien");

String jsonString = getJsonManager().toJsonString(user);
assertEquals("{\"name\":\"Stromgol\"}", jsonString);

Using mix-ins:

Many developers (us included) don't like to pollute their model classes with too many annotations. Lucky us, Jackson provides a way to configure objects from the outside, without annotating the objects directly, by using what is called mix-ins annotations.

Let's start with the same User class, without any Jackson annotations:

public class User implements IUser {

    private String name;
    private String title;

    @Override
    public String getName() {
        return this.name;
    }

    @Override
    public void setName(String name) {
        this.name = name;
    }

    @Override
    public String getTitle() {
        return this.title;
    }

    @Override
    public void setTitle(String title) {
        this.title = title;
    }
}

To use Json mix-ins in a Spincast application, you first need to create the mix-in abstract class. Interfaces work too, but only to annotate methods, not fields.

An example mix-in for our IUser objects:

public abstract class IUserMixin implements IUser {

    // Ignore this property!
    @Override
    @JsonIgnore
    public abstract String getTitle();
}

As you can see, a mix-in extends the class/interface to configure, and adds the Jackson annotations on the overriding fields or methods declarations.

Once the mix-in is defined, you have to register it, in your custom Guice module:

public class AppModule extends SpincastDefaultGuiceModule {

    public AppModule(String[] mainArgs) {
        super(mainArgs);
    }

    @Override
    protected void configure() {
        super.configure();

        bindJsonMixins();
        
        //...
    }

    protected void bindJsonMixins() {

        Multibinder<IJsonMixinInfo> jsonMixinsBinder = Multibinder.newSetBinder(binder(), IJsonMixinInfo.class);
        jsonMixinsBinder.addBinding().toInstance(new JsonMixinInfo(IUser.class, IUserMixin.class));
    }
}

Explanation :

  • 18 : A multibinder is used to collect the various mix-ins to register. The advantage of a multibinder is that it allows to register mix-ins from any Guice module. For example, some plugins may want to register their mix-ins, and you may want to register your custom ones.
  • 19 : We register our mix-in, by binding a JsonMixinInfo instance, which specifies the class to configure, and the class of the mix-in used to configure it.

With this in place, Spincast will automatically configure Jackson so it uses your mix-ins, and you would have the exact same result than annotating the User class directly:

IUser user = new User();
user.setName("Stromgol");
user.setTitle("alien");

String jsonString = getJsonManager().toJsonString(user);
assertEquals("{\"name\":\"Stromgol\"}", jsonString);

{% endblock %}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy