<chapter id="json">
    <title>JSON Support via Jackson</title>
    <para>RESTEasy supports integration with the Jackson project.
        For more on Jackson 2, see <ulink url="https://github.com/FasterXML/jackson-databind/wiki">https://github.com/FasterXML/jackson-databind/wiki</ulink>.
        Besides &XML-BIND-API; like APIs, it has a JavaBean based model, described at
        <ulink url="https://github.com/FasterXML/jackson-databind/wiki/Databind-annotations">https://github.com/FasterXML/jackson-databind/wiki/Databind-annotations</ulink>,
        which allows you to easily marshal Java objects to and from JSON.
        RESTEasy integrates with the JavaBean model.
        While Jackson does come with its own &REST-API; integration, RESTEasy expanded it a little, as decribed below.
    </para>
    <sect1>
        <title>Using Jackson 2 Outside of WildFly</title>
        <para>If you're deploying RESTEasy outside of WildFly,
        add the RESTEasy Jackson provder to your WAR pom.xml build:</para>
        <programlisting><![CDATA[
<dependency>
   <groupId>org.jboss.resteasy</groupId>
   <artifactId>resteasy-jackson2-provider</artifactId>
   <version>${version.resteasy}</version>
</dependency>
]]></programlisting>
    </sect1>
    <sect1>
        <title>&XML-BIND-API; Annotations</title>
        <para>
            In Jackson 2.13+ you must register the <code>com.fasterxml.jackson.module.jakarta.xmlbind.JakartaXmlBindAnnotationModule</code>
            in order to use XML binding annotations for Jackson to marshall/unmarshall them in JSON. To do this you
            must provide an <code>com.fasterxml.jackson.databind.ObjectMapper</code> via a
            <code>jakarta.ws.rs.ext.ContextResolver</code>.
        </para>
        <para>
            An example <code>jakarta.ws.rs.ext.ContextResolver</code>:
            <programlisting><![CDATA[
@Provider
public class ObjectMapperProvider implements ContextResolver<ObjectMapper> {
    static final JsonMapper MAPPER = JsonMapper.builder()
            .addModule(new JakartaXmlBindAnnotationModule())
            .build();

    @Override
    public ObjectMapper getContext(final Class<?> type) {
        return MAPPER;
    }
}
            ]]></programlisting>
        </para>
    </sect1>
    <sect1>
        <title>Using Jackson 2 Inside WildFly 9 and above</title>
        <para>If you're deploying RESTEasy with WildFly 9 or above,
        there's nothing you need to do except to make sure
        you've updated your installation with the latest and greatest RESTEasy.  See the
        <link linkend='Installation_Configuration'>Installation/Configuration</link> section
        of this documentation for more details.</para>
    </sect1>
    <sect1>
        <title>Additional RESTEasy Specifics</title>

    <para>The first extra piece that RESTEasy added to the integration was
        to support "application/*+json". Jackson would only accept "application/json" and "text/json" as valid
        media types. This allows you to create json-based media types and still
        let Jackson marshal things for you. For example:
    </para>
    <programlisting><![CDATA[
@Path("/customers")
public class MyService {

    @GET
    @Produces("application/vnd.customer+json")
    public Customer[] getCustomers() {}
}
]]></programlisting>
    </sect1>

    <sect1 id="JSONP_Support">
        <title>JSONP Support</title>
        <para>
            If you're using Jackson, RESTEasy has <ulink url="http://en.wikipedia.org/wiki/JSONP">JSONP</ulink> that you can turn on by adding
            the provider <literal>org.jboss.resteasy.plugins.providers.jackson.Jackson2JsonpInterceptor</literal> (Jackson2JsonpInterceptor if you're using the Jackson2 provider)
            to your deployments.
            If the media type of the response is json and a callback query parameter is given, the response will be a javascript snippet with
            a method call of the method defined by the callback parameter.
            For example:
<programlisting>
GET /resources/stuff?callback=processStuffResponse
</programlisting>
            will produce this response:
<programlisting>
processStuffResponse(&lt;nomal JSON body&gt;)
</programlisting>
            This supports the default behavior of <ulink url="http://api.jquery.com/jQuery.ajax/">jQuery</ulink>.
            To enable Jackson2JsonpInterceptor in WildFly, you need to import annotations from <literal>org.jboss.resteasy.resteasy-jackson2-provider</literal> module using jboss-deployment-structure.xml:
<programlisting><![CDATA[
<jboss-deployment-structure>
  <deployment>
    <dependencies>
      <module name="org.jboss.resteasy.resteasy-jackson2-provider" annotations="true"/>
    </dependencies>
  </deployment>
</jboss-deployment-structure>
]]></programlisting>
        </para>
        <para>
            You can change the name of the callback parameter by setting the callbackQueryParameter property.
        </para>
        <para>
            Jackson2JsonpInterceptor can wrap the response into a try-catch block:
<programlisting>
try{processStuffResponse(&lt;normal JSON body&gt;)}catch(e){}
</programlisting>
            You can enable this feature by setting the resteasy.jsonp.silent property to true
        </para>
        <para>
        <emphasis role="bold">Note.</emphasis> Because JSONP can be used in
        <emphasis role="bold">Cross Site Scripting Inclusion (XSSI) attacks</emphasis>,
        <methodname>Jackson2JsonpInterceptor</methodname>
        is disabled by default. Two steps are necessary to enable it:
        </para>
        <orderedlist>
           <listitem>As noted above, <methodname>Jackson2JsonpInterceptor</methodname> must be
           included in the deployment. For example,
           a service file META-INF/services/jakarta.ws.rs.ext.Providers with the line
<programlisting>
org.jboss.resteasy.plugins.providers.jackson.Jackson2JsonpInterceptor
</programlisting>
           may be included on the classpath
           </listitem>
           <listitem>Also, the parameter parameter "resteasy.jsonp.enable" must be set to "true".
           [See <xref linkend="microprofile_config"/> for more information about application configuration.]
           </listitem>
        </orderedlist>
    </sect1>
    <sect1 id="Jackson_JSON_Decorator">
        <title>Jackson JSON Decorator</title>
        <para>
            If you are using the Jackson 2 provider, RESTEasy has provided a pretty-printing annotation similar with the one in &XML-BIND-API; provider:
<programlisting>
org.jboss.resteasy.annotations.providers.jackson.Formatted
</programlisting>
            Here is an example:
<programlisting>
@GET
@Produces("application/json")
@Path("/formatted/{id}")
@Formatted
public Product getFormattedProduct()
{
    return new Product(333, "robot");
}
</programlisting>
            As the example shown above, the @Formatted annotation will enable the underlying Jackson option "SerializationFeature.INDENT_OUTPUT".
        </para>
    </sect1>

    <sect1 id="JSON_Filter_Support">
        <title>JSON Filter Support</title>
        <para>
            In Jackson2 , there is new feature <ulink url="http://fasterxml.github.io/jackson-annotations/javadoc/2.13/com/fasterxml/jackson/annotation/JsonFilter.html">JsonFilter</ulink> to allow annotate class with @JsonFilter and doing dynamic filtering.
Here is an example which defines mapping from "nameFilter" to filter instances and filter bean properties when serilize to json format:
<programlisting>
@JsonFilter(value="nameFilter")
public class Jackson2Product {
    protected String name;
    protected int id;
    public Jackson2Product() {
    }
    public Jackson2Product(final int id, final String name) {
        this.id = id;
        this.name = name;
    }
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getId() {
        return id;
    }
    public void setId(int id) {
        this.id = id;
    }
}
</programlisting>
@JsonFilter annotates resource class to filter out some property not to serialize in the json response. To map the filter id and instance we need to create another jackson class to add the id and filter instance map:
<programlisting>
<![CDATA[
public class ObjectFilterModifier extends ObjectWriterModifier {
	public ObjectFilterModifier() {
	}
	@Override
	public ObjectWriter modify(EndpointConfigBase<?> endpoint,
			MultivaluedMap<String, Object> httpHeaders, Object valueToWrite,
			ObjectWriter w, JsonGenerator jg) throws IOException {

		FilterProvider filterProvider = new SimpleFilterProvider().addFilter(
				"nameFilter",
				SimpleBeanPropertyFilter.filterOutAllExcept("name"));
		return w.with(filterProvider);

	}
}
]]>
</programlisting>
       Here the method <methodname>modify()</methodname> will take care of filtering all properties except "name" property before write. To make this work, we need let RESTEasy know this mapping info. This can be easily set in a WriterInterceptor using Jackson's <methodname>ObjectWriterInjector</methodname>:
<programlisting>
<![CDATA[
@Provider
public class JsonFilterWriteInterceptor implements WriterInterceptor{

	private ObjectFilterModifier modifier = new ObjectFilterModifier();
	@Override
	public void aroundWriteTo(WriterInterceptorContext context)
			throws IOException, WebApplicationException {
		//set a threadlocal modifier
	    ObjectWriterInjector.set(modifier);
		context.proceed();
	}

}
]]>
</programlisting>
Alternatively, Jackson's documentation suggest doing the same in a servlet filter; that however potentially leads to issues on RESTEasy, as the ObjectFilterModifier ends up being stored using a ThreadLocal object and there's no guarantee the same thread serving the servlet filter will be running the resource endpoint execution too. So, for the servlet filter scenario, RESTEasy offers its own injector that relies on the current thread context classloader for carrying over the specified modifier:
<programlisting>
<![CDATA[
public class ObjectWriterModifierFilter implements Filter {
	private static ObjectFilterModifier modifier = new ObjectFilterModifier();

	@Override
	public void init(FilterConfig filterConfig) throws ServletException {
	}

	@Override
	public void doFilter(ServletRequest request, ServletResponse response,
			FilterChain chain) throws IOException, ServletException {
		ResteasyObjectWriterInjector.set(Thread.currentThread().getContextClassLoader(), modifier);
		chain.doFilter(request, response);
	}

	@Override
	public void destroy() {
	}

}
]]>
</programlisting>
        </para>
    </sect1>

    <sect1 id="Polymorphic_Typing_deserialization">
        <title>Polymorphic Typing deserialization</title>
        <para>
           Due to numerous CVEs for a specific kind of Polymorphic Deserialization (see details in FasterXML Jackson documentation),
            starting from Jackson 2.10 users have a mean to allow only specified classes to be deserialized. RESTEasy
            enables this feature by default and allows controlling the contents of whitelist of allowed classes/packages.

<table frame="topbot">
                <tgroup cols="3" rowsep="1" colsep="1">
                    <thead>
                        <row>
                            <entry>
                                Property
                            </entry>
                            <entry>
                                Description
                            </entry>
                        </row>
                    </thead>
                    <tbody>
                        <row>
                            <entry>
                                resteasy.jackson.deserialization.whitelist.allowIfBaseType.prefix
                            </entry>
                            <entry>
                                Method for appending matcher that will allow all subtypes in cases where nominal base type's class name starts with specific prefix. "*" can be used for allowing any class.
                            </entry>
                        </row>
                        <row>
                            <entry>
                                resteasy.jackson.deserialization.whitelist.allowIfSubType.prefix
                            </entry>
                            <entry>
                                Method for appending matcher that will allow specific subtype (regardless of declared base type) in cases where subclass name starts with specified prefix. "*" can be used for allowing any class.
                            </entry>
                        </row>
                    </tbody>
                </tgroup>
            </table>
        </para>
    </sect1>

</chapter>
