{title:'Marshalling', created:'9.0.0'}

The juneau-marshall library includes easy-to-use and highly customizable serializers and parsers based around a common API. It allows you to marshall Java POJOs directly to and from a wide variety of language types without the need for intermediate Document Object Models making them extremely efficient.

Supported languages include:

- JSON
- XML
- HTML
- UON
- URL-Encoding
- MessagePack
- OpenAPI
- SOAP/XML
- CSV
- YAML (coming soon)
- RDF/XML
- RDF/XML-Abbrev
- N-Triple
- Turtle
- N3

- The marshalling support can be thought of as similar to Jackson except for support of a wide variety of languages. Additionally, JSON marshalling is about 20% faster than Jackson yet supports the same usecases.

The default serializers can often be used to serialize POJOs in a single line of code:

| // A simple bean | public class Person { | public String name = "John Smith"; | public int age = 21; | } | | // Produces: | // "{"name":"John Smith","age":21}" | String json = Json.of(new Person());

Parsing back into POJOs is equally simple for any of the supported languages. Language fragments are also supported.

| // Parse a JSON object as a bean. | String json = "{\"name\":\"John Smith\","\age\":21}"; | Person person = Json.to(json, Person.class);

Marshalling support is provided for a wide variety of POJO types including:

- Primitives and primitive objects
- Beans
- Java Collections Framework objects (e.g. Collections, Maps)
- Arrays
- POJOs

- Pojo Categories for an exhaustive list of categories supported out-of-the-box.

##### Serializer/Parser Builders

Marshallers like the one shown above are pairings of serializers and parsers. Serializers and parsers are builder-based using fluent methods allowing you to quickly create, clone, and modify them in single lines of code.

| // Create a serializer from scratch programmatically using a builder. | JsonSerializer serializer = JsonSerializer | .create() | .simple() // Simple mode | .sq() // Use single quotes | .timeZone(TimeZone.GMT) // For timezone-specific serialization | .locale(Locale.JAPAN) // For locale-specific serialization | .sortCollections() | .sortProperties() | .keepNullProperties() | .trimStrings() | .beanMethodVisibility(PROTECTED) // Control which fields/methods are serialized | .beanDictionary( // Adds type variables for resolution during parsing | MyBeanA.class, | MyBeanB.class | ) | .debug() // Debug mode | .build();

Many POJOs such as primitives, beans, collections, arrays, and classes with various known constructors and methods are serializable out-of-the-box.

Swaps allow you to replace non-serializable objects with serializable equivalents. The {@link oaj.swaps} package contains a variety of predefined swaps.

| // Create a serializer from scratch programmatically using a builder. | JsonSerializer serializer = JsonSerializer | .create() | .swaps( // Swap unserializable classes with surrogate POJOs | IteratorSwap.class, // Iterators swapped with lists | ByteArrayBase64Swap.class, // byte[] swapped with base-64 encoded strings | CalendarSwap.ISO8601DT.class // Calendars swapped with ISO8601-compliant strings | ) | .build();

Any POJO that doesn't fit into the category of a bean/collection/array/primitive and doesn't have a swap associated with it is converted to simple strings. By default, various instance and static methods and constructors on POJO classes are automatically detected and supported for marshalling a POJO to and from a string.

- for more information.

##### Bean Annotations

Beans and POJO classes, methods, fields, and constructors can also be annotated with a variety of annotations to customize how they are marshalled:

| // Sort bean properties by name. | // Exclude city/state from marshalling. | @Bean(sort=true, excludeProperties="city,state") | public class Address { ... } | | // Specify an implementation class for an interface. | @Marshalled(implClass=AutomobileImpl.class) | public interface Automobile { ... }

As a general rule, any capabilities provided by bean annotations can be programmatically specified via the builder APIs. This allows the marshallers to be used equivalently on either your own code that you have access to, or external code where you only have access to binaries.

- Java Beans Support for more information.

##### Configuration Annotations

Serializers and parsers can also be configured using annotations.

| @BeanConfig(sortProperties="true") | @SerializerConfig(quoteChar="'") | @RdfConfig(rdfxml_tab="5", addRootProperty="true") | public class MyAnnotatedClass {...} | | // Create a serializer configured using annotations. | JsonSerializer serializer = JsonSerializer | .create() | .applyAnnotations(MyAnnotatedClass.class) | .build();

Config annotations are extensively used in the REST Servlet APIs to configure how POJOs are marshalled through REST interfaces.

Config variables also support embedded variables for resolving settings at runtime.

| // Sort properties depending on value of system property "sortProperties". | @BeanConfig(sortProperties="$S{sortProperties,false}")

Default values for config settings can be overridden via system properties or environment variables. For example, the system property "BeanContext.sortProperties" or environment variable "BEANCONTEXT_SORTPROPERTIES" can be used to set the default value for the sort properties setting.

Bean annotations can also be programmatically attached to POJOs using config annototations like so:

| @Bean(onClass=Address.class, sort=true, excludeProperties="city,state") | public class MyAnnotatedClass {...}

- Context Annotations for more information.

##### JSON 5 Marshalling

The {@link oaj.json.Json5Serializer} class can be used to serialized POJOs into JSON 5 notation.

JSON 5 is similar to JSON except for the following:

- JSON attributes are only quoted when necessary.
- Uses single-quotes for quoting.

##### Examples:

| // Some free-form JSON. | Map map = JsonMap.of( | "foo", "x1", | "_bar", "x2", | " baz ", "x3", | "123", "x4", | "return", "x5", | "", "x6" | );

| // Serialized to standard JSON | { | "foo": "x1", | "_bar": "x2", | " baz ": "x3", | "123": "x4", | "return": "x5", | "": "x6" | }

