juneau-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From jamesbog...@apache.org
Subject [juneau] branch master updated: Swagger UI improvements.
Date Fri, 23 Mar 2018 23:42:23 GMT
This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/master by this push:
     new 27926a6  Swagger UI improvements.
27926a6 is described below

commit 27926a6dfd18825e33186715a2ccf6fce7b08a6b
Author: JamesBognar <jamesbognar@apache.org>
AuthorDate: Fri Mar 23 19:42:13 2018 -0400

    Swagger UI improvements.
---
 .../main/java/org/apache/juneau/config/Config.java |   24 +-
 .../org/apache/juneau/config/ConfigBuilder.java    |   10 +-
 .../java/org/apache/juneau/ComboRoundTripTest.java |   14 +-
 .../java/org/apache/juneau/ComboSerializeTest.java |    2 +-
 .../test/java/org/apache/juneau/MaxIndentTest.java |    2 +-
 .../java/org/apache/juneau/ParserReaderTest.java   |    2 +-
 .../java/org/apache/juneau/config/ConfigTest.java  |    4 +-
 .../org/apache/juneau/dto/swagger/SwaggerTest.java |    3 +-
 .../juneau/serializer/UriResolutionTest.java       |    4 +-
 .../org/apache/juneau/utils/StringUtilsTest.java   |   35 +
 .../org/apache/juneau/dto/swagger/Swagger.java     |   52 +-
 .../apache/juneau/dto/swagger/ui/SwaggerUI.java    |   28 +-
 .../org/apache/juneau/dto/swagger/ui/SwaggerUI.css |   50 +-
 .../org/apache/juneau/dto/swagger/ui/SwaggerUI.js  |   11 +-
 .../org/apache/juneau/jena/RdfParserBuilder.java   |   22 +-
 .../apache/juneau/jena/RdfSerializerBuilder.java   |   74 +-
 .../main/java/org/apache/juneau/BeanContext.java   |   54 +
 .../java/org/apache/juneau/BeanContextBuilder.java |   46 +
 .../src/main/java/org/apache/juneau/BeanMeta.java  |   14 +-
 .../InputStreamParser.java => BinaryFormat.java}   |   88 +-
 .../src/main/java/org/apache/juneau/ClassMeta.java |    2 +-
 .../java/org/apache/juneau/annotation/Bean.java    |   34 +
 .../org/apache/juneau/csv/CsvParserBuilder.java    |   22 +-
 .../apache/juneau/csv/CsvSerializerBuilder.java    |   74 +-
 .../org/apache/juneau/html/HtmlParserBuilder.java  |    4 +-
 .../org/apache/juneau/html/HtmlSerializer.java     |    6 +-
 .../apache/juneau/html/HtmlSerializerSession.java  |    2 +-
 .../java/org/apache/juneau/internal/AsciiSet.java  |    2 +-
 .../apache/juneau/internal/BeanPropertyUtils.java  |   59 +-
 .../org/apache/juneau/internal/StringUtils.java    |   83 +-
 .../org/apache/juneau/jso/JsoParserBuilder.java    |   20 +-
 .../apache/juneau/jso/JsoSerializerBuilder.java    |   44 +-
 .../org/apache/juneau/json/JsonParserBuilder.java  |   22 +-
 .../org/apache/juneau/json/JsonSchemaUtils.java    |  105 ++
 .../org/apache/juneau/json/JsonSerializer.java     |   12 +-
 .../apache/juneau/json/JsonSerializerBuilder.java  |   76 +-
 .../org/apache/juneau/msgpack/MsgPackParser.java   |   39 +
 .../juneau/msgpack/MsgPackParserBuilder.java       |   20 +-
 .../apache/juneau/msgpack/MsgPackSerializer.java   |   39 +
 .../juneau/msgpack/MsgPackSerializerBuilder.java   |   44 +-
 .../apache/juneau/parser/InputStreamParser.java    |   68 ++
 .../InputStreamParserBuilder.java}                 |  313 +++---
 .../juneau/parser/InputStreamParserSession.java    |   45 +-
 .../main/java/org/apache/juneau/parser/Parser.java |  102 +-
 .../org/apache/juneau/parser/ParserBuilder.java    |   81 --
 .../apache/juneau/parser/ParserGroupBuilder.java   |  104 +-
 .../java/org/apache/juneau/parser/ParserPipe.java  |   19 +-
 .../org/apache/juneau/parser/ParserSession.java    |   24 +-
 .../org/apache/juneau/parser/ReaderParser.java     |  122 +++
 .../ReaderParserBuilder.java}                      | 1110 ++++++++++----------
 .../apache/juneau/parser/ReaderParserSession.java  |   50 +-
 .../juneau/plaintext/PlainTextParserBuilder.java   |   22 +-
 .../plaintext/PlainTextSerializerBuilder.java      |   74 +-
 .../juneau/serializer/OutputStreamSerializer.java  |   84 +-
 .../OutputStreamSerializerBuilder.java}            |  233 ++--
 .../serializer/OutputStreamSerializerSession.java  |   24 +-
 .../org/apache/juneau/serializer/Serializer.java   |  149 +--
 .../juneau/serializer/SerializerBuilder.java       |  110 --
 .../juneau/serializer/SerializerGroupBuilder.java  |  150 +--
 .../juneau/serializer/SerializerSession.java       |   53 +-
 .../apache/juneau/serializer/WriterSerializer.java |  155 +++
 .../WriterSerializerBuilder.java}                  |  300 +++---
 .../juneau/serializer/WriterSerializerSession.java |   58 +-
 .../transform/AnnotationBeanFilterBuilder.java     |    3 +
 .../org/apache/juneau/transform/BeanFilter.java    |   12 +-
 .../apache/juneau/transform/BeanFilterBuilder.java |   62 +-
 .../org/apache/juneau/transform/BuilderSwap.java   |    2 +-
 .../transform/InterfaceBeanFilterBuilder.java      |    3 +
 .../org/apache/juneau/uon/UonParserBuilder.java    |   22 +-
 .../java/org/apache/juneau/uon/UonSerializer.java  |    2 +-
 .../apache/juneau/uon/UonSerializerBuilder.java    |   74 +-
 .../juneau/urlencoding/UrlEncodingSerializer.java  |    2 +-
 .../org/apache/juneau/xml/XmlParserBuilder.java    |   22 +-
 .../java/org/apache/juneau/xml/XmlSerializer.java  |   12 +-
 .../apache/juneau/xml/XmlSerializerBuilder.java    |   74 +-
 .../juneau/yaml/proto/YamlParserBuilder.java       |   22 +-
 .../juneau/yaml/proto/YamlSerializerBuilder.java   |   74 +-
 juneau-doc/src/main/javadoc/overview.html          |   47 +-
 .../juneau/examples/petstore/ApiResponse.java      |   93 +-
 .../apache/juneau/examples/petstore/Category.java  |   83 +-
 .../org/apache/juneau/examples/petstore/Order.java |  112 +-
 .../juneau/examples/petstore/OrderStatus.java      |   61 +-
 .../org/apache/juneau/examples/petstore/Pet.java   |  100 +-
 .../apache/juneau/examples/petstore/PetStatus.java |   61 +-
 .../juneau/examples/petstore/PetStoreResource.java |  436 ++++++++
 .../juneau/examples/petstore/PetStoreResource.json |  284 +++++
 .../org/apache/juneau/examples/petstore/Tag.java   |   83 +-
 .../org/apache/juneau/examples/petstore/User.java  |  119 ++-
 .../juneau/examples/rest/AtomFeedResource.java     |    2 +-
 .../juneau/examples/rest/PetStoreResource.java     |    3 +-
 .../apache/juneau/examples/rest/RootResources.java |    5 +-
 .../examples/rest/SystemPropertiesResource.java    |    4 +-
 .../rest/addressbook/AddressBookResource.java      |    4 +-
 .../microservice/resources/ConfigResource.java     |    2 +-
 .../juneau/rest/client/RestClientBuilder.java      |  246 +++--
 .../apache/juneau/rest/BasicRestInfoProvider.java  |   61 +-
 .../org/apache/juneau/rest/BasicRestServlet.java   |    6 +-
 .../java/org/apache/juneau/rest/RestRequest.java   |    2 +-
 .../java/org/apache/juneau/rest/RestUtils.java     |    2 +-
 .../org/apache/juneau/rest/styles/dark.css         |    4 +
 .../org/apache/juneau/rest/styles/devops.css       |    4 +
 .../org/apache/juneau/rest/styles/light.css        |    4 +
 .../org/apache/juneau/rest/styles/original.css     |    5 +
 103 files changed, 4185 insertions(+), 2732 deletions(-)

diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Config.java b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Config.java
index d56a3cf..4f3704c 100644
--- a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Config.java
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/Config.java
@@ -204,11 +204,11 @@ public final class Config extends Context implements ConfigEventListener, Writab
 	 * <h5 class='section'>Property:</h5>
 	 * <ul>
 	 * 	<li><b>Name:</b>  <js>"Config.binaryFormat.s"</js>
