blob: 2760f6c1908f98ab8322da12f9d89238fc356884 [file] [log] [blame]
<!DOCTYPE html>
<!--
| Generated by Apache Maven Doxia Site Renderer 1.9.2 from xdocs/index.xml at 20 September 2021
| Rendered using Apache Maven Fluido Skin 1.9
-->
<html xmlns="http://www.w3.org/1999/xhtml" lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<meta name="generator" content="Apache Maven Doxia Site Renderer 1.9.2" />
<meta name="author" content="Georg Kallidis" />
<title>Fulcrum JSON Component Service &#x2013; JSON Component</title>
<link rel="stylesheet" href="./css/apache-maven-fluido-1.9.min.css" />
<link rel="stylesheet" href="./css/site.css" />
<link rel="stylesheet" href="./css/print.css" media="print" />
<script src="./js/apache-maven-fluido-1.9.min.js"></script>
</head>
<body class="topBarDisabled">
<div class="container-fluid">
<header>
<div id="banner">
<div class="pull-left"><a href="https://turbine.apache.org/" id="bannerLeft" title="Apache Turbine"><img src="https://turbine.apache.org/images/turbine-project.png" alt="Apache Turbine"/></a></div>
<div class="pull-right"></div>
<div class="clear"><hr/></div>
</div>
<div id="breadcrumbs">
<ul class="breadcrumb">
<li id="publishDate">Last Published: 20 September 2021<span class="divider">|</span>
</li>
<li id="projectVersion">Version: 2.0.2-SNAPSHOT</li>
<li class="pull-right"><span class="divider">|</span>
<a href="https://turbine.apache.org/fulcrum/" class="externalLink" title="Fulcrum">Fulcrum</a></li>
<li class="pull-right"><span class="divider">|</span>
<a href="https://turbine.apache.org/" class="externalLink" title="Turbine">Turbine</a></li>
<li class="pull-right"><a href="https://www.apache.org" class="externalLink" title="Apache">Apache</a></li>
</ul>
</div>
</header>
<div class="row-fluid">
<header id="leftColumn" class="span2">
<nav class="well sidebar-nav">
<ul class="nav nav-list">
<li class="nav-header">Overview</li>
<li class="active"><a href="#"><span class="none"></span>Main</a></li>
<li class="nav-header">Modules</li>
<li><a href="fulcrum-json-api/index.html" title="Fulcrum JSON API"><span class="none"></span>Fulcrum JSON API</a></li>
<li><a href="fulcrum-json-gson/index.html" title="Fulcrum JSON GSON Impl"><span class="none"></span>Fulcrum JSON GSON Impl</a></li>
<li><a href="fulcrum-json-jackson2/index.html" title="Fulcrum JSON Jackson 2.x Impl"><span class="none"></span>Fulcrum JSON Jackson 2.x Impl</a></li>
<li><a href="fulcrum-json-dist/index.html" title="Fulcrum JSON Jar Distribution"><span class="none"></span>Fulcrum JSON Jar Distribution</a></li>
<li class="nav-header">Project Documentation</li>
<li><a href="project-info.html" title="Project Information"><span class="icon-chevron-down"></span>Project Information</a>
<ul class="nav nav-list">
<li><a href="dependencies.html" title="Dependencies"><span class="none"></span>Dependencies</a></li>
<li><a href="dependency-convergence.html" title="Dependency Convergence"><span class="none"></span>Dependency Convergence</a></li>
<li><a href="dependency-info.html" title="Dependency Information"><span class="none"></span>Dependency Information</a></li>
<li><a href="distribution-management.html" title="Distribution Management"><span class="none"></span>Distribution Management</a></li>
<li class="active"><a href="#"><span class="none"></span>About</a></li>
<li><a href="issue-management.html" title="Issue Management"><span class="none"></span>Issue Management</a></li>
<li><a href="licenses.html" title="Licenses"><span class="none"></span>Licenses</a></li>
<li><a href="mailing-lists.html" title="Mailing Lists"><span class="none"></span>Mailing Lists</a></li>
<li><a href="modules.html" title="Project Modules"><span class="none"></span>Project Modules</a></li>
<li><a href="plugin-management.html" title="Plugin Management"><span class="none"></span>Plugin Management</a></li>
<li><a href="plugins.html" title="Plugins"><span class="none"></span>Plugins</a></li>
<li><a href="scm.html" title="Source Code Management"><span class="none"></span>Source Code Management</a></li>
<li><a href="summary.html" title="Summary"><span class="none"></span>Summary</a></li>
<li><a href="team.html" title="Team"><span class="none"></span>Team</a></li>
</ul></li>
<li><a href="project-reports.html" title="Project Reports"><span class="icon-chevron-right"></span>Project Reports</a></li>
<li class="nav-header">Apache</li>
<li><a href="https://www.apache.org/" class="externalLink" title="Apache Website"><span class="none"></span>Apache Website</a></li>
<li><a href="https://www.apache.org/licenses/" class="externalLink" title="License"><span class="none"></span>License</a></li>
<li><a href="https://www.apache.org/foundation/how-it-works.html" class="externalLink" title="How the ASF works"><span class="none"></span>How the ASF works</a></li>
<li><a href="https://www.apache.org/foundation/sponsorship.html" class="externalLink" title="Sponsorship"><span class="none"></span>Sponsorship</a></li>
<li><a href="https://www.apache.org/foundation/thanks.html" class="externalLink" title="Thanks"><span class="none"></span>Thanks</a></li>
<li><a href="https://www.apache.org/security/" class="externalLink" title="Security"><span class="none"></span>Security</a></li>
</ul>
</nav>
<div class="well sidebar-nav">
<hr />
<div id="poweredBy">
<div class="clear"></div>
<div class="clear"></div>
<div class="clear"></div>
<a href="http://maven.apache.org/" title="Built by Maven" class="poweredBy"><img class="builtBy" alt="Built by Maven" src="./images/logos/maven-feather.png" /></a>
</div>
</div>
</header>
<main id="bodyColumn" class="span10" >
<section>
<h2><a name="Overview"></a>Overview</h2>
<p>The intent of this component is to provide a configurable and customized integration of JSON De-/Serializers using <a class="externalLink" href="https://github.com/google/gson/">GSON</a>, <a class="externalLink" href="http://wiki.fasterxml.com/JacksonHome">Jackson 1 and Jackson 2 APIs</a> into Avalon/Turbine. It is a common pattern with client-side MVC applications to embed data for a base set of objects in a page instead of making a separate AJAX request to load them.
It is written for use in Turbine but it can be used in any container compatible
with Avalon's ECM container. There are three implementations
</p>
<ul>
<li>GSONBuilderService and</li>
<li>Jackson2MapperService</li>
<li>JacksonMapperService</li>
</ul>
All Services provide basic serialization and deserialization functions for applications. Additional (optional) Features:
<ul>
<li>Support for <a class="externalLink" href="https://github.com/json-path/JsonPath/blob/master/README.md">JsonPath</a> in Gson and Jackson 2</li>
<li>Support for <a class="externalLink" href="https://github.com/FasterXML/jackson-datatype-json-org">org.json mapping</a> (as registered module or adapter)</li>
</ul>
</section>
<section>
<h2><a name="JSON_Service_Component_with_Jackson_1_.2F_2_API"></a>JSON Service Component with Jackson 1 / 2 API</h2>
<section>
<h3><a name="Overview"></a>Overview</h3>
<p>
This Service serves as a JSON serializer or deserializer using <a class="externalLink" href="https://github.com/FasterXML/jackson">Jackson</a> Version 2 or Version 1.
The JSON Jackson 2 sub module is the most elaborated of the three sub modules. It provides attribute and class filtering and cache cleaning mechanism.
</p>
<p>
It is written for use in Turbine but it can be used in any container compatible
with Avalon's ECM container.
</p>
</section>
<section>
<h3><a name="Role_Configuration"></a>Role Configuration</h3>
<p>Jackson Version 2.7.x</p>
<div class="source"><pre class="prettyprint">
&lt;role
name=&quot;org.apache.fulcrum.json.JsonService&quot;
shorthand=&quot;json&quot;
default-class=&quot;org.apache.fulcrum.json.jackson.Jackson2MapperService&quot;/&gt;
</pre></div>
<p>Jackson Version 1.9.13</p>
<div class="source"><pre class="prettyprint">
&lt;role
name=&quot;org.apache.fulcrum.json.JsonService&quot;
shorthand=&quot;json&quot;
default-class=&quot;org.apache.fulcrum.json.jackson.JacksonMapperService&quot;/&gt;
</pre></div>
</section>
<a name="compconf"></a><section id="compconf">
<h3><a name="Component_Configuration"></a>Component Configuration</h3>
<table border="0" class="table table-striped">
<tr class="a">
<th>Item</th>
<th>Datatype</th>
<th>Cardinality</th>
<th>Description</th>
</tr>
<tr class="b">
<td>annotationInspectors</td>
<td>Complex</td>
<td>[0|1]</td>
<td>
If empty <code>com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector</code> is set as annotation introspector. You could otherwise provide a primary and (optionally) a secondary introspector. Setting the special introspector <code>org.apache.fulcrum.json.jackson.SimpleNameIntrospector</code> yields property and class name based filtering. See the configuration example below and in <a href="#velocity">section Usage in Velocity Template</a>. Features could be set to <code>false</code> or <code>true</code> by setting the attribute <b>value</b> of the sub element feature. The feature attribute <b>type</b> should be the class name of any sub interface of <code>com.fasterxml.jackson.databind.cfg.ConfigFeature</code>. The element content itself defines any feature (enum value) for this feature. Cft. the configuration example below.
</td>
</tr>
<tr class="a">
<td>dateFormat</td>
<td>String</td>
<td>[0|*]</td>
<td>
If set changes the date format. The provided string should be in a format acceptable to the class <code>java.text.SimpleDateFormat.SimpleDateFormat(String)</code>. The default value is
<code>MM/dd/yyyy</code>.
</td>
</tr>
<tr class="b">
<td>defaultTyping</td>
<td>String</td>
<td>[0|*]</td>
<td>
The default is no defaultTyping. Otherwise set it to a Jackson 2 enum value in class <code>com.fasterxml.jackson.databind.ObjectMapper.DefaultTyping</code>.
</td>
</tr>
<tr class="a">
<td>cacheFilters</td>
<td>boolean</td>
<td>[0|*]</td>
<td>
If set to <code>true</code>, caching is enabled. Each filter applied remains valid and is not removed.
This implicits, that you cannot retrieve for the same class/bean different properties in different calls.
Otherwise different serializations per call are possible. You could invalidate (refresh) the cache per class, in most methods providing a Boolean parameter, cft. method parameters named <code>refresh*</code> or <code>clean*</code>. The default value is <code>true</code>.
</td>
</tr>
<tr class="b">
<td>escapeCharsGlobal</td>
<td>boolean</td>
<td>[0|1]</td>
<td>
If set to <code>true</code>, by default ASCII characters &lt;= 32 character code and the four characters '&lt;','&gt;','&amp;','\' (backslash) are escaped using com.fasterxml.jackson.core.io.CharacterEscapes.ESCAPE_STANDARD ('\u'). for details cft. com.fasterxml.jackson.core.io.CharTypes. The default value is <code>false</code>.
</td>
</tr>
<tr class="a">
<td>useJsonPath</td>
<td>boolean</td>
<td>[0|1]</td>
<td>
If set to <code>true</code>, JsonPath is enabled, which allows to apply JsonPath expressions using the integrated jackson provider by default (without setting this property to <code>true</code>, com.jayway.jsonpath.spi.mapper.JsonSmartMappingProvider will be used and would need to implement net.minidev.json.writer.JsonReaderI by default - which would fail as net.minidev.json package is excluded from dependencies; you would need to include this transitive dependency manually). The default value is <code>false</code>.
</td>
</tr>
</table>
</section>
<section>
<h3><a name="Component_Configuration_Example"></a>Component Configuration Example</h3>
<p>Jackson Version 2.x</p>
<div class="source"><pre class="prettyprint">
&lt;json&gt;
&lt;annotationInspectors&gt;
&lt;primary&gt;org.apache.fulcrum.json.jackson.SimpleNameIntrospector&lt;/primary&gt;
&lt;secondary&gt;com.fasterxml.jackson.databind.introspect.JacksonAnnotationIntrospector&lt;/secondary&gt;
&lt;features&gt;
&lt;feature value=&quot;false&quot; type=&quot;com.fasterxml.jackson.databind.SerializationFeature&quot;&gt;FAIL_ON_EMPTY_BEANS&lt;/feature&gt;
&lt;feature value=&quot;false&quot; type=&quot;com.fasterxml.jackson.databind.DeserializationFeature&quot;&gt;EAGER_DESERIALIZER_FETCH&lt;/feature&gt;
&lt;!-- do not fail of only getter is provided --&gt;
&lt;feature value=&quot;false&quot; type=&quot;com.fasterxml.jackson.databind.DeserializationFeature&quot;&gt;FAIL_ON_UNKNOWN_PROPERTIES&lt;/feature&gt;
&lt;feature value=&quot;false&quot; type=&quot;com.fasterxml.jackson.databind.MapperFeature&quot;&gt;ALLOW_FINAL_FIELDS_AS_MUTATORS&lt;/feature&gt;
&lt;feature value=&quot;true&quot; type=&quot;com.fasterxml.jackson.core.JsonParser&quot;&gt;ALLOW_UNQUOTED_FIELD_NAMES&lt;/feature&gt;
&lt;!-- feature value=&quot;true&quot;&gt;com.fasterxml.jackson.databind.SerializationFeature.INDENT_OUTPUT&lt;/feature--&gt;
&lt;/features&gt;
&lt;/annotationInspectors&gt;
&lt;dateFormat&gt;MM/dd/yyyy&lt;/dateFormat&gt;
&lt;defaultTyping type=&quot;NON_FINAL&quot; key=&quot;type&quot;/&gt;&lt;!-- or e.g. OBJECT_AND_NON_CONCRETE --&gt;
&lt;!-- cacheFilters&gt;false&lt;/cacheFilters --&gt;
&lt;!-- &lt;escapeCharsGlobal&gt;true&lt;/escapeCharsGlobal&gt; --&gt;
&lt;useJsonPath&gt;true&lt;/useJsonPath&gt;
&lt;/json&gt;
</pre></div>
<p>Jackson Version 1.9.x</p>
<div class="source"><pre class="prettyprint">
&lt;json&gt;
&lt;annotationInspectors&gt;
&lt;primary&gt;org.apache.fulcrum.json.jackson.CustomIntrospector&lt;/primary&gt;
&lt;secondary&gt;org.codehaus.jackson.xc.JaxbAnnotationIntrospector&lt;/secondary&gt;
&lt;features&gt;
&lt;!-- support up to now only serializing features --&gt;
&lt;feature value=&quot;false&quot;&gt;org.codehaus.jackson.map.SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS&lt;/feature&gt;
&lt;!-- feature value=&quot;true&quot;&gt;org.codehaus.jackson.map.SerializationConfig.Feature.INDENT_OUTPUT&lt;/feature--&gt;
&lt;/features&gt;
&lt;/annotationInspectors&gt;
&lt;dateFormat&gt;MM/dd/yyyy&lt;/dateFormat&gt;
&lt;!-- defaultTyping type=&quot;OBJECT_AND_NON_CONCRETE&quot; key=&quot;type&quot;/--&gt;
&lt;!-- cacheFilters&gt;false&lt;/cacheFilters--&gt;
&lt;/json&gt;
</pre></div>
</section>
<section>
<h3><a name="Usage"></a>Usage</h3>
<p>
You get a JSON service from the service like this:
</p>
<div class="source"><pre class="prettyprint">
JsonService jsonService = (JsonService)TurbineServices
.getInstance().getService(JsonService.ROLE);
</pre></div>
</section>
<a name="velocity"></a><section id="velocity">
<h3><a name="Usage_in_Velocity_Template:_Serialization_Example"></a>Usage in Velocity Template: Serialization Example</h3>
<p>
A lot of client data is nowadays provided by javascript and usage of Model-View-View Model (MVVM) frameworks is very popular. Having the required data in JSON format would be of some help.
Velocity provides the integration of Java objects into templates (HTML). To generate in this context
the data which should be exposed into Javascript you could integrate the provided serialization methods here, in the velocity context. As an example, you could provide it via the Turbine Pull service:
</p>
<div class="source"><pre class="prettyprint">
public Object getJson(Object src, String className, Boolean refresh, String... props ) {
String result= null;
try
{
Class clazz = Class.forName(className);
result = jsonService.serializeOnlyFilter( src, clazz, refresh, props );
}
catch ( Exception e )
{
log.error(e.getMessage(),e );
}
return result;
}
</pre></div>
You could then call the JSON method from this tool in a velocity template like this:
<div class="source"><pre class="prettyprint">
#set ($json = $!pullTool.getJson($items, &quot;x.y.z.Item&quot;, true, &quot;prop1&quot;, &quot;prop2&quot;, &quot;prop3&quot; ) )
## parse json in javascript ....
</pre></div>
What you get is the JSON data populated with all fields you provided (starting with the fourth parameter). Th result format may vary depending on the serialization parameters. The third parameter being true will cache not the result, but the call characteristics i.e. the parameters used for the serialization of the provided class.
<section>
<h4><a name="Configuration_Requirements"></a>Configuration Requirements</h4>
<p>
Add <code>org.apache.fulcrum.json.jackson.SimpleNameIntrospector</code> to the annotation inspectors as primary or secondary inspector. <b>[CHANGE in Version 1.1.0]:</b> SimpleNameIntrospector now extends from <a class="externalLink" href="https://github.com/FasterXML/jackson-databind/blob/master/src/main/java/com/fasterxml/jackson/databind/introspect/NopAnnotationIntrospector.java">NopAnnotationIntrospector</a> to cleary divide responsibilities. Default introspector e.g. JacksonAnnotationIntrospector could be provided as a primary/secondary introspector in <a href="#compconf">Component Configuration</a>.
</p>
</section></section>
<a name="deser"></a><section id="deser">
<h3><a name="JSON_to_Object_Deserialization"></a>JSON to Object Deserialization</h3>
<p>
This could be done by providing the JSON data as client parameter to a JSON-RPC-Service function (cft. services-&gt;JSON-RPC-Service). As an example consider this:
</p>
<div class="source"><pre class="prettyprint">
// class is registered in screen
public &lt;T&gt; void deSerJsonItem(String src ) {
try
{
Item result = jsonService.deSer( src, Item.class );
// do something with result
}
catch ( Exception e )
{
log.error(e.getMessage(),e );
}
}
}
</pre></div>
You could then call the JSON method in a Javascript section like this:
<div class="source"><pre class="prettyprint">
jsonrpc.myFunctions.deSerJsonItem( JSON.stringify(jsonitem) );
</pre></div>
</section>
</section>
<section>
<h2><a name="JSON_Service_Component_with_GSON_API"></a>JSON Service Component with GSON API</h2>
<section>
<h2><a name="Overview"></a>Overview</h2>
<p>
This Service serves as a JSON serializer or deserializer using <a class="externalLink" href="https://code.google.com/p/google-gson/">GSON</a> Version 2.3.1
The GSON sub module provides some include/exclude filtering strategies.
</p>
<p>
It is written for use in Turbine but it can be used in any container compatible
with Avalon's ECM container.
</p>
</section>
<section>
<h3><a name="Role_Configuration"></a>Role Configuration</h3>
<div class="source"><pre class="prettyprint">
&lt;role
name=&quot;org.apache.fulcrum.json.JsonService&quot;
shorthand=&quot;json&quot;
default-class=&quot;org.apache.fulcrum.json.gson.GSONBuilderService&quot;/&gt;
</pre></div>
</section>
<section>
<h3><a name="Component_Configuration"></a>Component Configuration</h3>
<table border="0" class="table table-striped">
<tr class="a">
<th>Item</th>
<th>Datatype</th>
<th>Cardinality</th>
<th>Description</th>
</tr>
<tr class="b">
<td>globalAdapters</td>
<td>Complex</td>
<td>[0|1]</td>
<td>
If not set no adapter is set. Otherwise provide for each sub element <code>adapter</code> the class name of the adapter and set the attribute <code>forClass</code> to the class name the adapter should be applied. See the configuration example below.
</td>
</tr>
<tr class="a">
<td>dateFormat</td>
<td>String</td>
<td>[0|*]</td>
<td>
If set changes the date format. Provided string should be in a Format acceptable to the class <code>java.text.SimpleDateFormat.SimpleDateFormat(String)</code>. The default value is
<code>MM/dd/yyyy</code>.
</td>
</tr>
<tr class="b">
<td>useJsonPath</td>
<td>boolean</td>
<td>[0|1]</td>
<td>
If set to <code>true</code>, JsonPath is enabled, which allows to apply JsonPath expressions using the integrated gson provider by default. The default value is <code>false</code>. For more information see jackson2 component configuration property description.
</td>
</tr>
</table>
</section>
<section>
<h3><a name="Component_Configuration_Example"></a>Component Configuration Example</h3>
<div class="source"><pre class="prettyprint">
&lt;json&gt;
&lt;dateFormat&gt;MM/dd/yyyy&lt;/dateFormat&gt;
&lt;globalAdapters&gt;&gt;
&lt;adapter forClass=&quot;x.y.z.Class&quot;&gt;a.b.c.d.AdapterForClassXYZ&lt;/adapter--&gt;
&lt;/globalAdapters&gt;
&lt;useJsonPath&gt;true&lt;/useJsonPath&gt;
&lt;/json&gt;
</pre></div>
</section>
<section>
<h3><a name="Usage"></a>Usage</h3>
<p>
You get a JSON service from the service like this:
</p>
<div class="source"><pre class="prettyprint">
JsonService jsonService = (JsonService)TurbineServices
.getInstance().getService(JsonService.ROLE);
</pre></div>
<p>
</p>
</section>
</section>
</main>
</div>
</div>
<hr/>
<footer>
<div class="container-fluid">
<div class="row-fluid">
<p>&#169; 2011&#x2013;2021
<a href="https://www.apache.org/">The Apache Software Foundation</a>
</p>
</div>
</div>
</footer>
</body>
</html>