blob: 4aad512733471d2c636a9ac37a4a882572f6ada5 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Google Tag Manager -->
<script>(function(w,d,s,l,i){w[l]=w[l]||[];w[l].push({'gtm.start':
new Date().getTime(),event:'gtm.js'});var f=d.getElementsByTagName(s)[0],
j=d.createElement(s),dl=l!='dataLayer'?'&l='+l:'';j.async=true;j.src=
'https://www.googletagmanager.com/gtm.js?id='+i+dl;f.parentNode.insertBefore(j,f);
})(window,document,'script','dataLayer','GTM-MT3PBTF');</script>
<!-- End Google Tag Manager -->
<style>
@import url("styles/juneau-code.css");
@import url("styles/juneau-doc.css");
</style>
</head>
<body>
<!-- Google Tag Manager (noscript) -->
<noscript><iframe src="https://www.googletagmanager.com/ns.html?id=GTM-MT3PBTF"
height="0" width="0" style="display:none;visibility:hidden"></iframe></noscript>
<!-- End Google Tag Manager (noscript) -->
<!-- ======================================================================================================= -->
<!-- === JUNEAU-MARSHALL =================================================================================== -->
<!-- ======================================================================================================= -->
<h5 class='toc' id='juneau-marshall'>juneau-marshall</h5>
<div>
<h5 class='figure'>Maven Dependency</h5>
<p class='bcode w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-marshall<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>8.1.2<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-marshall-8.1.2.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.marshall_8.1.2.jar
</p>
<p>
The <code>juneau-marshall</code> library includes easy-to-use and highly customizable serializers and parsers
based around a common API.
They provide support for the following languages:
</p>
<ul>
<li>JSON
<li>XML
<li>HTML
<li>UON (URL-Encoded Object Notation)
<li>URL-Encoding
<li>MessagePack
<li>SOAP/XML
<li>CSV
<li>OpenAPI (work-in-progress)
<li>BSON (coming soon)
<li>YAML (coming soon)
<li>Protobuf (coming soon)
<li>Amazon Ion (coming soon)
</ul>
<h5 class='section'>Features:</h5>
<ul class='spaced-list'>
<li>Serializers can send output directly to Writers, OutputStreams, Files, Strings, or byte arrays.
<li>Parsers can receive input directly from Readers, InputStreams, Files, Strings, or byte arrays.
<li>Parsers can reconstruct arbitrarily complex data structures consisting of maps, collections, beans, and other POJOs.
<li>Serializers and parsers do not use intermediate DOMs! POJOs are serialized directly to streams and parsed back directly to POJOs, making them extremely efficient and fast.
<li>Supported languages are highly-customizable and powerful. For example, JSON support includes:
<ul>
<li>Support for variants such as LAX syntax (unquoted attributes and single quotes).
<li>Support for embedded Javascript comments.
<li>Fully RFC1759 compliant.
<li>20% faster than Jackson.
</ul>
</ul>
<hr>
<p>
The default serializers can often be used to serialize POJOs in a single line of code:
</p>
<p class='bcode w800'>
<jc>// A simple bean</jc>
<jk>public class</jk> Person {
<jk>public</jk> String name = <js>"John Smith"</js>;
<jk>public int</jk> age = 21;
}
Person p = <jk>new</jk> Person(); <jc>// An arbitrary POJO</jc>
<jc>// Produces:
// "{name:'John Smith',age:21}"</jc>
String laxJson = SimpleJsonSerializer.<jsf>DEFAULT</jsf>.serialize(p);
<jc>// Produces:
// "{"name":"John Smith","age":21}"</jc>
String strictJson = JsonSerializer.<jsf>DEFAULT</jsf>.serialize(p);
<jc>// Produces:
// &lt;object&gt;
// &lt;name&gt;John Smith&lt;/name&gt;
// &lt;age&gt;21&lt;/age&gt;
// &lt;/object&gt;</jc>
String xml = XmlSerializer.<jsf>DEFAULT</jsf>.serialize(p);
<jc>// Produces:
// &lt;table&gt;
// &lt;tr&gt;&lt;td&gt;name&lt;/td&gt;&lt;td&gt;John Smith&lt;/td&gt;&lt;/tr&gt;
// &lt;tr&gt;&lt;td&gt;age&lt;/td&gt;&lt;td&gt;21&lt;/td&gt;&lt;/tr&gt;
// &lt;/table&gt;</jc>
String html = HtmlSerializer.<jsf>DEFAULT</jsf>.serialize(p);
<jc>// Same as Html, but wraps it in HTML and BODY elements with page title/description/links:</jc>
String htmlDoc = HtmlDocSerializer.<jsf>DEFAULT</jsf>.serialize(p);
<jc>// Produces:
// name='John+Smith'&amp;age=21</jc>
String urlEncoding = UrlEncodingSerializer.<jsf>DEFAULT</jsf>.serialize(p);
<jc>// Produces:
// (name='John Smith',age=21)</jc>
String uon = UonSerializer.<jsf>DEFAULT</jsf>.serialize(p);
<jc>// Produces:
// 82 A4 name AA 4A John Smith 68 A3 age 15</jc>
<jk>byte</jk>[] messagePack = MsgPackSerializer.<jsf>DEFAULT</jsf>.serialize(p);
</p>
<h5 class='section'>More Information:</h5>
<ul class='doctree'>
<li><a class='doclink' href='http://juneau.apache.org/site/apidocs-8.1.2/overview-summary.html#juneau-marshall.Serializers'>juneau-marshall > Serializers</a>
</ul>
<hr>
<p>
Parsing back into POJOs is equally simple for any of the supported languages shown above.
Language fragments are also supported.
</p>
<p>
JSON parsing shown here:
</p>
<p class='bcode w800'>
<jc>// Use one of the predefined parsers.</jc>
ReaderParser parser = JsonParser.<jsf>DEFAULT</jsf>;
<jc>// Parse a JSON object (creates a generic ObjectMap).</jc>
String json = <js>"{name:'John Smith',age:21}"</js>;
Map m1 = parser.parse(json, Map.<jk>class</jk>);
<jc>// Parse a JSON string.</jc>
json = <js>"'foobar'"</js>;
String s2 = parser.parse(json, String.<jk>class</jk>);
<jc>// Parse a JSON number as a Long or Float.</jc>
json = <js>"123"</js>;
Long l3 = parser.parse(json, Long.<jk>class</jk>);
Float f3 = parser.parse(json, Float.<jk>class</jk>);
<jc>// Parse a JSON object as a bean.</jc>
json = <js>"{name:'John Smith',age:21}"</js>;
Person p4 = parser.parse(json, Person.<jk>class</jk>);
<jc>// Parse a JSON object as a HashMap&lt;String,Person&gt;.</jc>
json = <js>"{a:{name:'John Smith',age:21},b:{name:'Joe Smith',age:42}}"</js>;
Map&lt;String,Person&gt; m5 = parser.parse(json, HashMap.<jk>class</jk>, String.<jk>class</jk>, Person.<jk>class</jk>);
<jc>// Parse a JSON object as a HashMap&lt;String,LinkedList&lt;Person&gt;&gt;.</jc>
json = <js>"{a:[{name:'John Smith',age:21},{name:'Joe Smith',age:42}]}"</js>;
Map&lt;String,List&lt;Person&gt;&gt; m6 = parser.parse(json, HashMap.<jk>class</jk>, String.<jk>class</jk>, LinkedList.<jk>class</jk>, Person.<jk>class</jk>);
<jc>// Parse a JSON array of integers as a Collection of Integers or int[] array.</jc>
json = <js>"[1,2,3]"</js>;
List&lt;Integer&gt; l7 = parser.parse(json, LinkedList.<jk>class</jk>, Integer.<jk>class</jk>);
<jk>int</jk>[] i7 = parser.parse(json, <jk>int</jk>[].<jk>class</jk>);
<jc>// Parse arbitrary input into ObjectMap or ObjectList objects
// (similar to JSONObject/JSONArray but generalized for all languages).</jc>
json = <js>"{name:'John Smith',age:21}"</js>;
ObjectMap m8a = parser.parse(json, ObjectMap.<jk>class</jk>);
<jk>int</jk> age = m8a.getInt(<js>"age"</js>);
ObjectMap m8b = (ObjectMap)parser.parse(json, Object.<jk>class</jk>); <jc>// Equivalent.</jc>
json = <js>"[1,true,null]"</js>;
ObjectList l9a = parser.parse(json, ObjectList.<jk>class</jk>);
<jk>boolean</jk> b = l9a.getBoolean(1);
ObjectList l9b = (ObjectList)parser.parse(json, Object.<jk>class</jk>); <jc>// Equivalent.</jc>
</p>
<h5 class='section'>More Information:</h5>
<ul class='doctree'>
<li><a class='doclink' href='http://juneau.apache.org/site/apidocs-8.1.2/overview-summary.html#juneau-marshall.Parsers'>juneau-marshall > Parsers</a>
</ul>
<hr>
<p>
Marshalls are pairings of serializers and parsers in a single class for even simpler code:
</p>
<p class='bcode w800'>
Person p = <jk>new</jk> Person(); <jc>// An arbitrary POJO</jc>
<jc>// Serialize</jc>
String json = Json.<jsf>DEFAULT</jsf>.write(p);
String simpleJson = SimpleJson.<jsf>DEFAULT</jsf>.write(p);
String xml = Xml.<jsf>DEFAULT</jsf>.write(p);
String html = Html.<jsf>DEFAULT</jsf>.write(p);
String uon = Uon.<jsf>DEFAULT</jsf>.write(p);
String urlEncoding = UrlEncoding.<jsf>DEFAULT</jsf>.write(p);
String openapi = OpenApi.<jsf>DEFAULT</jsf>.write(p);
<jk>byte</jk>[] msgPack = MsgPack.<jsf>DEFAULT</jsf>.write(p);
String rdfXml = RdfXml.<jsf>DEFAULT</jsf>.write(p);
String rdfXmlAbbrev = RdfXmlAbbrev.<jsf>DEFAULT</jsf>.write(p);
String n3 = N3.<jsf>DEFAULT</jsf>.write(p);
String nTuple = NTuple.<jsf>DEFAULT</jsf>.write(p);
String turtle = Turtle.<jsf>DEFAULT</jsf>.write(p);
<jc>// Parse</jc>
p = Json.<jsf>DEFAULT</jsf>.read(json, Person.<jk>class</jk>);
p = Xml.<jsf>DEFAULT</jsf>.read(xml, Person.<jk>class</jk>);
p = Html.<jsf>DEFAULT</jsf>.read(html, Person.<jk>class</jk>);
p = Uon.<jsf>DEFAULT</jsf>.read(uon, Person.<jk>class</jk>);
p = UrlEncoding.<jsf>DEFAULT</jsf>.read(urlEncoding, Person.<jk>class</jk>);
p = OpenApi.<jsf>DEFAULT</jsf>.read(openapi, Person.<jk>class</jk>);
p = MsgPack.<jsf>DEFAULT</jsf>.read(msgPack, Person.<jk>class</jk>);
p = RdfXml.<jsf>DEFAULT</jsf>.read(rdfXml, Person.<jk>class</jk>);
p = RdfXmlAbbrev.<jsf>DEFAULT</jsf>.read(rdfXmlAbbrev, Person.<jk>class</jk>);
p = N3.<jsf>DEFAULT</jsf>.read(n3, Person.<jk>class</jk>);
p = NTuple.<jsf>DEFAULT</jsf>.read(nTuple, Person.<jk>class</jk>);
p = Turtle.<jsf>DEFAULT</jsf>.read(turtle, Person.<jk>class</jk>);
</p>
<h5 class='section'>More Information:</h5>
<ul class='doctree'>
<li><a class='doclink' href='http://juneau.apache.org/site/apidocs-8.1.2/overview-summary.html#juneau-marshall.Marshalls'>juneau-marshall > Marshalls</a>
</ul>
<hr>
<p>
Serializers and parsers are builder-based. Build from scratch or clone existing instances. Lots of configuration options available for all the languages.
</p>
<p class='bcode w800'>
<jc>// Create a serializer from scratch programmatically using a builder.</jc>
JsonSerializer serializer = JsonSerializer.<jsm>create</jsm>()
.simple() <jc>// Simple mode</jc>
.sq() <jc>// Use single quotes</jc>
.pojoSwaps( <jc>// Swap unserializable classes with surrogate POJOs</jc>
IteratorSwap.<jk>class</jk>, <jc>// Iterators swapped with lists</jc>
ByteArrayBase64Swap.<jk>class</jk>, <jc>// byte[] swapped with base-64 encoded strings</jc>
CalendarSwap.ISO8601DT.<jk>class</jk> <jc>// Calendars swapped with ISO8601-compliant strings</jc>
)
.beanFilters(MyBeanFilter.<jk>class</jk>) <jc>// Control how bean properties are handled</jc>
.timeZone(TimeZone.<jsf>GMT</jsf>) <jc>// For serializing Calendars</jc>
.locale(Locale.<jsf>JAPAN</jsf>) <jc>// For timezone-specific serialization</jc>
.sortCollections() <jc>// For locale-specific serialization</jc>
.sortProperties() <jc>// Various behavior settings</jc>
.trimNullProperties()
.trimStrings()
.methodVisibility(<jsf>PROTECTED</jsf>) <jc>// Control which fields/methods are serialized</jc>
.beanDictionary( <jc>// Adds type variables for resolution during parsing</jc>
MyBeanA.<jk>class</jk>,
MyBeanB.<jk>class</jk>
)
.debug() <jc>// Debug mode</jc>
.build();
<jc>// Same as above, but using declarative named properties.</jc>
<jc>// This is how serializers and parsers are typically configured on REST servlets and clients.</jc>
JsonSerializer serializer = JsonSerializer.<jsm>create</jsm>()
.set(<jsf>JSON_simpleMode</jsf>, <jk>true</jk>)
.set(<jsf>SERIALIZER_quoteChar</jsf>, <js>'\''</js>)
.set(<jsf>BEAN_pojoSwaps_add</jsf>, IteratorSwap.<jk>class</jk>)
.set(<jsf>BEAN_pojoSwaps_add</jsf>, ByteArrayBase64Swap.<jk>class</jk>)
.set(<jsf>BEAN_pojoSwaps_add</jsf>, CalendarSwap.ISO8601DT.<jk>class</jk>)
.set(<jsf>BEAN_beanFilters_add</jsf>, MyBeanFilter.<jk>class</jk>)
.set(<jsf>BEAN_timeZone</jsf>, TimeZone.<jsf>GMT</jsf>)
.set(<jsf>BEAN_locale</jsf>, Locale.<jsf>JAPAN</jsf>)
.set(<jsf>SERIALIZER_sortCollections</jsf>, <jk>true</jk>)
.set(<jsf>BEAN_sortProperties</jsf>, <jk>true</jk>)
.set(<jsf>SERIALIZER_trimNullProperties</jsf>, <jk>true</jk>)
.set(<jsf>SERIALIZER_trimStrings</jsf>, <jk>true</jk>)
.set(<jsf>BEAN_methodVisibility</jsf>, <jsf>PROTECTED</jsf>)
.set(<jsf>BEAN_beanDictionary_add</jsf>, MyBeanA.<jk>class</jk>)
.set(<jsf>BEAN_beanDictionary_add</jsf>, MyBeanB.<jk>class</jk>)
.set(<jsf>BEAN_debug</jsf>, <jk>true</jk>)
.build();
<jc>// Clone an existing serializer and modify it to use single-quotes.</jc>
JsonSerializer serializer = JsonSerializer.<jsf>DEFAULT</jsf>.builder()
.sq()
.build();
</p>
<h5 class='section'>More Information:</h5>
<ul class='doctree'>
<li><a class='doclink' href='http://juneau.apache.org/site/apidocs-8.1.2/overview-summary.html#juneau-marshall.ConfigurableProperties'>juneau-marshall > Configurable Properties</a>
</ul>
<hr>
<p>
Many POJOs such as primitives, beans, collections, arrays, and classes with various known constructors and methods are serializable out-of-the-box.
For other objects, "transforms" allow you to perform various mutations on them before serialization and after parsing.
</p>
<ul class='spaced-list'>
<li>Transforms
<ul>
<li>Bean filters - Control how bean properties are handled (naming conventions, ordering, visibility,...).
<li>POJO swaps - Replace non-serializable POJOs with serializable equivalents.
<br>Predefined swaps provided for common cases: <code>ByteArrayBase64Swap</code>, 50+ variants of Calendar/Date swaps, <code>Enumeration/Iterator</code> swaps.
</ul>
<li>Annotations
<br>Various annotations available for your POJO classes that are recognized by ALL serializers and parsers:
<br><ja>@Bean</ja>, <ja>@Pojo</ja>, <ja>@BeanIgnore</ja>, <ja>@BeanParam</ja>, <ja>@BeanProperty</ja>, <ja>@NameProperty</ja>, <ja>@ParentProperty</ja>
<br>
<br>Annotations also provided for language-specific behaviors where it makes sense:
<br><ja>@Json</ja>, <ja>@Html</ja>, <ja>@Xml</ja>, <ja>@UrlEncoding</ja>
<br>
<br>All annotations have programmatic equivalents when you don't have access to POJO source.
<li>Swap methods
<br>By default, various instance and static methods and constructors are automatically detected and supported:
<br><code>valueOf(String)</code>, <code>parse(String)</code>, <code>parseString(String)</code>, <code>forName(String)</code>, <code>forString(String)</code>,
<code>fromString(String)</code>, <code>T(String)</code>, <code>Object swap(BeanSession)</code>, <code>T unswap(BeanSession, T.class)</code>
</ul>
<h5 class='section'>More Information:</h5>
<ul class='doctree'>
<li><a class='doclink' href='http://juneau.apache.org/site/apidocs-8.1.2/overview-summary.html#juneau-marshall.PojoCategories'>juneau-marshall > POJO Categories</a>
</ul>
<hr>
<p>
UON (URL-Encoded Object Notation) 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.
</p>
<p class='bcode w800'>
(
id=1,
name=<js>'John+Smith'</js>,
uri=<js>http://sample/addressBook/person/1</js>,
addressBookUri=<js>http://sample/addressBook</js>,
birthDate=<js>1946-08-12T00:00:00Z</js>,
addresses=@(
(
uri=<js>http://sample/addressBook/address/1</js>,
personUri=<js>http://sample/addressBook/person/1</js>,
id=<js>1</js>,
street=<js>'100+Main+Street'</js>,
city=<js>Anywhereville</js>,
state=<js>NY</js>,
zip=<js>12345</js>,
isCurrent=<jk>true</jk>
)
)
)
</p>
<h5 class='section'>More Information:</h5>
<ul class='doctree'>
<li><a class='doclink' href='http://juneau.apache.org/site/apidocs-8.1.2/overview-summary.html#juneau-marshall.UonDetails'>juneau-marshall > UON Details</a>
</ul>
<hr>
<p>
Lots of shortcuts are provided throughout the API to simplify tasks, and the APIs are often useful for debugging and logging purposes as well:
</p>
<p class='bcode w800'>
<jc>// Create JSON strings from scratch using fluent-style code.</jc>
String jsonObject = <jk>new</jk> ObjectMap().append(<js>"foo"</js>,<js>"bar"</js>).toString();
String jsonArray = <jk>new</jk> ObjectList().append(<js>"foo"</js>).append(123).append(<jk>null</jk>).toString();
<jc>// Create maps and beans directly from JSON.</jc>
Map&lt;String,Object&gt; myMap = <jk>new</jk> ObjectMap(<js>"{foo:'bar'}"</js>);
List&lt;Object&gt; myList = <jk>new</jk> ObjectList(<js>"['foo',123,null]"</js>);
<jc>// Load a POJO from a JSON file.</jc>
MyPojo myPojo = JsonParser.<jsf>DEFAULT</jsf>.parse(<jk>new</jk> File(<js>"myPojo.json"</js>));
<jc>// Serialize POJOs and ignore exceptions (great for logging)</jc>
String json = SimpleJson.<jsf>DEFAULT</jsf>.toString(myPojo);
<jc>// Dump a POJO to the console.</jc>
SimpleJson.<jsf>DEFAULT</jsf>.println(myPojo);
<jc>// Delayed serialization.</jc>
<jc>// (e.g. don't serialize an object if it's not going to be logged).</jc>
logger.log(<jsf>FINE</jsf>, <js>"My POJO was: {0}"</js>, <jk>new</jk> StringObject(myPojo));
logger.log(<jsf>FINE</jsf>, <js>"My POJO in XML was: {0}"</js>, <jk>new</jk> StringObject(XmlSerializer.<jsf>DEFAULT</jsf>, myPojo));
String message = <jk>new</jk> StringMessage(<js>"My POJO in {0}: {1}"</js>, <js>"JSON"</js>, <jk>new</jk> StringObject(myPojo)).toString();
<jc>// Create a 'REST-like' wrapper around a POJO.</jc>
<jc>// Allows you to manipulate POJO trees using URIs and GET/PUT/POST/DELETE commands.</jc>
PojoRest pojoRest = <jk>new</jk> PojoRest(myPojo);
pojoRest.get(String.<jk>class</jk>, <js>"addressBook/0/name"</js>);
pojoRest.put(<js>"addressBook/0/name"</js>, <js>"John Smith"</js>);
</p>
<h5 class='section'>More Information:</h5>
<ul class='doctree'>
<li><a class='doclink' href='http://juneau.apache.org/site/apidocs-8.1.2/overview-summary.html#juneau-marshall.ObjectMap'>juneau-marshall > ObjectMap and ObjectList</a>
</ul>
<hr>
<p>
<code>SerializerGroup</code> and <code>ParserGroup</code> classes allow serializers and parsers
to be retrieved by W3C-compliant HTTP <code>Accept</code> and <code>Content-Type</code> values:
</p>
<p class='bcode w800'>
<jc>// Construct a new serializer group with configuration parameters that get applied to all serializers.</jc>
SerializerGroup sg = SerializerGroup.<jsm>create</jsm>()
.append(JsonSerializer.<jk>class</jk>, UrlEncodingSerializer.<jk>class</jk>);
.ws() <jc>// or .setUseWhitespace(true) or .set(SERIALIZER_useWhitespace, true)</jc>
.pojoSwaps(CalendarSwap.ISO8601DT.<jk>class</jk>) <jc>// or .set(BEAN_pojoSwaps_add, CalendarSwap.ISO8601DT.class)</jc>
.build();
<jc>// Find the appropriate serializer by Accept type and serialize our POJO to the specified writer.</jc>
<jc>// Fully RFC2616 compliant.</jc>
sg.getSerializer(<js>"text/invalid, text/json;q=0.8, text/*;q:0.6, *\/*;q=0.0"</js>)
.serialize(myPersonObject, myWriter);
<jc>// Construct a new parser group with configuration parameters that get applied to all parsers.</jc>
ParserGroup pg = ParserGroup.<jsm>create</jsm>()
.append(JsonParser.<jk>class</jk>, UrlEncodingParser.<jk>class</jk>);
.pojoSwaps(CalendarSwap.ISO8601DT.<jk>class</jk>) <jc>// or .set(BEAN_pojoSwaps_add, CalendarSwap.ISO8601DT.class)</jc>
.build();
Person p = pg.getParser(<js>"text/json"</js>).parse(myReader, Person.<jk>class</jk>);
</p>
<h5 class='section'>More Information:</h5>
<ul class='doctree'>
<li><a class='doclink' href='http://juneau.apache.org/site/apidocs-8.1.2/overview-summary.html#juneau-marshall.Groups'>juneau-marshall > SerializerGroups and ParserGroups</a>
</ul>
<p>
The <code>org.apache.juneau.svl</code> 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
<js>"$varName{varKey}"</js>.
</p>
<p>
Variables can be recursively nested within the varKey (e.g. <js>"$FOO{$BAR{xxx},$BAZ{xxx}}"</js>).
Variables can also return values that themselves contain more variables.
</p>
<p class='bcode w800'>
<jc>// Use the default variable resolver to resolve a string that contains $S (system property) variables</jc>
String myProperty = VarResolver.<jsf>DEFAULT</jsf>.resolve(<js>"The Java home directory is $S{java.home}"</js>);
</p>
<p>
The following shows how variables can be arbitrarily nested:
</p>
<p class='bcode w800'>
<jc>// Look up a property in the following order:
// 1) MYPROPERTY environment variable.
// 2) 'my.property' system property if environment variable not found.
// 3) 'not found' string if system property not found.</jc>
String myproperty = VarResolver.<jsf>DEFAULT</jsf>.resolve(<js>"$E{MYPROPERTY,$S{my.property,not found}}"</js>);
</p>
<p>
SVL is a large topic on it's own.
It is used extensively in the ConfigFile, REST and Microservice APIs.
</p>
<p>
Plugging in your own variables is also easy.
</p>
<h5 class='section'>More Information:</h5>
<ul class='doctree'>
<li><a class='doclink' href='http://juneau.apache.org/site/apidocs-8.1.2/overview-summary.html#juneau-svl'>juneau-svl</a>
</ul>
</div>
<!-- ======================================================================================================= -->
<!-- === JUNEAU-MARSHALL-RDF =============================================================================== -->
<!-- ======================================================================================================= -->
<h5 class='toc' id='juneau-marshall-rdf'>juneau-marshall-rdf</h5>
<div>
<h5 class='figure'>Maven Dependency</h5>
<p class='bcode w500'>
<xt>&lt;dependency&gt;</xt>
<xt>&lt;groupId&gt;</xt>org.apache.juneau<xt>&lt;/groupId&gt;</xt>
<xt>&lt;artifactId&gt;</xt>juneau-marshall-rdf<xt>&lt;/artifactId&gt;</xt>
<xt>&lt;version&gt;</xt>8.1.2<xt>&lt;/version&gt;</xt>
<xt>&lt;/dependency&gt;</xt>
</p>
<h5 class='figure'>Java Library</h5>
<p class='bcode w500'>
juneau-marshall-rdf-8.1.2.jar
</p>
<h5 class='figure'>OSGi Module</h5>
<p class='bcode w500'>
org.apache.juneau.marshall.rdf_8.1.2.jar
</p>
<p>
The <code>juneau-marshall-rdf</code> library provides additional serializers and parsers for RDF.
These rely on the Apache Jena library to provide support for the following languages:
</p>
<ul>
<li>RDF/XML
<li>RDF/XML-Abbrev
<li>N-Triple
<li>Turtle
<li>N3
</ul>
<p>
The serializers and parsers work identically to those in <code>juneau-marshall</code>, but are
packaged separately so that you don't need to pull in the Jena dependency unless you need it.
</p>
<p class='bcode w800'>
<jc>// A simple bean</jc>
<jk>public class</jk> Person {
<jk>public</jk> String name = <js>"This is RDF format."</js>;
<jk>public</jk> String id = "rdf";
}
<jc>// Serialize a bean to various RDF languages</jc>
Person p = <jk>new</jk> Person();
<jc>// Produces:
// &lt;rdf:RDF
// xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
// xmlns:jp="http://www.apache.org/juneaubp/"
// xmlns:j="http://www.apache.org/juneau/"&gt;
// &lt;rdf:Description&gt;
// &lt;jp:name&gt;This is RDF format.&lt;/jp:name&gt;
// &lt;jp:id&gt;rdf&lt;/jp:id&gt;
// &lt;/rdf:Description&gt;
// &lt;/rdf:RDF&gt;</jc>
String rdfXml = RdfXmlAbbrevSerializer.<jsf>DEFAULT</jsf>.serialize(p);
<jc>// Produces:
// @prefix jp: &lt;http://www.apache.org/juneaubp/&gt; .
// @prefix j: &lt;http://www.apache.org/juneau/&gt; .
// [] jp:id "rdf" ;
// jp:name "This is RDF format." .</jc>
String rdfN3 = N3Serializer.<jsf>DEFAULT</jsf>.serialize(p);
<jc>// Produces:
// _:A3bf53c85X3aX157cf407e2dX3aXX2dX7ffd &lt;http://www.apache.org/juneaubp/name&gt; "This is RDF format." .
// _:A3bf53c85X3aX157cf407e2dX3aXX2dX7ffd &lt;http://www.apache.org/juneaubp/age&gt; "rdf" .</jc>
String rdfNTriple = NTripleSerializer.<jsf>DEFAULT</jsf>.serialize(p);
<jc>// Produces:
// @prefix jp: &lt;http://www.apache.org/juneaubp/&gt; .
// @prefix j: &lt;http://www.apache.org/juneau/&gt; .
// [] jp:id "rdf" ;
// jp:name "This is RDF format." .</jc>
String rdfTurtle = TurtleSerializer.<jsf>DEFAULT</jsf>.serialize(p);
</p>
<h5 class='section'>More Information:</h5>
<ul class='doctree'>
<li><a class='doclink' href='http://juneau.apache.org/site/apidocs-8.1.2/overview-summary.html#juneau-marshall-rdf'>juneau-marshall-rdf</a>
</ul>
</div>
</body>
</html>