-	 * 	<li><b>Data type:</b>  <code>String</code>
-	 * 	<li><b>Default:</b>  <js>"BASE64"</js>
+	 * 	<li><b>Data type:</b>  {@link BinaryFormat}
+	 * 	<li><b>Default:</b>  {@link BinaryFormat#BASE64}
 	 * 	<li><b>Methods:</b> 
 	 * 		<ul>
-	 * 			<li class='jm'>{@link ConfigBuilder#binaryFormat(String)}
+	 * 			<li class='jm'>{@link ConfigBuilder#binaryFormat(BinaryFormat)}
 	 * 		</ul>
 	 * </ul>
 	 * 
@@ -219,9 +219,9 @@ public final class Config extends Context implements ConfigEventListener, Writab
 	 * <p>
 	 * Possible values:
 	 * <ul>
-	 * 	<li><js>"BASE64"</js> - BASE64-encoded string.
-	 * 	<li><js>"HEX"</js> - Hexadecimal.
-	 * 	<li><js>"SPACED_HEX"</js> - Hexadecimal with spaces between bytes.
+	 * 	<li>{@link BinaryFormat#BASE64} - BASE64-encoded string.
+	 * 	<li>{@link BinaryFormat#HEX} - Hexadecimal.
+	 * 	<li>{@link BinaryFormat#SPACED_HEX} - Hexadecimal with spaces between bytes.
 	 * </ul>
 	 */
 	public static final String CONFIG_binaryFormat = PREFIX + "binaryFormat.s";
@@ -277,7 +277,7 @@ public final class Config extends Context implements ConfigEventListener, Writab
 	private final ConfigEncoder encoder;
 	private final VarResolverSession varSession;
 	private final int binaryLineLength;
-	private final String binaryFormat;
+	private final BinaryFormat binaryFormat;
 	private final boolean multiLineValuesOnSeparateLines, readOnly;
 	private final ConfigMap configMap;
 	private final BeanSession beanSession;
@@ -339,7 +339,7 @@ public final class Config extends Context implements ConfigEventListener, Writab
 			.build()
 			.createSession();
 		binaryLineLength = getIntegerProperty(CONFIG_binaryLineLength, -1);
-		binaryFormat = getStringProperty(CONFIG_binaryFormat, "BASE64").toUpperCase();
+		binaryFormat = getProperty(CONFIG_binaryFormat, BinaryFormat.class, BinaryFormat.BASE64);
 		multiLineValuesOnSeparateLines = getBooleanProperty(CONFIG_multiLineValuesOnSeparateLines, false);
 		readOnly = getBooleanProperty(CONFIG_readOnly, false);
 	}
@@ -1626,9 +1626,9 @@ public final class Config extends Context implements ConfigEventListener, Writab
 		if (value instanceof byte[]) {
 			String s = null;
 			byte[] b = (byte[])value;
-			if ("HEX".equals(binaryFormat))
+			if (binaryFormat == BinaryFormat.HEX)
 				s = toHex(b);
-			else if ("SPACED_HEX".equals(binaryFormat))
+			else if (binaryFormat == BinaryFormat.SPACED_HEX)
 				s = toSpacedHex(b);
 			else
 				s = base64Encode(b);
@@ -1673,8 +1673,8 @@ public final class Config extends Context implements ConfigEventListener, Writab
 				s = s.replaceAll("\n", "");
 			try {
 				switch (binaryFormat) {
-					case "HEX": return (T)fromHex(s);
-					case "SPACED_HEX": return (T)fromSpacedHex(s);
+					case HEX: return (T)fromHex(s);
+					case SPACED_HEX: return (T)fromSpacedHex(s);
 					default: return (T)base64Decode(s);
 				}
 			} catch (Exception e) {
diff --git a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/ConfigBuilder.java b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/ConfigBuilder.java
index b622b03..218d653 100644
--- a/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/ConfigBuilder.java
+++ b/juneau-core/juneau-config/src/main/java/org/apache/juneau/config/ConfigBuilder.java
@@ -255,17 +255,17 @@ public class ConfigBuilder extends ContextBuilder {
 	 * <p>
 	 * Possible values:
 	 * <ul>
-	 * 	<li><js>"BASE64"</js> - BASE64-encoded string.
-	 * 	<li><js>"HEX"</js> - Hexadecimal.
-	 * 	<li><js>"SPACED_HEX"</js> - Hexadecimal with spaces between bytes.
+	 * 	<li>{@link BinaryFormat#BASE64} - BASE64-encoded string.
+	 * 	<li>{@link BinaryFormat#HEX} - Hexadecimal.
+	 * 	<li>{@link BinaryFormat#SPACED_HEX} - Hexadecimal with spaces between bytes.
 	 * </ul>
 	 * 
 	 * @param value 
 	 * 	The new value for this property.
-	 * 	<br>The default is <js>"BASE64"</js>.
+	 * 	<br>The default is {@link BinaryFormat#BASE64}.
 	 * @return This object (for method chaining).
 	 */
-	public ConfigBuilder binaryFormat(String value) {
+	public ConfigBuilder binaryFormat(BinaryFormat value) {
 		return set(CONFIG_binaryFormat, value);
 	}
 
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ComboRoundTripTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ComboRoundTripTest.java
index e462b14..7b24e13 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ComboRoundTripTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ComboRoundTripTest.java
@@ -154,7 +154,7 @@ public abstract class ComboRoundTripTest {
 				return;
 			}
 
-			String r = s.isWriterSerializer() ? ((WriterSerializer)s).serialize(comboInput.getInput()) : ((OutputStreamSerializer)s).serializeToHex(comboInput.getInput());
+			String r = s.serializeToString(comboInput.getInput());
 
 			// Can't control RdfSerializer output well, so manually remove namespace declarations
 			// double-quotes with single-quotes, and spaces with tabs.
@@ -194,9 +194,9 @@ public abstract class ComboRoundTripTest {
 				return;
 			}
 
-			String r = s.isWriterSerializer() ? ((WriterSerializer)s).serialize(comboInput.getInput()) : ((OutputStreamSerializer)s).serializeToHex(comboInput.getInput());
+			String r = s.serializeToString(comboInput.getInput());
 			Object o = p.parse(r, comboInput.type);
-			r = s.isWriterSerializer() ? ((WriterSerializer)s).serialize(o) : ((OutputStreamSerializer)s).serializeToHex(o);
+			r = s.serializeToString(o);
 
 			if (isRdf)
 				r = r.replaceAll("<rdf:RDF[^>]*>", "<rdf:RDF>").replace('"', '\'');
@@ -218,7 +218,7 @@ public abstract class ComboRoundTripTest {
 			s = getSerializer(s);
 			p = getParser(p);
 
-			String r = s.isWriterSerializer() ? ((WriterSerializer)s).serialize(comboInput.getInput()) : ((OutputStreamSerializer)s).serializeToHex(comboInput.getInput());
+			String r = s.serializeToString(comboInput.getInput());
 			Object o = p.parse(r, comboInput.type);
 
 			comboInput.verify(o);
@@ -236,7 +236,7 @@ public abstract class ComboRoundTripTest {
 			p = (InputStreamParser)getParser(p);
 			WriterSerializer sJson = (WriterSerializer)getSerializer(this.sJson);
 
-			String r = s.serializeToHex(comboInput.getInput());
+			String r = s.serializeToString(comboInput.getInput());
 			Object o = p.parse(r, comboInput.type);
 			r = sJson.serialize(o);
 			assertEquals(comboInput.label + "/" + testName + " parse-normal failed on JSON equivalency", expected, r);
@@ -594,8 +594,8 @@ public abstract class ComboRoundTripTest {
 	//--------------------------------------------------------------------------------
 	// MsgPack
 	//--------------------------------------------------------------------------------
-	OutputStreamSerializer sMsgPack = MsgPackSerializer.DEFAULT;
-	InputStreamParser pMsgPack = MsgPackParser.DEFAULT;
+	OutputStreamSerializer sMsgPack = MsgPackSerializer.DEFAULT_SPACED_HEX;
+	InputStreamParser pMsgPack = MsgPackParser.DEFAULT_SPACED_HEX;
 
 	@Test
 	public void f11_serializeMsgPack() throws Exception {
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ComboSerializeTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ComboSerializeTest.java
index 17e14e1..7911592 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ComboSerializeTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ComboSerializeTest.java
@@ -120,7 +120,7 @@ public abstract class ComboSerializeTest {
 				return;
 			}
 
-			String r = s.isWriterSerializer() ? ((WriterSerializer)s).serialize(comboInput.getInput()) : ((OutputStreamSerializer)s).serializeToHex(comboInput.getInput());
+			String r = s.serializeToString(comboInput.getInput());
 
 			// Can't control RdfSerializer output well, so manually remove namespace declarations
 			// double-quotes with single-quotes, and spaces with tabs.
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/MaxIndentTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/MaxIndentTest.java
index 1af10f4..1ff8786 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/MaxIndentTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/MaxIndentTest.java
@@ -291,7 +291,7 @@ public class MaxIndentTest {
 
 	private void testSerialize(String testName, Serializer s, String expected) throws Exception {
 		try {
-			String r = s.isWriterSerializer() ? ((WriterSerializer)s).serialize(input.in) : ((OutputStreamSerializer)s).serializeToHex(input.in);
+			String r = s.serializeToString(input.in);
 
 			// Specifying "xxx" in the expected results will spit out what we should populate the field with.
 			if (expected.equals("xxx")) {
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ParserReaderTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ParserReaderTest.java
index db1ce1a..d8a2577 100755
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ParserReaderTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/ParserReaderTest.java
@@ -180,6 +180,6 @@ public class ParserReaderTest {
 	}
 
 	private ParserReader createParserReader(Object in) throws Exception {
-		return new ParserReader(new ParserPipe(in, false, false, false, false, null, null));
+		return new ParserReader(new ParserPipe(in, false, false, false, false, null, null, null));
 	}
 }
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigTest.java
index 64e6db7..822a24c 100755
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/config/ConfigTest.java
@@ -1357,7 +1357,7 @@ public class ConfigTest {
 	//====================================================================================================
 	@Test
 	public void testHex() throws Exception {
-		Config cf = init().builder().binaryFormat("HEX").build();
+		Config cf = init().builder().binaryFormat(BinaryFormat.HEX).build();
 	
 		cf.set("foo", "bar".getBytes("UTF-8"));
 		assertEquals("626172", cf.get("foo"));
@@ -1369,7 +1369,7 @@ public class ConfigTest {
 	//====================================================================================================
 	@Test
 	public void testSpacedHex() throws Exception {
-		Config cf = init().builder().binaryFormat("SPACED_HEX").build();
+		Config cf = init().builder().binaryFormat(BinaryFormat.SPACED_HEX).build();
 	
 		cf.set("foo", "bar".getBytes("UTF-8"));
 		assertEquals("62 61 72", cf.get("foo"));
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/dto/swagger/SwaggerTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/dto/swagger/SwaggerTest.java
index 99aa176..5898321 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/dto/swagger/SwaggerTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/dto/swagger/SwaggerTest.java
@@ -330,9 +330,8 @@ public class SwaggerTest {
 		
 		t.path("a", "a1", operation().description("a2"));
 		t.path("b", null, null);
-		t.path(null, "c1", operation().description("c2"));
 		
-		assertObjectEquals("{a:{a1:{description:'a2'}},b:{null:null},null:{c1:{description:'c2'}}}", t.getPaths());
+		assertObjectEquals("{a:{a1:{description:'a2'}},b:{null:null}}", t.getPaths());
 	}
 
 	/**
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/serializer/UriResolutionTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/serializer/UriResolutionTest.java
index 1933e33..870af2c 100644
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/serializer/UriResolutionTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/serializer/UriResolutionTest.java
@@ -546,7 +546,7 @@ public class UriResolutionTest {
 		try {
 			boolean isRdf = s instanceof RdfSerializer;
 
-			String r = s.isWriterSerializer() ? ((WriterSerializer)s).serialize(new TestURI()) : ((OutputStreamSerializer)s).serializeToHex(new TestURI());
+			String r = s.serializeToString(new TestURI());
 
 			// Can't control RdfSerializer output well, so manually remove namespace declarations
 			// double-quotes with single-quotes, and spaces with tabs.
@@ -576,7 +576,7 @@ public class UriResolutionTest {
 
 	private void testParse(Serializer s, Parser p) throws Exception {
 		try {
-			String r = s.isWriterSerializer() ? ((WriterSerializer)s).serialize(new TestURI()) : ((OutputStreamSerializer)s).serializeToHex(new TestURI());
+			String r = s.serializeToString(new TestURI());
 
 			TreeMap<String,String> m = p.parse(r, TreeMap.class, String.class, String.class);
 
diff --git a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
index c670c75..8bb9a89 100755
--- a/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
+++ b/juneau-core/juneau-core-test/src/test/java/org/apache/juneau/utils/StringUtilsTest.java
@@ -840,4 +840,39 @@ public class StringUtilsTest {
 		assertEquals("abc", join(splitEqually("abc", 3), '|'));
 		assertEquals("abc|d", join(splitEqually("abcd", 3), '|'));
 	}
+	
+	//====================================================================================================
+	// testIsObjectMap(Object)
+	//====================================================================================================
+	@Test
+	public void testIsObjectMap() {
+		assertTrue(isObjectMap("{foo:'bar'}", true));
+		assertTrue(isObjectMap(" { foo:'bar' } ", true));
+		assertFalse(isObjectMap(" { foo:'bar'  ", true));
+		assertFalse(isObjectMap("  foo:'bar' } ", true));
+		assertTrue(isObjectMap("/*foo*/ { foo:'bar' } /*foo*/", true));
+	}
+	
+	//====================================================================================================
+	// testIsObjectMap(Object)
+	//====================================================================================================
+	@Test
+	public void testIsObjectList() {
+		assertTrue(isObjectList("[123,'bar']", true));
+		assertTrue(isObjectList(" [ 123,'bar' ] ", true));
+		assertFalse(isObjectList(" [ 123,'bar'  ", true));
+		assertFalse(isObjectList("  123,'bar' ] ", true));
+		assertTrue(isObjectList("/*foo*/ [ 123,'bar' ] /*foo*/", true));
+	}
+
+	//====================================================================================================
+	// addLineNumbers(String)
+	//====================================================================================================
+	@Test
+	public void testAddLineNumbers() {
+		assertNull(addLineNumbers(null));
+		assertEquals("1: \n", addLineNumbers(""));
+		assertEquals("1: foo\n", addLineNumbers("foo"));
+		assertEquals("1: foo\n2: bar\n", addLineNumbers("foo\nbar"));
+	}
 }
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
index c0bc13e..c0388e0 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/Swagger.java
@@ -541,7 +541,7 @@ public class Swagger extends SwaggerElement {
 	 * @return This object (for method chaining).
 	 */
 	public Swagger setPaths(Map<String,Map<String,Operation>> value) {
-		paths = newMap(value);
+		paths = newSortedMap(value, null);
 		return this;
 	}
 
@@ -560,7 +560,7 @@ public class Swagger extends SwaggerElement {
 	 * @return This object (for method chaining).
 	 */
 	public Swagger addPaths(Map<String,Map<String,Operation>> values) {
-		paths = addToMap(paths, values);
+		paths = addToSortedMap(paths, values, null);
 		return this;
 	}
 	
@@ -574,10 +574,10 @@ public class Swagger extends SwaggerElement {
 	 */
 	public Swagger path(String path, String methodName, Operation operation) {
 		if (paths == null)
-			paths = new LinkedHashMap<>();
+			paths = new TreeMap<>();
 		Map<String,Operation> p = paths.get(path);
 		if (p == null) {
-			p = new LinkedHashMap<>();
+			p = new TreeMap<>(OP_SORTER);
 			paths.put(path, p);
 		}
 		p.put(methodName, operation);
@@ -603,6 +603,8 @@ public class Swagger extends SwaggerElement {
 	 */
 	@SuppressWarnings({ "unchecked", "rawtypes" })
 	public Swagger paths(Object...values) {
+		if (paths == null)
+			paths = new TreeMap<>();
 		paths = addToMap((Map)paths, values, String.class, Map.class, String.class, Operation.class);
 		return this;
 	}
@@ -1241,27 +1243,27 @@ public class Swagger extends SwaggerElement {
 		return new MultiSet<>(s, super.keySet());
 	}
 	
-//	static final class MethodSorter implements Comparator<String> {
-//		private final Map<String,Integer> methods = new AMap<String,Integer>()
-//			.append("get",7)
-//			.append("put",6)
-//			.append("post",5)
-//			.append("delete",4)
-//			.append("options",3)
-//			.append("head",2)
-//			.append("patch",1);
-//
-//		@Override
-//		public int compare(String o1, String o2) {
-//			Integer i1 = methods.get(o1);
-//			Integer i2 = methods.get(o2);
-//			if (i1 == null)
-//				i1 = 0;
-//			if (i2 == null)
-//				i2 = 0;
-//			return i2.compareTo(i1);
-//		}
-//	}
+	private static final Comparator<String> OP_SORTER = new Comparator<String>() {
+		private final Map<String,Integer> methods = new AMap<String,Integer>()
+			.append("get",7)
+			.append("put",6)
+			.append("post",5)
+			.append("delete",4)
+			.append("options",3)
+			.append("head",2)
+			.append("patch",1);
+
+		@Override
+		public int compare(String o1, String o2) {
+			Integer i1 = methods.get(o1);
+			Integer i2 = methods.get(o2);
+			if (i1 == null)
+				i1 = 0;
+			if (i2 == null)
+				i2 = 0;
+			return i2.compareTo(i1);
+		}
+	};
 
 	@Override /* Object */
 	public String toString() {
diff --git a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java
index b3b110a..aeb965b 100644
--- a/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java
+++ b/juneau-core/juneau-dto/src/main/java/org/apache/juneau/dto/swagger/ui/SwaggerUI.java
@@ -46,12 +46,14 @@ public class SwaggerUI extends PojoSwap<Swagger,Div> {
 		// Operations without tags are rendered first.
 		outer.child(div()._class("tag-block tag-block-open").children(tagBlockContents(s, null)));
 
-		for (Tag t : s.getTags()) {
-			Div tagBlock = div()._class("tag-block tag-block-open").children(
-				tagBlockSummary(t),
-				tagBlockContents(s, t)
-			);
-			outer.child(tagBlock);
+		if (s.getTags() != null) {
+			for (Tag t : s.getTags()) {
+				Div tagBlock = div()._class("tag-block tag-block-open").children(
+					tagBlockSummary(t),
+					tagBlockContents(s, t)
+				);
+				outer.child(tagBlock);
+			}
 		}
 		
 		return outer;
@@ -118,9 +120,10 @@ public class SwaggerUI extends PojoSwap<Swagger,Div> {
 			
 			for (ParameterInfo pi : op.getParameters()) {
 				String piName = "body".equals(pi.getIn()) ? "body" : pi.getName();
+				boolean required = pi.getRequired() == null ? false : pi.getRequired();
 				
 				Td parameterKey = td(
-					div(piName)._class("name" + (pi.getRequired() ? " required" : "")),
+					div(piName)._class("name" + (required ? " required" : "")),
 					div(pi.getType())._class("type"),
 					div('(' + pi.getIn() + ')')._class("in")
 				)._class("parameter-key");
@@ -199,6 +202,8 @@ public class SwaggerUI extends PojoSwap<Swagger,Div> {
 		String ref = si.getRef();
 		if (ref != null) 
 			si = s.findRef(ref, SchemaInfo.class);
+		if (si == null)
+			throw new BeanRuntimeException("Reference not found in swagger document: {0}", ref); 
 		return si;
 	}
 	
@@ -212,17 +217,16 @@ public class SwaggerUI extends PojoSwap<Swagger,Div> {
 		if (examples == null)
 			return null;
 		
-		Ul ul = ul()._class("tab");
-		Div div = div(ul)._class("examples");
+		Select select = (Select)select().onchange("selectExample(this)")._class("example-select");
+		select.child(option("model","model"));
+		Div div = div(select)._class("examples");
 		
-		ul.child(li("model").onclick("selectExample(this)").attr("data-name", "model")._class("active"));
 		div.child(div(getSchemaModel(s, si))._class("model active").attr("data-name", "model"));
 
 		for (Map.Entry<String,String> e : examples.entrySet()) {
 			String name = e.getKey();
 			String value = e.getValue();
-			
-			ul.child(li(name).onclick("selectExample(this)").attr("data-name", name));
+			select.child(option(name, name));
 			div.child(div(value.replaceAll("\\n", "\n"))._class("example").attr("data-name", name));
 		}
 		
diff --git a/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css b/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css
index e1b0b17..9984f06 100644
--- a/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css
+++ b/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.css
@@ -125,9 +125,11 @@
  ----------------------------------------------------------------------------------------------------------*/
 
 .op-block-section-header {
-	padding: 8px 20px;
-    background: hsla(0,0%,100%,.2);
-    box-shadow: 0 1px 2px rgba(0,0,0,.1);
+    padding: 8px 20px;
+    background: hsla(0,0%,100%,.3);
+    box-shadow: 1px 2px 3px rgba(0,0,0,.3);
+    margin: 10px;
+    border-radius: 4px;
 }
 
 .op-block-section-header .title {
@@ -202,33 +204,16 @@ td.parameter-value, td.response-value {
  - Examples
  ----------------------------------------------------------------------------------------------------------*/
  
-.op-block-contents .tab {
-    display: flex;
-    margin: 20px 0 10px;
-    padding: 0;
-    list-style: none;
-}
-
-.op-block-contents .tab li {
-    font-weight: bold;
-    opacity: 0.5;
-    font-size: 12px;
-	margin: 0px 2px;
-    cursor: pointer;
-}
-
-.op-block-contents .tab li.active {
-    opacity: 1.0;
-	cursor: auto;
-}
-
-.op-block-contents .tab li:not(:last-child):after {
-    content: " -";
-    box-sizing: inherit;
-}
-
-.op-block-contents .tab li:hover {
-    opacity: 1.0;
+.op-block-contents .example-select {
+    margin: 20px 0 10px 0;
+	border-width: 1px;
+	font-weight:bold;
+	font-size: 14px;
+    padding: 5px 40px 5px 10px;
+    border: 1px solid #41444e;
+    border-radius: 4px;
+    box-shadow: 0 1px 2px 0 rgba(0,0,0,.25);
+    background: hsla(0,0%,100%,.3);
 }
 
 .op-block-contents .example {
@@ -258,11 +243,6 @@ td.parameter-value, td.response-value {
 	display: none;
 }
 
-.op-block-contents .model th, 
-.op-block-contents .model td {
-    padding: 0px;
-}
-
 .op-block-contents .model.active {
 	display:block;
 }
diff --git a/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.js b/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.js
index 5d59506..2314da2 100644
--- a/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.js
+++ b/juneau-core/juneau-dto/src/main/resources/org/apache/juneau/dto/swagger/ui/SwaggerUI.js
@@ -41,18 +41,15 @@ function toggleOpBlock(e) {
 
 /* Shows an example */
 function selectExample(e) {
-	var dataName = e.getAttribute("data-name");
+	var dataName = e.value;
 	var examplesNode = e.parentNode.parentNode;
-	var lis = examplesNode.getElementsByTagName("li");
 	var divs = examplesNode.getElementsByTagName("div");
 	
-	for (var i in lis) {
-		var li = lis[i], div = divs[i];
-		if (li.getAttribute("data-name") == dataName) {
-			li.classList.add("active");
+	for (var i in divs) {
+		var div = divs[i];
+		if (div.getAttribute("data-name") == dataName) {
 			div.classList.add("active");
 		} else {
-			li.classList.remove("active");
 			div.classList.remove("active");
 		}
 	}
diff --git a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
index 1459a78..6b73e8d 100644
--- a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
+++ b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserBuilder.java
@@ -27,7 +27,7 @@ import org.apache.juneau.xml.annotation.*;
 /**
  * Builder class for building instances of RDF parsers.
  */
-public class RdfParserBuilder extends ParserBuilder {
+public class RdfParserBuilder extends ReaderParserBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -337,27 +337,27 @@ public class RdfParserBuilder extends ParserBuilder {
 		return language(Constants.LANG_RDF_XML_ABBREV);
 	}
 
-	@Override /* ParserBuilder */
-	public RdfParserBuilder autoCloseStreams(boolean value) {
-		super.autoCloseStreams(value);
+	@Override /* ReaderParserBuilder */
+	public RdfParserBuilder fileCharset(String value) {
+		super.fileCharset(value);
 		return this;
 	}
 
-	@Override /* ParserBuilder */
-	public RdfParserBuilder autoCloseStreams() {
-		super.autoCloseStreams();
+	@Override /* ReaderParserBuilder */
+	public RdfParserBuilder inputStreamCharset(String value) {
+		super.inputStreamCharset(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public RdfParserBuilder fileCharset(String value) {
-		super.fileCharset(value);
+	public RdfParserBuilder autoCloseStreams(boolean value) {
+		super.autoCloseStreams(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public RdfParserBuilder inputStreamCharset(String value) {
-		super.inputStreamCharset(value);
+	public RdfParserBuilder autoCloseStreams() {
+		super.autoCloseStreams();
 		return this;
 	}
 
diff --git a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
index 0a92639..4e33691 100644
--- a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
+++ b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerBuilder.java
@@ -27,7 +27,7 @@ import org.apache.juneau.xml.annotation.*;
 /**
  * Builder class for building instances of RDF serializers.
  */
-public class RdfSerializerBuilder extends SerializerBuilder {
+public class RdfSerializerBuilder extends WriterSerializerBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -423,6 +423,42 @@ public class RdfSerializerBuilder extends SerializerBuilder {
 		return language(Constants.LANG_RDF_XML_ABBREV);
 	}
 
+	@Override /* WriterSerializerBuilder */
+	public RdfSerializerBuilder maxIndent(int value) {
+		super.maxIndent(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public RdfSerializerBuilder quoteChar(char value) {
+		super.quoteChar(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public RdfSerializerBuilder sq() {
+		super.sq();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public RdfSerializerBuilder useWhitespace(boolean value) {
+		super.useWhitespace(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public RdfSerializerBuilder useWhitespace() {
+		super.useWhitespace();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public RdfSerializerBuilder ws() {
+		super.ws();
+		return this;
+	}
+
 	@Override /* SerializerBuilder */
 	public RdfSerializerBuilder abridged(boolean value) {
 		super.abridged(value);
@@ -483,18 +519,6 @@ public class RdfSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public RdfSerializerBuilder maxIndent(int value) {
-		super.maxIndent(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public RdfSerializerBuilder quoteChar(char value) {
-		super.quoteChar(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public RdfSerializerBuilder sortCollections(boolean value) {
 		super.sortCollections(value);
 		return this;
@@ -519,12 +543,6 @@ public class RdfSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public RdfSerializerBuilder sq() {
-		super.sq();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public RdfSerializerBuilder trimEmptyCollections(boolean value) {
 		super.trimEmptyCollections(value);
 		return this;
@@ -584,24 +602,6 @@ public class RdfSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
-	@Override /* SerializerBuilder */
-	public RdfSerializerBuilder useWhitespace(boolean value) {
-		super.useWhitespace(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public RdfSerializerBuilder useWhitespace() {
-		super.useWhitespace();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public RdfSerializerBuilder ws() {
-		super.ws();
-		return this;
-	}
-
 	@Override /* BeanContextBuilder */
 	public RdfSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
index 7f69424..41df0f1 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
@@ -907,6 +907,58 @@ public class BeanContext extends Context {
 	public static final String BEAN_excludeProperties = PREFIX + "excludeProperties.sms";
 
 	/**
+	 * Configuration property:  Find fluent setters.
+	 * 
+	 * <h5 class='section'>Property:</h5>
+	 * <ul>
+	 * 	<li><b>Name:</b>  <js>"BeanContext.fluentSetters.b"</js>
+	 * 	<li><b>Data type:</b>  <code>Boolean</code>
+	 * 	<li><b>Default:</b>  <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b>  <jk>false</jk>
+	 * 	<li><b>Annotations:</b> 
+	 * 		<ul>
+	 * 			<li class='ja'>{@link Bean#fluentSetters()} 
+	 * 		</ul>
+	 * 	<li><b>Methods:</b> 
+	 * 		<ul>
+	 * 			<li class='jm'>{@link BeanContextBuilder#fluentSetters(boolean)}
+	 * 			<li class='jm'>{@link BeanContextBuilder#fluentSetters()}
+	 * 			<li class='jm'>{@link BeanFilterBuilder#fluentSetters(boolean)}
+	 * 			<li class='jm'>{@link BeanFilterBuilder#fluentSetters()}
+	 * 		</ul>
+	 * </ul>
+	 * 
+	 * <h5 class='section'>Description:</h5>
+	 * <p>
+	 * When enabled, fluent setters are detected on beans.
+	 * 
+	 * <p>
+	 * Fluent setters must have the following attributes:
+	 * <ul>
+	 * 	<li>Public.
+	 * 	<li>Not static.
+	 * 	<li>Take in one parameter.
+	 * 	<li>Return the bean itself.
+	 * </ul>
+	 * 
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Create a serializer that finds fluent setters.</jc>
+	 * 	WriterSerializer s = JsonSerializer
+	 * 		.<jsm>create</jsm>()
+	 * 		.fluentSetters()
+	 * 		.build();
+	 * 
+	 * 	<jc>// Same, but use property.</jc>
+	 * 	WriterSerializer s = JsonSerializer
+	 * 		.<jsm>create</jsm>()
+	 * 		.set(<jsf>BEAN_fluentSetters</jsf>, <jk>true</jk>)
+	 * 		.build();
+	 * </p>
+	 */
+	public static final String BEAN_fluentSetters = PREFIX + "fluentSetters.b";
+
+	/**
 	 * Configuration property:  Ignore invocation errors on getters.
 	 * 
 	 * <h5 class='section'>Property:</h5>
@@ -1799,6 +1851,7 @@ public class BeanContext extends Context {
 		ignoreInvocationExceptionsOnSetters,
 		useJavaBeanIntrospector,
 		sortProperties,
+		fluentSetters,
 		debug;
 
 	final Visibility
@@ -1855,6 +1908,7 @@ public class BeanContext extends Context {
 		ignoreInvocationExceptionsOnSetters = getBooleanProperty(BEAN_ignoreInvocationExceptionsOnSetters, false);
 		useJavaBeanIntrospector = getBooleanProperty(BEAN_useJavaBeanIntrospector, false);
 		sortProperties = getBooleanProperty(BEAN_sortProperties, false);
+		fluentSetters = getBooleanProperty(BEAN_fluentSetters, false);
 		beanTypePropertyName = getStringProperty(BEAN_beanTypePropertyName, "_type");
 		debug = getBooleanProperty(BEAN_debug, false);
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
index dd3ca9c..c9a87b0 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextBuilder.java
@@ -665,6 +665,52 @@ public class BeanContextBuilder extends ContextBuilder {
 	}
 
 	/**
+	 * Configuration property:  Find fluent setters.
+	 * 
+	 * <p>
+	 * When enabled, fluent setters are detected on beans.
+	 * 
+	 * <p>
+	 * Fluent setters must have the following attributes:
+	 * <ul>
+	 * 	<li>Public.
+	 * 	<li>Not static.
+	 * 	<li>Take in one parameter.
+	 * 	<li>Return the bean itself.
+	 * </ul>
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link BeanContext#BEAN_fluentSetters}
+	 * </ul>
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default is <jk>false</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public BeanContextBuilder fluentSetters(boolean value) {
+		return set(BEAN_fluentSetters, value);
+	}
+
+	/**
+	 * Configuration property:  Find fluent setters.
+	 * 
+	 * <p>
+	 * Shortcut for calling <code>fluentSetters(<jk>true</jk>)</code>.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link BeanContext#BEAN_fluentSetters}
+	 * </ul>
+	 * 
+	 * @return This object (for method chaining).
+	 */
+	public BeanContextBuilder fluentSetters() {
+		return set(BEAN_fluentSetters, true);
+	}
+
+	/**
 	 * Configuration property:  Ignore invocation errors on getters.
 	 * 
 	 * <p>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
index 90268a3..a3efa3a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
@@ -12,8 +12,8 @@
 // ***************************************************************************************************************************
 package org.apache.juneau;
 
-import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.ClassFlags.*;
+import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.CollectionUtils.*;
 import static org.apache.juneau.internal.ReflectionUtils.*;
 import static org.apache.juneau.internal.StringUtils.*;
@@ -100,6 +100,7 @@ public class BeanMeta<T> {
 	final String notABeanReason;                           // Readable string explaining why this class wasn't a bean.
 	final BeanRegistry beanRegistry;
 	final boolean sortProperties;
+	final boolean fluentSetters;
 
 	/**
 	 * Constructor.
@@ -131,6 +132,7 @@ public class BeanMeta<T> {
 		this.typePropertyName = b.typePropertyName;
 		this.typeProperty = BeanPropertyMeta.builder(this, typePropertyName).canRead().canWrite().rawMetaType(ctx.string()).beanRegistry(beanRegistry).build();
 		this.sortProperties = b.sortProperties;
+		this.fluentSetters = b.fluentSetters;
 	}
 
 	private static final class Builder<T> {
@@ -150,7 +152,7 @@ public class BeanMeta<T> {
 		PropertyNamer propertyNamer;
 		BeanRegistry beanRegistry;
 		String dictionaryName, typePropertyName;
-		boolean sortProperties;
+		boolean sortProperties, fluentSetters;
 
 		Builder(ClassMeta<T> classMeta, BeanContext ctx, BeanFilter beanFilter, String[] pNames) {
 			this.classMeta = classMeta;
@@ -186,6 +188,8 @@ public class BeanMeta<T> {
 				if (typePropertyName == null)
 					typePropertyName = ctx.getBeanTypePropertyName();
 
+				fluentSetters = (ctx.fluentSetters || (beanFilter != null && beanFilter.isFluentSetters()));
+
 				// If @Bean.interfaceClass is specified on the parent class, then we want
 				// to use the properties defined on that class, not the subclass.
 				Class<?> c2 = (beanFilter != null && beanFilter.getInterfaceClass() != null ? beanFilter.getInterfaceClass() : c);
@@ -293,7 +297,7 @@ public class BeanMeta<T> {
 						}
 					}
 
-					List<BeanMethod> bms = findBeanMethods(c2, stopClass, mVis, fixedBeanProps, filterProps, propertyNamer);
+					List<BeanMethod> bms = findBeanMethods(c2, stopClass, mVis, fixedBeanProps, filterProps, propertyNamer, fluentSetters);
 
 					// Iterate through all the getters.
 					for (BeanMethod bm : bms) {
@@ -557,7 +561,7 @@ public class BeanMeta<T> {
 	 * @param fixedBeanProps Only include methods whose properties are in this list.
 	 * @param pn Use this property namer to determine property names from the method names.
 	 */
-	static final List<BeanMethod> findBeanMethods(Class<?> c, Class<?> stopClass, Visibility v, Set<String> fixedBeanProps, Set<String> filterProps, PropertyNamer pn) {
+	static final List<BeanMethod> findBeanMethods(Class<?> c, Class<?> stopClass, Visibility v, Set<String> fixedBeanProps, Set<String> filterProps, PropertyNamer pn, boolean fluentSetters) {
 		List<BeanMethod> l = new LinkedList<>();
 
 		for (Class<?> c2 : findClasses(c, stopClass)) {
@@ -617,6 +621,8 @@ public class BeanMeta<T> {
 						} else {
 							n = bpName;
 						}
+					} else if (fluentSetters && isParentClass(rt, c)) {
+						isSetter = true;
 					}
 				} else if (pt.length == 2) {
 					if ("*".equals(bpName)) {
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BinaryFormat.java
similarity index 62%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BinaryFormat.java
index ebb62b4..ea5de81 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BinaryFormat.java
@@ -1,44 +1,44 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.parser;
-
-import org.apache.juneau.*;
-
-/**
- * Subclass of {@link Parser} for byte-based parsers.
- * 
- * <h5 class='topic'>Description</h5>
- * 
- * This class is typically the parent class of all byte-based parsers.
- * It has 1 abstract method to implement...
- * <ul>
- * 	<li><code>parse(InputStream, ClassMeta, Parser)</code>
- * </ul>
-  */
-public abstract class InputStreamParser extends Parser {
-
-	/**
-	 * Constructor.
-	 * 
-	 * @param ps The property store containing all the settings for this object.
-	 * @param consumes The list of media types that this parser consumes (e.g. <js>"application/json"</js>).
-	 */
-	protected InputStreamParser(PropertyStore ps, String...consumes) {
-		super(ps, consumes);
-	}
-
-	@Override /* Parser */
-	public final boolean isReaderParser() {
-		return false;
-	}
-}
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              * 
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau;
+
+/**
+ * Possible values for encoding of byte arrays as strings.
+ */
+public enum BinaryFormat {
+
+	/**
+	 * Spaced-hex.
+	 * 
+	 * <h5 class='figure>Example:</h5>
+	 * <p class='bcode'>
+	 * 	12 34 56 78 90 AB CD EF
+	 * </p>
+	 */
+	SPACED_HEX,
+	
+	/**
+	 * Hex.
+	 * 
+	 * <h5 class='figure>Example:</h5>
+	 * <p class='bcode'>
+	 * 	1234567890ABCDEF
+	 * </p>
+	 */
+	HEX,
+	
+	/**
+	 * BASE-64.
+	 */
+	BASE64
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index f3b9c4f..aaf0fbe 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -13,8 +13,8 @@
 package org.apache.juneau;
 
 import static org.apache.juneau.ClassMeta.ClassCategory.*;
-import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.ClassFlags.*;
+import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.ReflectionUtils.*;
 
 import java.io.*;
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Bean.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Bean.java
index fbf9f6a..6ab7348 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Bean.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/annotation/Bean.java
@@ -69,6 +69,40 @@ public @interface Bean {
 	String excludeProperties() default "";
 
 	/**
+	 * Find fluent setters.
+	 * 
+	 * <p>
+	 * When <jk>true</jk>, fluent setters will be detected on beans.
+	 * 
+	 * <p>
+	 * Fluent setters 
+	 * 
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<ja>@Bean</ja>(fluentSetters=<jk>true</jk>)
+	 * 	<jk>public class</jk> MyBean {
+	 * 		<jk>public int</jk> getId() {...}
+	 * 		<jk>public</jk> MyBean id(<jk>int</jk> id) {...}
+	 * 	}
+	 * </p>
+	 * 
+	 * <p>
+	 * Fluent setters must have the following attributes:
+	 * <ul>
+	 * 	<li>Public.
+	 * 	<li>Not static.
+	 * 	<li>Take in one parameter.
+	 * 	<li>Return the bean itself.
+	 * </ul>
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link BeanContext#BEAN_fluentSetters}
+	 * </ul>
+	 */
+	boolean fluentSetters() default false;
+
+	/**
 	 * Identifies a class to be used as the interface class for this and all subclasses.
 	 * 
 	 * <p>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
index 3e2a396..7d4d297 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParserBuilder.java
@@ -21,7 +21,7 @@ import org.apache.juneau.parser.*;
 /**
  * Builder class for building instances of CSV parsers.
  */
-public class CsvParserBuilder extends ParserBuilder {
+public class CsvParserBuilder extends ReaderParserBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -48,27 +48,27 @@ public class CsvParserBuilder extends ParserBuilder {
 	// Properties
 	//--------------------------------------------------------------------------------
 
-	@Override /* ParserBuilder */
-	public CsvParserBuilder autoCloseStreams(boolean value) {
-		super.autoCloseStreams(value);
+	@Override /* ReaderParserBuilder */
+	public CsvParserBuilder fileCharset(String value) {
+		super.fileCharset(value);
 		return this;
 	}
 
-	@Override /* ParserBuilder */
-	public CsvParserBuilder autoCloseStreams() {
-		super.autoCloseStreams();
+	@Override /* ReaderParserBuilder */
+	public CsvParserBuilder inputStreamCharset(String value) {
+		super.inputStreamCharset(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public CsvParserBuilder fileCharset(String value) {
-		super.fileCharset(value);
+	public CsvParserBuilder autoCloseStreams(boolean value) {
+		super.autoCloseStreams(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public CsvParserBuilder inputStreamCharset(String value) {
-		super.inputStreamCharset(value);
+	public CsvParserBuilder autoCloseStreams() {
+		super.autoCloseStreams();
 		return this;
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
index 12c0ff9..b977d80 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerBuilder.java
@@ -21,7 +21,7 @@ import org.apache.juneau.serializer.*;
 /**
  * Builder class for building instances of CSV serializers.
  */
-public class CsvSerializerBuilder extends SerializerBuilder {
+public class CsvSerializerBuilder extends WriterSerializerBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -49,6 +49,42 @@ public class CsvSerializerBuilder extends SerializerBuilder {
 	// Properties
 	//--------------------------------------------------------------------------------
 
+	@Override /* WriterSerializerBuilder */
+	public CsvSerializerBuilder maxIndent(int value) {
+		super.maxIndent(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public CsvSerializerBuilder quoteChar(char value) {
+		super.quoteChar(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public CsvSerializerBuilder sq() {
+		super.sq();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public CsvSerializerBuilder useWhitespace(boolean value) {
+		super.useWhitespace(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public CsvSerializerBuilder useWhitespace() {
+		super.useWhitespace();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public CsvSerializerBuilder ws() {
+		super.ws();
+		return this;
+	}
+
 	@Override /* SerializerBuilder */
 	public CsvSerializerBuilder abridged(boolean value) {
 		super.abridged(value);
@@ -109,18 +145,6 @@ public class CsvSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public CsvSerializerBuilder maxIndent(int value) {
-		super.maxIndent(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public CsvSerializerBuilder quoteChar(char value) {
-		super.quoteChar(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public CsvSerializerBuilder sortCollections(boolean value) {
 		super.sortCollections(value);
 		return this;
@@ -145,12 +169,6 @@ public class CsvSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public CsvSerializerBuilder sq() {
-		super.sq();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public CsvSerializerBuilder trimEmptyCollections(boolean value) {
 		super.trimEmptyCollections(value);
 		return this;
@@ -210,24 +228,6 @@ public class CsvSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
-	@Override /* SerializerBuilder */
-	public CsvSerializerBuilder useWhitespace(boolean value) {
-		super.useWhitespace(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public CsvSerializerBuilder useWhitespace() {
-		super.useWhitespace();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public CsvSerializerBuilder ws() {
-		super.ws();
-		return this;
-	}
-
 	@Override /* BeanContextBuilder */
 	public CsvSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
index d5d4dad..3965271 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserBuilder.java
@@ -83,13 +83,13 @@ public class HtmlParserBuilder extends XmlParserBuilder {
 		return this;
 	}
 
-	@Override /* ParserBuilder */
+	@Override /* ReaderParserBuilder */
 	public HtmlParserBuilder fileCharset(String value) {
 		super.fileCharset(value);
 		return this;
 	}
 
-	@Override /* ParserBuilder */
+	@Override /* ReaderParserBuilder */
 	public HtmlParserBuilder inputStreamCharset(String value) {
 		super.inputStreamCharset(value);
 		return this;
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
index 123845b..d7d82ac 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
@@ -598,7 +598,7 @@ public class HtmlSerializer extends XmlSerializer {
 		public Sq(PropertyStore ps) {
 			super(
 				ps.builder()
-					.set(SERIALIZER_quoteChar, '\'')
+					.set(WSERIALIZER_quoteChar, '\'')
 					.build()
 			);
 		}
@@ -615,8 +615,8 @@ public class HtmlSerializer extends XmlSerializer {
 		public SqReadable(PropertyStore ps) {
 			super(
 				ps.builder()
-					.set(SERIALIZER_quoteChar, '\'')
-					.set(SERIALIZER_useWhitespace, true)
+					.set(WSERIALIZER_quoteChar, '\'')
+					.set(WSERIALIZER_useWhitespace, true)
 					.build()
 			);
 		}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
index bef6d36..d8e2700 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
@@ -13,8 +13,8 @@
 package org.apache.juneau.html;
 
 import static org.apache.juneau.html.HtmlSerializer.*;
-import static org.apache.juneau.xml.XmlSerializerSession.ContentResult.*;
 import static org.apache.juneau.internal.StringUtils.*;
+import static org.apache.juneau.xml.XmlSerializerSession.ContentResult.*;
 
 import java.io.*;
 import java.util.*;
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/AsciiSet.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/AsciiSet.java
index 14484fe..4efa915 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/AsciiSet.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/AsciiSet.java
@@ -12,7 +12,7 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.internal;
 
-import java.util.Arrays;
+import java.util.*;
 
 /**
  * Stores a set of ASCII characters for quick lookup.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/BeanPropertyUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/BeanPropertyUtils.java
index f0219b6..e88b64c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/BeanPropertyUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/BeanPropertyUtils.java
@@ -93,7 +93,7 @@ public final class BeanPropertyUtils {
 			List<T> l = appendTo == null ? new ArrayList<T>() : appendTo;
 			for (Object o : values) {
 				if (o != null) {
-					if (isObjectList(o)) {
+					if (isObjectList(o, false)) {
 						for (Object o2 : new ObjectList(o.toString())) 
 							l.add(toType(o2, type, args));
 					} else if (o instanceof Collection) {
@@ -133,7 +133,7 @@ public final class BeanPropertyUtils {
 			Map<K,V> m = appendTo == null ? new LinkedHashMap<K,V>() : appendTo;
 			for (Object o : values) {
 				if (o != null) {
-					if (isObjectMap(o)) {
+					if (isObjectMap(o, false)) {
 						for (Map.Entry<String,Object> e : new ObjectMap(o.toString()).entrySet()) 
 							m.put(toType(e.getKey(), keyType), toType(e.getValue(), valueType, valueTypeArgs));
 					} else if (o instanceof Map) {
@@ -240,4 +240,59 @@ public final class BeanPropertyUtils {
 		m.put(key, value);
 		return m;
 	}
+
+	/**
+	 * Creates a new map from the specified map.
+	 * 
+	 * @param val The value to copy from.
+	 * @param comparator The key comparator to use, or <jk>null</jk> to use natural ordering.
+	 * @return A new {@link LinkedHashMap}, or <jk>null</jk> if the input was null.
+	 */
+	public static <K,V> Map<K,V> newSortedMap(Map<K,V> val, Comparator<K> comparator) {
+		if (val == null)
+			return null;
+		Map<K,V> m = new TreeMap<>(comparator);
+		m.putAll(val);
+		return m;
+	}
+	
+	/**
+	 * Copies the specified values into an existing map.
+	 * 
+	 * @param m 
+	 * 	The map to add to.
+	 * 	<br>If <jk>null</jk>, a new {@link LinkedHashMap} will be created.
+	 * @param val The values to add.
+	 * @param comparator The key comparator to use, or <jk>null</jk> to use natural ordering.
+	 * @return The list with values copied into it.
+	 */
+	public static <K,V> Map<K,V> addToSortedMap(Map<K,V> m, Map<K,V> val, Comparator<K> comparator) {
+		if (val != null) {
+			if (m == null) {
+				m = new TreeMap<>(comparator);
+				m.putAll(val);
+			} else {
+				m.putAll(val);
+			}
+		}
+		return m;
+	}
+
+	/**
+	 * Adds a single entry into an existing map.
+	 * 
+	 * @param m 
+	 * 	The map to add to.
+	 * 	<br>If <jk>null</jk>, a new {@link LinkedHashMap} will be created.
+	 * @param key The entry key.
+	 * @param value The entry value.
+	 * @param comparator The key comparator to use, or <jk>null</jk> to use natural ordering.
+	 * @return The list with values copied into it.
+	 */
+	public static <K,V> Map<K,V> addToSortedMap(Map<K,V> m, K key, V value, Comparator<K> comparator) {
+		if (m == null) 
+			m = new TreeMap<>(comparator);
+		m.put(key, value);
+		return m;
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
index 4cc55fc..372dde2 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/internal/StringUtils.java
@@ -2033,12 +2033,23 @@ public final class StringUtils {
 	 * Returns <jk>true</jk> if the specified string appears to be an JSON array.
 	 * 
 	 * @param o The object to test.
+	 * @param ignoreWhitespaceAndComments If <jk>true</jk>, leading and trailing whitespace and comments will be ignored.
 	 * @return <jk>true</jk> if the specified string appears to be a JSON array.
 	 */
-	public static boolean isObjectList(Object o) {
+	public static boolean isObjectList(Object o, boolean ignoreWhitespaceAndComments) {
 		if (o instanceof CharSequence) {
 			String s = o.toString();
-			return (s.startsWith("[") && s.endsWith("]") && BeanContext.DEFAULT != null);
+			if (! ignoreWhitespaceAndComments)
+				return (s.startsWith("[") && s.endsWith("]"));
+			if (firstRealCharacter(s) != '[')
+				return false;
+			int i = s.lastIndexOf(']');
+			if (i == -1)
+				return false;
+			s = s.substring(i+1);
+			if (firstRealCharacter(s) != -1)
+				return false;
+			return true;
 		}
 		return false;
 	}
@@ -2047,13 +2058,77 @@ public final class StringUtils {
 	 * Returns <jk>true</jk> if the specified string appears to be a JSON object.
 	 * 
 	 * @param o The object to test.
+	 * @param ignoreWhitespaceAndComments If <jk>true</jk>, leading and trailing whitespace and comments will be ignored.
 	 * @return <jk>true</jk> if the specified string appears to be a JSON object.
 	 */
-	public static boolean isObjectMap(Object o) {
+	public static boolean isObjectMap(Object o, boolean ignoreWhitespaceAndComments) {
 		if (o instanceof CharSequence) {
 			String s = o.toString();
-			return (s.startsWith("{") && s.endsWith("}") && BeanContext.DEFAULT != null);
+			if (! ignoreWhitespaceAndComments)
+				return (s.startsWith("{") && s.endsWith("}"));
+			if (firstRealCharacter(s) != '{')
+				return false;
+			int i = s.lastIndexOf('}');
+			if (i == -1)
+				return false;
+			s = s.substring(i+1);
+			if (firstRealCharacter(s) != -1)
+				return false;
+			return true;
 		}
 		return false;
 	}
+	
+	private static int firstRealCharacter(String s) {
+		try (StringReader r = new StringReader(s)) {
+			int c = 0;
+			while ((c = r.read()) != -1) {
+				if (! Character.isWhitespace(c)) {
+					if (c == '/') {
+						skipComments(r);
+					} else {
+						return c;
+					}
+				}
+			}
+			return -1;
+		} catch (Exception e) {
+			throw new RuntimeException(e);
+		}
+	}
+	private static void skipComments(StringReader r) throws IOException {
+		int c = r.read();
+		//  "/* */" style comments
+		if (c == '*') {
+			while (c != -1)
+				if ((c = r.read()) == '*')
+					if ((c = r.read()) == '/')
+						return;
+		//  "//" style comments
+		} else if (c == '/') {
+			while (c != -1) {
+				c = r.read();
+				if (c == -1 || c == '\n')
+					return;
+			}
+		}
+	}
+
+	/**
+	 * Takes in a string, splits it by lines, and then prepends each line with line numbers.
+	 * 
+	 * @param s The string.
+	 * @return The string with line numbers added.
+	 */
+	public static String addLineNumbers(String s) {
+		if (s == null)
+			return null;
+		String[] lines = s.split("[\r\n]+");
+		final int digits = String.valueOf(lines.length).length();
+		StringBuilder sb = new StringBuilder();
+		int i = 1;
+		for (String l : lines) 
+			sb.append(String.format("%0"+digits+"d", i++)).append(": ").append(l).append("\n");
+		return sb.toString();
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
index 04ee3e6..8e71038 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoParserBuilder.java
@@ -21,7 +21,7 @@ import org.apache.juneau.parser.*;
 /**
  * Builder class for building instances of Java Serialized Object parsers.
  */
-public class JsoParserBuilder extends ParserBuilder {
+public class JsoParserBuilder extends InputStreamParserBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -49,6 +49,12 @@ public class JsoParserBuilder extends ParserBuilder {
 	// Properties
 	//--------------------------------------------------------------------------------
 
+	@Override /* InputStreamParserBuilder */
+	public JsoParserBuilder binaryFormat(BinaryFormat value) {
+		super.binaryFormat(value);
+		return this;
+	}
+
 	@Override /* ParserBuilder */
 	public JsoParserBuilder autoCloseStreams(boolean value) {
 		super.autoCloseStreams(value);
@@ -62,18 +68,6 @@ public class JsoParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* ParserBuilder */
-	public JsoParserBuilder fileCharset(String value) {
-		super.fileCharset(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public JsoParserBuilder inputStreamCharset(String value) {
-		super.inputStreamCharset(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
 	public JsoParserBuilder listener(Class<? extends ParserListener> value) {
 		super.listener(value);
 		return this;
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
index e6791ca..4db69fa 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoSerializerBuilder.java
@@ -21,7 +21,7 @@ import org.apache.juneau.serializer.*;
 /**
  * Builder class for building instances of Java Serialized Object serializers.
  */
-public class JsoSerializerBuilder extends SerializerBuilder {
+public class JsoSerializerBuilder extends OutputStreamSerializerBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -49,6 +49,12 @@ public class JsoSerializerBuilder extends SerializerBuilder {
 	// Properties
 	//--------------------------------------------------------------------------------
 
+	@Override /* OutputStreamSerializerBuilder */
+	public JsoSerializerBuilder binaryFormat(BinaryFormat value) {
+		super.binaryFormat(value);
+		return this;
+	}
+
 	@Override /* SerializerBuilder */
 	public JsoSerializerBuilder abridged(boolean value) {
 		super.abridged(value);
@@ -109,18 +115,6 @@ public class JsoSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public JsoSerializerBuilder maxIndent(int value) {
-		super.maxIndent(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public JsoSerializerBuilder quoteChar(char value) {
-		super.quoteChar(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public JsoSerializerBuilder sortCollections(boolean value) {
 		super.sortCollections(value);
 		return this;
@@ -145,12 +139,6 @@ public class JsoSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public JsoSerializerBuilder sq() {
-		super.sq();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public JsoSerializerBuilder trimEmptyCollections(boolean value) {
 		super.trimEmptyCollections(value);
 		return this;
@@ -210,24 +198,6 @@ public class JsoSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
-	@Override /* SerializerBuilder */
-	public JsoSerializerBuilder useWhitespace(boolean value) {
-		super.useWhitespace(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public JsoSerializerBuilder useWhitespace() {
-		super.useWhitespace();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public JsoSerializerBuilder ws() {
-		super.ws();
-		return this;
-	}
-
 	@Override /* BeanContextBuilder */
 	public JsoSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
index 826b6ef..f0a964b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
@@ -23,7 +23,7 @@ import org.apache.juneau.parser.*;
 /**
  * Builder class for building instances of JSON parsers.
  */
-public class JsonParserBuilder extends ParserBuilder {
+public class JsonParserBuilder extends ReaderParserBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -89,27 +89,27 @@ public class JsonParserBuilder extends ParserBuilder {
 		return set(JSON_validateEnd, true);
 	}
 
-	@Override /* ParserBuilder */
-	public JsonParserBuilder autoCloseStreams(boolean value) {
-		super.autoCloseStreams(value);
+	@Override /* ReaderParserBuilder */
+	public JsonParserBuilder fileCharset(String value) {
+		super.fileCharset(value);
 		return this;
 	}
 
-	@Override /* ParserBuilder */
-	public JsonParserBuilder autoCloseStreams() {
-		super.autoCloseStreams();
+	@Override /* ReaderParserBuilder */
+	public JsonParserBuilder inputStreamCharset(String value) {
+		super.inputStreamCharset(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public JsonParserBuilder fileCharset(String value) {
-		super.fileCharset(value);
+	public JsonParserBuilder autoCloseStreams(boolean value) {
+		super.autoCloseStreams(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public JsonParserBuilder inputStreamCharset(String value) {
-		super.inputStreamCharset(value);
+	public JsonParserBuilder autoCloseStreams() {
+		super.autoCloseStreams();
 		return this;
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaUtils.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaUtils.java
new file mode 100644
index 0000000..b6faa6c
--- /dev/null
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaUtils.java
@@ -0,0 +1,105 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              * 
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.json;
+
+import static org.apache.juneau.internal.ClassUtils.*;
+
+import java.lang.reflect.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.transform.*;
+
+/**
+ * Utility class for JSON-schema.
+ */
+public class JsonSchemaUtils {
+	
+	/**
+	 * Returns the JSON-schema for the specified type.
+	 * 
+	 * @param bs The current bean session.
+	 * @param type The object type.
+	 * @return The schema for the type.
+	 * @throws Exception
+	 */
+	public static ObjectMap getSchema(BeanSession bs, Type type) throws Exception {
+		return getSchema(bs, bs.getClassMeta(type), null, null);
+	}
+	
+	@SuppressWarnings({ "unchecked", "rawtypes" })
+	private static ObjectMap getSchema(BeanSession bs, ClassMeta<?> eType, String attrName, String[] pNames) throws Exception {
+		ObjectMap out = new ObjectMap();
+
+		if (eType == null)
+			eType = bs.object();
+
+		ClassMeta<?> aType;			// The actual type (will be null if recursion occurs)
+		ClassMeta<?> sType;			// The serialized type
+		
+		aType = eType;
+
+		sType = eType.getSerializedClassMeta(bs);
+		String type = null;
+
+		if (sType.isEnum() || sType.isCharSequence() || sType.isChar())
+			type = "string";
+		else if (sType.isNumber())
+			type = "number";
+		else if (sType.isBoolean())
+			type = "boolean";
+		else if (sType.isMapOrBean())
+			type = "object";
+		else if (sType.isCollectionOrArray())
+			type = "array";
+		else
+			type = "any";
+
+		out.put("type", type);
+		out.put("description", eType.toString());
+		PojoSwap f = eType.getPojoSwap(bs);
+		if (f != null)
+			out.put("transform", f);
+
+		if (aType != null) {
+			if (sType.isEnum())
+				out.put("enum", getEnumStrings((Class<Enum<?>>)sType.getInnerClass()));
+			else if (sType.isCollectionOrArray()) {
+				ClassMeta componentType = sType.getElementType();
+				if (sType.isCollection() && isParentClass(Set.class, sType.getInnerClass()))
+					out.put("uniqueItems", true);
+				out.put("items", getSchema(bs, componentType, "items", pNames));
+			} else if (sType.isBean()) {
+				ObjectMap properties = new ObjectMap();
+				BeanMeta bm = bs.getBeanMeta(sType.getInnerClass());
+				if (pNames != null)
+					bm = new BeanMetaFiltered(bm, pNames);
+				for (Iterator<BeanPropertyMeta> i = bm.getPropertyMetas().iterator(); i.hasNext();) {
+					BeanPropertyMeta p = i.next();
+					if (p.canRead())
+						properties.put(p.getName(), getSchema(bs, p.getClassMeta(), p.getName(), p.getProperties()));
+				}
+				out.put("properties", properties);
+			}
+		}
+		return out;
+	}
+
+	@SuppressWarnings({ "unchecked", "rawtypes" })
+	private static List<String> getEnumStrings(Class<? extends Enum> c) {
+		List<String> l = new LinkedList<>();
+		for (Object e : EnumSet.allOf(c))
+			l.add(e.toString());
+		return l;
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
index 8081465..d02af26 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
@@ -286,7 +286,7 @@ public class JsonSerializer extends WriterSerializer {
 		 */
 		public Readable(PropertyStore ps) {
 			super(
-				ps.builder().set(SERIALIZER_useWhitespace, true).build()
+				ps.builder().set(WSERIALIZER_useWhitespace, true).build()
 			);
 		}
 	}
@@ -303,7 +303,7 @@ public class JsonSerializer extends WriterSerializer {
 			super(
 				ps.builder()
 					.set(JSON_simpleMode, true)
-					.set(SERIALIZER_quoteChar, '\'')
+					.set(WSERIALIZER_quoteChar, '\'')
 					.build(),
 				"application/json",
 				"application/json+simple", "text/json+simple"
@@ -323,8 +323,8 @@ public class JsonSerializer extends WriterSerializer {
 			super(
 				ps.builder()
 					.set(JSON_simpleMode, true)
-					.set(SERIALIZER_quoteChar, '\'')
-					.set(SERIALIZER_useWhitespace, true)
+					.set(WSERIALIZER_quoteChar, '\'')
+					.set(WSERIALIZER_useWhitespace, true)
 					.build()
 			);
 		}
@@ -345,8 +345,8 @@ public class JsonSerializer extends WriterSerializer {
 			super(
 				ps.builder()
 					.set(JSON_simpleMode, true)
-					.set(SERIALIZER_quoteChar, '\'')
-					.set(SERIALIZER_useWhitespace, true)
+					.set(WSERIALIZER_quoteChar, '\'')
+					.set(WSERIALIZER_useWhitespace, true)
 					.set(SERIALIZER_detectRecursions, true)
 					.build()
 			);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
index e535186..32e3e13 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerBuilder.java
@@ -23,7 +23,7 @@ import org.apache.juneau.serializer.*;
 /**
  * Builder class for building instances of JSON serializers.
  */
-public class JsonSerializerBuilder extends SerializerBuilder {
+public class JsonSerializerBuilder extends WriterSerializerBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -135,7 +135,7 @@ public class JsonSerializerBuilder extends SerializerBuilder {
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
 	 * 	<li class='jf'>{@link JsonSerializer#JSON_simpleMode}
-	 * 	<li class='jf'>{@link JsonSerializer#SERIALIZER_quoteChar}
+	 * 	<li class='jf'>{@link JsonSerializer#WSERIALIZER_quoteChar}
 	 * </ul>
 	 * 
 	 * @return This object (for method chaining).
@@ -144,6 +144,42 @@ public class JsonSerializerBuilder extends SerializerBuilder {
 		return simple().sq();
 	}
 	
+	@Override /* WriterSerializerBuilder */
+	public JsonSerializerBuilder maxIndent(int value) {
+		super.maxIndent(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public JsonSerializerBuilder quoteChar(char value) {
+		super.quoteChar(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public JsonSerializerBuilder sq() {
+		super.sq();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public JsonSerializerBuilder useWhitespace(boolean value) {
+		super.useWhitespace(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public JsonSerializerBuilder useWhitespace() {
+		super.useWhitespace();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public JsonSerializerBuilder ws() {
+		super.ws();
+		return this;
+	}
+
 	@Override /* SerializerBuilder */
 	public JsonSerializerBuilder abridged(boolean value) {
 		super.abridged(value);
@@ -204,18 +240,6 @@ public class JsonSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public JsonSerializerBuilder maxIndent(int value) {
-		super.maxIndent(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public JsonSerializerBuilder quoteChar(char value) {
-		super.quoteChar(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public JsonSerializerBuilder sortCollections(boolean value) {
 		super.sortCollections(value);
 		return this;
@@ -240,12 +264,6 @@ public class JsonSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public JsonSerializerBuilder sq() {
-		super.sq();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public JsonSerializerBuilder trimEmptyCollections(boolean value) {
 		super.trimEmptyCollections(value);
 		return this;
@@ -305,24 +323,6 @@ public class JsonSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
-	@Override /* SerializerBuilder */
-	public JsonSerializerBuilder useWhitespace(boolean value) {
-		super.useWhitespace(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public JsonSerializerBuilder useWhitespace() {
-		super.useWhitespace();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public JsonSerializerBuilder ws() {
-		super.ws();
-		return this;
-	}
-
 	@Override /* BeanContextBuilder */
 	public JsonSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
index 85a5368..e933642 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
@@ -31,6 +31,45 @@ public class MsgPackParser extends InputStreamParser {
 	/** Default parser, all default settings.*/
 	public static final MsgPackParser DEFAULT = new MsgPackParser(PropertyStore.DEFAULT);
 
+	/** Default parser, all default settings, string input encoded as spaced-hex.*/
+	public static final MsgPackParser DEFAULT_SPACED_HEX = new SpacedHex(PropertyStore.DEFAULT);
+
+	/** Default parser, all default settings, string input encoded as BASE64.*/
+	public static final MsgPackParser DEFAULT_BASE64 = new Base64(PropertyStore.DEFAULT);
+	
+	//-------------------------------------------------------------------------------------------------------------------
+	// Predefined subclasses
+	//-------------------------------------------------------------------------------------------------------------------
+
+	/** Default parser, string input encoded as spaced-hex. */
+	public static class SpacedHex extends MsgPackParser {
+
+		/**
+		 * Constructor.
+		 * 
+		 * @param ps The property store containing all the settings for this object.
+		 */
+		public SpacedHex(PropertyStore ps) {
+			super(
+				ps.builder().set(ISPARSER_binaryFormat, BinaryFormat.SPACED_HEX).build()
+			);
+		}
+	}
+
+	/** Default parser, string input encoded as BASE64. */
+	public static class Base64 extends MsgPackParser {
+
+		/**
+		 * Constructor.
+		 * 
+		 * @param ps The property store containing all the settings for this object.
+		 */
+		public Base64(PropertyStore ps) {
+			super(
+				ps.builder().set(ISPARSER_binaryFormat, BinaryFormat.BASE64).build()
+			);
+		}
+	}
 
 	//-------------------------------------------------------------------------------------------------------------------
 	// Instance
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
index 894b569..3990e4b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserBuilder.java
@@ -21,7 +21,7 @@ import org.apache.juneau.parser.*;
 /**
  * Builder class for building instances of MessagePack parsers.
  */
-public class MsgPackParserBuilder extends ParserBuilder {
+public class MsgPackParserBuilder extends InputStreamParserBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -49,6 +49,12 @@ public class MsgPackParserBuilder extends ParserBuilder {
 	// Properties
 	//--------------------------------------------------------------------------------
 
+	@Override /* InputStreamParserBuilder */
+	public MsgPackParserBuilder binaryFormat(BinaryFormat value) {
+		super.binaryFormat(value);
+		return this;
+	}
+
 	@Override /* ParserBuilder */
 	public MsgPackParserBuilder autoCloseStreams(boolean value) {
 		super.autoCloseStreams(value);
@@ -62,18 +68,6 @@ public class MsgPackParserBuilder extends ParserBuilder {
 	}
 
 	@Override /* ParserBuilder */
-	public MsgPackParserBuilder fileCharset(String value) {
-		super.fileCharset(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public MsgPackParserBuilder inputStreamCharset(String value) {
-		super.inputStreamCharset(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
 	public MsgPackParserBuilder listener(Class<? extends ParserListener> value) {
 		super.listener(value);
 		return this;
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
index 611f8c6..6a4c1b5 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
@@ -66,6 +66,45 @@ public class MsgPackSerializer extends OutputStreamSerializer {
 	/** Default serializer, all default settings.*/
 	public static final MsgPackSerializer DEFAULT = new MsgPackSerializer(PropertyStore.DEFAULT);
 
+	/** Default serializer, all default settings, spaced-hex string output.*/
+	public static final MsgPackSerializer DEFAULT_SPACED_HEX = new SpacedHex(PropertyStore.DEFAULT);
+
+	/** Default serializer, all default settings, spaced-hex string output.*/
+	public static final MsgPackSerializer DEFAULT_BASE64 = new Base64(PropertyStore.DEFAULT);
+
+	//-------------------------------------------------------------------------------------------------------------------
+	// Predefined subclasses
+	//-------------------------------------------------------------------------------------------------------------------
+
+	/** Default serializer, spaced-hex string output. */
+	public static class SpacedHex extends MsgPackSerializer {
+
+		/**
+		 * Constructor.
+		 * 
+		 * @param ps The property store containing all the settings for this object.
+		 */
+		public SpacedHex(PropertyStore ps) {
+			super(
+				ps.builder().set(OSSERIALIZER_binaryFormat, BinaryFormat.SPACED_HEX).build()
+			);
+		}
+	}
+
+	/** Default serializer, BASE64 string output. */
+	public static class Base64 extends MsgPackSerializer {
+
+		/**
+		 * Constructor.
+		 * 
+		 * @param ps The property store containing all the settings for this object.
+		 */
+		public Base64(PropertyStore ps) {
+			super(
+				ps.builder().set(OSSERIALIZER_binaryFormat, BinaryFormat.BASE64).build()
+			);
+		}
+	}
 
 	//-------------------------------------------------------------------------------------------------------------------
 	// Instance
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
index 0360c95..024cb0f 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerBuilder.java
@@ -21,7 +21,7 @@ import org.apache.juneau.serializer.*;
 /**
  * Builder class for building instances of MessagePack serializers.
  */
-public class MsgPackSerializerBuilder extends SerializerBuilder {
+public class MsgPackSerializerBuilder extends OutputStreamSerializerBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -49,6 +49,12 @@ public class MsgPackSerializerBuilder extends SerializerBuilder {
 	// Properties
 	//--------------------------------------------------------------------------------
 
+	@Override /* OutputStreamSerializerBuilder */
+	public MsgPackSerializerBuilder binaryFormat(BinaryFormat value) {
+		super.binaryFormat(value);
+		return this;
+	}
+
 	@Override /* SerializerBuilder */
 	public MsgPackSerializerBuilder abridged(boolean value) {
 		super.abridged(value);
@@ -109,18 +115,6 @@ public class MsgPackSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public MsgPackSerializerBuilder maxIndent(int value) {
-		super.maxIndent(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public MsgPackSerializerBuilder quoteChar(char value) {
-		super.quoteChar(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public MsgPackSerializerBuilder sortCollections(boolean value) {
 		super.sortCollections(value);
 		return this;
@@ -145,12 +139,6 @@ public class MsgPackSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public MsgPackSerializerBuilder sq() {
-		super.sq();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public MsgPackSerializerBuilder trimEmptyCollections(boolean value) {
 		super.trimEmptyCollections(value);
 		return this;
@@ -210,24 +198,6 @@ public class MsgPackSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
-	@Override /* SerializerBuilder */
-	public MsgPackSerializerBuilder useWhitespace(boolean value) {
-		super.useWhitespace(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public MsgPackSerializerBuilder useWhitespace() {
-		super.useWhitespace();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public MsgPackSerializerBuilder ws() {
-		super.ws();
-		return this;
-	}
-
 	@Override /* BeanContextBuilder */
 	public MsgPackSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
index ebb62b4..7274a7a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
@@ -27,6 +27,64 @@ import org.apache.juneau.*;
   */
 public abstract class InputStreamParser extends Parser {
 
+	//-------------------------------------------------------------------------------------------------------------------
+	// Configurable properties
+	//-------------------------------------------------------------------------------------------------------------------
+
+	private static final String PREFIX = "InputStreamParser.";
+
+
+	/**
+	 * Configuration property:  Binary input format.
+	 * 
+	 * <h5 class='section'>Property:</h5>
+	 * <ul>
+	 * 	<li><b>Name:</b>  <js>"InputStreamParser.binaryFormat.s"</js>
+	 * 	<li><b>Data type:</b>  {@link BinaryFormat}
+	 * 	<li><b>Default:</b>  {@link BinaryFormat#HEX}
+	 * 	<li><b>Session-overridable:</b>  <jk>true</jk>
+	 * 	<li><b>Methods:</b> 
+	 * 		<ul>
+	 * 			<li class='jm'>{@link InputStreamParserBuilder#binaryFormat(BinaryFormat)}
+	 * 		</ul>
+	 * </ul>
+	 * 
+	 * <h5 class='section'>Description:</h5>
+	 * <p>
+	 * When using the {@link #parse(Object,Class)} method on stream-based parsers and the input is a string, this defines the format to use
+	 * when converting the string into a byte array.
+	 * 
+	 * 
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Create a parser that parses from BASE64.</jc>
+	 * 	InputStreamParser p = MsgPackParser
+	 * 		.<jsm>create</jsm>()
+	 * 		.binaryFormat(<jsf>BASE64</jsf>)
+	 * 		.build();
+	 * 	
+	 * 	<jc>// Same, but use property.</jc>
+	 * 	InputStreamParser p = MsgPackParser
+	 * 		.<jsm>create</jsm>()
+	 * 		.set(<jsf>ISPARSER_binaryFormat</jsf>, <js>"BASE64"</js>)
+	 * 		.build();
+	 * </p>
+	 */
+	public static final String ISPARSER_binaryFormat = PREFIX + "binaryFormat.s";
+	
+	static final InputStreamParser DEFAULT = new InputStreamParser(PropertyStore.create().build(), "") {
+		@Override
+		public InputStreamParserSession createSession(ParserSessionArgs args) {
+			throw new NoSuchMethodError();
+		}
+	};
+
+	//-------------------------------------------------------------------------------------------------------------------
+	// Instance
+	//-------------------------------------------------------------------------------------------------------------------
+
+	final BinaryFormat binaryFormat;
+	
 	/**
 	 * Constructor.
 	 * 
@@ -35,10 +93,20 @@ public abstract class InputStreamParser extends Parser {
 	 */
 	protected InputStreamParser(PropertyStore ps, String...consumes) {
 		super(ps, consumes);
+
+		binaryFormat = getProperty(ISPARSER_binaryFormat, BinaryFormat.class, BinaryFormat.HEX);
 	}
 
 	@Override /* Parser */
 	public final boolean isReaderParser() {
 		return false;
 	}
+
+	@Override /* Context */
+	public ObjectMap asMap() {
+		return super.asMap()
+			.append("InputStreamParser", new ObjectMap()
+				.append("binaryFormat", binaryFormat)
+			);
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserBuilder.java
similarity index 59%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserBuilder.java
index 826b6ef..04102d6 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserBuilder.java
@@ -10,25 +10,24 @@
 // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
 // * specific language governing permissions and limitations under the License.                                              *
 // ***************************************************************************************************************************
-package org.apache.juneau.json;
+package org.apache.juneau.parser;
 
-import static org.apache.juneau.json.JsonParser.*;
+import static org.apache.juneau.parser.InputStreamParser.*;
 
 import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
-import org.apache.juneau.parser.*;
 
 /**
- * Builder class for building instances of JSON parsers.
+ * Base builder class for building instances of stream-based parsers.
  */
-public class JsonParserBuilder extends ParserBuilder {
+public class InputStreamParserBuilder extends ParserBuilder {
 
 	/**
 	 * Constructor, default settings.
 	 */
-	public JsonParserBuilder() {
+	public InputStreamParserBuilder() {
 		super();
 	}
 
@@ -37,487 +36,457 @@ public class JsonParserBuilder extends ParserBuilder {
 	 * 
 	 * @param ps The initial configuration settings for this builder.
 	 */
-	public JsonParserBuilder(PropertyStore ps) {
+	public InputStreamParserBuilder(PropertyStore ps) {
 		super(ps);
 	}
 
-	@Override /* ContextBuilder */
-	public JsonParser build() {
-		return build(JsonParser.class);
-	}
-
-
 	//--------------------------------------------------------------------------------
 	// Properties
 	//--------------------------------------------------------------------------------
 
 	/**
-	 * Configuration property:  Validate end.
+	 * Configuration property:  Binary input format.
 	 * 
 	 * <p>
-	 * If <jk>true</jk>, after parsing a POJO from the input, verifies that the remaining input in 
-	 * the stream consists of only comments or whitespace.
+	 * When using the {@link Parser#parse(Object,Class)} method on stream-based parsers and the input is a string, this defines the format to use
+	 * when converting the string into a byte array.
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link JsonParser#JSON_validateEnd}
+	 * 	<li class='jf'>{@link InputStreamParser#ISPARSER_binaryFormat}
 	 * </ul>
 	 * 
 	 * @param value 
 	 * 	The new value for this property.
-	 * 	<br>The default value is <jk>false</jk>.
+	 * 	<br>The default value is {@link BinaryFormat#HEX}.
 	 * @return This object (for method chaining).
 	 */
-	public JsonParserBuilder validateEnd(boolean value) {
-		return set(JSON_validateEnd, value);
-	}
-	
-	/**
-	 * Configuration property:  Validate end.
-	 * 
-	 * <p>
-	 * Shortcut for calling <code>validateEnd(<jk>true</jk>)</code>.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link JsonParser#JSON_validateEnd}
-	 * </ul>
-	 * 
-	 * @return This object (for method chaining).
-	 */
-	public JsonParserBuilder validateEnd() {
-		return set(JSON_validateEnd, true);
+	public InputStreamParserBuilder binaryFormat(BinaryFormat value) {
+		return set(ISPARSER_binaryFormat, value);
 	}
 
 	@Override /* ParserBuilder */
-	public JsonParserBuilder autoCloseStreams(boolean value) {
+	public InputStreamParserBuilder autoCloseStreams(boolean value) {
 		super.autoCloseStreams(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public JsonParserBuilder autoCloseStreams() {
+	public InputStreamParserBuilder autoCloseStreams() {
 		super.autoCloseStreams();
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public JsonParserBuilder fileCharset(String value) {
-		super.fileCharset(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public JsonParserBuilder inputStreamCharset(String value) {
-		super.inputStreamCharset(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public JsonParserBuilder listener(Class<? extends ParserListener> value) {
+	public InputStreamParserBuilder listener(Class<? extends ParserListener> value) {
 		super.listener(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public JsonParserBuilder strict(boolean value) {
+	public InputStreamParserBuilder strict(boolean value) {
 		super.strict(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public JsonParserBuilder strict() {
+	public InputStreamParserBuilder strict() {
 		super.strict();
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public JsonParserBuilder trimStrings(boolean value) {
+	public InputStreamParserBuilder trimStrings(boolean value) {
 		super.trimStrings(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public JsonParserBuilder trimStrings() {
+	public InputStreamParserBuilder trimStrings() {
 		super.trimStrings();
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public JsonParserBuilder unbuffered(boolean value) {
+	public InputStreamParserBuilder unbuffered(boolean value) {
 		super.unbuffered(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public JsonParserBuilder unbuffered() {
+	public InputStreamParserBuilder unbuffered() {
 		super.unbuffered();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beansRequireDefaultConstructor(boolean value) {
-		super.beansRequireDefaultConstructor(value);
+	public InputStreamParserBuilder beanClassVisibility(Visibility value) {
+		super.beanClassVisibility(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beansRequireDefaultConstructor() {
-		super.beansRequireDefaultConstructor();
+	public InputStreamParserBuilder beanConstructorVisibility(Visibility value) {
+		super.beanConstructorVisibility(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beansRequireSerializable(boolean value) {
-		super.beansRequireSerializable(value);
+	public InputStreamParserBuilder beanDictionary(boolean append, Object...values) {
+		super.beanDictionary(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beansRequireSerializable() {
-		super.beansRequireSerializable();
+	public InputStreamParserBuilder beanDictionary(Class<?>...values) {
+		super.beanDictionary(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beansRequireSettersForGetters(boolean value) {
-		super.beansRequireSettersForGetters(value);
+	public InputStreamParserBuilder beanDictionary(Object...values) {
+		super.beanDictionary(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beansRequireSettersForGetters() {
-		super.beansRequireSettersForGetters();
+	public InputStreamParserBuilder beanDictionaryRemove(Object...values) {
+		super.beanDictionaryRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beansRequireSomeProperties(boolean value) {
-		super.beansRequireSomeProperties(value);
+	public InputStreamParserBuilder beanFieldVisibility(Visibility value) {
+		super.beanFieldVisibility(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanMapPutReturnsOldValue(boolean value) {
-		super.beanMapPutReturnsOldValue(value);
+	public InputStreamParserBuilder beanFilters(boolean append, Object...values) {
+		super.beanFilters(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanMapPutReturnsOldValue() {
-		super.beanMapPutReturnsOldValue();
+	public InputStreamParserBuilder beanFilters(Class<?>...values) {
+		super.beanFilters(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanConstructorVisibility(Visibility value) {
-		super.beanConstructorVisibility(value);
+	public InputStreamParserBuilder beanFilters(Object...values) {
+		super.beanFilters(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanClassVisibility(Visibility value) {
-		super.beanClassVisibility(value);
+	public InputStreamParserBuilder beanFiltersRemove(Object...values) {
+		super.beanFiltersRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanFieldVisibility(Visibility value) {
-		super.beanFieldVisibility(value);
+	public InputStreamParserBuilder beanMapPutReturnsOldValue(boolean value) {
+		super.beanMapPutReturnsOldValue(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanMethodVisibility(Visibility value) {
-		super.beanMethodVisibility(value);
+	public InputStreamParserBuilder beanMapPutReturnsOldValue() {
+		super.beanMapPutReturnsOldValue();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder useJavaBeanIntrospector(boolean value) {
-		super.useJavaBeanIntrospector(value);
+	public InputStreamParserBuilder beansRequireDefaultConstructor(boolean value) {
+		super.beansRequireDefaultConstructor(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder useJavaBeanIntrospector() {
-		super.useJavaBeanIntrospector();
+	public InputStreamParserBuilder beansRequireDefaultConstructor() {
+		super.beansRequireDefaultConstructor();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder useInterfaceProxies(boolean value) {
-		super.useInterfaceProxies(value);
+	public InputStreamParserBuilder beansRequireSerializable(boolean value) {
+		super.beansRequireSerializable(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder ignoreUnknownBeanProperties(boolean value) {
-		super.ignoreUnknownBeanProperties(value);
+	public InputStreamParserBuilder beansRequireSerializable() {
+		super.beansRequireSerializable();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder ignoreUnknownBeanProperties() {
-		super.ignoreUnknownBeanProperties();
+	public InputStreamParserBuilder beansRequireSettersForGetters(boolean value) {
+		super.beansRequireSettersForGetters(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder ignoreUnknownNullBeanProperties(boolean value) {
-		super.ignoreUnknownNullBeanProperties(value);
+	public InputStreamParserBuilder beansRequireSettersForGetters() {
+		super.beansRequireSettersForGetters();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder ignorePropertiesWithoutSetters(boolean value) {
-		super.ignorePropertiesWithoutSetters(value);
+	public InputStreamParserBuilder beansRequireSomeProperties(boolean value) {
+		super.beansRequireSomeProperties(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder ignoreInvocationExceptionsOnGetters(boolean value) {
-		super.ignoreInvocationExceptionsOnGetters(value);
+	public InputStreamParserBuilder beanTypePropertyName(String value) {
+		super.beanTypePropertyName(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder ignoreInvocationExceptionsOnGetters() {
-		super.ignoreInvocationExceptionsOnGetters();
+	public InputStreamParserBuilder debug() {
+		super.debug();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder ignoreInvocationExceptionsOnSetters(boolean value) {
-		super.ignoreInvocationExceptionsOnSetters(value);
+	public InputStreamParserBuilder ignoreInvocationExceptionsOnGetters(boolean value) {
+		super.ignoreInvocationExceptionsOnGetters(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder ignoreInvocationExceptionsOnSetters() {
-		super.ignoreInvocationExceptionsOnSetters();
+	public InputStreamParserBuilder ignoreInvocationExceptionsOnGetters() {
+		super.ignoreInvocationExceptionsOnGetters();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder sortProperties(boolean value) {
-		super.sortProperties(value);
+	public InputStreamParserBuilder ignoreInvocationExceptionsOnSetters(boolean value) {
+		super.ignoreInvocationExceptionsOnSetters(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder sortProperties() {
-		super.sortProperties();
+	public InputStreamParserBuilder ignoreInvocationExceptionsOnSetters() {
+		super.ignoreInvocationExceptionsOnSetters();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder notBeanPackages(Object...values) {
-		super.notBeanPackages(values);
+	public InputStreamParserBuilder ignorePropertiesWithoutSetters(boolean value) {
+		super.ignorePropertiesWithoutSetters(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder notBeanPackages(String...values) {
-		super.notBeanPackages(values);
+	public InputStreamParserBuilder ignoreUnknownBeanProperties(boolean value) {
+		super.ignoreUnknownBeanProperties(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder notBeanPackages(boolean append, Object...values) {
-		super.notBeanPackages(append, values);
+	public InputStreamParserBuilder ignoreUnknownBeanProperties() {
+		super.ignoreUnknownBeanProperties();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder notBeanPackagesRemove(Object...values) {
-		super.notBeanPackagesRemove(values);
+	public InputStreamParserBuilder ignoreUnknownNullBeanProperties(boolean value) {
+		super.ignoreUnknownNullBeanProperties(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder notBeanClasses(Object...values) {
-		super.notBeanClasses(values);
+	public <T> InputStreamParserBuilder implClass(Class<T> interfaceClass, Class<? extends T> implClass) {
+		super.implClass(interfaceClass, implClass);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder notBeanClasses(Class<?>...values) {
-		super.notBeanClasses(values);
+	public InputStreamParserBuilder implClasses(Map<String,Class<?>> values) {
+		super.implClasses(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder notBeanClasses(boolean append, Object...values) {
-		super.notBeanClasses(append, values);
+	public InputStreamParserBuilder locale(Locale value) {
+		super.locale(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder notBeanClassesRemove(Object...values) {
-		super.notBeanClassesRemove(values);
+	public InputStreamParserBuilder mediaType(MediaType value) {
+		super.mediaType(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanFilters(Object...values) {
-		super.beanFilters(values);
+	public InputStreamParserBuilder beanMethodVisibility(Visibility value) {
+		super.beanMethodVisibility(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanFilters(Class<?>...values) {
-		super.beanFilters(values);
+	public InputStreamParserBuilder notBeanClasses(boolean append, Object...values) {
+		super.notBeanClasses(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanFilters(boolean append, Object...values) {
-		super.beanFilters(append, values);
+	public InputStreamParserBuilder notBeanClasses(Class<?>...values) {
+		super.notBeanClasses(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanFiltersRemove(Object...values) {
-		super.beanFiltersRemove(values);
+	public InputStreamParserBuilder notBeanClasses(Object...values) {
+		super.notBeanClasses(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder pojoSwaps(Object...values) {
-		super.pojoSwaps(values);
+	public InputStreamParserBuilder notBeanClassesRemove(Object...values) {
+		super.notBeanClassesRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder pojoSwaps(Class<?>...values) {
-		super.pojoSwaps(values);
+	public InputStreamParserBuilder notBeanPackages(boolean append, Object...values) {
+		super.notBeanPackages(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder pojoSwaps(boolean append, Object...values) {
-		super.pojoSwaps(append, values);
+	public InputStreamParserBuilder notBeanPackages(Object...values) {
+		super.notBeanPackages(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder pojoSwapsRemove(Object...values) {
-		super.pojoSwapsRemove(values);
+	public InputStreamParserBuilder notBeanPackages(String...values) {
+		super.notBeanPackages(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder implClasses(Map<String,Class<?>> values) {
-		super.implClasses(values);
+	public InputStreamParserBuilder notBeanPackagesRemove(Object...values) {
+		super.notBeanPackagesRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public <T> JsonParserBuilder implClass(Class<T> interfaceClass, Class<? extends T> implClass) {
-		super.implClass(interfaceClass, implClass);
+	public InputStreamParserBuilder pojoSwaps(boolean append, Object...values) {
+		super.pojoSwaps(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanDictionary(Object...values) {
-		super.beanDictionary(values);
+	public InputStreamParserBuilder pojoSwaps(Class<?>...values) {
+		super.pojoSwaps(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanDictionary(Class<?>...values) {
-		super.beanDictionary(values);
+	public InputStreamParserBuilder pojoSwaps(Object...values) {
+		super.pojoSwaps(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanDictionary(boolean append, Object...values) {
-		super.beanDictionary(append, values);
+	public InputStreamParserBuilder pojoSwapsRemove(Object...values) {
+		super.pojoSwapsRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanDictionaryRemove(Object...values) {
-		super.beanDictionaryRemove(values);
+	public InputStreamParserBuilder sortProperties(boolean value) {
+		super.sortProperties(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder beanTypePropertyName(String value) {
-		super.beanTypePropertyName(value);
+	public InputStreamParserBuilder sortProperties() {
+		super.sortProperties();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder locale(Locale value) {
-		super.locale(value);
+	public InputStreamParserBuilder timeZone(TimeZone value) {
+		super.timeZone(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder timeZone(TimeZone value) {
-		super.timeZone(value);
+	public InputStreamParserBuilder useInterfaceProxies(boolean value) {
+		super.useInterfaceProxies(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder mediaType(MediaType value) {
-		super.mediaType(value);
+	public InputStreamParserBuilder useJavaBeanIntrospector(boolean value) {
+		super.useJavaBeanIntrospector(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public JsonParserBuilder debug() {
-		super.debug();
+	public InputStreamParserBuilder useJavaBeanIntrospector() {
+		super.useJavaBeanIntrospector();
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public JsonParserBuilder set(String name, Object value) {
+	public InputStreamParserBuilder set(String name, Object value) {
 		super.set(name, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public JsonParserBuilder set(boolean append, String name, Object value) {
+	public InputStreamParserBuilder set(boolean append, String name, Object value) {
 		super.set(append, name, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public JsonParserBuilder set(Map<String,Object> properties) {
+	public InputStreamParserBuilder set(Map<String,Object> properties) {
 		super.set(properties);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public JsonParserBuilder add(Map<String,Object> properties) {
+	public InputStreamParserBuilder add(Map<String,Object> properties) {
 		super.add(properties);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public JsonParserBuilder addTo(String name, Object value) {
+	public InputStreamParserBuilder addTo(String name, Object value) {
 		super.addTo(name, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public JsonParserBuilder addTo(String name, String key, Object value) {
+	public InputStreamParserBuilder addTo(String name, String key, Object value) {
 		super.addTo(name, key, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public JsonParserBuilder removeFrom(String name, Object value) {
+	public InputStreamParserBuilder removeFrom(String name, Object value) {
 		super.removeFrom(name, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public JsonParserBuilder apply(PropertyStore copyFrom) {
+	public InputStreamParserBuilder apply(PropertyStore copyFrom) {
 		super.apply(copyFrom);
 		return this;
 	}
+	
+	@Override /* Context */
+	public InputStreamParser build() {
+		return null;
+	}
 }
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserSession.java
index c12376a..44943d4 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParserSession.java
@@ -12,6 +12,12 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.parser;
 
+import static org.apache.juneau.parser.InputStreamParser.*;
+
+import java.io.*;
+
+import org.apache.juneau.*;
+
 /**
  * Subclass of parser session objects for byte-based parsers.
  * 
@@ -20,6 +26,8 @@ package org.apache.juneau.parser;
  */
 public abstract class InputStreamParserSession extends ParserSession {
 
+	private final BinaryFormat binaryFormat;
+	
 	/**
 	 * Create a new session using properties specified in the context.
 	 * 
@@ -29,8 +37,10 @@ public abstract class InputStreamParserSession extends ParserSession {
 	 * @param args
 	 * 	Runtime session arguments.
 	 */
-	protected InputStreamParserSession(Parser ctx, ParserSessionArgs args) {
+	protected InputStreamParserSession(InputStreamParser ctx, ParserSessionArgs args) {
 		super(ctx, args);
+		
+		binaryFormat = getProperty(ISPARSER_binaryFormat, BinaryFormat.class, BinaryFormat.HEX);
 	}
 
 	/**
@@ -40,11 +50,42 @@ public abstract class InputStreamParserSession extends ParserSession {
 	 * 	Runtime session arguments.
 	 */
 	protected InputStreamParserSession(ParserSessionArgs args) {
-		super(args);
+		this(InputStreamParser.DEFAULT, args);
 	}
 
 	@Override /* ParserSession */
 	public final boolean isReaderParser() {
 		return false;
 	}
+	
+	/**
+	 * Wraps the specified input object into a {@link ParserPipe} object so that it can be easily converted into
+	 * a stream or reader.
+	 * 
+	 * @param input
+	 * 	The input.
+	 * 	</ul>
+	 * 	<br>This can be any of the following types:
+	 * 	<ul>
+	 * 		<li><jk>null</jk>
+	 * 		<li>{@link InputStream}
+	 * 		<li><code><jk>byte</jk>[]</code>
+	 * 		<li>{@link File}
+	 * 		<li>{@link CharSequence} containing encoded bytes according to the {@link InputStreamParser#ISPARSER_binaryFormat} setting.
+	 * 	</ul>
+	 * @return
+	 * 	A new {@link ParserPipe} wrapper around the specified input object.
+	 */
+	@Override /* ParserSession */
+	public final ParserPipe createPipe(Object input) {
+		return new ParserPipe(input, isDebug(), strict, autoCloseStreams, unbuffered, null, null, binaryFormat);
+	}
+
+	@Override /* Session */
+	public ObjectMap asMap() {
+		return super.asMap()
+			.append("InputStreamParserSession", new ObjectMap()
+				.append("binaryFormat", binaryFormat)
+			);
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
index f7d4538..707b4e6 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
@@ -14,7 +14,6 @@ package org.apache.juneau.parser;
 
 import java.io.*;
 import java.lang.reflect.*;
-import java.nio.charset.*;
 import java.util.*;
 
 import org.apache.juneau.*;
@@ -169,95 +168,6 @@ public abstract class Parser extends BeanContext {
 	public static final String PARSER_autoCloseStreams = PREFIX + "autoCloseStreams.b";
 
 	/**
-	 * Configuration property:  File charset.
-	 * 
-	 * <h5 class='section'>Property:</h5>
-	 * <ul>
-	 * 	<li><b>Name:</b>  <js>"Parser.fileCharset.s"</js>
-	 * 	<li><b>Data type:</b>  <code>String</code>
-	 * 	<li><b>Default:</b>  <js>"DEFAULT"</js>
-	 * 	<li><b>Session-overridable:</b>  <jk>true</jk>
-	 * 	<li><b>Methods:</b> 
-	 * 		<ul>
-	 * 			<li class='jm'>{@link ParserBuilder#fileCharset(String)}
-	 * 			<li class='jm'>{@link ParserBuilder#fileCharset(Charset)}
-	 * 		</ul>
-	 * </ul>
-	 * 
-	 * <h5 class='section'>Description:</h5>
-	 * <p>
-	 * The character set to use for reading <code>Files</code> from the file system.
-	 * 
-	 * <p>
-	 * Used when passing in files to {@link Parser#parse(Object, Class)}.
-	 * 
-	 * <p>
-	 * <js>"DEFAULT"</js> can be used to indicate the JVM default file system charset.
-	 * 
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<jc>// Create a parser that reads UTF-8 files.</jc>
-	 * 	ReaderParser p = JsonParser.
-	 * 		.<jsm>create</jsm>()
-	 * 		.fileCharset(<js>"UTF-8"</js>)
-	 * 		.build();
-	 * 	
-	 * 	<jc>// Same, but use property.</jc>
-	 * 	ReaderParser p = JsonParser.
-	 * 		.<jsm>create</jsm>()
-	 * 		.set(<jsf>PARSER_fileCharset</jsf>, <js>"UTF-8"</js>)
-	 * 		.build();
-	 * 
-	 * 	<jc>// Use it to read a UTF-8 encoded file.</jc>
-	 * 	MyBean myBean = p.parse(<jk>new</jk> File(<js>"MyBean.txt"</js>), MyBean.<jk>class</jk>);
-	 * </p>
-	 */
-	public static final String PARSER_fileCharset = PREFIX + "fileCharset.s";
-
-	/**
-	 * Configuration property:  Input stream charset.
-	 * 
-	 * <h5 class='section'>Property:</h5>
-	 * <ul>
-	 * 	<li><b>Name:</b>  <js>"Parser.inputStreamCharset.s"</js>
-	 * 	<li><b>Data type:</b>  <code>String</code>
-	 * 	<li><b>Default:</b>  <js>"UTF-8"</js>
-	 * 	<li><b>Session-overridable:</b>  <jk>true</jk>
-	 * 	<li><b>Methods:</b> 
-	 * 		<ul>
-	 * 			<li class='jm'>{@link ParserBuilder#inputStreamCharset(String)}
-	 * 			<li class='jm'>{@link ParserBuilder#inputStreamCharset(Charset)}
-	 * 		</ul>
-	 * </ul>
-	 * 
-	 * <h5 class='section'>Description:</h5>
-	 * <p>
-	 * The character set to use for converting <code>InputStreams</code> and byte arrays to readers.
-	 * 
-	 * <p>
-	 * Used when passing in input streams and byte arrays to {@link Parser#parse(Object, Class)}.
-	 * 
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<jc>// Create a parser that reads UTF-8 files.</jc>
-	 * 	ReaderParser p = JsonParser.
-	 * 		.<jsm>create</jsm>()
-	 * 		.inputStreamCharset(<js>"UTF-8"</js>)
-	 * 		.build();
-	 * 	
-	 * 	<jc>// Same, but use property.</jc>
-	 * 	ReaderParser p = JsonParser.
-	 * 		.<jsm>create</jsm>()
-	 * 		.set(<jsf>PARSER_inputStreamCharset</jsf>, <js>"UTF-8"</js>)
-	 * 		.build();
-	 * 
-	 * 	<jc>// Use it to read a UTF-8 encoded input stream.</jc>
-	 * 	MyBean myBean = p.parse(<jk>new</jk> FileInputStream(<js>"MyBean.txt"</js>), MyBean.<jk>class</jk>);
-	 * </p>
-	 */
-	public static final String PARSER_inputStreamCharset = PREFIX + "inputStreamCharset.s";
-
-	/**
 	 * Configuration property:  Parser listener.
 	 * 
 	 * <h5 class='section'>Property:</h5>
@@ -517,7 +427,6 @@ public abstract class Parser extends BeanContext {
 	//-------------------------------------------------------------------------------------------------------------------
 
 	final boolean trimStrings, strict, autoCloseStreams, unbuffered;
-	final String inputStreamCharset, fileCharset;
 	final Class<? extends ParserListener> listener;
 
 	/** General parser properties currently set on this parser. */
@@ -531,8 +440,6 @@ public abstract class Parser extends BeanContext {
 		strict = getBooleanProperty(PARSER_strict, false);
 		autoCloseStreams = getBooleanProperty(PARSER_autoCloseStreams, false);
 		unbuffered = getBooleanProperty(PARSER_unbuffered, false);
-		inputStreamCharset = getStringProperty(PARSER_inputStreamCharset, "UTF-8");
-		fileCharset = getStringProperty(PARSER_fileCharset, "DEFAULT");
 		listener = getClassProperty(PARSER_listener, ParserListener.class, null);
 		this.consumes = new MediaType[consumes.length];
 		for (int i = 0; i < consumes.length; i++) {
@@ -643,11 +550,11 @@ public abstract class Parser extends BeanContext {
 	 * 		<li>{@link Reader}
 	 * 		<li>{@link CharSequence}
 	 * 		<li>{@link InputStream} containing UTF-8 encoded text (or charset defined by
-	 * 			{@link #PARSER_inputStreamCharset} property value).
+	 * 			{@link ReaderParser#RPARSER_inputStreamCharset} property value).
 	 * 		<li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or charset defined by
-	 * 			{@link #PARSER_inputStreamCharset} property value).
+	 * 			{@link ReaderParser#RPARSER_inputStreamCharset} property value).
 	 * 		<li>{@link File} containing system encoded text (or charset defined by
-	 * 			{@link #PARSER_fileCharset} property value).
+	 * 			{@link ReaderParser#RPARSER_fileCharset} property value).
 	 * 	</ul>
 	 * 	<br>Stream-based parsers can handle the following input class types:
 	 * 	<ul>
@@ -655,6 +562,7 @@ public abstract class Parser extends BeanContext {
 	 * 		<li>{@link InputStream}
 	 * 		<li><code><jk>byte</jk>[]</code>
 	 * 		<li>{@link File}
+	 * 		<li>{@link CharSequence} containing encoded bytes according to the {@link InputStreamParser#ISPARSER_binaryFormat} setting.
 	 * 	</ul>
 	 * @param type
 	 * 	The object type to create.
@@ -853,8 +761,6 @@ public abstract class Parser extends BeanContext {
 			.append("Parser", new ObjectMap()
 				.append("trimStrings", trimStrings)
 				.append("strict", strict)
-				.append("inputStreamCharset", inputStreamCharset)
-				.append("fileCharset", fileCharset)
 				.append("listener", listener)
 			);
 	}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserBuilder.java
index 56477a6..5163a57 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserBuilder.java
@@ -14,7 +14,6 @@ package org.apache.juneau.parser;
 
 import static org.apache.juneau.parser.Parser.*;
 
-import java.nio.charset.*;
 import java.util.*;
 
 import org.apache.juneau.*;
@@ -84,86 +83,6 @@ public class ParserBuilder extends BeanContextBuilder {
 	}
 
 	/**
-	 * Configuration property:  File charset.
-	 * 
-	 * <p>
-	 * The character set to use for reading <code>Files</code> from the file system.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Parser#PARSER_fileCharset}
-	 * </ul>
-	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>The default value is <js>"DEFAULT"</js> which causes the system default to be used.
-	 * @return This object (for method chaining).
-	 */
-	public ParserBuilder fileCharset(String value) {
-		return set(PARSER_fileCharset, value);
-	}
-
-	/**
-	 * Configuration property:  File charset.
-	 * 
-	 * <p>
-	 * The character set to use for reading <code>Files</code> from the file system.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Parser#PARSER_fileCharset}
-	 * </ul>
-	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>The default value is <js>"DEFAULT"</js> which causes the system default to be used.
-	 * @return This object (for method chaining).
-	 */
-	public ParserBuilder fileCharset(Charset value) {
-		return set(PARSER_fileCharset, value);
-	}
-
-	/**
-	 * Configuration property:  Input stream charset.
-	 * 
-	 * <p>
-	 * The character set to use for converting <code>InputStreams</code> and byte arrays to readers.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Parser#PARSER_inputStreamCharset}
-	 * </ul>
-	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>The default value is <js>"UTF-8"</js>.
-	 * @return This object (for method chaining).
-	 */
-	public ParserBuilder inputStreamCharset(String value) {
-		return set(PARSER_inputStreamCharset, value);
-	}
-
-	/**
-	 * Configuration property:  Input stream charset.
-	 * 
-	 * <p>
-	 * The character set to use for converting <code>InputStreams</code> and byte arrays to readers.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Parser#PARSER_inputStreamCharset}
-	 * </ul>
-	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>The default value is <js>"UTF-8"</js>.
-	 * @return This object (for method chaining).
-	 */
-	public ParserBuilder inputStreamCharset(Charset value) {
-		return set(PARSER_inputStreamCharset, value);
-	}
-
-	/**
 	 * Configuration property:  Parser listener.
 	 * 
 	 * <p>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
index 6136568..95f1f21 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserGroupBuilder.java
@@ -13,7 +13,8 @@
 package org.apache.juneau.parser;
 
 import static org.apache.juneau.internal.CollectionUtils.*;
-import static org.apache.juneau.parser.Parser.*;
+import static org.apache.juneau.parser.InputStreamParser.*;
+import static org.apache.juneau.parser.ReaderParser.*;
 
 import java.util.*;
 
@@ -168,46 +169,6 @@ public class ParserGroupBuilder extends BeanContextBuilder {
 	}
 
 	/**
-	 * Configuration property:  File charset.
-	 * 
-	 * <p>
-	 * The character set to use for reading <code>Files</code> from the file system.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Parser#PARSER_fileCharset}
-	 * </ul>
-	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>The default value is <js>"DEFAULT"</js> which causes the system default to be used.
-	 * @return This object (for method chaining).
-	 */
-	public ParserGroupBuilder fileCharset(String value) {
-		return set(PARSER_fileCharset, value);
-	}
-
-	/**
-	 * Configuration property:  Input stream charset.
-	 * 
-	 * <p>
-	 * The character set to use for converting <code>InputStreams</code> and byte arrays to readers.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Parser#PARSER_inputStreamCharset}
-	 * </ul>
-	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>The default value is <js>"UTF-8"</js>.
-	 * @return This object (for method chaining).
-	 */
-	public ParserGroupBuilder inputStreamCharset(String value) {
-		return set(PARSER_inputStreamCharset, value);
-	}
-
-	/**
 	 * Configuration property:  Parser listener.
 	 * 
 	 * <p>
@@ -337,6 +298,67 @@ public class ParserGroupBuilder extends BeanContextBuilder {
 		return set(PARSER_unbuffered, true);
 	}
 
+	/**
+	 * Configuration property:  File charset.
+	 * 
+	 * <p>
+	 * The character set to use for reading <code>Files</code> from the file system.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link ReaderParser#RPARSER_fileCharset}
+	 * </ul>
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default value is <js>"DEFAULT"</js> which causes the system default to be used.
+	 * @return This object (for method chaining).
+	 */
+	public ParserGroupBuilder fileCharset(String value) {
+		return set(RPARSER_fileCharset, value);
+	}
+
+	/**
+	 * Configuration property:  Input stream charset.
+	 * 
+	 * <p>
+	 * The character set to use for converting <code>InputStreams</code> and byte arrays to readers.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link ReaderParser#RPARSER_inputStreamCharset}
+	 * </ul>
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default value is <js>"UTF-8"</js>.
+	 * @return This object (for method chaining).
+	 */
+	public ParserGroupBuilder inputStreamCharset(String value) {
+		return set(RPARSER_inputStreamCharset, value);
+	}
+
+	/**
+	 * Configuration property:  Binary input format.
+	 * 
+	 * <p>
+	 * When using the {@link Parser#parse(Object,Class)} method on stream-based parsers and the input is a string, this defines the format to use
+	 * when converting the string into a byte array.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link InputStreamParser#ISPARSER_binaryFormat}
+	 * </ul>
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default value is {@link BinaryFormat#HEX}.
+	 * @return This object (for method chaining).
+	 */
+	public ParserGroupBuilder binaryFormat(BinaryFormat value) {
+		return set(ISPARSER_binaryFormat, value);
+	}
+
 	@Override /* BeanContextBuilder */
 	public ParserGroupBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserPipe.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserPipe.java
index aa2bba9..16962b1 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserPipe.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserPipe.java
@@ -60,6 +60,7 @@ public final class ParserPipe implements Closeable {
 	private Reader reader;
 	private ParserReader parserReader;
 	private boolean doClose;
+	private BinaryFormat binaryFormat;
 
 	/**
 	 * Constructor.
@@ -85,8 +86,9 @@ public final class ParserPipe implements Closeable {
 	 * @param inputStreamCharset
 	 * 	The charset to expect when reading from {@link InputStream InputStreams}.
 	 * 	Use <js>"default"</js> to specify {@link Charset#defaultCharset()}.
+	 * @param binaryFormat The binary format of input strings when converted to bytes.
 	 */
-	public ParserPipe(Object input, boolean debug, boolean strict, boolean autoCloseStreams, boolean unbuffered, String fileCharset, String inputStreamCharset) {
+	public ParserPipe(Object input, boolean debug, boolean strict, boolean autoCloseStreams, boolean unbuffered, String fileCharset, String inputStreamCharset, BinaryFormat binaryFormat) {
 		this.input = input;
 		this.debug = debug;
 		this.strict = strict;
@@ -96,6 +98,7 @@ public final class ParserPipe implements Closeable {
 		this.inputStreamCharset = inputStreamCharset;
 		if (input instanceof CharSequence)
 			this.inputString = input.toString();
+		this.binaryFormat = binaryFormat;
 	}
 
 	/**
@@ -107,7 +110,7 @@ public final class ParserPipe implements Closeable {
 	 * @param input The input object.
 	 */
 	public ParserPipe(Object input) {
-		this(input, false, false, false, false, null, null);
+		this(input, false, false, false, false, null, null, null);
 	}
 
 	/**
@@ -139,7 +142,7 @@ public final class ParserPipe implements Closeable {
 			doClose = false;
 		} else if (input instanceof String) {
 			inputString = (String)input;
-			inputStream = new ByteArrayInputStream(fromHex((String)input));
+			inputStream = new ByteArrayInputStream(convertFromString((String)input));
 			doClose = false;
 		} else if (input instanceof File) {
 			if (debug) {
@@ -156,7 +159,15 @@ public final class ParserPipe implements Closeable {
 
 		return inputStream;
 	}
-
+	
+	private byte[] convertFromString(String in) {
+		switch(binaryFormat) {
+			case BASE64: return base64Decode(in);
+			case HEX: return fromHex(in);
+			case SPACED_HEX: return fromSpacedHex(in);
+			default:	return new byte[0];
+		}
+	}
 
 	/**
 	 * Wraps the specified input object inside a reader.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java
index d8fca04..7fd0d08 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ParserSession.java
@@ -33,8 +33,7 @@ import org.apache.juneau.utils.*;
  */
 public abstract class ParserSession extends BeanSession {
 
-	private final boolean trimStrings, strict, autoCloseStreams, unbuffered;
-	private final String inputStreamCharset, fileCharset;
+	final boolean trimStrings, strict, autoCloseStreams, unbuffered;
 	private final Method javaMethod;
 	private final Object outer;
 
@@ -58,8 +57,6 @@ public abstract class ParserSession extends BeanSession {
 		strict = getProperty(PARSER_strict, boolean.class, ctx.strict);
 		autoCloseStreams = getProperty(PARSER_autoCloseStreams, boolean.class, ctx.autoCloseStreams);
 		unbuffered = getProperty(PARSER_unbuffered, boolean.class, ctx.unbuffered);
-		inputStreamCharset = getProperty(PARSER_inputStreamCharset, String.class, ctx.inputStreamCharset);
-		fileCharset = getProperty(PARSER_fileCharset, String.class, ctx.fileCharset);
 		javaMethod = args.javaMethod;
 		outer = args.outer;
 		listener = getInstanceProperty(PARSER_listener, ParserListener.class, ctx.listener);
@@ -79,8 +76,6 @@ public abstract class ParserSession extends BeanSession {
 	public ObjectMap asMap() {
 		return super.asMap()
 			.append("ParserSession", new ObjectMap()
-				.append("fileCharset", fileCharset)
-				.append("inputStreamCharset", inputStreamCharset)
 				.append("javaMethod", javaMethod)
 				.append("listener", listener)
 				.append("outer", outer)
@@ -132,11 +127,11 @@ public abstract class ParserSession extends BeanSession {
 	 * 		<li>{@link Reader}
 	 * 		<li>{@link CharSequence}
 	 * 		<li>{@link InputStream} containing UTF-8 encoded text (or whatever the encoding specified by
-	 * 			{@link Parser#PARSER_inputStreamCharset}).
+	 * 			{@link ReaderParser#RPARSER_inputStreamCharset}).
 	 * 		<li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or whatever the encoding specified by
-	 * 			{@link Parser#PARSER_inputStreamCharset}).
+	 * 			{@link ReaderParser#RPARSER_inputStreamCharset}).
 	 * 		<li>{@link File} containing system encoded text (or whatever the encoding specified by
-	 * 			{@link Parser#PARSER_fileCharset}).
+	 * 			{@link ReaderParser#RPARSER_fileCharset}).
 	 * 	</ul>
 	 * 	<br>For byte-based parsers, this can be any of the following types:
 	 * 	<ul>
@@ -144,13 +139,12 @@ public abstract class ParserSession extends BeanSession {
 	 * 		<li>{@link InputStream}
 	 * 		<li><code><jk>byte</jk>[]</code>
 	 * 		<li>{@link File}
+	 * 		<li>{@link CharSequence} containing encoded bytes according to the {@link InputStreamParser#ISPARSER_binaryFormat} setting.
 	 * 	</ul>
 	 * @return
 	 * 	A new {@link ParserPipe} wrapper around the specified input object.
 	 */
-	public final ParserPipe createPipe(Object input) {
-		return new ParserPipe(input, isDebug(), strict, autoCloseStreams, unbuffered, fileCharset, inputStreamCharset);
-	}
+	public abstract ParserPipe createPipe(Object input);
 
 	/**
 	 * Returns information used to determine at what location in the parse a failure occurred.
@@ -398,11 +392,11 @@ public abstract class ParserSession extends BeanSession {
 	 * 		<li>{@link Reader}
 	 * 		<li>{@link CharSequence}
 	 * 		<li>{@link InputStream} containing UTF-8 encoded text (or charset defined by
-	 * 			{@link Parser#PARSER_inputStreamCharset} property value).
+	 * 			{@link ReaderParser#RPARSER_inputStreamCharset} property value).
 	 * 		<li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or charset defined by
-	 * 			{@link Parser#PARSER_inputStreamCharset} property value).
+	 * 			{@link ReaderParser#RPARSER_inputStreamCharset} property value).
 	 * 		<li>{@link File} containing system encoded text (or charset defined by
-	 * 			{@link Parser#PARSER_fileCharset} property value).
+	 * 			{@link ReaderParser#RPARSER_fileCharset} property value).
 	 * 	</ul>
 	 * 	<br>Stream-based parsers can handle the following input class types:
 	 * 	<ul>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
index ca1771e..b977f18 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
@@ -12,6 +12,8 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.parser;
 
+import java.nio.charset.*;
+
 import org.apache.juneau.*;
 
 /**
@@ -27,6 +29,114 @@ import org.apache.juneau.*;
  */
 public abstract class ReaderParser extends Parser {
 
+	//-------------------------------------------------------------------------------------------------------------------
+	// Configurable properties
+	//-------------------------------------------------------------------------------------------------------------------
+
+	private static final String PREFIX = "ReaderParser.";
+
+	/**
+	 * Configuration property:  File charset.
+	 * 
+	 * <h5 class='section'>Property:</h5>
+	 * <ul>
+	 * 	<li><b>Name:</b>  <js>"ReaderParser.fileCharset.s"</js>
+	 * 	<li><b>Data type:</b>  <code>String</code>
+	 * 	<li><b>Default:</b>  <js>"DEFAULT"</js>
+	 * 	<li><b>Session-overridable:</b>  <jk>true</jk>
+	 * 	<li><b>Methods:</b> 
+	 * 		<ul>
+	 * 			<li class='jm'>{@link ReaderParserBuilder#fileCharset(String)}
+	 * 			<li class='jm'>{@link ReaderParserBuilder#fileCharset(Charset)}
+	 * 		</ul>
+	 * </ul>
+	 * 
+	 * <h5 class='section'>Description:</h5>
+	 * <p>
+	 * The character set to use for reading <code>Files</code> from the file system.
+	 * 
+	 * <p>
+	 * Used when passing in files to {@link Parser#parse(Object, Class)}.
+	 * 
+	 * <p>
+	 * <js>"DEFAULT"</js> can be used to indicate the JVM default file system charset.
+	 * 
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Create a parser that reads UTF-8 files.</jc>
+	 * 	ReaderParser p = JsonParser.
+	 * 		.<jsm>create</jsm>()
+	 * 		.fileCharset(<js>"UTF-8"</js>)
+	 * 		.build();
+	 * 	
+	 * 	<jc>// Same, but use property.</jc>
+	 * 	ReaderParser p = JsonParser.
+	 * 		.<jsm>create</jsm>()
+	 * 		.set(<jsf>PARSER_fileCharset</jsf>, <js>"UTF-8"</js>)
+	 * 		.build();
+	 * 
+	 * 	<jc>// Use it to read a UTF-8 encoded file.</jc>
+	 * 	MyBean myBean = p.parse(<jk>new</jk> File(<js>"MyBean.txt"</js>), MyBean.<jk>class</jk>);
+	 * </p>
+	 */
+	public static final String RPARSER_fileCharset = PREFIX + "fileCharset.s";
+
+	/**
+	 * Configuration property:  Input stream charset.
+	 * 
+	 * <h5 class='section'>Property:</h5>
+	 * <ul>
+	 * 	<li><b>Name:</b>  <js>"ReaderParser.inputStreamCharset.s"</js>
+	 * 	<li><b>Data type:</b>  <code>String</code>
+	 * 	<li><b>Default:</b>  <js>"UTF-8"</js>
+	 * 	<li><b>Session-overridable:</b>  <jk>true</jk>
+	 * 	<li><b>Methods:</b> 
+	 * 		<ul>
+	 * 			<li class='jm'>{@link ReaderParserBuilder#inputStreamCharset(String)}
+	 * 			<li class='jm'>{@link ReaderParserBuilder#inputStreamCharset(Charset)}
+	 * 		</ul>
+	 * </ul>
+	 * 
+	 * <h5 class='section'>Description:</h5>
+	 * <p>
+	 * The character set to use for converting <code>InputStreams</code> and byte arrays to readers.
+	 * 
+	 * <p>
+	 * Used when passing in input streams and byte arrays to {@link Parser#parse(Object, Class)}.
+	 * 
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Create a parser that reads UTF-8 files.</jc>
+	 * 	ReaderParser p = JsonParser.
+	 * 		.<jsm>create</jsm>()
+	 * 		.inputStreamCharset(<js>"UTF-8"</js>)
+	 * 		.build();
+	 * 	
+	 * 	<jc>// Same, but use property.</jc>
+	 * 	ReaderParser p = JsonParser.
+	 * 		.<jsm>create</jsm>()
+	 * 		.set(<jsf>PARSER_inputStreamCharset</jsf>, <js>"UTF-8"</js>)
+	 * 		.build();
+	 * 
+	 * 	<jc>// Use it to read a UTF-8 encoded input stream.</jc>
+	 * 	MyBean myBean = p.parse(<jk>new</jk> FileInputStream(<js>"MyBean.txt"</js>), MyBean.<jk>class</jk>);
+	 * </p>
+	 */
+	public static final String RPARSER_inputStreamCharset = PREFIX + "inputStreamCharset.s";
+
+	static final ReaderParser DEFAULT = new ReaderParser(PropertyStore.create().build(), "") {
+		@Override
+		public ReaderParserSession createSession(ParserSessionArgs args) {
+			throw new NoSuchMethodError();
+		}
+	};
+
+	//-------------------------------------------------------------------------------------------------------------------
+	// Instance
+	//-------------------------------------------------------------------------------------------------------------------
+	
+	final String inputStreamCharset, fileCharset;
+
 	/**
 	 * Constructor.
 	 * 
@@ -35,10 +145,22 @@ public abstract class ReaderParser extends Parser {
 	 */
 	protected ReaderParser(PropertyStore ps, String...consumes) {
 		super(ps, consumes);
+		
+		inputStreamCharset = getStringProperty(RPARSER_inputStreamCharset, "UTF-8");
+		fileCharset = getStringProperty(RPARSER_fileCharset, "DEFAULT");
 	}
 
 	@Override /* Parser */
 	public final boolean isReaderParser() {
 		return true;
 	}
+	
+	@Override /* Context */
+	public ObjectMap asMap() {
+		return super.asMap()
+			.append("ReaderParser", new ObjectMap()
+				.append("inputStreamCharset", inputStreamCharset)
+				.append("fileCharset", fileCharset)
+			);
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserBuilder.java
similarity index 56%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserBuilder.java
index 2f41431..0082354 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserBuilder.java
@@ -1,562 +1,548 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.uon;
-
-import static org.apache.juneau.uon.UonParser.*;
-
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.http.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.urlencoding.*;
-
-/**
- * Builder class for building instances of UON parsers.
- */
-public class UonParserBuilder extends ParserBuilder {
-
-	/**
-	 * Constructor, default settings.
-	 */
-	public UonParserBuilder() {
-		super();
-	}
-
-	/**
-	 * Constructor.
-	 * 
-	 * @param ps The initial configuration settings for this builder.
-	 */
-	public UonParserBuilder(PropertyStore ps) {
-		super(ps);
-	}
-
-	@Override /* ContextBuilder */
-	public UonParser build() {
-		return build(UonParser.class);
-	}
-
-
-	//--------------------------------------------------------------------------------
-	// Properties
-	//--------------------------------------------------------------------------------
-
-	/**
-	 * Configuration property: Decode <js>"%xx"</js> sequences.
-	 * 
-	 * <p>
-	 * Specify <jk>true</jk> if URI encoded characters should be decoded, <jk>false</jk> if they've already been
-	 * decoded before being passed to this parser.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link UonParser#UON_decoding}
-	 * </ul>
-	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>Default is <jk>false</jk> for {@link UonParser}, <jk>true</jk> for {@link UrlEncodingParser}
-	 * @return This object (for method chaining).
-	 */
-	public UonParserBuilder decoding(boolean value) {
-		return set(UON_decoding, value);
-	}
-
-	/**
-	 * Configuration property: Decode <js>"%xx"</js> sequences.
-	 * 
-	 * <p>
-	 * Shortcut for calling <code>decodeChars(<jk>true</jk>)</code>.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link UonParser#UON_decoding}
-	 * </ul>
-	 * 
-	 * @return This object (for method chaining).
-	 */
-	public UonParserBuilder decoding() {
-		return decoding(true);
-	}
-
-	/**
-	 * Configuration property:  Validate end.
-	 * 
-	 * <p>
-	 * If <jk>true</jk>, after parsing a POJO from the input, verifies that the remaining input in 
-	 * the stream consists of only whitespace.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link UonParser#UON_validateEnd}
-	 * </ul>
-	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>The default value is <jk>false</jk>.
-	 * @return This object (for method chaining).
-	 */
-	public UonParserBuilder validateEnd(boolean value) {
-		return set(UON_validateEnd, value);
-	}
-	
-	/**
-	 * Configuration property:  Validate end.
-	 * 
-	 * <p>
-	 * Shortcut for calling <code>validateEnd(<jk>true</jk>)</code>.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link UonParser#UON_validateEnd}
-	 * </ul>
-	 * 
-	 * @return This object (for method chaining).
-	 */
-	public UonParserBuilder validateEnd() {
-		return set(UON_validateEnd, true);
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder autoCloseStreams(boolean value) {
-		super.autoCloseStreams(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder autoCloseStreams() {
-		super.autoCloseStreams();
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder fileCharset(String value) {
-		super.fileCharset(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder inputStreamCharset(String value) {
-		super.inputStreamCharset(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder listener(Class<? extends ParserListener> value) {
-		super.listener(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder strict(boolean value) {
-		super.strict(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder strict() {
-		super.strict();
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder trimStrings(boolean value) {
-		super.trimStrings(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder trimStrings() {
-		super.trimStrings();
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder unbuffered(boolean value) {
-		super.unbuffered(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder unbuffered() {
-		super.unbuffered();
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireDefaultConstructor(boolean value) {
-		super.beansRequireDefaultConstructor(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireDefaultConstructor() {
-		super.beansRequireDefaultConstructor();
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireSerializable(boolean value) {
-		super.beansRequireSerializable(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireSerializable() {
-		super.beansRequireSerializable();
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireSettersForGetters(boolean value) {
-		super.beansRequireSettersForGetters(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireSettersForGetters() {
-		super.beansRequireSettersForGetters();
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireSomeProperties(boolean value) {
-		super.beansRequireSomeProperties(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanMapPutReturnsOldValue(boolean value) {
-		super.beanMapPutReturnsOldValue(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanMapPutReturnsOldValue() {
-		super.beanMapPutReturnsOldValue();
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanConstructorVisibility(Visibility value) {
-		super.beanConstructorVisibility(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanClassVisibility(Visibility value) {
-		super.beanClassVisibility(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanFieldVisibility(Visibility value) {
-		super.beanFieldVisibility(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanMethodVisibility(Visibility value) {
-		super.beanMethodVisibility(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder useJavaBeanIntrospector(boolean value) {
-		super.useJavaBeanIntrospector(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder useJavaBeanIntrospector() {
-		super.useJavaBeanIntrospector();
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder useInterfaceProxies(boolean value) {
-		super.useInterfaceProxies(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreUnknownBeanProperties(boolean value) {
-		super.ignoreUnknownBeanProperties(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreUnknownBeanProperties() {
-		super.ignoreUnknownBeanProperties();
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreUnknownNullBeanProperties(boolean value) {
-		super.ignoreUnknownNullBeanProperties(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignorePropertiesWithoutSetters(boolean value) {
-		super.ignorePropertiesWithoutSetters(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreInvocationExceptionsOnGetters(boolean value) {
-		super.ignoreInvocationExceptionsOnGetters(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreInvocationExceptionsOnGetters() {
-		super.ignoreInvocationExceptionsOnGetters();
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreInvocationExceptionsOnSetters(boolean value) {
-		super.ignoreInvocationExceptionsOnSetters(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreInvocationExceptionsOnSetters() {
-		super.ignoreInvocationExceptionsOnSetters();
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder sortProperties(boolean value) {
-		super.sortProperties(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder sortProperties() {
-		super.sortProperties();
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanPackages(Object...values) {
-		super.notBeanPackages(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanPackages(String...values) {
-		super.notBeanPackages(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanPackages(boolean append, Object...values) {
-		super.notBeanPackages(append, values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanPackagesRemove(Object...values) {
-		super.notBeanPackagesRemove(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanClasses(Object...values) {
-		super.notBeanClasses(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanClasses(Class<?>...values) {
-		super.notBeanClasses(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanClasses(boolean append, Object...values) {
-		super.notBeanClasses(append, values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanClassesRemove(Object...values) {
-		super.notBeanClassesRemove(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanFilters(Object...values) {
-		super.beanFilters(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanFilters(Class<?>...values) {
-		super.beanFilters(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanFilters(boolean append, Object...values) {
-		super.beanFilters(append, values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanFiltersRemove(Object...values) {
-		super.beanFiltersRemove(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder pojoSwaps(Object...values) {
-		super.pojoSwaps(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder pojoSwaps(Class<?>...values) {
-		super.pojoSwaps(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder pojoSwaps(boolean append, Object...values) {
-		super.pojoSwaps(append, values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder pojoSwapsRemove(Object...values) {
-		super.pojoSwapsRemove(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder implClasses(Map<String,Class<?>> values) {
-		super.implClasses(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public <T> UonParserBuilder implClass(Class<T> interfaceClass, Class<? extends T> implClass) {
-		super.implClass(interfaceClass, implClass);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanDictionary(Object...values) {
-		super.beanDictionary(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanDictionary(Class<?>...values) {
-		super.beanDictionary(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanDictionary(boolean append, Object...values) {
-		super.beanDictionary(append, values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanDictionaryRemove(Object...values) {
-		super.beanDictionaryRemove(values);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanTypePropertyName(String value) {
-		super.beanTypePropertyName(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder locale(Locale value) {
-		super.locale(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder timeZone(TimeZone value) {
-		super.timeZone(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder mediaType(MediaType value) {
-		super.mediaType(value);
-		return this;
-	}
-
-	@Override /* BeanContextBuilder */
-	public UonParserBuilder debug() {
-		super.debug();
-		return this;
-	}
-
-	@Override /* ContextBuilder */
-	public UonParserBuilder set(String name, Object value) {
-		super.set(name, value);
-		return this;
-	}
-
-	@Override /* ContextBuilder */
-	public UonParserBuilder set(boolean append, String name, Object value) {
-		super.set(append, name, value);
-		return this;
-	}
-
-	@Override /* ContextBuilder */
-	public UonParserBuilder set(Map<String,Object> properties) {
-		super.set(properties);
-		return this;
-	}
-
-	@Override /* ContextBuilder */
-	public UonParserBuilder add(Map<String,Object> properties) {
-		super.add(properties);
-		return this;
-	}
-
-	@Override /* ContextBuilder */
-	public UonParserBuilder addTo(String name, Object value) {
-		super.addTo(name, value);
-		return this;
-	}
-
-	@Override /* ContextBuilder */
-	public UonParserBuilder addTo(String name, String key, Object value) {
-		super.addTo(name, key, value);
-		return this;
-	}
-
-	@Override /* ContextBuilder */
-	public UonParserBuilder removeFrom(String name, Object value) {
-		super.removeFrom(name, value);
-		return this;
-	}
-
-	@Override /* ContextBuilder */
-	public UonParserBuilder apply(PropertyStore copyFrom) {
-		super.apply(copyFrom);
-		return this;
-	}
-}
\ No newline at end of file
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.parser;
+
+import static org.apache.juneau.parser.ReaderParser.*;
+
+import java.nio.charset.*;
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.http.*;
+
+/**
+ * Base builder class for building instances of reader-based parsers.
+ */
+public abstract class ReaderParserBuilder extends ParserBuilder {
+
+	/**
+	 * Constructor, default settings.
+	 */
+	public ReaderParserBuilder() {
+		super();
+	}
+
+	/**
+	 * Constructor.
+	 * 
+	 * @param ps The initial configuration settings for this builder.
+	 */
+	public ReaderParserBuilder(PropertyStore ps) {
+		super(ps);
+	}
+	
+	
+	//--------------------------------------------------------------------------------
+	// Properties
+	//--------------------------------------------------------------------------------
+
+	/**
+	 * Configuration property:  File charset.
+	 * 
+	 * <p>
+	 * The character set to use for reading <code>Files</code> from the file system.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link ReaderParser#RPARSER_fileCharset}
+	 * </ul>
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default value is <js>"DEFAULT"</js> which causes the system default to be used.
+	 * @return This object (for method chaining).
+	 */
+	public ReaderParserBuilder fileCharset(String value) {
+		return set(RPARSER_fileCharset, value);
+	}
+
+	/**
+	 * Configuration property:  File charset.
+	 * 
+	 * <p>
+	 * The character set to use for reading <code>Files</code> from the file system.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link ReaderParser#RPARSER_fileCharset}
+	 * </ul>
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default value is <js>"DEFAULT"</js> which causes the system default to be used.
+	 * @return This object (for method chaining).
+	 */
+	public ReaderParserBuilder fileCharset(Charset value) {
+		return set(RPARSER_fileCharset, value);
+	}
+
+	/**
+	 * Configuration property:  Input stream charset.
+	 * 
+	 * <p>
+	 * The character set to use for converting <code>InputStreams</code> and byte arrays to readers.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link ReaderParser#RPARSER_inputStreamCharset}
+	 * </ul>
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default value is <js>"UTF-8"</js>.
+	 * @return This object (for method chaining).
+	 */
+	public ReaderParserBuilder inputStreamCharset(String value) {
+		return set(RPARSER_inputStreamCharset, value);
+	}
+
+	/**
+	 * Configuration property:  Input stream charset.
+	 * 
+	 * <p>
+	 * The character set to use for converting <code>InputStreams</code> and byte arrays to readers.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link ReaderParser#RPARSER_inputStreamCharset}
+	 * </ul>
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default value is <js>"UTF-8"</js>.
+	 * @return This object (for method chaining).
+	 */
+	public ReaderParserBuilder inputStreamCharset(Charset value) {
+		return set(RPARSER_inputStreamCharset, value);
+	}
+
+	@Override /* ParserBuilder */
+	public ReaderParserBuilder autoCloseStreams(boolean value) {
+		super.autoCloseStreams(value);
+		return this;
+	}
+
+	@Override /* ParserBuilder */
+	public ReaderParserBuilder autoCloseStreams() {
+		super.autoCloseStreams();
+		return this;
+	}
+
+	@Override /* ParserBuilder */
+	public ReaderParserBuilder listener(Class<? extends ParserListener> value) {
+		super.listener(value);
+		return this;
+	}
+
+	@Override /* ParserBuilder */
+	public ReaderParserBuilder strict(boolean value) {
+		super.strict(value);
+		return this;
+	}
+
+	@Override /* ParserBuilder */
+	public ReaderParserBuilder strict() {
+		super.strict();
+		return this;
+	}
+
+	@Override /* ParserBuilder */
+	public ReaderParserBuilder trimStrings(boolean value) {
+		super.trimStrings(value);
+		return this;
+	}
+
+	@Override /* ParserBuilder */
+	public ReaderParserBuilder trimStrings() {
+		super.trimStrings();
+		return this;
+	}
+
+	@Override /* ParserBuilder */
+	public ReaderParserBuilder unbuffered(boolean value) {
+		super.unbuffered(value);
+		return this;
+	}
+
+	@Override /* ParserBuilder */
+	public ReaderParserBuilder unbuffered() {
+		super.unbuffered();
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beansRequireDefaultConstructor(boolean value) {
+		super.beansRequireDefaultConstructor(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beansRequireDefaultConstructor() {
+		super.beansRequireDefaultConstructor();
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beansRequireSerializable(boolean value) {
+		super.beansRequireSerializable(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beansRequireSerializable() {
+		super.beansRequireSerializable();
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beansRequireSettersForGetters(boolean value) {
+		super.beansRequireSettersForGetters(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beansRequireSettersForGetters() {
+		super.beansRequireSettersForGetters();
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beansRequireSomeProperties(boolean value) {
+		super.beansRequireSomeProperties(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanMapPutReturnsOldValue(boolean value) {
+		super.beanMapPutReturnsOldValue(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanMapPutReturnsOldValue() {
+		super.beanMapPutReturnsOldValue();
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanConstructorVisibility(Visibility value) {
+		super.beanConstructorVisibility(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanClassVisibility(Visibility value) {
+		super.beanClassVisibility(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanFieldVisibility(Visibility value) {
+		super.beanFieldVisibility(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanMethodVisibility(Visibility value) {
+		super.beanMethodVisibility(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder useJavaBeanIntrospector(boolean value) {
+		super.useJavaBeanIntrospector(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder useJavaBeanIntrospector() {
+		super.useJavaBeanIntrospector();
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder useInterfaceProxies(boolean value) {
+		super.useInterfaceProxies(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder ignoreUnknownBeanProperties(boolean value) {
+		super.ignoreUnknownBeanProperties(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder ignoreUnknownBeanProperties() {
+		super.ignoreUnknownBeanProperties();
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder ignoreUnknownNullBeanProperties(boolean value) {
+		super.ignoreUnknownNullBeanProperties(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder ignorePropertiesWithoutSetters(boolean value) {
+		super.ignorePropertiesWithoutSetters(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder ignoreInvocationExceptionsOnGetters(boolean value) {
+		super.ignoreInvocationExceptionsOnGetters(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder ignoreInvocationExceptionsOnGetters() {
+		super.ignoreInvocationExceptionsOnGetters();
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder ignoreInvocationExceptionsOnSetters(boolean value) {
+		super.ignoreInvocationExceptionsOnSetters(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder ignoreInvocationExceptionsOnSetters() {
+		super.ignoreInvocationExceptionsOnSetters();
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder sortProperties(boolean value) {
+		super.sortProperties(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder sortProperties() {
+		super.sortProperties();
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder notBeanPackages(Object...values) {
+		super.notBeanPackages(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder notBeanPackages(String...values) {
+		super.notBeanPackages(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder notBeanPackages(boolean append, Object...values) {
+		super.notBeanPackages(append, values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder notBeanPackagesRemove(Object...values) {
+		super.notBeanPackagesRemove(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder notBeanClasses(Object...values) {
+		super.notBeanClasses(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder notBeanClasses(Class<?>...values) {
+		super.notBeanClasses(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder notBeanClasses(boolean append, Object...values) {
+		super.notBeanClasses(append, values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder notBeanClassesRemove(Object...values) {
+		super.notBeanClassesRemove(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanFilters(Object...values) {
+		super.beanFilters(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanFilters(Class<?>...values) {
+		super.beanFilters(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanFilters(boolean append, Object...values) {
+		super.beanFilters(append, values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanFiltersRemove(Object...values) {
+		super.beanFiltersRemove(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder pojoSwaps(Object...values) {
+		super.pojoSwaps(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder pojoSwaps(Class<?>...values) {
+		super.pojoSwaps(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder pojoSwaps(boolean append, Object...values) {
+		super.pojoSwaps(append, values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder pojoSwapsRemove(Object...values) {
+		super.pojoSwapsRemove(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder implClasses(Map<String,Class<?>> values) {
+		super.implClasses(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public <T> ReaderParserBuilder implClass(Class<T> interfaceClass, Class<? extends T> implClass) {
+		super.implClass(interfaceClass, implClass);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanDictionary(Object...values) {
+		super.beanDictionary(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanDictionary(Class<?>...values) {
+		super.beanDictionary(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanDictionary(boolean append, Object...values) {
+		super.beanDictionary(append, values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanDictionaryRemove(Object...values) {
+		super.beanDictionaryRemove(values);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder beanTypePropertyName(String value) {
+		super.beanTypePropertyName(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder locale(Locale value) {
+		super.locale(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder timeZone(TimeZone value) {
+		super.timeZone(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder mediaType(MediaType value) {
+		super.mediaType(value);
+		return this;
+	}
+
+	@Override /* BeanContextBuilder */
+	public ReaderParserBuilder debug() {
+		super.debug();
+		return this;
+	}
+
+	@Override /* ContextBuilder */
+	public ReaderParserBuilder set(String name, Object value) {
+		super.set(name, value);
+		return this;
+	}
+
+	@Override /* ContextBuilder */
+	public ReaderParserBuilder set(boolean append, String name, Object value) {
+		super.set(append, name, value);
+		return this;
+	}
+
+	@Override /* ContextBuilder */
+	public ReaderParserBuilder set(Map<String,Object> properties) {
+		super.set(properties);
+		return this;
+	}
+
+	@Override /* ContextBuilder */
+	public ReaderParserBuilder add(Map<String,Object> properties) {
+		super.add(properties);
+		return this;
+	}
+
+	@Override /* ContextBuilder */
+	public ReaderParserBuilder addTo(String name, Object value) {
+		super.addTo(name, value);
+		return this;
+	}
+
+	@Override /* ContextBuilder */
+	public ReaderParserBuilder addTo(String name, String key, Object value) {
+		super.addTo(name, key, value);
+		return this;
+	}
+
+	@Override /* ContextBuilder */
+	public ReaderParserBuilder removeFrom(String name, Object value) {
+		super.removeFrom(name, value);
+		return this;
+	}
+
+	@Override /* ContextBuilder */
+	public ReaderParserBuilder apply(PropertyStore copyFrom) {
+		super.apply(copyFrom);
+		return this;
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java
index 4dc3e0a..1e3b818 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java
@@ -12,6 +12,12 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.parser;
 
+import static org.apache.juneau.parser.ReaderParser.*;
+
+import java.io.*;
+
+import org.apache.juneau.*;
+
 /**
  * Subclass of parser session objects for character-based parsers.
  * 
@@ -20,6 +26,8 @@ package org.apache.juneau.parser;
  */
 public abstract class ReaderParserSession extends ParserSession {
 
+	private final String inputStreamCharset, fileCharset;
+
 	/**
 	 * Create a new session using properties specified in the context.
 	 * 
@@ -29,8 +37,11 @@ public abstract class ReaderParserSession extends ParserSession {
 	 * @param args
 	 * 	Runtime session arguments.
 	 */
-	protected ReaderParserSession(Parser ctx, ParserSessionArgs args) {
+	protected ReaderParserSession(ReaderParser ctx, ParserSessionArgs args) {
 		super(ctx, args);
+
+		inputStreamCharset = getProperty(RPARSER_inputStreamCharset, String.class, ctx.inputStreamCharset);
+		fileCharset = getProperty(RPARSER_fileCharset, String.class, ctx.fileCharset);
 	}
 
 	/**
@@ -40,7 +51,7 @@ public abstract class ReaderParserSession extends ParserSession {
 	 * 	Runtime session arguments.
 	 */
 	protected ReaderParserSession(ParserSessionArgs args) {
-		super(args);
+		this(ReaderParser.DEFAULT, args);
 	}
 
 
@@ -48,4 +59,39 @@ public abstract class ReaderParserSession extends ParserSession {
 	public final boolean isReaderParser() {
 		return true;
 	}
+	
+	/**
+	 * Wraps the specified input object into a {@link ParserPipe} object so that it can be easily converted into
+	 * a stream or reader.
+	 * 
+	 * @param input
+	 * 	The input.
+	 * 	<br>This can be any of the following types:
+	 * 	<ul>
+	 * 		<li><jk>null</jk>
+	 * 		<li>{@link Reader}
+	 * 		<li>{@link CharSequence}
+	 * 		<li>{@link InputStream} containing UTF-8 encoded text (or whatever the encoding specified by
+	 * 			{@link ReaderParser#RPARSER_inputStreamCharset}).
+	 * 		<li><code><jk>byte</jk>[]</code> containing UTF-8 encoded text (or whatever the encoding specified by
+	 * 			{@link ReaderParser#RPARSER_inputStreamCharset}).
+	 * 		<li>{@link File} containing system encoded text (or whatever the encoding specified by
+	 * 			{@link ReaderParser#RPARSER_fileCharset}).
+	 * 	</ul>
+	 * @return
+	 * 	A new {@link ParserPipe} wrapper around the specified input object.
+	 */
+	@Override /* ParserSesson */
+	public final ParserPipe createPipe(Object input) {
+		return new ParserPipe(input, isDebug(), strict, autoCloseStreams, unbuffered, fileCharset, inputStreamCharset, null);
+	}
+
+	@Override /* Session */
+	public ObjectMap asMap() {
+		return super.asMap()
+			.append("ReaderParserSession", new ObjectMap()
+				.append("fileCharset", fileCharset)
+				.append("inputStreamCharset", inputStreamCharset)
+			);
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
index ae63bd0..7dbeb19 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParserBuilder.java
@@ -21,7 +21,7 @@ import org.apache.juneau.parser.*;
 /**
  * Builder class for building instances of plain-text parsers.
  */
-public class PlainTextParserBuilder extends ParserBuilder {
+public class PlainTextParserBuilder extends ReaderParserBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -49,27 +49,27 @@ public class PlainTextParserBuilder extends ParserBuilder {
 	// Properties
 	//--------------------------------------------------------------------------------
 
-	@Override /* ParserBuilder */
-	public PlainTextParserBuilder autoCloseStreams(boolean value) {
-		super.autoCloseStreams(value);
+	@Override /* ReaderParserBuilder */
+	public PlainTextParserBuilder fileCharset(String value) {
+		super.fileCharset(value);
 		return this;
 	}
 
-	@Override /* ParserBuilder */
-	public PlainTextParserBuilder autoCloseStreams() {
-		super.autoCloseStreams();
+	@Override /* ReaderParserBuilder */
+	public PlainTextParserBuilder inputStreamCharset(String value) {
+		super.inputStreamCharset(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public PlainTextParserBuilder fileCharset(String value) {
-		super.fileCharset(value);
+	public PlainTextParserBuilder autoCloseStreams(boolean value) {
+		super.autoCloseStreams(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public PlainTextParserBuilder inputStreamCharset(String value) {
-		super.inputStreamCharset(value);
+	public PlainTextParserBuilder autoCloseStreams() {
+		super.autoCloseStreams();
 		return this;
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
index 29bf784..07da65b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializerBuilder.java
@@ -21,7 +21,7 @@ import org.apache.juneau.serializer.*;
 /**
  * Builder class for building instances of plain-text serializers.
  */
-public class PlainTextSerializerBuilder extends SerializerBuilder {
+public class PlainTextSerializerBuilder extends WriterSerializerBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -49,6 +49,42 @@ public class PlainTextSerializerBuilder extends SerializerBuilder {
 	// Properties
 	//--------------------------------------------------------------------------------
 
+	@Override /* WriterSerializerBuilder */
+	public PlainTextSerializerBuilder maxIndent(int value) {
+		super.maxIndent(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public PlainTextSerializerBuilder quoteChar(char value) {
+		super.quoteChar(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public PlainTextSerializerBuilder sq() {
+		super.sq();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public PlainTextSerializerBuilder useWhitespace(boolean value) {
+		super.useWhitespace(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public PlainTextSerializerBuilder useWhitespace() {
+		super.useWhitespace();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public PlainTextSerializerBuilder ws() {
+		super.ws();
+		return this;
+	}
+
 	@Override /* SerializerBuilder */
 	public PlainTextSerializerBuilder abridged(boolean value) {
 		super.abridged(value);
@@ -109,18 +145,6 @@ public class PlainTextSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public PlainTextSerializerBuilder maxIndent(int value) {
-		super.maxIndent(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public PlainTextSerializerBuilder quoteChar(char value) {
-		super.quoteChar(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public PlainTextSerializerBuilder sortCollections(boolean value) {
 		super.sortCollections(value);
 		return this;
@@ -145,12 +169,6 @@ public class PlainTextSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public PlainTextSerializerBuilder sq() {
-		super.sq();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public PlainTextSerializerBuilder trimEmptyCollections(boolean value) {
 		super.trimEmptyCollections(value);
 		return this;
@@ -210,24 +228,6 @@ public class PlainTextSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
-	@Override /* SerializerBuilder */
-	public PlainTextSerializerBuilder useWhitespace(boolean value) {
-		super.useWhitespace(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public PlainTextSerializerBuilder useWhitespace() {
-		super.useWhitespace();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public PlainTextSerializerBuilder ws() {
-		super.ws();
-		return this;
-	}
-
 	@Override /* BeanContextBuilder */
 	public PlainTextSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializer.java
index c70729c..4240531 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializer.java
@@ -12,8 +12,6 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.serializer;
 
-import static org.apache.juneau.internal.StringUtils.*;
-
 import org.apache.juneau.*;
 
 /**
@@ -21,6 +19,69 @@ import org.apache.juneau.*;
  */
 public abstract class OutputStreamSerializer extends Serializer {
 
+	//-------------------------------------------------------------------------------------------------------------------
+	// Configurable properties
+	//-------------------------------------------------------------------------------------------------------------------
+
+	private static final String PREFIX = "OutputStreamSerializer.";
+
+	/**
+	 * Configuration property:  Binary output format.
+	 * 
+	 * <h5 class='section'>Property:</h5>
+	 * <ul>
+	 * 	<li><b>Name:</b>  <js>"OutputStreamSerializer.binaryFormat.s"</js>
+	 * 	<li><b>Data type:</b>  {@link BinaryFormat}
+	 * 	<li><b>Default:</b>  {@link BinaryFormat#HEX}
+	 * 	<li><b>Session-overridable:</b>  <jk>true</jk>
+	 * 	<li><b>Methods:</b> 
+	 * 		<ul>
+	 * 			<li class='jm'>{@link OutputStreamSerializerBuilder#binaryFormat(BinaryFormat)}
+	 * 		</ul>
+	 * </ul>
+	 * 
+	 * <h5 class='section'>Description:</h5>
+	 * <p>
+	 * When using the {@link #serializeToString(Object)} method on stream-based serializers, this defines the format to use
+	 * when converting the resulting byte array to a string.
+	 * 
+	 * 
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Create a serializer that serializes to BASE64.</jc>
+	 * 	OutputStreamSerializer s = MsgPackSerializer
+	 * 		.<jsm>create</jsm>()
+	 * 		.binaryFormat(<jsf>BASE64</jsf>)
+	 * 		.build();
+	 * 	
+	 * 	<jc>// Same, but use property.</jc>
+	 * 	OutputStreamSerializer s = MsgPackSerializer
+	 * 		.<jsm>create</jsm>()
+	 * 		.set(<jsf>SERIALIZER_binaryOutputFormat</jsf>, <js>"BASE64"</js>)
+	 * 		.build();
+	 * 
+	 * 	<jc>// The bean we want to serialize.</jc>
+	 * 	<jk>public class</jk> MyBean {...}
+	 * 
+	 * 	<jc>// MessagePack will generate BASE64-encoded string.</jc>
+	 * 	String msgPack = s.serializeToString(<jk>new</jk> MyBean());
+	 * </p>
+	 */
+	public static final String OSSERIALIZER_binaryFormat = PREFIX + "binaryFormat.s";
+
+	static final OutputStreamSerializer DEFAULT = new OutputStreamSerializer(PropertyStore.create().build(), "") {
+		@Override
+		public OutputStreamSerializerSession createSession(SerializerSessionArgs args) {
+			throw new NoSuchMethodError();
+		}
+	};
+
+	//-------------------------------------------------------------------------------------------------------------------
+	// Instance
+	//-------------------------------------------------------------------------------------------------------------------
+
+	final BinaryFormat binaryFormat;
+	
 	/**
 	 * Constructor.
 	 * 
@@ -48,6 +109,8 @@ public abstract class OutputStreamSerializer extends Serializer {
 	 */
 	protected OutputStreamSerializer(PropertyStore ps, String produces, String...accept) {
 		super(ps, produces, accept);
+	
+		binaryFormat = getProperty(OSSERIALIZER_binaryFormat, BinaryFormat.class, BinaryFormat.HEX);
 	}
 
 
@@ -79,15 +142,12 @@ public abstract class OutputStreamSerializer extends Serializer {
 	public final byte[] serialize(Object o) throws SerializeException {
 		return createSession(createDefaultSessionArgs()).serialize(o);
 	}
-
-	/**
-	 * Convenience method for serializing an object to a hex-encoded String.
-	 * 
-	 * @param o The object to serialize.
-	 * @return The output serialized to a hex-encoded string.
-	 * @throws SerializeException If a problem occurred trying to convert the output.
-	 */
-	public final String serializeToHex(Object o) throws SerializeException {
-		return toHex(serialize(o));
+	
+	@Override /* Context */
+	public ObjectMap asMap() {
+		return super.asMap()
+			.append("OutputStreamSerializer", new ObjectMap()
+				.append("binaryFormat", binaryFormat)
+			);
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerBuilder.java
similarity index 57%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlParserBuilder.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerBuilder.java
index c9c8ee0..bb47e8d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerBuilder.java
@@ -2,7 +2,7 @@
 // * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
 // * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
 // * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
+// * with the License.  You may obtain a copy of the License at                                                              * 
 // *                                                                                                                         *
 // *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
 // *                                                                                                                         *
@@ -10,23 +10,24 @@
 // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
 // * specific language governing permissions and limitations under the License.                                              *
 // ***************************************************************************************************************************
-package org.apache.juneau.yaml.proto;
+package org.apache.juneau.serializer;
+
+import static org.apache.juneau.serializer.OutputStreamSerializer.*;
 
 import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
-import org.apache.juneau.parser.*;
 
 /**
- * Builder class for building instances of JSON parsers.
+ * Base class for all stream-based serializer builders.
  */
-public class YamlParserBuilder extends ParserBuilder {
+public class OutputStreamSerializerBuilder extends SerializerBuilder {
 
 	/**
 	 * Constructor, default settings.
 	 */
-	public YamlParserBuilder() {
+	public OutputStreamSerializerBuilder() {
 		super();
 	}
 
@@ -35,449 +36,403 @@ public class YamlParserBuilder extends ParserBuilder {
 	 * 
 	 * @param ps The initial configuration settings for this builder.
 	 */
-	public YamlParserBuilder(PropertyStore ps) {
+	public OutputStreamSerializerBuilder(PropertyStore ps) {
 		super(ps);
 	}
 
-	@Override /* ContextBuilder */
-	public YamlParser build() {
-		return build(YamlParser.class);
-	}
-
 
 	//--------------------------------------------------------------------------------
 	// Properties
 	//--------------------------------------------------------------------------------
 
-	@Override /* ParserBuilder */
-	public YamlParserBuilder autoCloseStreams(boolean value) {
-		super.autoCloseStreams(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public YamlParserBuilder autoCloseStreams() {
-		super.autoCloseStreams();
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public YamlParserBuilder fileCharset(String value) {
-		super.fileCharset(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public YamlParserBuilder inputStreamCharset(String value) {
-		super.inputStreamCharset(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public YamlParserBuilder listener(Class<? extends ParserListener> value) {
-		super.listener(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public YamlParserBuilder strict(boolean value) {
-		super.strict(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public YamlParserBuilder strict() {
-		super.strict();
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public YamlParserBuilder trimStrings(boolean value) {
-		super.trimStrings(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public YamlParserBuilder trimStrings() {
-		super.trimStrings();
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public YamlParserBuilder unbuffered(boolean value) {
-		super.unbuffered(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public YamlParserBuilder unbuffered() {
-		super.unbuffered();
-		return this;
+	/**
+	 * Configuration property:  Binary output format.
+	 * 
+	 * <p>
+	 * When using the {@link Serializer#serializeToString(Object)} method on stream-based serializers, this defines the format to use
+	 * when converting the resulting byte array to a string.
+	 * 
+	 * <ul>
+	 * 	<li class='jf'>{@link OutputStreamSerializer#OSSERIALIZER_binaryFormat}
+	 * </ul>
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default is {@link BinaryFormat#HEX}.
+	 * @return This object (for method chaining).
+	 */
+	public OutputStreamSerializerBuilder binaryFormat(BinaryFormat value) {
+		return set(OSSERIALIZER_binaryFormat, value);
 	}
-
+	
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beansRequireDefaultConstructor(boolean value) {
+	public OutputStreamSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beansRequireDefaultConstructor() {
+	public OutputStreamSerializerBuilder beansRequireDefaultConstructor() {
 		super.beansRequireDefaultConstructor();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beansRequireSerializable(boolean value) {
+	public OutputStreamSerializerBuilder beansRequireSerializable(boolean value) {
 		super.beansRequireSerializable(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beansRequireSerializable() {
+	public OutputStreamSerializerBuilder beansRequireSerializable() {
 		super.beansRequireSerializable();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beansRequireSettersForGetters(boolean value) {
+	public OutputStreamSerializerBuilder beansRequireSettersForGetters(boolean value) {
 		super.beansRequireSettersForGetters(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beansRequireSettersForGetters() {
+	public OutputStreamSerializerBuilder beansRequireSettersForGetters() {
 		super.beansRequireSettersForGetters();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beansRequireSomeProperties(boolean value) {
+	public OutputStreamSerializerBuilder beansRequireSomeProperties(boolean value) {
 		super.beansRequireSomeProperties(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanMapPutReturnsOldValue(boolean value) {
+	public OutputStreamSerializerBuilder beanMapPutReturnsOldValue(boolean value) {
 		super.beanMapPutReturnsOldValue(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanMapPutReturnsOldValue() {
+	public OutputStreamSerializerBuilder beanMapPutReturnsOldValue() {
 		super.beanMapPutReturnsOldValue();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanConstructorVisibility(Visibility value) {
+	public OutputStreamSerializerBuilder beanConstructorVisibility(Visibility value) {
 		super.beanConstructorVisibility(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanClassVisibility(Visibility value) {
+	public OutputStreamSerializerBuilder beanClassVisibility(Visibility value) {
 		super.beanClassVisibility(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanFieldVisibility(Visibility value) {
+	public OutputStreamSerializerBuilder beanFieldVisibility(Visibility value) {
 		super.beanFieldVisibility(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanMethodVisibility(Visibility value) {
+	public OutputStreamSerializerBuilder beanMethodVisibility(Visibility value) {
 		super.beanMethodVisibility(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder useJavaBeanIntrospector(boolean value) {
+	public OutputStreamSerializerBuilder useJavaBeanIntrospector(boolean value) {
 		super.useJavaBeanIntrospector(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder useJavaBeanIntrospector() {
+	public OutputStreamSerializerBuilder useJavaBeanIntrospector() {
 		super.useJavaBeanIntrospector();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder useInterfaceProxies(boolean value) {
+	public OutputStreamSerializerBuilder useInterfaceProxies(boolean value) {
 		super.useInterfaceProxies(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder ignoreUnknownBeanProperties(boolean value) {
+	public OutputStreamSerializerBuilder ignoreUnknownBeanProperties(boolean value) {
 		super.ignoreUnknownBeanProperties(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder ignoreUnknownBeanProperties() {
+	public OutputStreamSerializerBuilder ignoreUnknownBeanProperties() {
 		super.ignoreUnknownBeanProperties();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder ignoreUnknownNullBeanProperties(boolean value) {
+	public OutputStreamSerializerBuilder ignoreUnknownNullBeanProperties(boolean value) {
 		super.ignoreUnknownNullBeanProperties(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder ignorePropertiesWithoutSetters(boolean value) {
+	public OutputStreamSerializerBuilder ignorePropertiesWithoutSetters(boolean value) {
 		super.ignorePropertiesWithoutSetters(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder ignoreInvocationExceptionsOnGetters(boolean value) {
+	public OutputStreamSerializerBuilder ignoreInvocationExceptionsOnGetters(boolean value) {
 		super.ignoreInvocationExceptionsOnGetters(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder ignoreInvocationExceptionsOnGetters() {
+	public OutputStreamSerializerBuilder ignoreInvocationExceptionsOnGetters() {
 		super.ignoreInvocationExceptionsOnGetters();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder ignoreInvocationExceptionsOnSetters(boolean value) {
+	public OutputStreamSerializerBuilder ignoreInvocationExceptionsOnSetters(boolean value) {
 		super.ignoreInvocationExceptionsOnSetters(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder ignoreInvocationExceptionsOnSetters() {
+	public OutputStreamSerializerBuilder ignoreInvocationExceptionsOnSetters() {
 		super.ignoreInvocationExceptionsOnSetters();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder sortProperties(boolean value) {
+	public OutputStreamSerializerBuilder sortProperties(boolean value) {
 		super.sortProperties(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder sortProperties() {
+	public OutputStreamSerializerBuilder sortProperties() {
 		super.sortProperties();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder notBeanPackages(Object...values) {
+	public OutputStreamSerializerBuilder notBeanPackages(Object...values) {
 		super.notBeanPackages(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder notBeanPackages(String...values) {
+	public OutputStreamSerializerBuilder notBeanPackages(String...values) {
 		super.notBeanPackages(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder notBeanPackages(boolean append, Object...values) {
+	public OutputStreamSerializerBuilder notBeanPackages(boolean append, Object...values) {
 		super.notBeanPackages(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder notBeanPackagesRemove(Object...values) {
+	public OutputStreamSerializerBuilder notBeanPackagesRemove(Object...values) {
 		super.notBeanPackagesRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder notBeanClasses(Object...values) {
+	public OutputStreamSerializerBuilder notBeanClasses(Object...values) {
 		super.notBeanClasses(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder notBeanClasses(Class<?>...values) {
+	public OutputStreamSerializerBuilder notBeanClasses(Class<?>...values) {
 		super.notBeanClasses(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder notBeanClasses(boolean append, Object...values) {
+	public OutputStreamSerializerBuilder notBeanClasses(boolean append, Object...values) {
 		super.notBeanClasses(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder notBeanClassesRemove(Object...values) {
+	public OutputStreamSerializerBuilder notBeanClassesRemove(Object...values) {
 		super.notBeanClassesRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanFilters(Object...values) {
+	public OutputStreamSerializerBuilder beanFilters(Object...values) {
 		super.beanFilters(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanFilters(Class<?>...values) {
+	public OutputStreamSerializerBuilder beanFilters(Class<?>...values) {
 		super.beanFilters(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanFilters(boolean append, Object...values) {
+	public OutputStreamSerializerBuilder beanFilters(boolean append, Object...values) {
 		super.beanFilters(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanFiltersRemove(Object...values) {
+	public OutputStreamSerializerBuilder beanFiltersRemove(Object...values) {
 		super.beanFiltersRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder pojoSwaps(Object...values) {
+	public OutputStreamSerializerBuilder pojoSwaps(Object...values) {
 		super.pojoSwaps(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder pojoSwaps(Class<?>...values) {
+	public OutputStreamSerializerBuilder pojoSwaps(Class<?>...values) {
 		super.pojoSwaps(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder pojoSwaps(boolean append, Object...values) {
+	public OutputStreamSerializerBuilder pojoSwaps(boolean append, Object...values) {
 		super.pojoSwaps(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder pojoSwapsRemove(Object...values) {
+	public OutputStreamSerializerBuilder pojoSwapsRemove(Object...values) {
 		super.pojoSwapsRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder implClasses(Map<String,Class<?>> values) {
+	public OutputStreamSerializerBuilder implClasses(Map<String,Class<?>> values) {
 		super.implClasses(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public <T> YamlParserBuilder implClass(Class<T> interfaceClass, Class<? extends T> implClass) {
+	public <T> SerializerBuilder implClass(Class<T> interfaceClass, Class<? extends T> implClass) {
 		super.implClass(interfaceClass, implClass);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanDictionary(Object...values) {
+	public OutputStreamSerializerBuilder beanDictionary(Object...values) {
 		super.beanDictionary(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanDictionary(Class<?>...values) {
+	public OutputStreamSerializerBuilder beanDictionary(Class<?>...values) {
 		super.beanDictionary(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanDictionary(boolean append, Object...values) {
+	public OutputStreamSerializerBuilder beanDictionary(boolean append, Object...values) {
 		super.beanDictionary(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanDictionaryRemove(Object...values) {
+	public OutputStreamSerializerBuilder beanDictionaryRemove(Object...values) {
 		super.beanDictionaryRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder beanTypePropertyName(String value) {
+	public OutputStreamSerializerBuilder beanTypePropertyName(String value) {
 		super.beanTypePropertyName(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder locale(Locale value) {
+	public OutputStreamSerializerBuilder locale(Locale value) {
 		super.locale(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder timeZone(TimeZone value) {
+	public OutputStreamSerializerBuilder timeZone(TimeZone value) {
 		super.timeZone(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder mediaType(MediaType value) {
+	public OutputStreamSerializerBuilder mediaType(MediaType value) {
 		super.mediaType(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public YamlParserBuilder debug() {
+	public OutputStreamSerializerBuilder debug() {
 		super.debug();
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public YamlParserBuilder set(String name, Object value) {
+	public OutputStreamSerializerBuilder set(String name, Object value) {
 		super.set(name, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public YamlParserBuilder set(boolean append, String name, Object value) {
+	public OutputStreamSerializerBuilder set(boolean append, String name, Object value) {
 		super.set(append, name, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public YamlParserBuilder set(Map<String,Object> properties) {
+	public OutputStreamSerializerBuilder set(Map<String,Object> properties) {
 		super.set(properties);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public YamlParserBuilder add(Map<String,Object> properties) {
+	public OutputStreamSerializerBuilder add(Map<String,Object> properties) {
 		super.add(properties);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public YamlParserBuilder addTo(String name, Object value) {
+	public OutputStreamSerializerBuilder addTo(String name, Object value) {
 		super.addTo(name, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public YamlParserBuilder addTo(String name, String key, Object value) {
+	public OutputStreamSerializerBuilder addTo(String name, String key, Object value) {
 		super.addTo(name, key, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public YamlParserBuilder removeFrom(String name, Object value) {
+	public OutputStreamSerializerBuilder removeFrom(String name, Object value) {
 		super.removeFrom(name, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public YamlParserBuilder apply(PropertyStore copyFrom) {
+	public OutputStreamSerializerBuilder apply(PropertyStore copyFrom) {
 		super.apply(copyFrom);
 		return this;
 	}
-}
\ No newline at end of file
+	
+	@Override /* Context */
+	public OutputStreamSerializer build() {
+		return null;
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerSession.java
index b9c4f55..aaf2bb4 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializerSession.java
@@ -12,8 +12,13 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.serializer;
 
+import static org.apache.juneau.serializer.OutputStreamSerializer.*;
+
 import java.io.*;
 
+import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
+
 /**
  * Subclass of {@link SerializerSession} for stream-based serializers.
  * 
@@ -27,6 +32,8 @@ import java.io.*;
  */
 public abstract class OutputStreamSerializerSession extends SerializerSession {
 
+	private final BinaryFormat binaryFormat;
+
 	/**
 	 * Create a new session using properties specified in the context.
 	 * 
@@ -39,8 +46,10 @@ public abstract class OutputStreamSerializerSession extends SerializerSession {
 	 * 	It also include session-level properties that override the properties defined on the bean and
 	 * 	serializer contexts.
 	 */
-	protected OutputStreamSerializerSession(Serializer ctx, SerializerSessionArgs args) {
+	protected OutputStreamSerializerSession(OutputStreamSerializer ctx, SerializerSessionArgs args) {
 		super(ctx, args);
+		
+		binaryFormat = getProperty(OSSERIALIZER_binaryFormat, BinaryFormat.class, BinaryFormat.HEX);
 	}
 
 	/**
@@ -50,7 +59,7 @@ public abstract class OutputStreamSerializerSession extends SerializerSession {
 	 * 	Runtime session arguments.
 	 */
 	protected OutputStreamSerializerSession(SerializerSessionArgs args) {
-		super(args);
+		this(OutputStreamSerializer.DEFAULT, args);
 	}
 
 	@Override /* SerializerSession */
@@ -71,4 +80,15 @@ public abstract class OutputStreamSerializerSession extends SerializerSession {
 		serialize(o, baos);
 		return baos.toByteArray();
 	}
+	
+	@Override /* SerializerSession */
+	public final String serializeToString(Object o) throws SerializeException {
+		byte[] b = serialize(o);
+		switch(binaryFormat) {
+			case SPACED_HEX:  return StringUtils.toSpacedHex(b);
+			case HEX:  return StringUtils.toHex(b);
+			case BASE64:  return StringUtils.base64Encode(b);
+			default: return null;
+		}
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
index 18433ef..8c71722 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
@@ -406,85 +406,6 @@ public abstract class Serializer extends BeanContext {
 	public static final String SERIALIZER_maxDepth = PREFIX + "maxDepth.i";
 
 	/**
-	 * Configuration property:  Maximum indentation.
-	 * 
-	 * <h5 class='section'>Property:</h5>
-	 * <ul>
-	 * 	<li><b>Name:</b>  <js>"Serializer.maxIndent.i"</js>
-	 * 	<li><b>Data type:</b>  <code>Integer</code>
-	 * 	<li><b>Default:</b>  <code>100</code>
-	 * 	<li><b>Session-overridable:</b>  <jk>true</jk>
-	 * 	<li><b>Methods:</b> 
-	 * 		<ul>
-	 * 			<li class='jm'>{@link SerializerBuilder#maxIndent(int)}
-	 * 		</ul>
-	 * </ul>
-	 * 
-	 * <h5 class='section'>Description:</h5>
-	 * <p>
-	 * Specifies the maximum indentation level in the serialized document.
-	 * 
-	 * <p>
-	 * This setting does not apply to the MessagePack or RDF serializers.
-	 * 
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<jc>// Create a serializer that indents a maximum of 20 tabs.</jc>
-	 * 	WriterSerializer s = JsonSerializer
-	 * 		.<jsm>create</jsm>()
-	 * 		.maxIndent(20)
-	 * 		.build();
-	 * 	
-	 * 	<jc>// Same, but use property.</jc>
-	 * 	WriterSerializer s = JsonSerializer
-	 * 		.<jsm>create</jsm>()
-	 * 		.set(<jsf>SERIALIZER_maxIndent</jsf>, 20)
-	 * 		.build();
-	 * </p>
-	 */
-	public static final String SERIALIZER_maxIndent = PREFIX + "maxIndent.i";
-
-	/**
-	 * Configuration property:  Quote character.
-	 * 
-	 * <h5 class='section'>Property:</h5>
-	 * <ul>
-	 * 	<li><b>Name:</b>  <js>"Serializer.quoteChar.s"</js>
-	 * 	<li><b>Data type:</b>  <code>String</code>
-	 * 	<li><b>Default:</b>  <js>"\""</js>
-	 * 	<li><b>Session-overridable:</b>  <jk>true</jk>
-	 * 	<li><b>Methods:</b> 
-	 * 		<ul>
-	 * 			<li class='jm'>{@link SerializerBuilder#quoteChar(char)}
-	 * 			<li class='jm'>{@link SerializerBuilder#sq()}
-	 * 		</ul>
-	 * </ul>
-	 * 
-	 * <h5 class='section'>Description:</h5>
-	 * <p>
-	 * This is the character used for quoting attributes and values.
-	 * 
-	 * <p>
-	 * This setting does not apply to the MessagePack or RDF serializers.
-	 * 
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<jc>// Create a serializer that uses single quotes.</jc>
-	 * 	WriterSerializer s = JsonSerializer
-	 * 		.<jsm>create</jsm>()
-	 * 		.sq()
-	 * 		.build();
-	 * 	
-	 * 	<jc>// Same, but use property.</jc>
-	 * 	WriterSerializer s = JsonSerializer
-	 * 		.<jsm>create</jsm>()
-	 * 		.set(<jsf>SERIALIZER_quoteChar</jsf>, <js>'\''</js>)
-	 * 		.build();
-	 * </p>
-	 */
-	public static final String SERIALIZER_quoteChar = PREFIX + "quoteChar.s";
-
-	/**
 	 * Configuration property:  Sort arrays and collections alphabetically.
 	 * 
 	 * <h5 class='section'>Property:</h5>
@@ -912,50 +833,6 @@ public abstract class Serializer extends BeanContext {
 	 */
 	public static final String SERIALIZER_uriResolution = PREFIX + "uriResolution.s";
 
-	/**
-	 * Configuration property:  Use whitespace.
-	 * 
-	 * <h5 class='section'>Property:</h5>
-	 * <ul>
-	 * 	<li><b>Name:</b>  <js>"Serializer.useWhitespace.b"</js>
-	 * 	<li><b>Data type:</b>  <code>Boolean</code>
-	 * 	<li><b>Default:</b>  <jk>false</jk>
-	 * 	<li><b>Session-overridable:</b>  <jk>true</jk>
-	 * 	<li><b>Methods:</b> 
-	 * 		<ul>
-	 * 			<li class='jm'>{@link SerializerBuilder#useWhitespace(boolean)}
-	 * 			<li class='jm'>{@link SerializerBuilder#useWhitespace()}
-	 * 			<li class='jm'>{@link SerializerBuilder#ws()}
-	 * 		</ul>
-	 * </ul>
-	 * 
-	 * <h5 class='section'>Description:</h5>
-	 * <p>
-	 * If <jk>true</jk>, whitespace is added to the output to improve readability.
-	 * 
-	 * <p>
-	 * This setting does not apply to the MessagePack serializer.
-	 * 
-	 * <h5 class='section'>Example:</h5>
-	 * <p class='bcode'>
-	 * 	<jc>// Create a serializer with whitespace enabled.</jc>
-	 * 	WriterSerializer s = JsonSerializer
-	 * 		.<jsm>create</jsm>()
-	 * 		.ws()
-	 * 		.build();
-	 * 	
-	 * 	<jc>// Same, but use property.</jc>
-	 * 	WriterSerializer s = JsonSerializer
-	 * 		.<jsm>create</jsm>()
-	 * 		.set(<jsf>SERIALIZER_useWhitespace</jsf>, <jk>true</jk>)
-	 * 		.build();
-	 * 
-	 * 	<jc>// Produces "\{\n\t'foo': 'bar'\n\}\n"</jc>
-	 * 	String json = s.serialize(<jk>new</jk> MyBean());
-	 * </p>
-	 */
-	public static final String SERIALIZER_useWhitespace = PREFIX + "useWhitespace.b";
-
 	
 	static final Serializer DEFAULT = new Serializer(PropertyStore.create().build(), "") {
 		@Override
@@ -968,11 +845,10 @@ public abstract class Serializer extends BeanContext {
 	// Instance
 	//-------------------------------------------------------------------------------------------------------------------
 
-	final int maxDepth, initialDepth, maxIndent;
+	final int initialDepth, maxDepth;
 	final boolean
 		detectRecursions,
 		ignoreRecursions,
-		useWhitespace,
 		addBeanTypeProperties,
 		trimNulls,
 		trimEmptyCollections,
@@ -981,7 +857,6 @@ public abstract class Serializer extends BeanContext {
 		sortCollections,
 		sortMaps,
 		abridged;
-	final char quoteChar;
 	final UriContext uriContext;
 	final UriResolution uriResolution;
 	final UriRelativity uriRelativity;
@@ -998,8 +873,6 @@ public abstract class Serializer extends BeanContext {
 		initialDepth = getIntegerProperty(SERIALIZER_initialDepth, 0);
 		detectRecursions = getBooleanProperty(SERIALIZER_detectRecursions, false);
 		ignoreRecursions = getBooleanProperty(SERIALIZER_ignoreRecursions, false);
-		useWhitespace = getBooleanProperty(SERIALIZER_useWhitespace, false);
-		maxIndent = getIntegerProperty(SERIALIZER_maxIndent, 100);
 		addBeanTypeProperties = getBooleanProperty(SERIALIZER_addBeanTypeProperties, true);
 		trimNulls = getBooleanProperty(SERIALIZER_trimNullProperties, true);
 		trimEmptyCollections = getBooleanProperty(SERIALIZER_trimEmptyCollections, false);
@@ -1008,7 +881,6 @@ public abstract class Serializer extends BeanContext {
 		sortCollections = getBooleanProperty(SERIALIZER_sortCollections, false);
 		sortMaps = getBooleanProperty(SERIALIZER_sortMaps, false);
 		abridged = getBooleanProperty(SERIALIZER_abridged, false);
-		quoteChar = getStringProperty(SERIALIZER_quoteChar, "\"").charAt(0);
 		uriContext = getProperty(SERIALIZER_uriContext, UriContext.class, UriContext.DEFAULT);
 		uriResolution = getProperty(SERIALIZER_uriResolution, UriResolution.class, UriResolution.NONE);
 		uriRelativity = getProperty(SERIALIZER_uriRelativity, UriRelativity.class, UriRelativity.RESOURCE);
@@ -1113,6 +985,22 @@ public abstract class Serializer extends BeanContext {
 		return createSession().serialize(o);
 	}
 
+	/**
+	 * Convenience method for serializing an object to a String.
+	 * 
+	 * <p>
+	 * For writer-based serializers, this is identical to calling {@link #serialize(Object)}.
+	 * <br>For stream-based serializers, this converts the returned byte array to a string based on 
+	 * the {@link OutputStreamSerializer#OSSERIALIZER_binaryFormat} setting.
+	 * 
+	 * @param o The object to serialize.
+	 * @return The output serialized to a string.
+	 * @throws SerializeException If a problem occurred trying to convert the output.
+	 */
+	public final String serializeToString(Object o) throws SerializeException {
+		return createSession().serializeToString(o);
+	}
+
 	//--------------------------------------------------------------------------------
 	// Other methods
 	//--------------------------------------------------------------------------------
@@ -1154,8 +1042,6 @@ public abstract class Serializer extends BeanContext {
 				.append("initialDepth", initialDepth)
 				.append("detectRecursions", detectRecursions)
 				.append("ignoreRecursions", ignoreRecursions)
-				.append("useWhitespace", useWhitespace)
-				.append("maxIndent", maxIndent)
 				.append("addBeanTypeProperties", addBeanTypeProperties)
 				.append("trimNulls", trimNulls)
 				.append("trimEmptyCollections", trimEmptyCollections)
@@ -1164,7 +1050,6 @@ public abstract class Serializer extends BeanContext {
 				.append("sortCollections", sortCollections)
 				.append("sortMaps", sortMaps)
 				.append("parserKnowsRootTypes", abridged)
-				.append("quoteChar", quoteChar)
 				.append("uriContext", uriContext)
 				.append("uriResolution", uriResolution)
 				.append("uriRelativity", uriRelativity)
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
index 36514ec..91a1c5c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerBuilder.java
@@ -253,46 +253,6 @@ public class SerializerBuilder extends BeanContextBuilder {
 	}
 
 	/**
-	 * Configuration property:  Maximum indentation.
-	 * 
-	 * <p>
-	 * Specifies the maximum indentation level in the serialized document.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Serializer#SERIALIZER_maxIndent}
-	 * </ul>
-	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>The default is <code>100</code>.
-	 * @return This object (for method chaining).
-	 */
-	public SerializerBuilder maxIndent(int value) {
-		return set(SERIALIZER_maxIndent, value);
-	}
-
-	/**
-	 * Configuration property:  Quote character.
-	 * 
-	 * <p>
-	 * This is the character used for quoting attributes and values.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Serializer#SERIALIZER_quoteChar}
-	 * </ul>
-	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>The default is <js>'"'</js>.
-	 * @return This object (for method chaining).
-	 */
-	public SerializerBuilder quoteChar(char value) {
-		return set(SERIALIZER_quoteChar, value);
-	}
-
-	/**
 	 * Configuration property:  Sort arrays and collections alphabetically.
 	 * 
 	 * <p>
@@ -367,23 +327,6 @@ public class SerializerBuilder extends BeanContextBuilder {
 	}
 
 	/**
-	 * Configuration property:  Quote character.
-	 * 
-	 * <p>
-	 * Shortcut for calling <code>quoteChar(<js>'\''</js>)</code>.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Serializer#SERIALIZER_quoteChar}
-	 * </ul>
-	 * 
-	 * @return This object (for method chaining).
-	 */
-	public SerializerBuilder sq() {
-		return quoteChar('\'');
-	}
-
-	/**
 	 * Configuration property:  Trim empty lists and arrays.
 	 * 
 	 * <p>
@@ -654,59 +597,6 @@ public class SerializerBuilder extends BeanContextBuilder {
 		return set(SERIALIZER_uriResolution, value);
 	}
 
-	/**
-	 * Configuration property:  Use whitespace.
-	 * 
-	 * <p>
-	 * If <jk>true</jk>, newlines and indentation and spaces are added to the output to improve readability.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Serializer#SERIALIZER_useWhitespace}
-	 * </ul>
-	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>The default is <jk>false</jk>.
-	 * @return This object (for method chaining).
-	 */
-	public SerializerBuilder useWhitespace(boolean value) {
-		return set(SERIALIZER_useWhitespace, value);
-	}
-
-	/**
-	 * Configuration property:  Use whitespace.
-	 * 
-	 * <p>
-	 * Shortcut for calling <code>useWhitespace(<jk>true</jk>)</code>.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Serializer#SERIALIZER_useWhitespace}
-	 * </ul>
-	 * @return This object (for method chaining).
-	 */
-	public SerializerBuilder useWhitespace() {
-		return set(SERIALIZER_useWhitespace, true);
-	}
-
-	/**
-	 * Configuration property:  Use whitespace.
-	 * 
-	 * <p>
-	 * Shortcut for calling <code>useWhitespace(<jk>true</jk>)</code>.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Serializer#SERIALIZER_useWhitespace}
-	 * </ul>
-	 * 
-	 * @return This object (for method chaining).
-	 */
-	public SerializerBuilder ws() {
-		return useWhitespace();
-	}
-
 	@Override /* BeanContextBuilder */
 	public SerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
index 20a4a62..c2e771b 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerGroupBuilder.java
@@ -13,7 +13,8 @@
 package org.apache.juneau.serializer;
 
 import static org.apache.juneau.internal.CollectionUtils.*;
-import static org.apache.juneau.serializer.Serializer.*;
+import static org.apache.juneau.serializer.OutputStreamSerializer.*;
+import static org.apache.juneau.serializer.WriterSerializer.*;
 
 import java.util.*;
 
@@ -338,46 +339,6 @@ public class SerializerGroupBuilder extends BeanContextBuilder {
 	}
 
 	/**
-	 * Configuration property:  Maximum indentation.
-	 * 
-	 * <p>
-	 * Specifies the maximum indentation level in the serialized document.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Serializer#SERIALIZER_maxIndent}
-	 * </ul>
-	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>The default is <code>100</code>.
-	 * @return This object (for method chaining).
-	 */
-	public SerializerGroupBuilder maxIndent(int value) {
-		return set(SERIALIZER_maxIndent, value);
-	}
-
-	/**
-	 * Configuration property:  Quote character.
-	 * 
-	 * <p>
-	 * This is the character used for quoting attributes and values.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Serializer#SERIALIZER_quoteChar}
-	 * </ul>
-	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>The default is <js>'"'</js>.
-	 * @return This object (for method chaining).
-	 */
-	public SerializerGroupBuilder quoteChar(char value) {
-		return set(SERIALIZER_quoteChar, value);
-	}
-
-	/**
 	 * Configuration property:  Sort arrays and collections alphabetically.
 	 * 
 	 * <h5 class='section'>See Also:</h5>
@@ -446,23 +407,6 @@ public class SerializerGroupBuilder extends BeanContextBuilder {
 	}
 
 	/**
-	 * Configuration property:  Sort maps alphabetically.
-	 * 
-	 * <p>
-	 * Shortcut for calling <code>quoteChar(<js>'\''</js>)</code>.
-	 * 
-	 * <h5 class='section'>See Also:</h5>
-	 * <ul>
-	 * 	<li class='jf'>{@link Serializer#SERIALIZER_quoteChar}
-	 * </ul>
-	 * 
-	 * @return This object (for method chaining).
-	 */
-	public SerializerGroupBuilder sq() {
-		return quoteChar('\'');
-	}
-
-	/**
 	 * Configuration property:  Trim empty lists and arrays.
 	 * 
 	 * <p>
@@ -651,6 +595,65 @@ public class SerializerGroupBuilder extends BeanContextBuilder {
 		return set(SERIALIZER_uriResolution, value);
 	}
 
+	//--- WriterSerializer ---
+	
+	/**
+	 * Configuration property:  Maximum indentation.
+	 * 
+	 * <p>
+	 * Specifies the maximum indentation level in the serialized document.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link WriterSerializer#WSERIALIZER_maxIndent}
+	 * </ul>
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default is <code>100</code>.
+	 * @return This object (for method chaining).
+	 */
+	public SerializerGroupBuilder maxIndent(int value) {
+		return set(WSERIALIZER_maxIndent, value);
+	}
+
+	/**
+	 * Configuration property:  Quote character.
+	 * 
+	 * <p>
+	 * This is the character used for quoting attributes and values.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link WriterSerializer#WSERIALIZER_quoteChar}
+	 * </ul>
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default is <js>'"'</js>.
+	 * @return This object (for method chaining).
+	 */
+	public SerializerGroupBuilder quoteChar(char value) {
+		return set(WSERIALIZER_quoteChar, value);
+	}
+
+	/**
+	 * Configuration property:  Use single quotes.
+	 * 
+	 * <p>
+	 * Shortcut for calling <code>quoteChar(<js>'\''</js>)</code>.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link WriterSerializer#WSERIALIZER_quoteChar}
+	 * </ul>
+	 * 
+	 * @return This object (for method chaining).
+	 */
+	public SerializerGroupBuilder sq() {
+		return quoteChar('\'');
+	}
+
 	/**
 	 * Configuration property:  Use whitespace.
 	 * 
@@ -659,7 +662,7 @@ public class SerializerGroupBuilder extends BeanContextBuilder {
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link Serializer#SERIALIZER_useWhitespace}
+	 * 	<li class='jf'>{@link WriterSerializer#WSERIALIZER_useWhitespace}
 	 * </ul>
 	 * 
 	 * @param value 
@@ -668,7 +671,7 @@ public class SerializerGroupBuilder extends BeanContextBuilder {
 	 * @return This object (for method chaining).
 	 */
 	public SerializerGroupBuilder useWhitespace(boolean value) {
-		return set(SERIALIZER_useWhitespace, value);
+		return set(WSERIALIZER_useWhitespace, value);
 	}
 
 	/**
@@ -679,12 +682,12 @@ public class SerializerGroupBuilder extends BeanContextBuilder {
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link Serializer#SERIALIZER_useWhitespace}
+	 * 	<li class='jf'>{@link WriterSerializer#WSERIALIZER_useWhitespace}
 	 * </ul>
 	 * @return This object (for method chaining).
 	 */
 	public SerializerGroupBuilder useWhitespace() {
-		return set(SERIALIZER_useWhitespace, true);
+		return set(WSERIALIZER_useWhitespace, true);
 	}
 
 	/**
@@ -695,7 +698,7 @@ public class SerializerGroupBuilder extends BeanContextBuilder {
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link Serializer#SERIALIZER_useWhitespace}
+	 * 	<li class='jf'>{@link WriterSerializer#WSERIALIZER_useWhitespace}
 	 * </ul>
 	 * 
 	 * @return This object (for method chaining).
@@ -704,7 +707,28 @@ public class SerializerGroupBuilder extends BeanContextBuilder {
 		return useWhitespace();
 	}
 
+	//--- OutputStreamSerializer ---
 
+	/**
+	 * Configuration property:  Binary string format.
+	 * 
+	 * <p>
+	 * When using the {@link Serializer#serializeToString(Object)} method on stream-based serializers, this defines the format to use
+	 * when converting the resulting byte array to a string.
+	 * 
+	 * <ul>
+	 * 	<li class='jf'>{@link OutputStreamSerializer#OSSERIALIZER_binaryFormat}
+	 * </ul>
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default is {@link BinaryFormat#HEX}.
+	 * @return This object (for method chaining).
+	 */
+	public SerializerGroupBuilder binaryOutputFormat(BinaryFormat value) {
+		return set(OSSERIALIZER_binaryFormat, value);
+	}
+	
 	@Override /* BeanContextBuilder */
 	public SerializerGroupBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
index 49e4ecd..dce03a4 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
@@ -49,11 +49,10 @@ import org.apache.juneau.transform.*;
  */
 public abstract class SerializerSession extends BeanSession {
 
-	private final int maxDepth, initialDepth, maxIndent;
+	private final int maxDepth, initialDepth;
 	private final boolean
 		detectRecursions,
 		ignoreRecursions,
-		useWhitespace,
 		addBeanTypeProperties,
 		trimNulls,
 		trimEmptyCollections,
@@ -62,7 +61,6 @@ public abstract class SerializerSession extends BeanSession {
 		sortCollections,
 		sortMaps,
 		abridged;
-	private final char quoteChar;
 	private final UriResolver uriResolver;
 
 	private final Map<Object,Object> set;                                           // Contains the current objects in the current branch of the model.
@@ -103,14 +101,11 @@ public abstract class SerializerSession extends BeanSession {
 		initialDepth = getProperty(SERIALIZER_initialDepth, int.class, ctx.initialDepth);
 		detectRecursions = getProperty(SERIALIZER_detectRecursions, boolean.class, ctx.detectRecursions);
 		ignoreRecursions = getProperty(SERIALIZER_ignoreRecursions, boolean.class, ctx.ignoreRecursions);
-		useWhitespace = getProperty(SERIALIZER_useWhitespace, boolean.class, ctx.useWhitespace);
-		maxIndent = getProperty(SERIALIZER_maxIndent, int.class, ctx.maxIndent);
 		addBeanTypeProperties = getProperty(SERIALIZER_addBeanTypeProperties, boolean.class, ctx.addBeanTypeProperties);
 		trimNulls = getProperty(SERIALIZER_trimNullProperties, boolean.class, ctx.trimNulls);
 		trimEmptyCollections = getProperty(SERIALIZER_trimEmptyCollections, boolean.class, ctx.trimEmptyCollections);
 		trimEmptyMaps = getProperty(SERIALIZER_trimEmptyMaps, boolean.class, ctx.trimEmptyMaps);
 		trimStrings = getProperty(SERIALIZER_trimStrings, boolean.class, ctx.trimStrings);
-		quoteChar = getProperty(SERIALIZER_quoteChar, String.class, ""+ctx.quoteChar).charAt(0);
 		sortCollections = getProperty(SERIALIZER_sortCollections, boolean.class, ctx.sortMaps);
 		sortMaps = getProperty(SERIALIZER_sortMaps, boolean.class, ctx.sortMaps);
 		abridged = getProperty(SERIALIZER_abridged, boolean.class, ctx.abridged);
@@ -149,10 +144,8 @@ public abstract class SerializerSession extends BeanSession {
 			.append("SerializerSession", new ObjectMap()
 				.append("maxDepth", maxDepth)
 				.append("initialDepth", initialDepth)
-				.append("maxIndent", maxIndent)
 				.append("detectRecursions", detectRecursions)
 				.append("ignoreRecursions", ignoreRecursions)
-				.append("useWhitespace", useWhitespace)
 				.append("addBeanTypeProperties", addBeanTypeProperties)
 				.append("trimNulls", trimNulls)
 				.append("trimEmptyCollections", trimEmptyCollections)
@@ -161,7 +154,6 @@ public abstract class SerializerSession extends BeanSession {
 				.append("sortCollections", sortCollections)
 				.append("sortMaps", sortMaps)
 				.append("abridged", abridged)
-				.append("quoteChar", quoteChar)
 				.append("uriResolver", uriResolver)
 			);
 	}
@@ -215,13 +207,25 @@ public abstract class SerializerSession extends BeanSession {
 	 * @param o The object to serialize.
 	 * @return
 	 * 	The serialized object.
-	 * 	<br>Character-based serializers will return a <code>String</code>
-	 * 	<br>Stream-based serializers will return a <code><jk>byte</jk>[]</code>
+	 * 	<br>Character-based serializers will return a <code>String</code>.
+	 * 	<br>Stream-based serializers will return a <code><jk>byte</jk>[]</code>.
 	 * @throws SerializeException If a problem occurred trying to convert the output.
 	 */
 	public abstract Object serialize(Object o) throws SerializeException;
 
 	/**
+	 * Shortcut method for serializing an object to a String.
+	 * 
+	 * @param o The object to serialize.
+	 * @return
+	 * 	The serialized object.
+	 * 	<br>Character-based serializers will return a <code>String</code>
+	 * 	<br>Stream-based serializers will return a <code><jk>byte</jk>[]</code> converted to a string based on the {@link OutputStreamSerializer#OSSERIALIZER_binaryFormat} setting.
+	 * @throws SerializeException If a problem occurred trying to convert the output.
+	 */
+	public abstract String serializeToString(Object o) throws SerializeException;
+
+	/**
 	 * Returns <jk>true</jk> if this serializer subclasses from {@link WriterSerializer}.
 	 * 
 	 * @return <jk>true</jk> if this serializer subclasses from {@link WriterSerializer}.
@@ -332,24 +336,6 @@ public abstract class SerializerSession extends BeanSession {
 	}
 
 	/**
-	 * Returns the {@link Serializer#SERIALIZER_useWhitespace} setting value for this session.
-	 * 
-	 * @return The {@link Serializer#SERIALIZER_useWhitespace} setting value for this session.
-	 */
-	protected boolean isUseWhitespace() {
-		return useWhitespace;
-	}
-
-	/**
-	 * Returns the {@link Serializer#SERIALIZER_maxIndent} setting value for this session.
-	 * 
-	 * @return The {@link Serializer#SERIALIZER_maxIndent} setting value for this session.
-	 */
-	protected int getMaxIndent() {
-		return maxIndent;
-	}
-
-	/**
 	 * Returns the {@link Serializer#SERIALIZER_addBeanTypeProperties} setting value for this session.
 	 * 
 	 * @return The {@link Serializer#SERIALIZER_addBeanTypeProperties} setting value for this session.
@@ -359,15 +345,6 @@ public abstract class SerializerSession extends BeanSession {
 	}
 
 	/**
-	 * Returns the {@link Serializer#SERIALIZER_quoteChar} setting value for this session.
-	 * 
-	 * @return The {@link Serializer#SERIALIZER_quoteChar} setting value for this session.
-	 */
-	protected char getQuoteChar() {
-		return quoteChar;
-	}
-
-	/**
 	 * Returns the {@link Serializer#SERIALIZER_trimNullProperties} setting value for this session.
 	 * 
 	 * @return The {@link Serializer#SERIALIZER_trimNullProperties} setting value for this session.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
index 03ac99a..03f3eb5 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
@@ -20,6 +20,147 @@ import org.apache.juneau.utils.*;
  */
 public abstract class WriterSerializer extends Serializer {
 
+	//-------------------------------------------------------------------------------------------------------------------
+	// Configurable properties
+	//-------------------------------------------------------------------------------------------------------------------
+
+	private static final String PREFIX = "WriterSerializer.";
+
+	/**
+	 * Configuration property:  Maximum indentation.
+	 * 
+	 * <h5 class='section'>Property:</h5>
+	 * <ul>
+	 * 	<li><b>Name:</b>  <js>"WriterSerializer.maxIndent.i"</js>
+	 * 	<li><b>Data type:</b>  <code>Integer</code>
+	 * 	<li><b>Default:</b>  <code>100</code>
+	 * 	<li><b>Session-overridable:</b>  <jk>true</jk>
+	 * 	<li><b>Methods:</b> 
+	 * 		<ul>
+	 * 			<li class='jm'>{@link WriterSerializerBuilder#maxIndent(int)}
+	 * 		</ul>
+	 * </ul>
+	 * 
+	 * <h5 class='section'>Description:</h5>
+	 * <p>
+	 * Specifies the maximum indentation level in the serialized document.
+	 * 
+	 * <p>
+	 * This setting does not apply to the RDF serializers.
+	 * 
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Create a serializer that indents a maximum of 20 tabs.</jc>
+	 * 	WriterSerializer s = JsonSerializer
+	 * 		.<jsm>create</jsm>()
+	 * 		.maxIndent(20)
+	 * 		.build();
+	 * 	
+	 * 	<jc>// Same, but use property.</jc>
+	 * 	WriterSerializer s = JsonSerializer
+	 * 		.<jsm>create</jsm>()
+	 * 		.set(<jsf>SERIALIZER_maxIndent</jsf>, 20)
+	 * 		.build();
+	 * </p>
+	 */
+	public static final String WSERIALIZER_maxIndent = PREFIX + "maxIndent.i";
+
+	/**
+	 * Configuration property:  Quote character.
+	 * 
+	 * <h5 class='section'>Property:</h5>
+	 * <ul>
+	 * 	<li><b>Name:</b>  <js>"WriterSerializer.quoteChar.s"</js>
+	 * 	<li><b>Data type:</b>  <code>String</code>
+	 * 	<li><b>Default:</b>  <js>"\""</js>
+	 * 	<li><b>Session-overridable:</b>  <jk>true</jk>
+	 * 	<li><b>Methods:</b> 
+	 * 		<ul>
+	 * 			<li class='jm'>{@link WriterSerializerBuilder#quoteChar(char)}
+	 * 			<li class='jm'>{@link WriterSerializerBuilder#sq()}
+	 * 		</ul>
+	 * </ul>
+	 * 
+	 * <h5 class='section'>Description:</h5>
+	 * <p>
+	 * This is the character used for quoting attributes and values.
+	 * 
+	 * <p>
+	 * This setting does not apply to the RDF serializers.
+	 * 
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Create a serializer that uses single quotes.</jc>
+	 * 	WriterSerializer s = JsonSerializer
+	 * 		.<jsm>create</jsm>()
+	 * 		.sq()
+	 * 		.build();
+	 * 	
+	 * 	<jc>// Same, but use property.</jc>
+	 * 	WriterSerializer s = JsonSerializer
+	 * 		.<jsm>create</jsm>()
+	 * 		.set(<jsf>WSERIALIZER_quoteChar</jsf>, <js>'\''</js>)
+	 * 		.build();
+	 * </p>
+	 */
+	public static final String WSERIALIZER_quoteChar = PREFIX + "quoteChar.s";
+
+	/**
+	 * Configuration property:  Use whitespace.
+	 * 
+	 * <h5 class='section'>Property:</h5>
+	 * <ul>
+	 * 	<li><b>Name:</b>  <js>"WriterSerializer.useWhitespace.b"</js>
+	 * 	<li><b>Data type:</b>  <code>Boolean</code>
+	 * 	<li><b>Default:</b>  <jk>false</jk>
+	 * 	<li><b>Session-overridable:</b>  <jk>true</jk>
+	 * 	<li><b>Methods:</b> 
+	 * 		<ul>
+	 * 			<li class='jm'>{@link WriterSerializerBuilder#useWhitespace(boolean)}
+	 * 			<li class='jm'>{@link WriterSerializerBuilder#useWhitespace()}
+	 * 			<li class='jm'>{@link WriterSerializerBuilder#ws()}
+	 * 		</ul>
+	 * </ul>
+	 * 
+	 * <h5 class='section'>Description:</h5>
+	 * <p>
+	 * If <jk>true</jk>, whitespace is added to the output to improve readability.
+	 * 
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Create a serializer with whitespace enabled.</jc>
+	 * 	WriterSerializer s = JsonSerializer
+	 * 		.<jsm>create</jsm>()
+	 * 		.ws()
+	 * 		.build();
+	 * 	
+	 * 	<jc>// Same, but use property.</jc>
+	 * 	WriterSerializer s = JsonSerializer
+	 * 		.<jsm>create</jsm>()
+	 * 		.set(<jsf>WSERIALIZER_useWhitespace</jsf>, <jk>true</jk>)
+	 * 		.build();
+	 * 
+	 * 	<jc>// Produces "\{\n\t'foo': 'bar'\n\}\n"</jc>
+	 * 	String json = s.serialize(<jk>new</jk> MyBean());
+	 * </p>
+	 */
+	public static final String WSERIALIZER_useWhitespace = PREFIX + "useWhitespace.b";
+
+	static final WriterSerializer DEFAULT = new WriterSerializer(PropertyStore.create().build(), "") {
+		@Override
+		public WriterSerializerSession createSession(SerializerSessionArgs args) {
+			throw new NoSuchMethodError();
+		}
+	};
+
+	//-------------------------------------------------------------------------------------------------------------------
+	// Instance
+	//-------------------------------------------------------------------------------------------------------------------
+	
+	final int maxIndent;
+	final boolean useWhitespace;
+	final char quoteChar;
+
 	/**
 	 * Constructor.
 	 * 
@@ -47,6 +188,10 @@ public abstract class WriterSerializer extends Serializer {
 	 */
 	protected WriterSerializer(PropertyStore ps, String produces, String...accept) {
 		super(ps, produces, accept);
+		
+		useWhitespace = getBooleanProperty(WSERIALIZER_useWhitespace, false);
+		maxIndent = getIntegerProperty(WSERIALIZER_maxIndent, 100);
+		quoteChar = getStringProperty(WSERIALIZER_quoteChar, "\"").charAt(0);
 	}
 
 
@@ -116,4 +261,14 @@ public abstract class WriterSerializer extends Serializer {
 		System.out.println(toString(o));  // NOT DEBUG
 		return this;
 	}
+	
+	@Override /* Context */
+	public ObjectMap asMap() {
+		return super.asMap()
+			.append("WriterSerializer", new ObjectMap()
+				.append("useWhitespace", useWhitespace)
+				.append("maxIndent", maxIndent)
+				.append("quoteChar", quoteChar)
+			);
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerBuilder.java
similarity index 53%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
copy to juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerBuilder.java
index 2f41431..8c13bf0 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerBuilder.java
@@ -2,7 +2,7 @@
 // * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
 // * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
 // * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
+// * with the License.  You may obtain a copy of the License at                                                              * 
 // *                                                                                                                         *
 // *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
 // *                                                                                                                         *
@@ -10,26 +10,24 @@
 // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
 // * specific language governing permissions and limitations under the License.                                              *
 // ***************************************************************************************************************************
-package org.apache.juneau.uon;
+package org.apache.juneau.serializer;
 
-import static org.apache.juneau.uon.UonParser.*;
+import static org.apache.juneau.serializer.WriterSerializer.*;
 
 import java.util.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.http.*;
-import org.apache.juneau.parser.*;
-import org.apache.juneau.urlencoding.*;
 
 /**
- * Builder class for building instances of UON parsers.
+ * Base class for all writer-based serializer builders.
  */
-public class UonParserBuilder extends ParserBuilder {
-
+public class WriterSerializerBuilder extends SerializerBuilder {
+	
 	/**
 	 * Constructor, default settings.
 	 */
-	public UonParserBuilder() {
+	public WriterSerializerBuilder() {
 		super();
 	}
 
@@ -38,525 +36,493 @@ public class UonParserBuilder extends ParserBuilder {
 	 * 
 	 * @param ps The initial configuration settings for this builder.
 	 */
-	public UonParserBuilder(PropertyStore ps) {
+	public WriterSerializerBuilder(PropertyStore ps) {
 		super(ps);
 	}
 
-	@Override /* ContextBuilder */
-	public UonParser build() {
-		return build(UonParser.class);
-	}
-
 
 	//--------------------------------------------------------------------------------
 	// Properties
 	//--------------------------------------------------------------------------------
 
 	/**
-	 * Configuration property: Decode <js>"%xx"</js> sequences.
+	 * Configuration property:  Maximum indentation.
 	 * 
 	 * <p>
-	 * Specify <jk>true</jk> if URI encoded characters should be decoded, <jk>false</jk> if they've already been
-	 * decoded before being passed to this parser.
+	 * Specifies the maximum indentation level in the serialized document.
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link UonParser#UON_decoding}
+	 * 	<li class='jf'>{@link WriterSerializer#WSERIALIZER_maxIndent}
 	 * </ul>
 	 * 
 	 * @param value 
 	 * 	The new value for this property.
-	 * 	<br>Default is <jk>false</jk> for {@link UonParser}, <jk>true</jk> for {@link UrlEncodingParser}
+	 * 	<br>The default is <code>100</code>.
 	 * @return This object (for method chaining).
 	 */
-	public UonParserBuilder decoding(boolean value) {
-		return set(UON_decoding, value);
+	public WriterSerializerBuilder maxIndent(int value) {
+		return set(WSERIALIZER_maxIndent, value);
 	}
 
 	/**
-	 * Configuration property: Decode <js>"%xx"</js> sequences.
+	 * Configuration property:  Quote character.
 	 * 
 	 * <p>
-	 * Shortcut for calling <code>decodeChars(<jk>true</jk>)</code>.
+	 * This is the character used for quoting attributes and values.
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link UonParser#UON_decoding}
+	 * 	<li class='jf'>{@link WriterSerializer#WSERIALIZER_quoteChar}
 	 * </ul>
 	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default is <js>'"'</js>.
 	 * @return This object (for method chaining).
 	 */
-	public UonParserBuilder decoding() {
-		return decoding(true);
+	public WriterSerializerBuilder quoteChar(char value) {
+		return set(WSERIALIZER_quoteChar, value);
 	}
 
 	/**
-	 * Configuration property:  Validate end.
+	 * Configuration property:  Quote character.
 	 * 
 	 * <p>
-	 * If <jk>true</jk>, after parsing a POJO from the input, verifies that the remaining input in 
-	 * the stream consists of only whitespace.
+	 * Shortcut for calling <code>quoteChar(<js>'\''</js>)</code>.
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link UonParser#UON_validateEnd}
+	 * 	<li class='jf'>{@link WriterSerializer#WSERIALIZER_quoteChar}
 	 * </ul>
 	 * 
-	 * @param value 
-	 * 	The new value for this property.
-	 * 	<br>The default value is <jk>false</jk>.
 	 * @return This object (for method chaining).
 	 */
-	public UonParserBuilder validateEnd(boolean value) {
-		return set(UON_validateEnd, value);
+	public WriterSerializerBuilder sq() {
+		return quoteChar('\'');
 	}
-	
+
 	/**
-	 * Configuration property:  Validate end.
+	 * Configuration property:  Use whitespace.
 	 * 
 	 * <p>
-	 * Shortcut for calling <code>validateEnd(<jk>true</jk>)</code>.
+	 * If <jk>true</jk>, newlines and indentation and spaces are added to the output to improve readability.
 	 * 
 	 * <h5 class='section'>See Also:</h5>
 	 * <ul>
-	 * 	<li class='jf'>{@link UonParser#UON_validateEnd}
+	 * 	<li class='jf'>{@link WriterSerializer#WSERIALIZER_useWhitespace}
 	 * </ul>
 	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default is <jk>false</jk>.
 	 * @return This object (for method chaining).
 	 */
-	public UonParserBuilder validateEnd() {
-		return set(UON_validateEnd, true);
+	public WriterSerializerBuilder useWhitespace(boolean value) {
+		return set(WSERIALIZER_useWhitespace, value);
 	}
 
-	@Override /* ParserBuilder */
-	public UonParserBuilder autoCloseStreams(boolean value) {
-		super.autoCloseStreams(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder autoCloseStreams() {
-		super.autoCloseStreams();
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder fileCharset(String value) {
-		super.fileCharset(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder inputStreamCharset(String value) {
-		super.inputStreamCharset(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder listener(Class<? extends ParserListener> value) {
-		super.listener(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder strict(boolean value) {
-		super.strict(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder strict() {
-		super.strict();
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder trimStrings(boolean value) {
-		super.trimStrings(value);
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder trimStrings() {
-		super.trimStrings();
-		return this;
-	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder unbuffered(boolean value) {
-		super.unbuffered(value);
-		return this;
+	/**
+	 * Configuration property:  Use whitespace.
+	 * 
+	 * <p>
+	 * Shortcut for calling <code>useWhitespace(<jk>true</jk>)</code>.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link WriterSerializer#WSERIALIZER_useWhitespace}
+	 * </ul>
+	 * @return This object (for method chaining).
+	 */
+	public WriterSerializerBuilder useWhitespace() {
+		return set(WSERIALIZER_useWhitespace, true);
 	}
-
-	@Override /* ParserBuilder */
-	public UonParserBuilder unbuffered() {
-		super.unbuffered();
-		return this;
+	
+	/**
+	 * Configuration property:  Use whitespace.
+	 * 
+	 * <p>
+	 * Shortcut for calling <code>useWhitespace(<jk>true</jk>)</code>.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='jf'>{@link WriterSerializer#WSERIALIZER_useWhitespace}
+	 * </ul>
+	 * 
+	 * @return This object (for method chaining).
+	 */
+	public WriterSerializerBuilder ws() {
+		return useWhitespace();
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireDefaultConstructor(boolean value) {
+	public WriterSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireDefaultConstructor() {
+	public WriterSerializerBuilder beansRequireDefaultConstructor() {
 		super.beansRequireDefaultConstructor();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireSerializable(boolean value) {
+	public WriterSerializerBuilder beansRequireSerializable(boolean value) {
 		super.beansRequireSerializable(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireSerializable() {
+	public WriterSerializerBuilder beansRequireSerializable() {
 		super.beansRequireSerializable();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireSettersForGetters(boolean value) {
+	public WriterSerializerBuilder beansRequireSettersForGetters(boolean value) {
 		super.beansRequireSettersForGetters(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireSettersForGetters() {
+	public WriterSerializerBuilder beansRequireSettersForGetters() {
 		super.beansRequireSettersForGetters();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beansRequireSomeProperties(boolean value) {
+	public WriterSerializerBuilder beansRequireSomeProperties(boolean value) {
 		super.beansRequireSomeProperties(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanMapPutReturnsOldValue(boolean value) {
+	public WriterSerializerBuilder beanMapPutReturnsOldValue(boolean value) {
 		super.beanMapPutReturnsOldValue(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanMapPutReturnsOldValue() {
+	public WriterSerializerBuilder beanMapPutReturnsOldValue() {
 		super.beanMapPutReturnsOldValue();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanConstructorVisibility(Visibility value) {
+	public WriterSerializerBuilder beanConstructorVisibility(Visibility value) {
 		super.beanConstructorVisibility(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanClassVisibility(Visibility value) {
+	public WriterSerializerBuilder beanClassVisibility(Visibility value) {
 		super.beanClassVisibility(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanFieldVisibility(Visibility value) {
+	public WriterSerializerBuilder beanFieldVisibility(Visibility value) {
 		super.beanFieldVisibility(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanMethodVisibility(Visibility value) {
+	public WriterSerializerBuilder beanMethodVisibility(Visibility value) {
 		super.beanMethodVisibility(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder useJavaBeanIntrospector(boolean value) {
+	public WriterSerializerBuilder useJavaBeanIntrospector(boolean value) {
 		super.useJavaBeanIntrospector(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder useJavaBeanIntrospector() {
+	public WriterSerializerBuilder useJavaBeanIntrospector() {
 		super.useJavaBeanIntrospector();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder useInterfaceProxies(boolean value) {
+	public WriterSerializerBuilder useInterfaceProxies(boolean value) {
 		super.useInterfaceProxies(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreUnknownBeanProperties(boolean value) {
+	public WriterSerializerBuilder ignoreUnknownBeanProperties(boolean value) {
 		super.ignoreUnknownBeanProperties(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreUnknownBeanProperties() {
+	public WriterSerializerBuilder ignoreUnknownBeanProperties() {
 		super.ignoreUnknownBeanProperties();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreUnknownNullBeanProperties(boolean value) {
+	public WriterSerializerBuilder ignoreUnknownNullBeanProperties(boolean value) {
 		super.ignoreUnknownNullBeanProperties(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignorePropertiesWithoutSetters(boolean value) {
+	public WriterSerializerBuilder ignorePropertiesWithoutSetters(boolean value) {
 		super.ignorePropertiesWithoutSetters(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreInvocationExceptionsOnGetters(boolean value) {
+	public WriterSerializerBuilder ignoreInvocationExceptionsOnGetters(boolean value) {
 		super.ignoreInvocationExceptionsOnGetters(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreInvocationExceptionsOnGetters() {
+	public WriterSerializerBuilder ignoreInvocationExceptionsOnGetters() {
 		super.ignoreInvocationExceptionsOnGetters();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreInvocationExceptionsOnSetters(boolean value) {
+	public WriterSerializerBuilder ignoreInvocationExceptionsOnSetters(boolean value) {
 		super.ignoreInvocationExceptionsOnSetters(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder ignoreInvocationExceptionsOnSetters() {
+	public WriterSerializerBuilder ignoreInvocationExceptionsOnSetters() {
 		super.ignoreInvocationExceptionsOnSetters();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder sortProperties(boolean value) {
+	public WriterSerializerBuilder sortProperties(boolean value) {
 		super.sortProperties(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder sortProperties() {
+	public WriterSerializerBuilder sortProperties() {
 		super.sortProperties();
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanPackages(Object...values) {
+	public WriterSerializerBuilder notBeanPackages(Object...values) {
 		super.notBeanPackages(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanPackages(String...values) {
+	public WriterSerializerBuilder notBeanPackages(String...values) {
 		super.notBeanPackages(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanPackages(boolean append, Object...values) {
+	public WriterSerializerBuilder notBeanPackages(boolean append, Object...values) {
 		super.notBeanPackages(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanPackagesRemove(Object...values) {
+	public WriterSerializerBuilder notBeanPackagesRemove(Object...values) {
 		super.notBeanPackagesRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanClasses(Object...values) {
+	public WriterSerializerBuilder notBeanClasses(Object...values) {
 		super.notBeanClasses(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanClasses(Class<?>...values) {
+	public WriterSerializerBuilder notBeanClasses(Class<?>...values) {
 		super.notBeanClasses(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanClasses(boolean append, Object...values) {
+	public WriterSerializerBuilder notBeanClasses(boolean append, Object...values) {
 		super.notBeanClasses(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder notBeanClassesRemove(Object...values) {
+	public WriterSerializerBuilder notBeanClassesRemove(Object...values) {
 		super.notBeanClassesRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanFilters(Object...values) {
+	public WriterSerializerBuilder beanFilters(Object...values) {
 		super.beanFilters(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanFilters(Class<?>...values) {
+	public WriterSerializerBuilder beanFilters(Class<?>...values) {
 		super.beanFilters(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanFilters(boolean append, Object...values) {
+	public WriterSerializerBuilder beanFilters(boolean append, Object...values) {
 		super.beanFilters(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanFiltersRemove(Object...values) {
+	public WriterSerializerBuilder beanFiltersRemove(Object...values) {
 		super.beanFiltersRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder pojoSwaps(Object...values) {
+	public WriterSerializerBuilder pojoSwaps(Object...values) {
 		super.pojoSwaps(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder pojoSwaps(Class<?>...values) {
+	public WriterSerializerBuilder pojoSwaps(Class<?>...values) {
 		super.pojoSwaps(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder pojoSwaps(boolean append, Object...values) {
+	public WriterSerializerBuilder pojoSwaps(boolean append, Object...values) {
 		super.pojoSwaps(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder pojoSwapsRemove(Object...values) {
+	public WriterSerializerBuilder pojoSwapsRemove(Object...values) {
 		super.pojoSwapsRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder implClasses(Map<String,Class<?>> values) {
+	public WriterSerializerBuilder implClasses(Map<String,Class<?>> values) {
 		super.implClasses(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public <T> UonParserBuilder implClass(Class<T> interfaceClass, Class<? extends T> implClass) {
+	public <T> SerializerBuilder implClass(Class<T> interfaceClass, Class<? extends T> implClass) {
 		super.implClass(interfaceClass, implClass);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanDictionary(Object...values) {
+	public WriterSerializerBuilder beanDictionary(Object...values) {
 		super.beanDictionary(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanDictionary(Class<?>...values) {
+	public WriterSerializerBuilder beanDictionary(Class<?>...values) {
 		super.beanDictionary(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanDictionary(boolean append, Object...values) {
+	public WriterSerializerBuilder beanDictionary(boolean append, Object...values) {
 		super.beanDictionary(append, values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanDictionaryRemove(Object...values) {
+	public WriterSerializerBuilder beanDictionaryRemove(Object...values) {
 		super.beanDictionaryRemove(values);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder beanTypePropertyName(String value) {
+	public WriterSerializerBuilder beanTypePropertyName(String value) {
 		super.beanTypePropertyName(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder locale(Locale value) {
+	public WriterSerializerBuilder locale(Locale value) {
 		super.locale(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder timeZone(TimeZone value) {
+	public WriterSerializerBuilder timeZone(TimeZone value) {
 		super.timeZone(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder mediaType(MediaType value) {
+	public WriterSerializerBuilder mediaType(MediaType value) {
 		super.mediaType(value);
 		return this;
 	}
 
 	@Override /* BeanContextBuilder */
-	public UonParserBuilder debug() {
+	public WriterSerializerBuilder debug() {
 		super.debug();
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public UonParserBuilder set(String name, Object value) {
+	public WriterSerializerBuilder set(String name, Object value) {
 		super.set(name, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public UonParserBuilder set(boolean append, String name, Object value) {
+	public WriterSerializerBuilder set(boolean append, String name, Object value) {
 		super.set(append, name, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public UonParserBuilder set(Map<String,Object> properties) {
+	public WriterSerializerBuilder set(Map<String,Object> properties) {
 		super.set(properties);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public UonParserBuilder add(Map<String,Object> properties) {
+	public WriterSerializerBuilder add(Map<String,Object> properties) {
 		super.add(properties);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public UonParserBuilder addTo(String name, Object value) {
+	public WriterSerializerBuilder addTo(String name, Object value) {
 		super.addTo(name, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public UonParserBuilder addTo(String name, String key, Object value) {
+	public WriterSerializerBuilder addTo(String name, String key, Object value) {
 		super.addTo(name, key, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public UonParserBuilder removeFrom(String name, Object value) {
+	public WriterSerializerBuilder removeFrom(String name, Object value) {
 		super.removeFrom(name, value);
 		return this;
 	}
 
 	@Override /* ContextBuilder */
-	public UonParserBuilder apply(PropertyStore copyFrom) {
+	public WriterSerializerBuilder apply(PropertyStore copyFrom) {
 		super.apply(copyFrom);
 		return this;
 	}
-}
\ No newline at end of file
+	
+	@Override /* Context */
+	public WriterSerializer build() {
+		return null;
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
index 3c63cdd..11aeab0 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializerSession.java
@@ -12,8 +12,12 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.serializer;
 
+import static org.apache.juneau.serializer.WriterSerializer.*;
+
 import java.io.*;
 
+import org.apache.juneau.*;
+
 /**
  * Subclass of {@link SerializerSession} for character-based serializers.
  * 
@@ -32,6 +36,10 @@ import java.io.*;
  */
 public abstract class WriterSerializerSession extends SerializerSession {
 
+	private final int maxIndent;
+	private final boolean useWhitespace;
+	private final char quoteChar;
+
 	/**
 	 * Create a new session using properties specified in the context.
 	 * 
@@ -44,8 +52,12 @@ public abstract class WriterSerializerSession extends SerializerSession {
 	 * 	It also include session-level properties that override the properties defined on the bean and
 	 * 	serializer contexts.
 	 */
-	protected WriterSerializerSession(Serializer ctx, SerializerSessionArgs args) {
+	protected WriterSerializerSession(WriterSerializer ctx, SerializerSessionArgs args) {
 		super(ctx, args);
+		
+		useWhitespace = getProperty(WSERIALIZER_useWhitespace, boolean.class, ctx.useWhitespace);
+		maxIndent = getProperty(WSERIALIZER_maxIndent, int.class, ctx.maxIndent);
+		quoteChar = getProperty(WSERIALIZER_quoteChar, String.class, ""+ctx.quoteChar).charAt(0);
 	}
 
 	/**
@@ -55,7 +67,7 @@ public abstract class WriterSerializerSession extends SerializerSession {
 	 * 	Runtime session arguments.
 	 */
 	protected WriterSerializerSession(SerializerSessionArgs args) {
-		super(args);
+		this(WriterSerializer.DEFAULT, args);
 	}
 
 	@Override /* SerializerSession */
@@ -76,4 +88,46 @@ public abstract class WriterSerializerSession extends SerializerSession {
 		serialize(o, w);
 		return w.toString();
 	}
+	
+	@Override /* SerializerSession */
+	public final String serializeToString(Object o) throws SerializeException {
+		return serialize(o);
+	}
+	
+	/**
+	 * Returns the {@link WriterSerializer#WSERIALIZER_useWhitespace} setting value for this session.
+	 * 
+	 * @return The {@link WriterSerializer#WSERIALIZER_useWhitespace} setting value for this session.
+	 */
+	protected boolean isUseWhitespace() {
+		return useWhitespace;
+	}
+
+	/**
+	 * Returns the {@link WriterSerializer#WSERIALIZER_maxIndent} setting value for this session.
+	 * 
+	 * @return The {@link WriterSerializer#WSERIALIZER_maxIndent} setting value for this session.
+	 */
+	protected int getMaxIndent() {
+		return maxIndent;
+	}
+
+	/**
+	 * Returns the {@link WriterSerializer#WSERIALIZER_quoteChar} setting value for this session.
+	 * 
+	 * @return The {@link WriterSerializer#WSERIALIZER_quoteChar} setting value for this session.
+	 */
+	protected char getQuoteChar() {
+		return quoteChar;
+	}
+
+	@Override /* Session */
+	public ObjectMap asMap() {
+		return super.asMap()
+			.append("WriterSerializerSession", new ObjectMap()
+				.append("maxIndent", maxIndent)
+				.append("useWhitespace", useWhitespace)
+				.append("quoteChar", quoteChar)
+			);
+	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java
index 920cae7..818dcf6 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java
@@ -53,6 +53,9 @@ public final class AnnotationBeanFilterBuilder<T> extends BeanFilterBuilder<T> {
 			if (b.sort())
 				sortProperties(true);
 
+			if (b.fluentSetters())
+				fluentSetters(true);
+
 			if (! b.excludeProperties().isEmpty())
 				excludeProperties(split(b.excludeProperties()));
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BeanFilter.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BeanFilter.java
index 8940218..fdba6f8 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BeanFilter.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BeanFilter.java
@@ -39,7 +39,7 @@ public final class BeanFilter {
 	private final String[] properties, excludeProperties;
 	private final PropertyNamer propertyNamer;
 	private final Class<?> interfaceClass, stopClass;
-	private final boolean sortProperties;
+	private final boolean sortProperties, fluentSetters;
 	private final String typeName;
 	private final Class<?>[] beanDictionary;
 	private final PropertyFilter propertyFilter;
@@ -55,6 +55,7 @@ public final class BeanFilter {
 		this.interfaceClass = builder.interfaceClass;
 		this.stopClass = builder.stopClass;
 		this.sortProperties = builder.sortProperties;
+		this.fluentSetters = builder.fluentSetters;
 		this.propertyNamer = ClassUtils.newInstance(PropertyNamer.class, builder.propertyNamer);
 		this.beanDictionary =
 			builder.beanDictionary == null
@@ -118,6 +119,15 @@ public final class BeanFilter {
 	}
 
 	/**
+	 * Returns <jk>true</jk> if we should find fluent setters.
+	 * 
+	 * @return <jk>true</jk> if fluent setters should be found.
+	 */
+	public boolean isFluentSetters() {
+		return fluentSetters;
+	}
+
+	/**
 	 * Returns the list of properties to ignore on a bean.
 	 * 
 	 * @return The name of the properties to ignore on a bean, or <jk>null</jk> to not ignore any properties.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java
index 799c446..bdf5b92 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java
@@ -62,7 +62,7 @@ public class BeanFilterBuilder<T> {
 	String typeName;
 	String[] includeProperties, excludeProperties;
 	Class<?> interfaceClass, stopClass;
-	boolean sortProperties;
+	boolean sortProperties, fluentSetters;
 	Object propertyNamer;
 	List<Class<?>> beanDictionary;
 	Object propertyFilter;
@@ -383,6 +383,66 @@ public class BeanFilterBuilder<T> {
 	}
 
 	/**
+	 * Configuration property:  Find fluent setters.
+	 * 
+	 * <p>
+	 * When enabled, fluent setters are detected on beans.
+	 * 
+	 * <p>
+	 * Fluent setters must have the following attributes:
+	 * <ul>
+	 * 	<li>Public.
+	 * 	<li>Not static.
+	 * 	<li>Take in one parameter.
+	 * 	<li>Return the bean itself.
+	 * </ul>
+	 * 
+	 * <h5 class='section'>Example:</h5>
+	 * <p class='bcode'>
+	 * 	<jc>// Define our filter.</jc>
+	 * 	<jk>public class</jk> MyFilter <jk>extends</jk> BeanFilterBuilder&lt;MyBean&gt; {
+	 * 		<jk>public</jk> MyFilter() {
+	 * 			fluentSetters();
+	 * 		}
+	 * 	}	
+	 * </p>
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='ja'>{@link Bean#fluentSetters()}
+	 * 	<li class='jf'>{@link BeanContext#BEAN_fluentSetters}
+	 * </ul>
+	 * 
+	 * @param value 
+	 * 	The new value for this property.
+	 * 	<br>The default is <jk>false</jk>.
+	 * @return This object (for method chaining).
+	 */
+	public BeanFilterBuilder<T> fluentSetters(boolean value) {
+		this.fluentSetters = value;
+		return this;
+	}
+
+	/**
+	 * Configuration property:  Find fluent setters.
+	 * 
+	 * <p>
+	 * Shortcut for calling <code>fluentSetters(<jk>true</jk>)</code>.
+	 * 
+	 * <h5 class='section'>See Also:</h5>
+	 * <ul>
+	 * 	<li class='ja'>{@link Bean#fluentSetters()}
+	 * 	<li class='jf'>{@link BeanContext#BEAN_fluentSetters}
+	 * </ul>
+	 * 
+	 * @return This object (for method chaining).
+	 */
+	public BeanFilterBuilder<T> fluentSetters() {
+		this.fluentSetters = true;
+		return this;
+	}
+
+	/**
 	 * Configuration property:  Bean property namer
 	 * 
 	 * <p>
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BuilderSwap.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BuilderSwap.java
index d129d43..676d3af 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BuilderSwap.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/BuilderSwap.java
@@ -12,8 +12,8 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.transform;
 
-import static org.apache.juneau.internal.ClassUtils.*;
 import static org.apache.juneau.internal.ClassFlags.*;
+import static org.apache.juneau.internal.ClassUtils.*;
 
 import java.lang.reflect.*;
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/InterfaceBeanFilterBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/InterfaceBeanFilterBuilder.java
index 83d8431..0c2d9ed 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/InterfaceBeanFilterBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/transform/InterfaceBeanFilterBuilder.java
@@ -69,6 +69,9 @@ public class InterfaceBeanFilterBuilder<T> extends BeanFilterBuilder<T> {
 			if (b.sort())
 				sortProperties(true);
 
+			if (b.fluentSetters())
+				fluentSetters(true);
+
 			if (! b.excludeProperties().isEmpty())
 				excludeProperties(split(b.excludeProperties()));
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
index 2f41431..a7d278c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserBuilder.java
@@ -24,7 +24,7 @@ import org.apache.juneau.urlencoding.*;
 /**
  * Builder class for building instances of UON parsers.
  */
-public class UonParserBuilder extends ParserBuilder {
+public class UonParserBuilder extends ReaderParserBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -128,27 +128,27 @@ public class UonParserBuilder extends ParserBuilder {
 		return set(UON_validateEnd, true);
 	}
 
-	@Override /* ParserBuilder */
-	public UonParserBuilder autoCloseStreams(boolean value) {
-		super.autoCloseStreams(value);
+	@Override /* ReaderParserBuilder */
+	public UonParserBuilder fileCharset(String value) {
+		super.fileCharset(value);
 		return this;
 	}
 
-	@Override /* ParserBuilder */
-	public UonParserBuilder autoCloseStreams() {
-		super.autoCloseStreams();
+	@Override /* ReaderParserBuilder */
+	public UonParserBuilder inputStreamCharset(String value) {
+		super.inputStreamCharset(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public UonParserBuilder fileCharset(String value) {
-		super.fileCharset(value);
+	public UonParserBuilder autoCloseStreams(boolean value) {
+		super.autoCloseStreams(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public UonParserBuilder inputStreamCharset(String value) {
-		super.inputStreamCharset(value);
+	public UonParserBuilder autoCloseStreams() {
+		super.autoCloseStreams();
 		return this;
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializer.java
index 0edfcf7..0e8a920 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializer.java
@@ -279,7 +279,7 @@ public class UonSerializer extends WriterSerializer {
 		 * @param ps The property store containing all the settings for this object.
 		 */
 		public Readable(PropertyStore ps) {
-			super(ps.builder().set(SERIALIZER_useWhitespace, true).build());
+			super(ps.builder().set(WSERIALIZER_useWhitespace, true).build());
 		}
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
index b605b7b..d121114 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerBuilder.java
@@ -23,7 +23,7 @@ import org.apache.juneau.serializer.*;
 /**
  * Builder class for building instances of UON serializers.
  */
-public class UonSerializerBuilder extends SerializerBuilder {
+public class UonSerializerBuilder extends WriterSerializerBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -125,6 +125,42 @@ public class UonSerializerBuilder extends SerializerBuilder {
 		return set(UON_paramFormat, ParamFormat.PLAINTEXT);
 	}
 
+	@Override /* WriterSerializerBuilder */
+	public UonSerializerBuilder maxIndent(int value) {
+		super.maxIndent(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public UonSerializerBuilder quoteChar(char value) {
+		super.quoteChar(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public UonSerializerBuilder sq() {
+		super.sq();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public UonSerializerBuilder useWhitespace(boolean value) {
+		super.useWhitespace(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public UonSerializerBuilder useWhitespace() {
+		super.useWhitespace();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public UonSerializerBuilder ws() {
+		super.ws();
+		return this;
+	}
+
 	@Override /* SerializerBuilder */
 	public UonSerializerBuilder abridged(boolean value) {
 		super.abridged(value);
@@ -185,18 +221,6 @@ public class UonSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public UonSerializerBuilder maxIndent(int value) {
-		super.maxIndent(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public UonSerializerBuilder quoteChar(char value) {
-		super.quoteChar(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public UonSerializerBuilder sortCollections(boolean value) {
 		super.sortCollections(value);
 		return this;
@@ -221,12 +245,6 @@ public class UonSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public UonSerializerBuilder sq() {
-		super.sq();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public UonSerializerBuilder trimEmptyCollections(boolean value) {
 		super.trimEmptyCollections(value);
 		return this;
@@ -286,24 +304,6 @@ public class UonSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
-	@Override /* SerializerBuilder */
-	public UonSerializerBuilder useWhitespace(boolean value) {
-		super.useWhitespace(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public UonSerializerBuilder useWhitespace() {
-		super.useWhitespace();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public UonSerializerBuilder ws() {
-		super.ws();
-		return this;
-	}
-
 	@Override /* BeanContextBuilder */
 	public UonSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
index af0a939..ee8f811 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
@@ -222,7 +222,7 @@ public class UrlEncodingSerializer extends UonSerializer {
 		 * @param ps The property store containing all the settings for this object.
 		 */
 		public Readable(PropertyStore ps) {
-			super(ps.builder().set(SERIALIZER_useWhitespace, true).build());
+			super(ps.builder().set(WSERIALIZER_useWhitespace, true).build());
 		}
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
index a3d1a19..0bd9a6a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserBuilder.java
@@ -26,7 +26,7 @@ import org.apache.juneau.parser.*;
 /**
  * Builder class for building XML parsers.
  */
-public class XmlParserBuilder extends ParserBuilder {
+public class XmlParserBuilder extends ReaderParserBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -183,27 +183,27 @@ public class XmlParserBuilder extends ParserBuilder {
 		return set(XML_validating, true);
 	}
 
-	@Override /* ParserBuilder */
-	public XmlParserBuilder autoCloseStreams(boolean value) {
-		super.autoCloseStreams(value);
+	@Override /* ReaderParserBuilder */
+	public XmlParserBuilder fileCharset(String value) {
+		super.fileCharset(value);
 		return this;
 	}
 
-	@Override /* ParserBuilder */
-	public XmlParserBuilder autoCloseStreams() {
-		super.autoCloseStreams();
+	@Override /* ReaderParserBuilder */
+	public XmlParserBuilder inputStreamCharset(String value) {
+		super.inputStreamCharset(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public XmlParserBuilder fileCharset(String value) {
-		super.fileCharset(value);
+	public XmlParserBuilder autoCloseStreams(boolean value) {
+		super.autoCloseStreams(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public XmlParserBuilder inputStreamCharset(String value) {
-		super.inputStreamCharset(value);
+	public XmlParserBuilder autoCloseStreams() {
+		super.autoCloseStreams();
 		return this;
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializer.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializer.java
index 7a542b6..bffdc1a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializer.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializer.java
@@ -361,7 +361,7 @@ public class XmlSerializer extends WriterSerializer {
 		public Sq(PropertyStore ps) {
 			super(
 				ps.builder()
-					.set(SERIALIZER_quoteChar, '\'')
+					.set(WSERIALIZER_quoteChar, '\'')
 					.build()
 				);
 		}
@@ -378,8 +378,8 @@ public class XmlSerializer extends WriterSerializer {
 		public SqReadable(PropertyStore ps) {
 			super(
 				ps.builder()
-					.set(SERIALIZER_quoteChar, '\'')
-					.set(SERIALIZER_useWhitespace, true)
+					.set(WSERIALIZER_quoteChar, '\'')
+					.set(WSERIALIZER_useWhitespace, true)
 					.build()
 				);
 		}
@@ -416,7 +416,7 @@ public class XmlSerializer extends WriterSerializer {
 			super(
 				ps.builder()
 					.set(XML_enableNamespaces, true)
-					.set(SERIALIZER_quoteChar, '\'')
+					.set(WSERIALIZER_quoteChar, '\'')
 					.build()
 				);
 		}
@@ -434,8 +434,8 @@ public class XmlSerializer extends WriterSerializer {
 			super(
 				ps.builder()
 					.set(XML_enableNamespaces, true)
-					.set(SERIALIZER_quoteChar, '\'')
-					.set(SERIALIZER_useWhitespace, true)
+					.set(WSERIALIZER_quoteChar, '\'')
+					.set(WSERIALIZER_useWhitespace, true)
 					.build()
 				);
 		}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
index 39e4171..40f028a 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerBuilder.java
@@ -23,7 +23,7 @@ import org.apache.juneau.serializer.*;
 /**
  * Builder class for building instances of XML serializers.
  */
-public class XmlSerializerBuilder extends SerializerBuilder {
+public class XmlSerializerBuilder extends WriterSerializerBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -221,6 +221,42 @@ public class XmlSerializerBuilder extends SerializerBuilder {
 		return set(XML_xsNamespace, value);
 	}
 
+	@Override /* WriterSerializerBuilder */
+	public XmlSerializerBuilder maxIndent(int value) {
+		super.maxIndent(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public XmlSerializerBuilder quoteChar(char value) {
+		super.quoteChar(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public XmlSerializerBuilder sq() {
+		super.sq();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public XmlSerializerBuilder useWhitespace(boolean value) {
+		super.useWhitespace(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public XmlSerializerBuilder useWhitespace() {
+		super.useWhitespace();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public XmlSerializerBuilder ws() {
+		super.ws();
+		return this;
+	}
+
 	@Override /* SerializerBuilder */
 	public XmlSerializerBuilder abridged(boolean value) {
 		super.abridged(value);
@@ -281,18 +317,6 @@ public class XmlSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public XmlSerializerBuilder maxIndent(int value) {
-		super.maxIndent(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public XmlSerializerBuilder quoteChar(char value) {
-		super.quoteChar(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public XmlSerializerBuilder sortCollections(boolean value) {
 		super.sortCollections(value);
 		return this;
@@ -317,12 +341,6 @@ public class XmlSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public XmlSerializerBuilder sq() {
-		super.sq();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public XmlSerializerBuilder trimEmptyCollections(boolean value) {
 		super.trimEmptyCollections(value);
 		return this;
@@ -382,24 +400,6 @@ public class XmlSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
-	@Override /* SerializerBuilder */
-	public XmlSerializerBuilder useWhitespace(boolean value) {
-		super.useWhitespace(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public XmlSerializerBuilder useWhitespace() {
-		super.useWhitespace();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public XmlSerializerBuilder ws() {
-		super.ws();
-		return this;
-	}
-
 	@Override /* BeanContextBuilder */
 	public XmlSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlParserBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlParserBuilder.java
index c9c8ee0..6c76cee 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlParserBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlParserBuilder.java
@@ -21,7 +21,7 @@ import org.apache.juneau.parser.*;
 /**
  * Builder class for building instances of JSON parsers.
  */
-public class YamlParserBuilder extends ParserBuilder {
+public class YamlParserBuilder extends ReaderParserBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -49,27 +49,27 @@ public class YamlParserBuilder extends ParserBuilder {
 	// Properties
 	//--------------------------------------------------------------------------------
 
-	@Override /* ParserBuilder */
-	public YamlParserBuilder autoCloseStreams(boolean value) {
-		super.autoCloseStreams(value);
+	@Override /* ReaderParserBuilder */
+	public YamlParserBuilder fileCharset(String value) {
+		super.fileCharset(value);
 		return this;
 	}
 
-	@Override /* ParserBuilder */
-	public YamlParserBuilder autoCloseStreams() {
-		super.autoCloseStreams();
+	@Override /* ReaderParserBuilder */
+	public YamlParserBuilder inputStreamCharset(String value) {
+		super.inputStreamCharset(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public YamlParserBuilder fileCharset(String value) {
-		super.fileCharset(value);
+	public YamlParserBuilder autoCloseStreams(boolean value) {
+		super.autoCloseStreams(value);
 		return this;
 	}
 
 	@Override /* ParserBuilder */
-	public YamlParserBuilder inputStreamCharset(String value) {
-		super.inputStreamCharset(value);
+	public YamlParserBuilder autoCloseStreams() {
+		super.autoCloseStreams();
 		return this;
 	}
 
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerBuilder.java b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerBuilder.java
index 2ab79c0..1813d4d 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerBuilder.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/proto/YamlSerializerBuilder.java
@@ -23,7 +23,7 @@ import org.apache.juneau.serializer.*;
 /**
  * Builder class for building instances of JSON serializers.
  */
-public class YamlSerializerBuilder extends SerializerBuilder {
+public class YamlSerializerBuilder extends WriterSerializerBuilder {
 
 	/**
 	 * Constructor, default settings.
@@ -105,6 +105,42 @@ public class YamlSerializerBuilder extends SerializerBuilder {
 		return simple(true).sq();
 	}
 
+	@Override /* WriterSerializerBuilder */
+	public YamlSerializerBuilder maxIndent(int value) {
+		super.maxIndent(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public YamlSerializerBuilder quoteChar(char value) {
+		super.quoteChar(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public YamlSerializerBuilder sq() {
+		super.sq();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public YamlSerializerBuilder useWhitespace(boolean value) {
+		super.useWhitespace(value);
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public YamlSerializerBuilder useWhitespace() {
+		super.useWhitespace();
+		return this;
+	}
+
+	@Override /* WriterSerializerBuilder */
+	public YamlSerializerBuilder ws() {
+		super.ws();
+		return this;
+	}
+
 	@Override /* SerializerBuilder */
 	public YamlSerializerBuilder abridged(boolean value) {
 		super.abridged(value);
@@ -165,18 +201,6 @@ public class YamlSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public YamlSerializerBuilder maxIndent(int value) {
-		super.maxIndent(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public YamlSerializerBuilder quoteChar(char value) {
-		super.quoteChar(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public YamlSerializerBuilder sortCollections(boolean value) {
 		super.sortCollections(value);
 		return this;
@@ -201,12 +225,6 @@ public class YamlSerializerBuilder extends SerializerBuilder {
 	}
 
 	@Override /* SerializerBuilder */
-	public YamlSerializerBuilder sq() {
-		super.sq();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
 	public YamlSerializerBuilder trimEmptyCollections(boolean value) {
 		super.trimEmptyCollections(value);
 		return this;
@@ -266,24 +284,6 @@ public class YamlSerializerBuilder extends SerializerBuilder {
 		return this;
 	}
 
-	@Override /* SerializerBuilder */
-	public YamlSerializerBuilder useWhitespace(boolean value) {
-		super.useWhitespace(value);
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public YamlSerializerBuilder useWhitespace() {
-		super.useWhitespace();
-		return this;
-	}
-
-	@Override /* SerializerBuilder */
-	public YamlSerializerBuilder ws() {
-		super.ws();
-		return this;
-	}
-
 	@Override /* BeanContextBuilder */
 	public YamlSerializerBuilder beansRequireDefaultConstructor(boolean value) {
 		super.beansRequireDefaultConstructor(value);
diff --git a/juneau-doc/src/main/javadoc/overview.html b/juneau-doc/src/main/javadoc/overview.html
index 9702e63..14849a4 100644
--- a/juneau-doc/src/main/javadoc/overview.html
+++ b/juneau-doc/src/main/javadoc/overview.html
@@ -1135,8 +1135,6 @@
 					<li class='jf'>{@link org.apache.juneau.serializer.Serializer#SERIALIZER_initialDepth SERIALIZER_initialDepth}
 					<li class='jf'>{@link org.apache.juneau.serializer.Serializer#SERIALIZER_listener SERIALIZER_listener}
 					<li class='jf'>{@link org.apache.juneau.serializer.Serializer#SERIALIZER_maxDepth SERIALIZER_maxDepth}
-					<li class='jf'>{@link org.apache.juneau.serializer.Serializer#SERIALIZER_maxIndent SERIALIZER_maxIndent}
-					<li class='jf'>{@link org.apache.juneau.serializer.Serializer#SERIALIZER_quoteChar SERIALIZER_quoteChar}
 					<li class='jf'>{@link org.apache.juneau.serializer.Serializer#SERIALIZER_sortCollections SERIALIZER_sortCollections}
 					<li class='jf'>{@link org.apache.juneau.serializer.Serializer#SERIALIZER_sortMaps SERIALIZER_sortMaps}
 					<li class='jf'>{@link org.apache.juneau.serializer.Serializer#SERIALIZER_trimEmptyCollections SERIALIZER_trimEmptyCollections}
@@ -1146,7 +1144,16 @@
 					<li class='jf'>{@link org.apache.juneau.serializer.Serializer#SERIALIZER_uriContext SERIALIZER_uriContext}
 					<li class='jf'>{@link org.apache.juneau.serializer.Serializer#SERIALIZER_uriRelativity SERIALIZER_uriRelativity}
 					<li class='jf'>{@link org.apache.juneau.serializer.Serializer#SERIALIZER_uriResolution SERIALIZER_uriResolution}
-					<li class='jf'>{@link org.apache.juneau.serializer.Serializer#SERIALIZER_useWhitespace SERIALIZER_useWhitespace}
+					<li class='jc'>{@link org.apache.juneau.serializer.WriterSerializer}
+					<ul>
+						<li class='jf'>{@link org.apache.juneau.serializer.WriterSerializer#WSERIALIZER_maxIndent WSERIALIZER_maxIndent}
+						<li class='jf'>{@link org.apache.juneau.serializer.WriterSerializer#WSERIALIZER_quoteChar WSERIALIZER_quoteChar}
+						<li class='jf'>{@link org.apache.juneau.serializer.WriterSerializer#WSERIALIZER_useWhitespace WSERIALIZER_useWhitespace}
+					</ul>
+					<li class='jc'>{@link org.apache.juneau.serializer.OutputStreamSerializer}
+					<ul>
+						<li class='jf'>{@link org.apache.juneau.serializer.OutputStreamSerializer#OSSERIALIZER_binaryFormat OSSERIALIZER_binaryFormat}
+					</ul>
 				</ul>
 			</ul>
 		</div>
@@ -1162,12 +1169,19 @@
 				<li class='jc'>{@link org.apache.juneau.parser.Parser}
 				<ul>
 					<li class='jf'>{@link org.apache.juneau.parser.Parser#PARSER_autoCloseStreams PARSER_autoCloseStreams}
-					<li class='jf'>{@link org.apache.juneau.parser.Parser#PARSER_fileCharset PARSER_fileCharset}
-					<li class='jf'>{@link org.apache.juneau.parser.Parser#PARSER_inputStreamCharset PARSER_inputStreamCharset}
 					<li class='jf'>{@link org.apache.juneau.parser.Parser#PARSER_listener PARSER_listener}
 					<li class='jf'>{@link org.apache.juneau.parser.Parser#PARSER_strict PARSER_strict}
 					<li class='jf'>{@link org.apache.juneau.parser.Parser#PARSER_trimStrings PARSER_trimStrings}
 					<li class='jf'>{@link org.apache.juneau.parser.Parser#PARSER_unbuffered PARSER_unbuffered}
+					<li class='jc'>{@link org.apache.juneau.parser.ReaderParser}
+					<ul>
+						<li class='jf'>{@link org.apache.juneau.parser.ReaderParser#RPARSER_fileCharset RPARSER_fileCharset}
+						<li class='jf'>{@link org.apache.juneau.parser.ReaderParser#RPARSER_inputStreamCharset RPARSER_inputStreamCharset}
+					</ul>
+					<li class='jc'>{@link org.apache.juneau.parser.InputStreamParser}
+					<ul>
+						<li class='jf'>{@link org.apache.juneau.parser.InputStreamParser#ISPARSER_binaryFormat ISPARSER_binaryFormat}
+					</ul>
 				</ul>
 			</ul>
 		</div>
@@ -1223,7 +1237,7 @@
 		</ul>
 		<p>
 			Each context object in the hierarchy define properties that can be stored in a <code>PropertyStore</code>
-			such as <jsf>SERIALIZER_useWhitespace</jsf> or <jsf>JSON_simpleMode</jsf>.
+			such as <jsf>WSERIALIZER_useWhitespace</jsf> or <jsf>JSON_simpleMode</jsf>.
 		</p>
 		<p>
 			The class hierarchy for <code>JsonSerializerBuilder</code> is:
@@ -1237,7 +1251,10 @@
 					<ul>
 						<li class='jac'>{@link org.apache.juneau.serializer.SerializerBuilder}
 						<ul>
-							<li class='jc'>{@link org.apache.juneau.json.JsonSerializerBuilder}
+							<li class='jac'>{@link org.apache.juneau.serializer.WriterSerializerBuilder}
+							<ul>
+								<li class='jc'>{@link org.apache.juneau.json.JsonSerializerBuilder}
+							</ul>
 						</ul>
 					</ul>
 				</ul>
@@ -14520,7 +14537,7 @@
 				<td class='code'>&amp;plainText=true</td>
 				<td>
 					Response will always be <l>Content-Type: text/plain</l> and the returned text will be human-readable
-					({@link org.apache.juneau.serializer.Serializer#SERIALIZER_useWhitespace SERIALIZER_useWhitespace} enabled).
+					({@link org.apache.juneau.serializer.WriterSerializer#WSERIALIZER_useWhitespace WSERIALIZER_useWhitespace} enabled).
 					<br>Useful for debugging.
 				</td>
 			</tr>
@@ -21257,6 +21274,18 @@
 				HTML serializer will now serializers beans and maps as HTML even when those objects are embedded
 				within an object with <code><ja>@Html</ja>(format=<jsf>XML</jsf>)</code>.
 				<br>The previous behavior was to serialize it as XML.
+			<li>
+				New settings for binary-based serializers and parsers:
+				<ul class='doctree'>
+					<li class='jf'>{@link org.apache.juneau.serializer.OutputStreamSerializer#OSSERIALIZER_binaryFormat}
+					<li class='jf'>{@link org.apache.juneau.parser.InputStreamParser#ISPARSER_binaryFormat}
+				</ul>
+			<li>
+				Added support for auto-detection of fluent-style setters:
+				<ul class='doctree'>
+					<li class='jf'>{@link org.apache.juneau.BeanContext#BEAN_fluentSetters}
+					<li class='ja'>{@link org.apache.juneau.annotation.Bean#fluentSetters()}
+				</ul>
 		</ul>
 		
 		<h5 class='topic w800'>juneau-dto</h5>
@@ -23533,7 +23562,7 @@
 					serializers since there is no separate simple mode anymore.
 				<li>Eliminated the <code>UonParserContext.<jsf>UON_simpleMode</jsf></code> configuration setting.
 			</ul>
-			<li>Added new {@link org.apache.juneau.serializer.OutputStreamSerializer#serializeToHex(Object)} method. 
+			<li>Added new <code><del>OutputStreamSerializer.serializeToHex(Object)</del></code> method. 
 				<br>Useful mostly for testing purposes.
 				<br>Equivalently, the {@link org.apache.juneau.parser.InputStreamParser#parse(Object,Class)} method can now 
 					read the output from this method.
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/ApiResponse.java
similarity index 61%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
copy to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/ApiResponse.java
index ebb62b4..a2a5401 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/ApiResponse.java
@@ -1,44 +1,49 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.parser;
-
-import org.apache.juneau.*;
-
-/**
- * Subclass of {@link Parser} for byte-based parsers.
- * 
- * <h5 class='topic'>Description</h5>
- * 
- * This class is typically the parent class of all byte-based parsers.
- * It has 1 abstract method to implement...
- * <ul>
- * 	<li><code>parse(InputStream, ClassMeta, Parser)</code>
- * </ul>
-  */
-public abstract class InputStreamParser extends Parser {
-
-	/**
-	 * Constructor.
-	 * 
-	 * @param ps The property store containing all the settings for this object.
-	 * @param consumes The list of media types that this parser consumes (e.g. <js>"application/json"</js>).
-	 */
-	protected InputStreamParser(PropertyStore ps, String...consumes) {
-		super(ps, consumes);
-	}
-
-	@Override /* Parser */
-	public final boolean isReaderParser() {
-		return false;
-	}
-}
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              * 
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.examples.petstore;
+
+import org.apache.juneau.annotation.*;
+
+@Bean(fluentSetters=true)
+public class ApiResponse {
+	private int code;
+	private String type;
+	private String message;
+
+	public int getCode() {
+		return code;
+	}
+	
+	public ApiResponse code(int code) {
+		this.code = code;
+		return this;
+	}
+
+	public String getType() {
+		return type;
+	}
+
+	public ApiResponse type(String type) {
+		this.type = type;
+		return this;
+	}
+
+	public String getMessage() {
+		return message;
+	}
+
+	public ApiResponse message(String message) {
+		this.message = message;
+		return this;
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Category.java
similarity index 61%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
copy to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Category.java
index ebb62b4..e8a48d4 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Category.java
@@ -1,44 +1,39 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.parser;
-
-import org.apache.juneau.*;
-
-/**
- * Subclass of {@link Parser} for byte-based parsers.
- * 
- * <h5 class='topic'>Description</h5>
- * 
- * This class is typically the parent class of all byte-based parsers.
- * It has 1 abstract method to implement...
- * <ul>
- * 	<li><code>parse(InputStream, ClassMeta, Parser)</code>
- * </ul>
-  */
-public abstract class InputStreamParser extends Parser {
-
-	/**
-	 * Constructor.
-	 * 
-	 * @param ps The property store containing all the settings for this object.
-	 * @param consumes The list of media types that this parser consumes (e.g. <js>"application/json"</js>).
-	 */
-	protected InputStreamParser(PropertyStore ps, String...consumes) {
-		super(ps, consumes);
-	}
-
-	@Override /* Parser */
-	public final boolean isReaderParser() {
-		return false;
-	}
-}
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              * 
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.examples.petstore;
+
+import org.apache.juneau.annotation.*;
+
+@Bean(typeName="Category", fluentSetters=true)
+public class Category {
+	private long id;
+	private String name;
+	
+	public long getId() {
+		return id;
+	}
+	
+	public Category id(long id) {
+		this.id = id;
+		return this;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public Category name(String name) {
+		this.name = name;
+		return this;
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Order.java
similarity index 60%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
copy to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Order.java
index ca1771e..5699c3c 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Order.java
@@ -1,44 +1,68 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.parser;
-
-import org.apache.juneau.*;
-
-/**
- * Subclass of {@link Parser} for characters-based parsers.
- * 
- * <h5 class='topic'>Description</h5>
- * 
- * This class is typically the parent class of all character-based parsers.
- * It has 1 abstract method to implement...
- * <ul>
- * 	<li><code>parse(ParserSession, ClassMeta)</code>
- * </ul>
- */
-public abstract class ReaderParser extends Parser {
-
-	/**
-	 * Constructor.
-	 * 
-	 * @param ps The property store containing all the settings for this object.
-	 * @param consumes The list of media types that this parser consumes (e.g. <js>"application/json"</js>, <js>"*&#8203;/json"</js>).
-	 */
-	protected ReaderParser(PropertyStore ps, String...consumes) {
-		super(ps, consumes);
-	}
-
-	@Override /* Parser */
-	public final boolean isReaderParser() {
-		return true;
-	}
-}
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              * 
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.examples.petstore;
+
+import org.apache.juneau.annotation.*;
+
+@Bean(fluentSetters=true)
+public class Order {
+	private long id, petId;
+	private int quantity;
+	private String shipDate;
+	private OrderStatus status;
+	
+	public long getId() {
+		return id;
+	}
+	
+	public Order id(long id) {
+		this.id = id;
+		return this;
+	}
+	
+	public long getPetId() {
+		return petId;
+	}
+	
+	public Order petId(long petId) {
+		this.petId = petId;
+		return this;
+	}
+	
+	public int getQuantity() {
+		return quantity;
+	}
+	
+	public Order quantity(int quantity) {
+		this.quantity = quantity;
+		return this;
+	}
+	
+	public String getShipDate() {
+		return shipDate;
+	}
+	
+	public Order shipDate(String shipDate) {
+		this.shipDate = shipDate;
+		return this;
+	}
+	
+	public OrderStatus getStatus() {
+		return status;
+	}
+	
+	public Order status(OrderStatus status) {
+		this.status = status;
+		return this;
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/OrderStatus.java
similarity index 61%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
copy to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/OrderStatus.java
index ebb62b4..774ae77 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/OrderStatus.java
@@ -1,44 +1,17 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.parser;
-
-import org.apache.juneau.*;
-
-/**
- * Subclass of {@link Parser} for byte-based parsers.
- * 
- * <h5 class='topic'>Description</h5>
- * 
- * This class is typically the parent class of all byte-based parsers.
- * It has 1 abstract method to implement...
- * <ul>
- * 	<li><code>parse(InputStream, ClassMeta, Parser)</code>
- * </ul>
-  */
-public abstract class InputStreamParser extends Parser {
-
-	/**
-	 * Constructor.
-	 * 
-	 * @param ps The property store containing all the settings for this object.
-	 * @param consumes The list of media types that this parser consumes (e.g. <js>"application/json"</js>).
-	 */
-	protected InputStreamParser(PropertyStore ps, String...consumes) {
-		super(ps, consumes);
-	}
-
-	@Override /* Parser */
-	public final boolean isReaderParser() {
-		return false;
-	}
-}
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              * 
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.examples.petstore;
+
+public enum OrderStatus {
+	PLACED, APPROVED, DELIVERED;
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Pet.java
similarity index 53%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java
copy to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Pet.java
index 4dc3e0a..21c4751 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Pet.java
@@ -2,7 +2,7 @@
 // * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
 // * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
 // * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
+// * with the License.  You may obtain a copy of the License at                                                              * 
 // *                                                                                                                         *
 // *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
 // *                                                                                                                         *
@@ -10,42 +10,84 @@
 // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
 // * specific language governing permissions and limitations under the License.                                              *
 // ***************************************************************************************************************************
-package org.apache.juneau.parser;
+package org.apache.juneau.examples.petstore;
+
+import java.util.*;
+
+import org.apache.juneau.annotation.*;
+import org.apache.juneau.xml.annotation.*;
 
 /**
- * Subclass of parser session objects for character-based parsers.
  * 
- * <p>
- * This class is NOT thread safe.  It is typically discarded after one-time use.
  */
-public abstract class ReaderParserSession extends ParserSession {
-
-	/**
-	 * Create a new session using properties specified in the context.
-	 * 
-	 * @param ctx
-	 * 	The parser creating this session object.
-	 * 	The parser contains all the configuration settings for this object.
-	 * @param args
-	 * 	Runtime session arguments.
-	 */
-	protected ReaderParserSession(Parser ctx, ParserSessionArgs args) {
-		super(ctx, args);
+@Bean(typeName="Pet", fluentSetters=true)
+public class Pet {
+	private long id;
+	private Category category;
+	private String name;
+	private List<String> photoUrls;
+	private List<Tag> tags;
+	private PetStatus status;
+	
+	@Example
+	public static Pet example() {
+		return new Pet()
+			.id(123);
 	}
 
-	/**
-	 * Constructor for sessions that don't require context.
-	 * 
-	 * @param args
-	 * 	Runtime session arguments.
-	 */
-	protected ReaderParserSession(ParserSessionArgs args) {
-		super(args);
+	public long getId() {
+		return id;
 	}
 
+	public Pet id(long id) {
+		this.id = id;
+		return this;
+	}
+	
+	public Category getCategory() {
+		return category;
+	}
+	
+	public Pet category(Category category) {
+		this.category = category;
+		return this;
+	}
+	
+	public String getName() {
+		return name;
+	}
+	
+	public Pet name(String name) {
+		this.name = name;
+		return this;
+	}
+	
+	@URI
+	@Xml(childName="photoUrl")
+	public List<String> getPhotoUrls() {
+		return photoUrls;
+	}
+	
+	public Pet photoUrls(List<String> photoUrls) {
+		this.photoUrls = photoUrls;
+		return this;
+	}
+	
+	public List<Tag> getTags() {
+		return tags;
+	}
 
-	@Override /* ParserSession */
-	public final boolean isReaderParser() {
-		return true;
+	public Pet tags(List<Tag> tags) {
+		this.tags = tags;
+		return this;
+	}
+	
+	public PetStatus getStatus() {
+		return status;
+	}
+	
+	public Pet status(PetStatus status) {
+		this.status = status;
+		return this;
 	}
 }
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStatus.java
similarity index 61%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
copy to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStatus.java
index ebb62b4..e475bf3 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStatus.java
@@ -1,44 +1,17 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.parser;
-
-import org.apache.juneau.*;
-
-/**
- * Subclass of {@link Parser} for byte-based parsers.
- * 
- * <h5 class='topic'>Description</h5>
- * 
- * This class is typically the parent class of all byte-based parsers.
- * It has 1 abstract method to implement...
- * <ul>
- * 	<li><code>parse(InputStream, ClassMeta, Parser)</code>
- * </ul>
-  */
-public abstract class InputStreamParser extends Parser {
-
-	/**
-	 * Constructor.
-	 * 
-	 * @param ps The property store containing all the settings for this object.
-	 * @param consumes The list of media types that this parser consumes (e.g. <js>"application/json"</js>).
-	 */
-	protected InputStreamParser(PropertyStore ps, String...consumes) {
-		super(ps, consumes);
-	}
-
-	@Override /* Parser */
-	public final boolean isReaderParser() {
-		return false;
-	}
-}
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              * 
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.examples.petstore;
+
+public enum PetStatus {
+	AVAILABLE, PENDING, SOLD;
+}
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStoreResource.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStoreResource.java
new file mode 100644
index 0000000..9bbfe9b
--- /dev/null
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStoreResource.java
@@ -0,0 +1,436 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the 'License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.examples.petstore;
+
+import java.util.*;
+
+import org.apache.juneau.microservice.*;
+import org.apache.juneau.rest.annotation.*;
+import org.apache.juneau.rest.widget.*;
+
+/**
+ * Sample resource that shows how to generate ATOM feeds.
+ */
+@RestResource(
+	path="/petstore2",
+	title="Swagger Petstore",
+	description="This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.",
+	htmldoc=@HtmlDoc(
+		widgets={
+			ContentTypeMenuItem.class,
+			StyleMenuItem.class
+		},
+		navlinks={
+			"up: request:/..",
+			"options: servlet:/?method=OPTIONS",
+			"$W{ContentTypeMenuItem}",
+			"$W{StyleMenuItem}",
+			"source: $C{Source/gitHub}/org/apache/juneau/examples/rest/petstore/$R{servletClassSimple}.java"
+		}
+	),
+	swagger="$F{PetStoreResource.json}"
+)
+public class PetStoreResource extends BasicRestServletJena {
+	private static final long serialVersionUID = 1L;
+	
+	@RestMethod(name="GET", path="/*") 
+	public String doGet() {
+		return "Hello";
+	}
+	
+	@RestMethod(
+		name="POST", 
+		path="/pet",
+		swagger={
+			"tags:['pet'],",
+			"parameters:[",
+//				"{ in:'body', name:'body', description:'Pet object that needs to be added to the store', required:true, schema:{ $ref:'#/definitions/Pet' } }",
+				"{ in:'body', description:'Pet object that needs to be added to the store', required:true }",
+			"],",
+			"responses:{",
+				"405: { description:'Invalid input' }",
+			"},",
+			"security:[",
+				"{ petstore_auth:['write:pets','read:pets'] }",
+			"]"
+		}
+	)
+	public void addPet(@Body Pet pet) {
+	}
+	
+	@RestMethod(
+		name="PUT", 
+		path="/pet/{petId}",
+		summary="Update an existing pet",
+		swagger={
+			"tags:['pet'],",
+			"parameters:[",
+//				"{ in:'body', description:'Pet object that needs to be added to the store', required:true, schema:{ $ref:'#/definitions/Pet'} }",
+				"{ in:'body', description:'Pet object that needs to be added to the store', required:true }",
+			"],",
+			"responses:{",
+				"400:{ description:'Invalid ID supplied' },",
+				"404:{ description:'Pet not found' },",
+				"405:{ description:'Validation exception' }",
+			"},",
+			"security:[ { petstore_auth: ['write:pets','read:pets'] } ]",
+		}
+	)
+	public void updatePet(@Body Pet pet) {}
+
+	@RestMethod(
+		name="GET", 
+		path="/pet/findByStatus",
+		summary="Finds Pets by status",
+		description="Multiple status values can be provided with comma separated strings.",
+		swagger={
+			"tags:['pet'],",
+			"parameters: [",
+				"{",
+					"name:'status', in:'query', description:'Status values that need to be considered for filter', required:true, type:'array',",
+					"items:{ type:'string', enum:[ 'available','pending','sold' ], default:'available' },",
+					"collectionFormat:'multi'",
+				"}",
+			"],",
+			"responses: {",
+				"200:{ description:'successful operation', schema:{ type:'array', items:{ $ref:'#/definitions/Pet' } } },",
+				"400:{ description':'Invalid status value' }",
+			"},",
+			"security:[",
+				"{ petstore_auth:[ 'write:pets','read:pets' ] }",
+			"]"
+		}
+	)
+	public List<Pet> findByStatus(@Query("status") PetStatus[] status) {
+		return null;
+	}
+	
+	@RestMethod(
+		name="GET", 
+		path="/pet/findByTags",
+		summary="Finds Pets by tags",
+		description="Multiple tags can be provided with comma separated strings. Use tag1, tag2, tag3 for testing.",
+		swagger={
+			"tags:['pet'],",
+			"parameters:[",
+				"{ name:'tags', in:'query', description:'Tags to filter by', required:true, type:'array', items:{ type:'string' }, collectionFormat:'multi' }",
+			"],",
+			"responses:{",
+				"200:{ description:'successful operation', schema:{ type:'array', items:{ $ref:'#/definitions/Pet' } } },",
+				"400:{ description:'Invalid tag value' }",
+			"},",
+			"security:[ { petstore_auth:[ 'write:pets','read:pets' ] } ],",
+			"deprecated:true"
+		}
+	)
+	public List<Pet> findByTags(@Query("tags") String[] tags) {
+		return null;
+	}
+
+	@RestMethod(
+		name="GET", 
+		path="/pet/{petId}",
+		summary="Find pet by ID",
+		description="Returns a single pet.",
+		swagger={
+			"tags:[ 'pet' ],",
+			"parameters:[",
+				"{ name:'petId', in:'path', description:'ID of pet to return', required:true, type:'integer', format:'int64' }",
+			"],",
+			"responses:{",
+				"200:{ description:'successful operation', schema:{ $ref:'#/definitions/Pet' } },",
+				"400:{ description:'Invalid ID supplied' },",
+				"404:{ description:'Pet not found' }",
+			"},",
+			"security:[ { api_key:[] } ]"
+		}
+	)
+	public Pet getPet(@Path long petId) {
+		return null;
+	}
+	
+	@RestMethod(
+		name="POST", 
+		path="/pet/{petId}",
+		summary="Updates a pet in the store with form data",
+		swagger={
+			"tags:[ 'pet' ],",
+			"parameters:[",
+				"{ name:'petId', in:'path', description:'ID of pet that needs to be updated', required:true, type:'integer', format:'int64' },",
+				"{ name:'name', in:'formData', description:'Updated name of the pet', required:false, type:'string'},",
+				"{ name:'status', in:'formData', description:'Updated status of the pet', required:false, type:'string' }",
+			"],",
+			"responses:{",
+				"405:{ description:'Invalid input' }",
+			"},",
+			"security:[ { petstore_auth:[ 'write:pets', 'read:pets' ] } ]"
+		}
+	)
+	public void updatePetForm(@Path long petId, @FormData("name") String name, @FormData("status") String status) {}
+
+	@RestMethod(
+		name="DELETE", 
+		path="/pet/{petId}",
+		summary="Deletes a pet",
+		swagger={
+			"tags:[ 'pet' ],",
+			"parameters:[",
+				"{ name:'api_key', in:'header', required:false, type:'string' },",
+				"{ name:'petId', in:'path', description:'Pet id to delete', required:true, type:'integer', format:'int64' }",
+			"],",
+			"responses:{",
+				"400:{ description:'Invalid ID supplied' },",
+				"404:{ description:'Pet not found' }",
+			"},",
+			"security:[ { petstore_auth:[ 'write:pets','read:pets' ] } ]"
+		}
+	)
+	public void deletePet(@Header("api_key") String apiKey, @Path long petId) {}
+
+	@RestMethod(
+		name="POST", 
+		path="/pet/{petId}/uploadImage",
+		summary="Uploads an image",
+		swagger={
+			"tags:[ 'pet' ],",
+			"parameters:[",
+				"{ name:'petId', in:'path', description:'ID of pet to update', required:true, type:'integer', format:'int64' },",
+				"{ name:'additionalMetadata', in:'formData', description:'Additional data to pass to server', required:false, type:'string' },",
+				"{ name:'file', in:'formData', description:'file to upload', required:false, type:'file' }",
+			"],",
+			"responses:{",
+				"200:{ description:'successful operation', schema:{ $ref:'#/definitions/ApiResponse' } }",
+			"},",
+			"security:[ { petstore_auth:[ 'write:pets','read:pets' ] } ]"
+		}
+	)
+	public void uploadImage(@Path long petId, @FormData("additionalMetadata") String additionalMetadata, @FormData("file") byte[] file) {}
+
+	@RestMethod(
+		name="GET", 
+		path="/store/inventory",
+		summary="Returns pet inventories by status",
+		description="Returns a map of status codes to quantities",
+		swagger={
+			"tags:[ 'store' ],",
+			"responses:{",
+				"200:{ description:'successful operation', schema:{ type:'object', additionalProperties:{ type:'integer', format:'int32' } } }",
+			"},",
+			"security:[ { api_key:[] } ]"
+		}
+	)
+	public void getStoreInventory() {}
+
+	@RestMethod(
+		name="POST", 
+		path="/store/order",
+		summary="Place an order for a pet",
+		swagger={
+			"tags:[ 'store' ],",
+			"parameters:[",
+				"{ in:'body', name:'body', description:'order placed for purchasing the pet', required:true, schema:{ $ref:'#/definitions/Order' } }",
+			"],",
+			"responses:{",
+				"200:{ description:'successful operation', schema:{ $ref:'#/definitions/Order' } },",
+				"400:{ description:'Invalid Order' }",
+			"}"
+		}
+	)
+	public Order placeOrder(@Body Order order) {
+		return order;
+	}
+
+	@RestMethod(
+		name="GET", 
+		path="/store/order/{orderId}",
+		summary="Find purchase order by ID",
+		description="For valid response try integer IDs with value >= 1 and <= 10. Other values will generated exceptions",
+		swagger={
+			"tags:[ 'store' ],",
+			"parameters:[",
+				"{ name:'orderId', in:'path', description:'ID of pet that needs to be fetched', required:true, type:'integer', maximum:10.0, minimum:1.0, format:'int64' }",
+			"],",
+			"responses:{",
+				"200:{ description:'successful operation', schema:{ $ref:'#/definitions/Order' } },",
+				"400:{ description:'Invalid ID supplied' },",
+				"404:{ description:'Order not found' }",
+			"}"
+		}
+	)
+	public Order findPurchaseOrder(@Path String orderId) {
+		return null;
+	}
+
+	@RestMethod(
+		name="DELETE", 
+		path="/store/order/{orderId}",
+		summary="Delete purchase order by ID",
+		description="For valid response try integer IDs with positive integer value. Negative or non-integer values will generate API errors.",
+		swagger={
+			"tags:[ 'store' ],",
+			"parameters:[",
+				"{ name:'orderId', in:'path', description:'ID of the order that needs to be deleted', required:true, type:'integer', minimum:1.0, format:'int64' }",
+			"],",
+			"responses:{",
+				"400:{ description:'Invalid ID supplied' },",
+				"404:{ description:'Order not found' }",
+			"}"
+		}
+	)
+	public void deletePurchaseOrder(@Path String orderId) {}
+
+	@RestMethod(
+		name="POST", 
+		path="/user",
+		summary="Create user",
+		description="This can only be done by the logged in user.",
+		swagger={
+			"tags:[ 'user' ],",
+			"parameters:[",
+				"{ in:'body', name:'body', description:'Created user object', required:true, schema:{ $ref:'#/definitions/User' } }",
+			"],",
+			"responses:{",
+				"default:{ description:'successful operation' }",
+			"}"
+		}
+	)
+	public void createUser(@Body User user) {}
+
+	@RestMethod(
+		name="POST", 
+		path="/user/createWithArray",
+		summary="Creates list of users with given input array",
+		swagger={
+			"tags:[ 'user' ],",
+			"parameters:[",
+				"{ in:'body', name:'body', description:'List of user object', required:true, schema:{ type:'array', items:{ $ref:'#/definitions/User' } } }",
+			"],",
+			"responses:{",
+				"default:{ description:'successful operation' }",
+			"}"
+		}
+	)
+	public void createUsersWithArrayInput(@Body User[] users) {}
+
+	@RestMethod(
+		name="POST", 
+		path="/user/createWithList",
+		summary="Creates list of users with given input array",
+		description="This can only be done by the logged in user.",
+		swagger={
+			"tags:[ 'user' ],",
+			"operationId:'createUsersWithListInput',",
+			"parameters:[",
+				"{ in:'body', name:'body', description:'List of user object', required:true, schema:{ type:'array', items:{ $ref:'#/definitions/User' } } }",
+			"],",
+			"responses:{",
+				"default:{ description:'successful operation' }",
+			"}"
+		}
+	)
+	public void createUsersWithListInput(@Body List<User> users) {}
+
+	@RestMethod(
+		name="GET", 
+		path="/user/login",
+		summary="Logs user into the system",
+		swagger={
+			"tags:[ 'user' ],",
+			"parameters:[",
+				"{ name:'username', in:'query', description:'The user name for login', required:true, type:'string' },",
+				"{ name:'password', in:'query', description:'The password for login in clear text', required:true, type:'string' }",
+			"],",
+			"responses:{",
+				"200:{",
+					"description:'successful operation', schema:{ type:'string' },",
+					"headers:{",
+						"X-Rate-Limit:{ type:'integer', format:'int32', description:'calls per hour allowed by the user' },",
+						"X-Expires-After:{ type:'string', format:'date-time', description:'date in UTC when token expires' }",
+					"}",
+				"},",
+				"400:{ description:'Invalid username/password supplied' }",
+			"}"
+		}
+	)
+	public void login(@Query("username") String username, @Query("password") String password) {}
+
+	@RestMethod(
+		name="GET", 
+		path="/user/logout",
+		summary="Logs out current logged in user session",
+		swagger={
+			"tags:[ 'user' ],",
+			"responses:{",
+				"default:{ description:'successful operation' }",
+			"}"
+		}
+	)
+	public void logout() {}
+
+	@RestMethod(
+		name="GET", 
+		path="/user/{username}",
+		summary="Get user by user name",
+		swagger={
+			"tags:[ 'user' ],",
+			"parameters:[",
+				"{ name:'username', in:'path', description:'The name that needs to be fetched. Use user1 for testing. ', required:true, type:'string' }",
+			"],",
+			"responses:{",
+				"200:{ description:'successful operation', schema:{ $ref:'#/definitions/User' } },",
+				"400:{ description:'Invalid username supplied' },",
+				"404:{ description:'User not found' }",
+			"}"
+		}
+	)
+	public User getUser(@Path String username) {
+		return null;
+	}
+
+	@RestMethod(
+		name="PUT", 
+		path="/user/{username}",
+		summary="Update user",
+		description="This can only be done by the logged in user.",
+		swagger={
+			"tags:[ 'user' ],",
+			"parameters:[",
+				"{ name:'username', in:'path', description:'name that need to be updated', required:true, type:'string' },",
+				"{ in:'body', name:'body', description:'Updated user object', required:true, schema:{ $ref:'#/definitions/User' } }",
+			"],",
+			"responses:{",
+				"400:{ description:'Invalid user supplied' },",
+				"404:{ description:'User not found' }",
+			"}"
+		}
+	)
+	public void updateUser(@Path String username, @Body User user) {}
+
+	@RestMethod(
+		name="DELETE", 
+		path="/user/{username}",
+		summary="Delete user",
+		description="This can only be done by the logged in user.",
+		swagger={
+			"tags:[ 'user' ],",
+			"parameters:[",
+				"{ name:'username', in:'path', description:'The name that needs to be deleted', required:true, type:'string' }",
+			"],",
+			"responses:{",
+				"400:{ description:'Invalid username supplied' },",
+				"404:{ description:'User not found' }",
+			"}"
+		}
+	)
+	public void deleteUser(@Path String username) {}
+}
\ No newline at end of file
diff --git a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStoreResource.json b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStoreResource.json
new file mode 100644
index 0000000..138c141
--- /dev/null
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/PetStoreResource.json
@@ -0,0 +1,284 @@
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              *
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+
+{
+	"swagger": "2.0",
+	"info": {
+		"description": "This is a sample server Petstore server. You can find out more about Swagger at [http://swagger.io](http://swagger.io) or on [irc.freenode.net, #swagger](http://swagger.io/irc/). For this sample, you can use the api key `special-key` to test the authorization filters.",
+		"version": "1.0.0",
+		"title": "Swagger Petstore",
+		"termsOfService": "http://swagger.io/terms/",
+		"contact": {
+			"email": "apiteam@swagger.io"
+		},
+		"license": {
+			"name": "Apache 2.0",
+			"url": "http://www.apache.org/licenses/LICENSE-2.0.html"
+		}
+	},
+	"host": "petstore.swagger.io",
+	"basePath": "/v2",
+	"tags": [
+		{
+			"name": "pet",
+			"description": "Everything about your Pets",
+			"externalDocs": {
+				"description": "Find out more",
+				"url": "http://swagger.io"
+			}
+		},
+		{
+			"name": "store",
+			"description": "Access to Petstore orders"
+		},
+		{
+			"name": "user",
+			"description": "Operations about user",
+			"externalDocs": {
+				"description": "Find out more about our store",
+				"url": "http://swagger.io"
+			}
+		}
+	],
+	"schemes": [
+		"http"
+	],
+	"securityDefinitions": {
+		"petstore_auth": {
+			"type": "oauth2",
+			"authorizationUrl": "http://petstore.swagger.io/oauth/dialog",
+			"flow": "implicit",
+			"scopes": {
+				"write:pets": "modify pets in your account",
+				"read:pets": "read your pets"
+			}
+		},
+		"api_key": {
+			"type": "apiKey",
+			"name": "api_key",
+			"in": "header"
+		}
+	},
+	"definitions": {
+		"Order": {
+			"type": "object",
+			"properties": {
+				"id": {
+					"type": "integer",
+					"format": "int64"
+				},
+				"petId": {
+					"type": "integer",
+					"format": "int64"
+				},
+				"quantity": {
+					"type": "integer",
+					"format": "int32"
+				},
+				"shipDate": {
+					"type": "string",
+					"format": "date-time"
+				},
+				"status": {
+					"type": "string",
+					"description": "Order Status",
+					"enum": [
+						"placed",
+						"approved",
+						"delivered"
+					]
+				},
+				"complete": {
+					"type": "boolean",
+					"default": false
+				}
+			},
+			"xml": {
+				"name": "Order"
+			},
+			"x-examples": {
+				"application/json": "{\n\tfoo: 'bar',\n\tbaz: 123\n}",
+				"text/xml": "<foo>bar</foo>",
+				"text/html": "<table>foo</table>",
+				"octal-messagepack": "12 34 56 AB CD EF"
+			}
+		},
+		"User": {
+			"type": "object",
+			"properties": {
+				"id": {
+					"type": "integer",
+					"format": "int64"
+				},
+				"username": {
+					"type": "string"
+				},
+				"firstName": {
+					"type": "string"
+				},
+				"lastName": {
+					"type": "string"
+				},
+				"email": {
+					"type": "string"
+				},
+				"password": {
+					"type": "string"
+				},
+				"phone": {
+					"type": "string"
+				},
+				"userStatus": {
+					"type": "integer",
+					"format": "int32",
+					"description": "User Status"
+				}
+			},
+			"xml": {
+				"name": "User"
+			},
+			"x-examples": {
+				"application/json": "{\n\tfoo: 'bar',\n\tbaz: 123\n}",
+				"text/xml": "<foo>bar</foo>",
+				"text/html": "<table>foo</table>",
+				"octal-messagepack": "12 34 56 AB CD EF"
+			}
+		},
+		"Category": {
+			"type": "object",
+			"properties": {
+				"id": {
+					"type": "integer",
+					"format": "int64"
+				},
+				"name": {
+					"type": "string"
+				}
+			},
+			"xml": {
+				"name": "Category"
+			},
+			"x-examples": {
+				"application/json": "{\n\tfoo: 'bar',\n\tbaz: 123,\n\tflags:[\n\t\t'f1',\n\t\t'f1',\n\t\t'f3'\n\t]\n}",
+				"text/xml": "<foo>bar</foo>",
+				"text/html": "<table>foo</table>",
+				"octal-messagepack": "12 34 56 AB CD EF"
+			}
+		},
+		"Tag": {
+			"type": "object",
+			"properties": {
+				"id": {
+					"type": "integer",
+					"format": "int64"
+				},
+				"name": {
+					"type": "string"
+				}
+			},
+			"xml": {
+				"name": "Tag"
+			},
+			"x-examples": {
+				"application/json": "{\n\tfoo: 'bar',\n\tbaz: 123\n}",
+				"text/xml": "<foo>bar</foo>",
+				"text/html": "<table>foo</table>",
+				"octal-messagepack": "12 34 56 AB CD EF"
+			}
+		},
+/*		"Pet": {
+			"type": "object",
+			"required": [
+				"name",
+				"photoUrls"
+			],
+			"properties": {
+				"id": {
+					"type": "integer",
+					"format": "int64"
+				},
+				"category": {
+					"$ref": "#/definitions/Category"
+				},
+				"name": {
+					"type": "string",
+					"example": "doggie"
+				},
+				"photoUrls": {
+					"type": "array",
+					"xml": {
+						"name": "photoUrl",
+						"wrapped": true
+					},
+					"items": {
+						"type": "string"
+					}
+				},
+				"tags": {
+					"type": "array",
+					"xml": {
+						"name": "tag",
+						"wrapped": true
+					},
+					"items": {
+						"$ref": "#/definitions/Tag"
+					}
+				},
+				"status": {
+					"type": "string",
+					"description": "pet status in the store",
+					"enum": [
+						"available",
+						"pending",
+						"sold"
+					]
+				}
+			},
+			"xml": {
+				"name": "Pet"
+			},
+			"x-examples": {
+				"application/json": "{\n\tfoo: 'bar',\n\tbaz: 123,\n\tflags:[\n\t\t'f1',\n\t\t'f1',\n\t\t'f3'\n\t]\n}",
+				"text/xml": "<foo>bar</foo>",
+				"text/html": "<table>foo</table>",
+				"octal-messagepack": "12 34 56 AB CD EF"
+			}
+		},
+*/
+		"ApiResponse": {
+			"type": "object",
+			"properties": {
+				"code": {
+					"type": "integer",
+					"format": "int32"
+				},
+				"type": {
+					"type": "string"
+				},
+				"message": {
+					"type": "string"
+				}
+			},
+			"x-examples": {
+				"application/json": "{\n\tfoo: 'bar',\n\tbaz: 123\n}",
+				"text/xml": "<foo>bar</foo>",
+				"text/html": "<table>foo</table>",
+				"octal-messagepack": "12 34 56 AB CD EF"
+			}
+		}
+	},
+	"externalDocs": {
+		"description": "Find out more about Swagger",
+		"url": "http://swagger.io"
+	}
+}
\ No newline at end of file
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Tag.java
similarity index 61%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
copy to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Tag.java
index ebb62b4..298b885 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/Tag.java
@@ -1,44 +1,39 @@
-// ***************************************************************************************************************************
-// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
-// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
-// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
-// *                                                                                                                         *
-// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
-// *                                                                                                                         *
-// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
-// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
-// * specific language governing permissions and limitations under the License.                                              *
-// ***************************************************************************************************************************
-package org.apache.juneau.parser;
-
-import org.apache.juneau.*;
-
-/**
- * Subclass of {@link Parser} for byte-based parsers.
- * 
- * <h5 class='topic'>Description</h5>
- * 
- * This class is typically the parent class of all byte-based parsers.
- * It has 1 abstract method to implement...
- * <ul>
- * 	<li><code>parse(InputStream, ClassMeta, Parser)</code>
- * </ul>
-  */
-public abstract class InputStreamParser extends Parser {
-
-	/**
-	 * Constructor.
-	 * 
-	 * @param ps The property store containing all the settings for this object.
-	 * @param consumes The list of media types that this parser consumes (e.g. <js>"application/json"</js>).
-	 */
-	protected InputStreamParser(PropertyStore ps, String...consumes) {
-		super(ps, consumes);
-	}
-
-	@Override /* Parser */
-	public final boolean isReaderParser() {
-		return false;
-	}
-}
+// ***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                                                              * 
+// *                                                                                                                         *
+// *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
+// *                                                                                                                         *
+// * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the License.                                              *
+// ***************************************************************************************************************************
+package org.apache.juneau.examples.petstore;
+
+import org.apache.juneau.annotation.*;
+
+@Bean(typeName="Tag", fluentSetters=true)
+public class Tag {
+	private long id;
+	private String name;
+
+	public long getId() {
+		return id;
+	}
+
+	public Tag id(long id) {
+		this.id = id;
+		return this;
+	}
+
+	public String getName() {
+		return name;
+	}
+
+	public Tag name(String name) {
+		this.name = name;
+		return this;
+	}
+}
diff --git a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/User.java
similarity index 51%
copy from juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java
copy to juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/User.java
index 4dc3e0a..05a79e0 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParserSession.java
+++ b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/petstore/User.java
@@ -2,7 +2,7 @@
 // * Licensed to the Apache Software Foundation (ASF) under one or more contributor license agreements.  See the NOTICE file *
 // * distributed with this work for additional information regarding copyright ownership.  The ASF licenses this file        *
 // * to you under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance            *
-// * with the License.  You may obtain a copy of the License at                                                              *
+// * with the License.  You may obtain a copy of the License at                                                              * 
 // *                                                                                                                         *
 // *  http://www.apache.org/licenses/LICENSE-2.0                                                                             *
 // *                                                                                                                         *
@@ -10,42 +10,85 @@
 // * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the License for the        *
 // * specific language governing permissions and limitations under the License.                                              *
 // ***************************************************************************************************************************
-package org.apache.juneau.parser;
-
-/**
- * Subclass of parser session objects for character-based parsers.
- * 
- * <p>
- * This class is NOT thread safe.  It is typically discarded after one-time use.
- */
-public abstract class ReaderParserSession extends ParserSession {
-
-	/**
-	 * Create a new session using properties specified in the context.
-	 * 
-	 * @param ctx
-	 * 	The parser creating this session object.
-	 * 	The parser contains all the configuration settings for this object.
-	 * @param args
-	 * 	Runtime session arguments.
-	 */
-	protected ReaderParserSession(Parser ctx, ParserSessionArgs args) {
-		super(ctx, args);
-	}
-
-	/**
-	 * Constructor for sessions that don't require context.
-	 * 
-	 * @param args
-	 * 	Runtime session arguments.
-	 */
-	protected ReaderParserSession(ParserSessionArgs args) {
-		super(args);
-	}
-
-
-	@Override /* ParserSession */
-	public final boolean isReaderParser() {
-		return true;
+package org.apache.juneau.examples.petstore;
+
+import org.apache.juneau.annotation.*;
+
+@Bean(typeName="User", fluentSetters=true)
+public class User {
+	private long id;
+	private String username, firstName, lastName, email, password, phone;
+	private int userStatus;
+	
+	public long getId() {
+		return id;
+	}
+
+	public User id(long id) {
+		this.id = id;
+		return this;
+	}
+
+	public String getUsername() {
+		return username;
+	}
+
+	public User username(String username) {
+		this.username = username;
+		return this;
+	}
+
+	public String getFirstName() {
+		return firstName;
+	}
+
+	public User firstName(String firstName) {
+		this.firstName = firstName;
+		return this;
+	}
+
+	public String getLastName() {
+		return lastName;
+	}
+
+	public User lastName(String lastName) {
+		this.lastName = lastName;
+		return this;
+	}
+
+	public String getEmail() {
+		return email;
+	}
+
+	public User email(String email) {
+		this.email = email;
+		return this;
+	}
+
+	public String getPassword() {
+		return password;
+	}
+
+	public User password(String password) {
+		this.password = password;
+		return this;
... 735 lines suppressed ...

-- 
To stop receiving notification emails like this one, please contact
jamesbognar@apache.org.

Mime
View raw message