// Serialized to JSON 5 | { | foo: 'x1', | _bar: 'x2', | ' baz ': 'x3', // Quoted due to embedded spaces. | '123': 'x4', // Quoted to prevent confusion with number. | 'return': 'x5', // Quoted because it's a keyword. | '': 'x6' // Quoted because it's an empty string. | }

JSON 5 is still valid Javascript. The advantage to simplified JSON is you can represent it in a Java String in minimal form with minimal escaping. This is particularly useful in cases such as unit testing where you can easily validate POJOs by simplifying them to JSON 5 and do a simple string comparison.

| WriterSerializer serializer = Json5Serializer.DEFAULT; | assertString(serializer.toString(myPojo)).is("{foo:'bar',baz:123}");

- JSON 5 for more information.

##### UON Marshalling

The Marshalling API also supports UON (URL-Encoded Object Notation). It allows JSON-like data structures (OBJECT, ARRAY, NUMBER, BOOLEAN, STRING, NULL) in HTTP constructs (query parameters, form parameters, headers, URL parts) without violating RFC2396. This allows POJOs to be converted directly into these HTTP constructs which is not possible in other languages such as JSON.

| ( | id=1, | name='John+Smith', | uri=http://sample/addressBook/person/1, | addressBookUri=http://sample/addressBook, | birthDate=1946-08-12T00:00:00Z, | addresses=@( | ( | uri=http://sample/addressBook/address/1, | personUri=http://sample/addressBook/person/1, | id=1, | street='100+Main+Street', | city=Anywhereville, | state=NY, | zip=12345, | isCurrent=true | ) | ) | )

- UON Details for more information.

##### OpenAPI Marshalling

The Marshalling API also supports schema-based OpenAPI serialization. It allows HTTP parts to be marshalled to-and-from POJOs based on OpenAPI schema definitions.

| import static org.apache.juneau.httpart.HttpPartSchema.*; | | // Schema - Pipe-delimited list of comma-delimited longs. | HttpPartSchema schema = tArrayPipes().items( | tArrayCsv().items( | tInt64() | ) | ).build(); | | // Our value to serialize | Object value = new long[][]{{1,2,3},{4,5,6},{7,8,9}}; | | // Produces "1,2,3|4,5,6|7,8,9" | String output = OpenApi.of(schema, value);

Schema-based serialization and parsing is used heavily in both the server and client REST APIs with built-in schema validations support in various HTTP part annotations.

| // REST server method with HTTP parts using schema validation. | @RestGet | public void doGet( | @Query(name="myParam", schema=@Schema(min=1, max=32)) int myParam, | @Header("MyHeader", schema=@Schema(pattern="foo.*")) String p2 | ) {...}

- OpenAPI Details for more information.

##### JsonMap/JsonList

The {@link oaj.collections.JsonMap} and {@link oaj.collections.JsonList} collections classes allow you to programmatically build generic JSON data structures. They are similar in concept to JSONObject and JSONArray that you find in other JSON marshalling APIs but can be used to generate DOMs in any of the supported languages.

| // Create JSON strings from scratch using fluent-style code. | String myMap = JsonMap.create().append("foo","bar").asJson(); | String myList = JsonList.of("foo", 123, null, jsonObject).asJson(); | | // Parse directly from JSON into generic DOMs. | Map<String,Object> myMap = JsonMap.ofJson("{foo:'bar'}"); | List<Object> myList = JsonList.ofJson("['foo',123,null]");

These classes provide lots of convenience methods including:

- Methods for direct marshalling to/from any of the other supported languages.
- Methods for quick conversions to other data types including collections, beans, arrays, etc...

- JsonMap and JsonList for more information.

##### Serializer and Parser Sets

{@link oaj.serializer.SerializerSet} and {@link oaj.parser.ParserSet} classes allow serializers and parsers to be retrieved by W3C-compliant HTTP `Accept` and `Content-Type` values:

| // Construct a new serializer group with configuration parameters that get applied | // to all serializers. | SerializerSet serializerSet = SerializerSet | .create() | .add(JsonSerializer.class, UrlEncodingSerializer.class); | .forEach(x -> x.swaps(CalendarSwap.ISO8601DT.class)) | .forEachWS(x -> x.useWhitespace()) | .build(); | | // Find the appropriate serializer by Accept type and serialize our POJO to the specified writer. | // Fully RFC2616 compliant. | serializerSet | .getSerializer("text/invalid, text/json;q=0.8, text/*;q:0.6, *\/*;q=0.0") | .serialize(person, myWriter); | | // Construct a new parser group with configuration parameters that get applied to all parsers. | ParserSet parserSet = ParserSet | .create() | .add(JsonParser.class, UrlEncodingParser.class); | .forEach(x -> x.swaps(CalendarSwap.ISO8601DT.class)) | .build(); | | Person person = parserSet | .getParser("text/json") | .parse(myReader, Person.class);

- SerializerSets and ParserSets for more information.

##### SVL Variables

The {@link oaj.svl} package defines an API for a language called "Simple Variable Language". In a nutshell, Simple Variable Language (or SVL) is text that contains variables of the form "$varName{varKey}".

Variables can be recursively nested within the varKey (e.g. "$FOO{$BAR{xxx},$BAZ{xxx}}"). Variables can also return values that themselves contain more variables.

| // Use the default variable resolver to resolve a string that | // contains $S (system property) variables | String myProperty = VarResolver.DEFAULT.resolve("The Java home directory is $S{java.home}");

The SVL variables are used widely throughout various annotations defined in Juneau allowing many features to be configured via external sources such as configuration files or environment variables/system properties. The SVL APIs are extensible allowing for the addition of new types of variables.

- Simple Variable Language for more information.