| = TomEE and JSON |
| :jbake-date: 2016-03-16 |
| :jbake-type: page |
| :jbake-status: published |
| :jbake-tomeepdf: |
| |
| Since TomEE 7.0, TomEE comes with Apache Johnzon. |
| It means you can use JSON-P out of the box but also Johnzon Mapper |
| which is the default JAX-RS provider for JSON. |
| |
| IMPORTANT: this is a breaking change with 1.x which was using jettison. |
| This last one was relying on JAXB model to generate JSON which often led |
| to unexpected JSON tree and some unexpected escaping too. |
| |
| == Getting started with Johnzon Mapper |
| |
| http://johnzon.apache.org/ will get more informations than this quick |
| getting started but here are the basics of the mapping with Johnzon. |
| |
| The mapper uses a direct java to json representation. |
| |
| For instance this java bean: |
| |
| [source,java] |
| ---- |
| public class MyModel { |
| private int id; |
| private String name; |
| |
| // getters/setters |
| } |
| ---- |
| |
| will be mapped to: |
| |
| [source,java] |
| ---- |
| { |
| "id": 1234, |
| "name": "Johnzon doc" |
| } |
| ---- |
| |
| Note that Johnzon supports several customization either directly on the MapperBuilder of through annotations. |
| |
| === @JohnzonIgnore |
| |
| @JohnzonIgnore is used to ignore a field. You can optionally say you ignore the field until some version |
| if the mapper has a version: |
| |
| [source,java] |
| ---- |
| public class MyModel { |
| @JohnzonIgnore |
| private String name; |
| |
| // getters/setters |
| } |
| ---- |
| |
| Or to support name for version 3, 4, ... but ignore it for 1 and 2: |
| |
| |
| [source,java] |
| ---- |
| public class MyModel { |
| @JohnzonIgnore(minVersion = 3) |
| private String name; |
| |
| // getters/setters |
| } |
| ---- |
| |
| === @JohnzonConverter |
| |
| Converters are used for advanced mapping between java and json. |
| |
| There are several converter types: |
| |
| 1. Converter: map java to json and the opposite based on the string representation |
| 2. Adapter: a converter not limited to String |
| 3. ObjectConverter.Reader: to converter from json to java at low level |
| 4. ObjectConverter.Writer: to converter from java to json at low level |
| 4. ObjectConverter.Codec: a Reader and Writer |
| |
| The most common is to customize date format but they all take. For that simple case we often use a Converter: |
| |
| [source,java] |
| ---- |
| public class LocalDateConverter implements Converter<LocalDate> { |
| @Override |
| public String toString(final LocalDate instance) { |
| return instance.toString(); |
| } |
| |
| @Override |
| public LocalDate fromString(final String text) { |
| return LocalDate.parse(text); |
| } |
| } |
| ---- |
| |
| If you need a more advanced use case and modify the structure of the json (wrapping the value for instance) |
| you will likely need Reader/Writer or a Codec. |
| |
| Then once your converter developed you can either register globally on the MapperBuilder or simply decorate |
| the field you want to convert with @JohnzonConverter: |
| |
| [source,java] |
| ---- |
| public class MyModel { |
| @JohnzonConverter(LocalDateConverter.class) |
| private LocalDate date; |
| |
| // getters/setters |
| } |
| ---- |
| |
| === @JohnzonProperty |
| |
| Sometimes the json name is not java friendly (_foo or foo-bar or even 200 for instance). For that cases |
| @JohnzonProperty allows to customize the name used: |
| |
| [source,java] |
| ---- |
| public class MyModel { |
| @JohnzonProperty("__date") |
| private LocalDate date; |
| |
| // getters/setters |
| } |
| ---- |
| |
| === AccessMode |
| |
| On MapperBuilder you have several AccessMode available by default but you can also create your own one. |
| |
| The default available names are: |
| |
| * field: to use fields model and ignore getters/setters |
| * method: use getters/setters (means if you have a getter but no setter you will serialize the property but not read it) |
| * strict-method (default based on Pojo convention): same as method but getters for collections are not used to write |
| |
| You can use these names with setAccessModeName(). |
| |
| === Your own mapper |
| |
| Since johnzon is in tomee libraries you can use it yourself (if you use maven/gradle set johnzon-mapper as provided): |
| |
| [source,java] |
| ---- |
| final MySuperObject object = createObject(); |
| |
| final Mapper mapper = new MapperBuilder().build(); |
| mapper.writeObject(object, outputStream); |
| |
| final MySuperObject otherObject = mapper.readObject(inputStream, MySuperObject.class); |
| ---- |
| |
| == Johnzon and JAX-RS |
| |
| TomEE uses by default Johnzon as JAX-RS provider for versions 7.x. If you want however to customize it you need to follow this procedure: |
| |
| 1. Create a WEB-INF/openejb-jar.xml: |
| |
| [source,xml] |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <openejb-jar> |
| <pojo-deployment class-name="jaxrs-application"> |
| <properties> |
| # optional but requires to skip scanned providers if set to true |
| cxf.jaxrs.skip-provider-scanning = true |
| # list of providers we want |
| cxf.jaxrs.providers = johnzon,org.apache.openejb.server.cxf.rs.EJBAccessExceptionMapper |
| </properties> |
| </pojo-deployment> |
| </openejb-jar> |
| ---- |
| |
| 2. Create a WEB-INF/resources.xml to define johnzon service which will be use to instantiate the provider |
| |
| [source,xml] |
| ---- |
| <?xml version="1.0" encoding="UTF-8"?> |
| <resources> |
| <Service id="johnzon" class-name="org.apache.johnzon.jaxrs.ConfigurableJohnzonProvider"> |
| # 1M |
| maxSize = 1048576 |
| bufferSize = 1048576 |
| |
| # ordered attributes |
| attributeOrder = $order |
| |
| # Additional types to ignore |
| ignores = org.apache.cxf.jaxrs.ext.multipart.MultipartBody |
| </Service> |
| |
| <Service id="order" class-name="com.company.MyAttributeSorter" /> |
| |
| </resources> |
| ---- |
| |
| Note: as you can see you mainly just need to define a service with the id johnzon (same as in openejb-jar.xml) |
| and you can reference other instances using $id for services and @id for resources. |
| |