You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@juneau.apache.org by ja...@apache.org on 2017/02/15 20:50:43 UTC

[4/8] incubator-juneau git commit: Modification to UON spec. Remove bean subtype support.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
index a897d1a..ac4a096 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonParser.java
@@ -101,7 +101,6 @@ public final class JsonParser extends ReaderParser {
 		ClassMeta<?> sType = eType.getSerializedClassMeta();
 		session.setCurrentClass(sType);
 		String wrapperAttr = sType.getExtendedMeta(JsonClassMeta.class).getWrapperAttr();
-		BeanRegistry breg = pMeta == null ? session.getBeanRegistry() : pMeta.getBeanRegistry();
 
 		Object o = null;
 
@@ -124,7 +123,7 @@ public final class JsonParser extends ReaderParser {
 			if (c == '{') {
 				ObjectMap m2 = new ObjectMap(session);
 				parseIntoMap2(session, r, m2, string(), object(), pMeta);
-				o = breg.cast(m2);
+				o = session.cast(m2, pMeta, eType);
 			} else if (c == '[') {
 				o = parseIntoCollection2(session, r, new ObjectList(session), object(), pMeta);
 			} else if (c == '\'' || c == '"') {
@@ -155,7 +154,7 @@ public final class JsonParser extends ReaderParser {
 			if (c == '{') {
 				ObjectMap m = new ObjectMap(session);
 				parseIntoMap2(session, r, m, string(), object(), pMeta);
-				o = breg.cast(m);
+				o = session.cast(m, pMeta, eType);
 			} else {
 				Collection l = (sType.canCreateNewInstance(outer) ? (Collection)sType.newInstance() : new ObjectList(session));
 				o = parseIntoCollection2(session, r, l, sType.getElementType(), pMeta);
@@ -171,7 +170,7 @@ public final class JsonParser extends ReaderParser {
 			if (c == '{') {
 				ObjectMap m = new ObjectMap(session);
 				parseIntoMap2(session, r, m, string(), object(), pMeta);
-				o = breg.cast(m);
+				o = session.cast(m, pMeta, eType);
 			} else {
 				ArrayList l = (ArrayList)parseIntoCollection2(session, r, new ArrayList(), sType.getElementType(), pMeta);
 				o = session.toArray(sType, l);
@@ -180,7 +179,7 @@ public final class JsonParser extends ReaderParser {
 			Map m = new ObjectMap(session);
 			parseIntoMap2(session, r, m, sType.getKeyType(), sType.getValueType(), pMeta);
 			if (m.containsKey(session.getBeanTypePropertyName()))
-				o = breg.cast((ObjectMap)m);
+				o = session.cast((ObjectMap)m, pMeta, eType);
 			else
 				throw new ParseException(session, "Class ''{0}'' could not be instantiated.  Reason: ''{1}''", sType.getInnerClass().getName(), sType.getNotABeanReason());
 		} else if (sType.canCreateNewInstanceFromString(outer) && ! session.isStrict()) {
@@ -222,7 +221,7 @@ public final class JsonParser extends ReaderParser {
 			// Need to weed out octal and hexadecimal formats:  0123,-0123,0x123,-0x123.
 			// Don't weed out 0 or -0.
 			boolean isNegative = false;
-			char c = (s.length() == 0 ? 'x' : s.charAt(0));
+			char c = s.charAt(0);
 			if (c == '-') {
 				isNegative = true;
 				c = (s.length() == 1 ? 'x' : s.charAt(1));
@@ -505,13 +504,8 @@ public final class JsonParser extends ReaderParser {
 						BeanPropertyMeta pMeta = m.getPropertyMeta(currAttr);
 						session.setCurrentProperty(pMeta);
 						if (pMeta == null) {
-							if (m.getMeta().isSubTyped()) {
-								Object value = parseAnything(session, object(), r.unread(), m.getBean(false), null);
-								m.put(currAttr, value);
-							} else {
-								onUnknownProperty(session, currAttr, m, currAttrLine, currAttrCol);
-								parseAnything(session, object(), r.unread(), m.getBean(false), null); // Read content anyway to ignore it
-							}
+							onUnknownProperty(session, currAttr, m, currAttrLine, currAttrCol);
+							parseAnything(session, object(), r.unread(), m.getBean(false), null); // Read content anyway to ignore it
 						} else {
 							ClassMeta<?> cm = pMeta.getClassMeta();
 							Object value = parseAnything(session, cm, r.unread(), m.getBean(false), pMeta);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
index 07121d3..3a89b68 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializer.java
@@ -113,7 +113,6 @@ public class JsonSerializer extends WriterSerializer {
 		/** Constructor */
 		public Readable() {
 			setUseWhitespace(true);
-			setUseIndentation(true);
 		}
 	}
 
@@ -132,7 +131,6 @@ public class JsonSerializer extends WriterSerializer {
 		/** Constructor */
 		public SimpleReadable() {
 			setUseWhitespace(true);
-			setUseIndentation(true);
 		}
 	}
 
@@ -162,7 +160,6 @@ public class JsonSerializer extends WriterSerializer {
 		if (eType == null)
 			eType = object();
 
-		boolean addTypeProperty;    // Add "_type" attribute to element?
 		ClassMeta<?> aType;			// The actual type
 		ClassMeta<?> sType;			// The serialized type
 
@@ -176,7 +173,7 @@ public class JsonSerializer extends WriterSerializer {
 		}
 
 		sType = aType.getSerializedClassMeta();
-		addTypeProperty = (session.isAddBeanTypeProperties() && ! eType.equals(aType));
+		String typeName = session.getBeanTypeName(eType, aType, pMeta);
 
 		// Swap if necessary
 		PojoSwap swap = aType.getPojoSwap();
@@ -201,12 +198,12 @@ public class JsonSerializer extends WriterSerializer {
 		else if (sType.isNumber() || sType.isBoolean())
 			out.append(o);
 		else if (sType.isBean())
-			serializeBeanMap(session, out, session.toBeanMap(o), addTypeProperty);
+			serializeBeanMap(session, out, session.toBeanMap(o), typeName);
 		else if (sType.isUri() || (pMeta != null && pMeta.isUri()))
 			out.q().appendUri(o).q();
 		else if (sType.isMap()) {
 			if (o instanceof BeanMap)
-				serializeBeanMap(session, out, (BeanMap)o, addTypeProperty);
+				serializeBeanMap(session, out, (BeanMap)o, typeName);
 			else
 				serializeMap(session, out, (Map)o, eType);
 		}
@@ -260,12 +257,12 @@ public class JsonSerializer extends WriterSerializer {
 		return out;
 	}
 
-	private SerializerWriter serializeBeanMap(JsonSerializerSession session, JsonWriter out, BeanMap<?> m, boolean addTypeProperty) throws Exception {
+	private SerializerWriter serializeBeanMap(JsonSerializerSession session, JsonWriter out, BeanMap<?> m, String typeName) throws Exception {
 		int depth = session.getIndent();
 		out.append('{');
 
 		boolean addComma = false;
-		for (BeanPropertyValue p : m.getValues(session.isTrimNulls(), addTypeProperty ? session.createBeanTypeNameProperty(m) : null)) {
+		for (BeanPropertyValue p : m.getValues(session.isTrimNulls(), typeName != null ? session.createBeanTypeNameProperty(m, typeName) : null)) {
 			BeanPropertyMeta pMeta = p.getMeta();
 			ClassMeta<?> cMeta = p.getClassMeta();
 			String key = p.getName();
@@ -373,32 +370,6 @@ public class JsonSerializer extends WriterSerializer {
 	}
 
 	/**
-	 * <b>Configuration property:</b>  Use whitespace.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"JsonSerializer.useWhitespace"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>false</jk>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * If <jk>true</jk>, whitespace is added to the output to improve readability.
-	 * <p>
-	 * <h5 class='section'>Notes:</h5>
-	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>JSON_useWhitespace</jsf>, value)</code>.
-	 * </ul>
-	 *
-	 * @param value The new value for this property.
-	 * @return This object (for method chaining).
-	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see JsonSerializerContext#JSON_useWhitespace
-	 */
-	public JsonSerializer setUseWhitespace(boolean value) throws LockedException {
-		return setProperty(JSON_useWhitespace, value);
-	}
-
-	/**
 	 * <b>Configuration property:</b>  Prefix solidus <js>'/'</js> characters with escapes.
 	 * <p>
 	 * <ul>
@@ -452,8 +423,8 @@ public class JsonSerializer extends WriterSerializer {
 	}
 
 	@Override /* Serializer */
-	public JsonSerializer setUseIndentation(boolean value) throws LockedException {
-		super.setUseIndentation(value);
+	public JsonSerializer setUseWhitespace(boolean value) throws LockedException {
+		super.setUseWhitespace(value);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerContext.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerContext.java
index eec89c8..6cdceb3 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerContext.java
@@ -49,20 +49,6 @@ public final class JsonSerializerContext extends SerializerContext {
 	public static final String JSON_simpleMode = "JsonSerializer.simpleMode";
 
 	/**
-	 * <b>Configuration property:</b>  Use whitespace.
-	 * <p>
-	 * <ul>
-	 * 	<li><b>Name:</b> <js>"JsonSerializer.useWhitespace"</js>
-	 * 	<li><b>Data type:</b> <code>Boolean</code>
-	 * 	<li><b>Default:</b> <jk>false</jk>
-	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
-	 * </ul>
-	 * <p>
-	 * If <jk>true</jk>, whitespace is added to the output to improve readability.
-	 */
-	public static final String JSON_useWhitespace = "JsonSerializer.useWhitespace";
-
-	/**
 	 * <b>Configuration property:</b>  Prefix solidus <js>'/'</js> characters with escapes.
 	 * <p>
 	 * <ul>
@@ -82,7 +68,6 @@ public final class JsonSerializerContext extends SerializerContext {
 
 	final boolean
 		simpleMode,
-		useWhitespace,
 		escapeSolidus;
 
 	/**
@@ -95,7 +80,6 @@ public final class JsonSerializerContext extends SerializerContext {
 	public JsonSerializerContext(ContextFactory cf) {
 		super(cf);
 		simpleMode = cf.getProperty(JSON_simpleMode, boolean.class, false);
-		useWhitespace = cf.getProperty(JSON_useWhitespace, boolean.class, false);
 		escapeSolidus = cf.getProperty(JSON_escapeSolidus, boolean.class, false);
 	}
 
@@ -104,7 +88,6 @@ public final class JsonSerializerContext extends SerializerContext {
 		return super.asMap()
 			.append("JsonSerializerContext", new ObjectMap()
 				.append("simpleMode", simpleMode)
-				.append("useWhitespace", useWhitespace)
 				.append("escapeSolidus", escapeSolidus)
 			);
 	}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
index ae0fb4a..1d99bf7 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
@@ -18,7 +18,6 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
-import org.apache.juneau.MediaType;
 import org.apache.juneau.serializer.*;
 
 /**
@@ -28,7 +27,7 @@ import org.apache.juneau.serializer.*;
  */
 public final class JsonSerializerSession extends SerializerSession {
 
-	private final boolean simpleMode, useWhitespace, escapeSolidus;
+	private final boolean simpleMode, escapeSolidus;
 
 	/**
 	 * Create a new session using properties specified in the context.
@@ -49,11 +48,9 @@ public final class JsonSerializerSession extends SerializerSession {
 		super(ctx, op, output, javaMethod, locale, timeZone, mediaType);
 		if (op == null || op.isEmpty()) {
 			simpleMode = ctx.simpleMode;
-			useWhitespace = ctx.useWhitespace;
 			escapeSolidus = ctx.escapeSolidus;
 		} else {
 			simpleMode = op.getBoolean(JSON_simpleMode, ctx.simpleMode);
-			useWhitespace = op.getBoolean(JSON_useWhitespace, ctx.useWhitespace);
 			escapeSolidus = op.getBoolean(JSON_escapeSolidus, ctx.escapeSolidus);
 		}
 	}
@@ -68,15 +65,6 @@ public final class JsonSerializerSession extends SerializerSession {
 	}
 
 	/**
-	 * Returns the {@link JsonSerializerContext#JSON_useWhitespace} setting value for this session.
-	 *
-	 * @return The {@link JsonSerializerContext#JSON_useWhitespace} setting value for this session.
-	 */
-	public final boolean isUseWhitespace() {
-		return useWhitespace;
-	}
-
-	/**
 	 * Returns the {@link JsonSerializerContext#JSON_escapeSolidus} setting value for this session.
 	 *
 	 * @return The {@link JsonSerializerContext#JSON_escapeSolidus} setting value for this session.
@@ -90,6 +78,6 @@ public final class JsonSerializerSession extends SerializerSession {
 		Object output = getOutput();
 		if (output instanceof JsonWriter)
 			return (JsonWriter)output;
-		return new JsonWriter(super.getWriter(), isUseIndentation(), isUseWhitespace(), isEscapeSolidus(), getQuoteChar(), isSimpleMode(), isTrimStrings(), getRelativeUriBase(), getAbsolutePathUriBase());
+		return new JsonWriter(super.getWriter(), isUseWhitespace(), isEscapeSolidus(), getQuoteChar(), isSimpleMode(), isTrimStrings(), getRelativeUriBase(), getAbsolutePathUriBase());
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/json/JsonWriter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/json/JsonWriter.java b/juneau-core/src/main/java/org/apache/juneau/json/JsonWriter.java
index 4b3af99..093a4f0 100644
--- a/juneau-core/src/main/java/org/apache/juneau/json/JsonWriter.java
+++ b/juneau-core/src/main/java/org/apache/juneau/json/JsonWriter.java
@@ -55,8 +55,7 @@ public final class JsonWriter extends SerializerWriter {
 	/**
 	 * Constructor.
 	 * @param out The writer being wrapped.
-	 * @param useIndentation If <jk>true</jk>, tabs will be used in output.
-	 * @param useWhitespace If <jk>true</jk>, whitespace will be used in output.
+	 * @param useWhitespace If <jk>true</jk>, tabs and spaces will be used in output.
 	 * @param escapeSolidus If <jk>true</jk>, forward slashes should be escaped in the output.
 	 * @param quoteChar The quote character to use (i.e. <js>'\''</js> or <js>'"'</js>)
 	 * @param laxMode If <jk>true</jk>, JSON attributes will only be quoted when necessary.
@@ -64,8 +63,8 @@ public final class JsonWriter extends SerializerWriter {
 	 * @param relativeUriBase The base (e.g. <js>https://localhost:9443/contextPath"</js>) for relative URIs (e.g. <js>"my/path"</js>).
 	 * @param absolutePathUriBase The base (e.g. <js>https://localhost:9443"</js>) for relative URIs with absolute paths (e.g. <js>"/contextPath/my/path"</js>).
 	 */
-	protected JsonWriter(Writer out, boolean useIndentation, boolean useWhitespace, boolean escapeSolidus, char quoteChar, boolean laxMode, boolean trimStrings, String relativeUriBase, String absolutePathUriBase) {
-		super(out, useIndentation, useWhitespace, trimStrings, quoteChar, relativeUriBase, absolutePathUriBase);
+	protected JsonWriter(Writer out, boolean useWhitespace, boolean escapeSolidus, char quoteChar, boolean laxMode, boolean trimStrings, String relativeUriBase, String absolutePathUriBase) {
+		super(out, useWhitespace, trimStrings, quoteChar, relativeUriBase, absolutePathUriBase);
 		this.laxMode = laxMode;
 		this.escapeSolidus = escapeSolidus;
 		this.ec = escapeSolidus ? encodedChars2 : encodedChars;
@@ -90,8 +89,6 @@ public final class JsonWriter extends SerializerWriter {
 		  */
 		if (s == null)
 			return this;
-//		if (trimStrings)
-//			s = s.trim();
 		boolean doConvert = false;
 		for (int i = 0; i < s.length() && ! doConvert; i++) {
 			char c = s.charAt(i);

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
index 0b15adc..08b80e4 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
@@ -53,7 +53,6 @@ public final class MsgPackParser extends InputStreamParser {
 		PojoSwap<T,Object> transform = (PojoSwap<T,Object>)eType.getPojoSwap();
 		ClassMeta<?> sType = eType.getSerializedClassMeta();
 		session.setCurrentClass(sType);
-		BeanRegistry breg = (pMeta == null ? session.getBeanRegistry() : pMeta.getBeanRegistry());
 
 		Object o = null;
 		DataType dt = is.readDataType();
@@ -83,7 +82,7 @@ public final class MsgPackParser extends InputStreamParser {
 				ObjectMap om = new ObjectMap(session);
 				for (int i = 0; i < length; i++)
 					om.put(parseAnything(session, string(), is, outer, pMeta), parseAnything(session, object(), is, om, pMeta));
-				o = breg.cast(om);
+				o = session.cast(om, pMeta, eType);
 			}
 
 			if (sType.isObject()) {
@@ -135,7 +134,7 @@ public final class MsgPackParser extends InputStreamParser {
 					ObjectMap m = new ObjectMap(session);
 					for (int i = 0; i < length; i++)
 						m.put(parseAnything(session, string(), is, outer, pMeta), parseAnything(session, object(), is, m, pMeta));
-					o = breg.cast(m);
+					o = session.cast(m, pMeta, eType);
 				} else if (dt == ARRAY) {
 					Collection l = (sType.canCreateNewInstance(outer) ? (Collection)sType.newInstance() : new ObjectList(session));
 					for (int i = 0; i < length; i++)
@@ -149,7 +148,7 @@ public final class MsgPackParser extends InputStreamParser {
 					ObjectMap m = new ObjectMap(session);
 					for (int i = 0; i < length; i++)
 						m.put(parseAnything(session, string(), is, outer, pMeta), parseAnything(session, object(), is, m, pMeta));
-					o = breg.cast(m);
+					o = session.cast(m, pMeta, eType);
 				} else if (dt == ARRAY) {
 					Collection l = (sType.isCollection() && sType.canCreateNewInstance(outer) ? (Collection)sType.newInstance() : new ObjectList(session));
 					for (int i = 0; i < length; i++)
@@ -163,7 +162,7 @@ public final class MsgPackParser extends InputStreamParser {
 				for (int i = 0; i < length; i++)
 					m.put(parseAnything(session, string(), is, outer, pMeta), parseAnything(session, object(), is, m, pMeta));
 				if (m.containsKey(session.getBeanTypePropertyName()))
-					o = breg.cast(m);
+					o = session.cast(m, pMeta, eType);
 				else
 					throw new ParseException(session, "Class ''{0}'' could not be instantiated.  Reason: ''{1}''", sType.getInnerClass().getName(), sType.getNotABeanReason());
 			} else {
@@ -204,277 +203,277 @@ public final class MsgPackParser extends InputStreamParser {
 	//--------------------------------------------------------------------------------
 
 	@Override /* Parser */
-	public Parser setTrimStrings(boolean value) throws LockedException {
+	public MsgPackParser setTrimStrings(boolean value) throws LockedException {
 		super.setTrimStrings(value);
 		return this;
 	}
 
 	@Override /* Parser */
-	public Parser setStrict(boolean value) throws LockedException {
+	public MsgPackParser setStrict(boolean value) throws LockedException {
 		super.setStrict(value);
 		return this;
 	}
 
 	@Override /* Parser */
-	public Parser setInputStreamCharset(String value) throws LockedException {
+	public MsgPackParser setInputStreamCharset(String value) throws LockedException {
 		super.setInputStreamCharset(value);
 		return this;
 	}
 
 	@Override /* Parser */
-	public Parser setFileCharset(String value) throws LockedException {
+	public MsgPackParser setFileCharset(String value) throws LockedException {
 		super.setFileCharset(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setBeansRequireDefaultConstructor(boolean value) throws LockedException {
+	public MsgPackParser setBeansRequireDefaultConstructor(boolean value) throws LockedException {
 		super.setBeansRequireDefaultConstructor(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setBeansRequireSerializable(boolean value) throws LockedException {
+	public MsgPackParser setBeansRequireSerializable(boolean value) throws LockedException {
 		super.setBeansRequireSerializable(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setBeansRequireSettersForGetters(boolean value) throws LockedException {
+	public MsgPackParser setBeansRequireSettersForGetters(boolean value) throws LockedException {
 		super.setBeansRequireSettersForGetters(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setBeansRequireSomeProperties(boolean value) throws LockedException {
+	public MsgPackParser setBeansRequireSomeProperties(boolean value) throws LockedException {
 		super.setBeansRequireSomeProperties(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setBeanMapPutReturnsOldValue(boolean value) throws LockedException {
+	public MsgPackParser setBeanMapPutReturnsOldValue(boolean value) throws LockedException {
 		super.setBeanMapPutReturnsOldValue(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setBeanConstructorVisibility(Visibility value) throws LockedException {
+	public MsgPackParser setBeanConstructorVisibility(Visibility value) throws LockedException {
 		super.setBeanConstructorVisibility(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setBeanClassVisibility(Visibility value) throws LockedException {
+	public MsgPackParser setBeanClassVisibility(Visibility value) throws LockedException {
 		super.setBeanClassVisibility(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setBeanFieldVisibility(Visibility value) throws LockedException {
+	public MsgPackParser setBeanFieldVisibility(Visibility value) throws LockedException {
 		super.setBeanFieldVisibility(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setMethodVisibility(Visibility value) throws LockedException {
+	public MsgPackParser setMethodVisibility(Visibility value) throws LockedException {
 		super.setMethodVisibility(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setUseJavaBeanIntrospector(boolean value) throws LockedException {
+	public MsgPackParser setUseJavaBeanIntrospector(boolean value) throws LockedException {
 		super.setUseJavaBeanIntrospector(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setUseInterfaceProxies(boolean value) throws LockedException {
+	public MsgPackParser setUseInterfaceProxies(boolean value) throws LockedException {
 		super.setUseInterfaceProxies(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setIgnoreUnknownBeanProperties(boolean value) throws LockedException {
+	public MsgPackParser setIgnoreUnknownBeanProperties(boolean value) throws LockedException {
 		super.setIgnoreUnknownBeanProperties(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setIgnoreUnknownNullBeanProperties(boolean value) throws LockedException {
+	public MsgPackParser setIgnoreUnknownNullBeanProperties(boolean value) throws LockedException {
 		super.setIgnoreUnknownNullBeanProperties(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setIgnorePropertiesWithoutSetters(boolean value) throws LockedException {
+	public MsgPackParser setIgnorePropertiesWithoutSetters(boolean value) throws LockedException {
 		super.setIgnorePropertiesWithoutSetters(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setIgnoreInvocationExceptionsOnGetters(boolean value) throws LockedException {
+	public MsgPackParser setIgnoreInvocationExceptionsOnGetters(boolean value) throws LockedException {
 		super.setIgnoreInvocationExceptionsOnGetters(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setIgnoreInvocationExceptionsOnSetters(boolean value) throws LockedException {
+	public MsgPackParser setIgnoreInvocationExceptionsOnSetters(boolean value) throws LockedException {
 		super.setIgnoreInvocationExceptionsOnSetters(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setSortProperties(boolean value) throws LockedException {
+	public MsgPackParser setSortProperties(boolean value) throws LockedException {
 		super.setSortProperties(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setNotBeanPackages(String...values) throws LockedException {
+	public MsgPackParser setNotBeanPackages(String...values) throws LockedException {
 		super.setNotBeanPackages(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setNotBeanPackages(Collection<String> values) throws LockedException {
+	public MsgPackParser setNotBeanPackages(Collection<String> values) throws LockedException {
 		super.setNotBeanPackages(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser addNotBeanPackages(String...values) throws LockedException {
+	public MsgPackParser addNotBeanPackages(String...values) throws LockedException {
 		super.addNotBeanPackages(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser addNotBeanPackages(Collection<String> values) throws LockedException {
+	public MsgPackParser addNotBeanPackages(Collection<String> values) throws LockedException {
 		super.addNotBeanPackages(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser removeNotBeanPackages(String...values) throws LockedException {
+	public MsgPackParser removeNotBeanPackages(String...values) throws LockedException {
 		super.removeNotBeanPackages(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser removeNotBeanPackages(Collection<String> values) throws LockedException {
+	public MsgPackParser removeNotBeanPackages(Collection<String> values) throws LockedException {
 		super.removeNotBeanPackages(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setNotBeanClasses(Class<?>...values) throws LockedException {
+	public MsgPackParser setNotBeanClasses(Class<?>...values) throws LockedException {
 		super.setNotBeanClasses(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setNotBeanClasses(Collection<Class<?>> values) throws LockedException {
+	public MsgPackParser setNotBeanClasses(Collection<Class<?>> values) throws LockedException {
 		super.setNotBeanClasses(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser addNotBeanClasses(Class<?>...values) throws LockedException {
+	public MsgPackParser addNotBeanClasses(Class<?>...values) throws LockedException {
 		super.addNotBeanClasses(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser addNotBeanClasses(Collection<Class<?>> values) throws LockedException {
+	public MsgPackParser addNotBeanClasses(Collection<Class<?>> values) throws LockedException {
 		super.addNotBeanClasses(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser removeNotBeanClasses(Class<?>...values) throws LockedException {
+	public MsgPackParser removeNotBeanClasses(Class<?>...values) throws LockedException {
 		super.removeNotBeanClasses(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser removeNotBeanClasses(Collection<Class<?>> values) throws LockedException {
+	public MsgPackParser removeNotBeanClasses(Collection<Class<?>> values) throws LockedException {
 		super.removeNotBeanClasses(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setBeanFilters(Class<?>...values) throws LockedException {
+	public MsgPackParser setBeanFilters(Class<?>...values) throws LockedException {
 		super.setBeanFilters(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setBeanFilters(Collection<Class<?>> values) throws LockedException {
+	public MsgPackParser setBeanFilters(Collection<Class<?>> values) throws LockedException {
 		super.setBeanFilters(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser addBeanFilters(Class<?>...values) throws LockedException {
+	public MsgPackParser addBeanFilters(Class<?>...values) throws LockedException {
 		super.addBeanFilters(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser addBeanFilters(Collection<Class<?>> values) throws LockedException {
+	public MsgPackParser addBeanFilters(Collection<Class<?>> values) throws LockedException {
 		super.addBeanFilters(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser removeBeanFilters(Class<?>...values) throws LockedException {
+	public MsgPackParser removeBeanFilters(Class<?>...values) throws LockedException {
 		super.removeBeanFilters(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser removeBeanFilters(Collection<Class<?>> values) throws LockedException {
+	public MsgPackParser removeBeanFilters(Collection<Class<?>> values) throws LockedException {
 		super.removeBeanFilters(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setPojoSwaps(Class<?>...values) throws LockedException {
+	public MsgPackParser setPojoSwaps(Class<?>...values) throws LockedException {
 		super.setPojoSwaps(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setPojoSwaps(Collection<Class<?>> values) throws LockedException {
+	public MsgPackParser setPojoSwaps(Collection<Class<?>> values) throws LockedException {
 		super.setPojoSwaps(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser addPojoSwaps(Class<?>...values) throws LockedException {
+	public MsgPackParser addPojoSwaps(Class<?>...values) throws LockedException {
 		super.addPojoSwaps(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser addPojoSwaps(Collection<Class<?>> values) throws LockedException {
+	public MsgPackParser addPojoSwaps(Collection<Class<?>> values) throws LockedException {
 		super.addPojoSwaps(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser removePojoSwaps(Class<?>...values) throws LockedException {
+	public MsgPackParser removePojoSwaps(Class<?>...values) throws LockedException {
 		super.removePojoSwaps(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser removePojoSwaps(Collection<Class<?>> values) throws LockedException {
+	public MsgPackParser removePojoSwaps(Collection<Class<?>> values) throws LockedException {
 		super.removePojoSwaps(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setImplClasses(Map<Class<?>,Class<?>> values) throws LockedException {
+	public MsgPackParser setImplClasses(Map<Class<?>,Class<?>> values) throws LockedException {
 		super.setImplClasses(values);
 		return this;
 	}
@@ -486,109 +485,109 @@ public final class MsgPackParser extends InputStreamParser {
 	}
 
 	@Override /* CoreApi */
-	public Parser setBeanDictionary(Class<?>...values) throws LockedException {
+	public MsgPackParser setBeanDictionary(Class<?>...values) throws LockedException {
 		super.setBeanDictionary(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setBeanDictionary(Collection<Class<?>> values) throws LockedException {
+	public MsgPackParser setBeanDictionary(Collection<Class<?>> values) throws LockedException {
 		super.setBeanDictionary(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser addToBeanDictionary(Class<?>...values) throws LockedException {
+	public MsgPackParser addToBeanDictionary(Class<?>...values) throws LockedException {
 		super.addToBeanDictionary(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser addToBeanDictionary(Collection<Class<?>> values) throws LockedException {
+	public MsgPackParser addToBeanDictionary(Collection<Class<?>> values) throws LockedException {
 		super.addToBeanDictionary(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser removeFromBeanDictionary(Class<?>...values) throws LockedException {
+	public MsgPackParser removeFromBeanDictionary(Class<?>...values) throws LockedException {
 		super.removeFromBeanDictionary(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser removeFromBeanDictionary(Collection<Class<?>> values) throws LockedException {
+	public MsgPackParser removeFromBeanDictionary(Collection<Class<?>> values) throws LockedException {
 		super.removeFromBeanDictionary(values);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setBeanTypePropertyName(String value) throws LockedException {
+	public MsgPackParser setBeanTypePropertyName(String value) throws LockedException {
 		super.setBeanTypePropertyName(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setDefaultParser(Class<?> value) throws LockedException {
+	public MsgPackParser setDefaultParser(Class<?> value) throws LockedException {
 		super.setDefaultParser(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setLocale(Locale value) throws LockedException {
+	public MsgPackParser setLocale(Locale value) throws LockedException {
 		super.setLocale(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setTimeZone(TimeZone value) throws LockedException {
+	public MsgPackParser setTimeZone(TimeZone value) throws LockedException {
 		super.setTimeZone(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setMediaType(MediaType value) throws LockedException {
+	public MsgPackParser setMediaType(MediaType value) throws LockedException {
 		super.setMediaType(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setDebug(boolean value) throws LockedException {
+	public MsgPackParser setDebug(boolean value) throws LockedException {
 		super.setDebug(value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setProperty(String name, Object value) throws LockedException {
+	public MsgPackParser setProperty(String name, Object value) throws LockedException {
 		super.setProperty(name, value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser setProperties(ObjectMap properties) throws LockedException {
+	public MsgPackParser setProperties(ObjectMap properties) throws LockedException {
 		super.setProperties(properties);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser addToProperty(String name, Object value) throws LockedException {
+	public MsgPackParser addToProperty(String name, Object value) throws LockedException {
 		super.addToProperty(name, value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser putToProperty(String name, Object key, Object value) throws LockedException {
+	public MsgPackParser putToProperty(String name, Object key, Object value) throws LockedException {
 		super.putToProperty(name, key, value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser putToProperty(String name, Object value) throws LockedException {
+	public MsgPackParser putToProperty(String name, Object value) throws LockedException {
 		super.putToProperty(name, value);
 		return this;
 	}
 
 	@Override /* CoreApi */
-	public Parser removeFromProperty(String name, Object value) throws LockedException {
+	public MsgPackParser removeFromProperty(String name, Object value) throws LockedException {
 		super.removeFromProperty(name, value);
 		return this;
 	}
@@ -599,7 +598,7 @@ public final class MsgPackParser extends InputStreamParser {
 	//--------------------------------------------------------------------------------
 
 	@Override /* CoreApi */
-	public Parser setClassLoader(ClassLoader classLoader) throws LockedException {
+	public MsgPackParser setClassLoader(ClassLoader classLoader) throws LockedException {
 		super.setClassLoader(classLoader);
 		return this;
 	}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
index 4ce103d..cd842d6 100644
--- a/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
@@ -57,7 +57,6 @@ public class MsgPackSerializer extends OutputStreamSerializer {
 		if (eType == null)
 			eType = object();
 
-		boolean addTypeProperty;		// Add "_type" attribute to element?
 		ClassMeta<?> aType;			// The actual type
 		ClassMeta<?> sType;			// The serialized type
 
@@ -71,7 +70,7 @@ public class MsgPackSerializer extends OutputStreamSerializer {
 		}
 
 		sType = aType.getSerializedClassMeta();
-		addTypeProperty = (session.isAddBeanTypeProperties() && ! eType.equals(aType));
+		String typeName = session.getBeanTypeName(eType, aType, pMeta);
 
 		// Swap if necessary
 		PojoSwap swap = aType.getPojoSwap();
@@ -92,12 +91,12 @@ public class MsgPackSerializer extends OutputStreamSerializer {
 		else if (sType.isNumber())
 			out.appendNumber((Number)o);
 		else if (sType.isBean())
-			serializeBeanMap(session, out, session.toBeanMap(o), addTypeProperty);
+			serializeBeanMap(session, out, session.toBeanMap(o), typeName);
 		else if (sType.isUri() || (pMeta != null && pMeta.isUri()))
 			out.appendString(session.resolveUri(o.toString()));
 		else if (sType.isMap()) {
 			if (o instanceof BeanMap)
-				serializeBeanMap(session, out, (BeanMap)o, addTypeProperty);
+				serializeBeanMap(session, out, (BeanMap)o, typeName);
 			else
 				serializeMap(session, out, (Map)o, eType);
 		}
@@ -138,9 +137,9 @@ public class MsgPackSerializer extends OutputStreamSerializer {
 		}
 	}
 
-	private void serializeBeanMap(MsgPackSerializerSession session, MsgPackOutputStream out, final BeanMap<?> m, boolean addTypeProperty) throws Exception {
+	private void serializeBeanMap(MsgPackSerializerSession session, MsgPackOutputStream out, final BeanMap<?> m, String typeName) throws Exception {
 
-		List<BeanPropertyValue> values = m.getValues(session.isTrimNulls(), addTypeProperty ? session.createBeanTypeNameProperty(m) : null);
+		List<BeanPropertyValue> values = m.getValues(session.isTrimNulls(), typeName != null ? session.createBeanTypeNameProperty(m, typeName) : null);
 
 		int size = values.size();
 		for (BeanPropertyValue p : values)
@@ -234,8 +233,8 @@ public class MsgPackSerializer extends OutputStreamSerializer {
 	}
 
 	@Override /* Serializer */
-	public MsgPackSerializer setUseIndentation(boolean value) throws LockedException {
-		super.setUseIndentation(value);
+	public MsgPackSerializer setUseWhitespace(boolean value) throws LockedException {
+		super.setUseWhitespace(value);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
index 6f2247b..3d9fa30 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserGroup.java
@@ -78,7 +78,7 @@ public final class ParserGroup extends Lockable {
 	 */
 	public ParserGroup append(Parser p) {
 		checkLock();
-		synchronized(parsers) {
+		synchronized(this) {
 			cache.clear();
 			parsers.add(0, p);
 		}
@@ -110,7 +110,7 @@ public final class ParserGroup extends Lockable {
 			append(p.newInstance());
 		} catch (NoClassDefFoundError e) {
 			// Ignore if dependent library not found (e.g. Jena).
-			System.err.println(e);
+			System.err.println(e); // NOT DEBUG
 		}
 		return this;
 	}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/parser/ParserReader.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserReader.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserReader.java
index 07f21fe..de3187a 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserReader.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserReader.java
@@ -109,6 +109,20 @@ public class ParserReader extends Reader {
 	}
 
 	/**
+	 * Same as {@link #read()} but skips over any whitespace characters.
+	 *
+	 * @return The first non-whitespace character, or -1 if the end of stream reached.
+	 * @throws IOException
+	 */
+	public final int readSkipWs() throws IOException {
+		while (true) {
+			int c = read();
+			if (c == -1 || ! Character.isWhitespace(c))
+				return c;
+		}
+	}
+
+	/**
 	 * Same as {@link #read()} but detects and combines extended unicode characters (i.e. characters
 	 * 	above 0x10000).
 	 *
@@ -205,7 +219,7 @@ public class ParserReader extends Reader {
 	/**
 	 * Peeks the next character in the stream.
 	 * <p>
-	 * 	This is equivalent to doing a {@code read()} followed by an {@code unread()}.
+	 * This is equivalent to doing a {@code read()} followed by an {@code unread()}.
 	 *
 	 * @return The peeked character, or (char)-1 if the end of the stream has been reached.
 	 * @throws IOException If a problem occurred trying to read from the reader.
@@ -218,6 +232,25 @@ public class ParserReader extends Reader {
 	}
 
 	/**
+	 * Same as {@link #peek()} but skips over any whitespace characters.
+	 * <p>
+	 * This is equivalent to doing a {@code read()} followed by an {@code unread()}.
+	 *
+	 * @return The peeked character, or (char)-1 if the end of the stream has been reached.
+	 * @throws IOException If a problem occurred trying to read from the reader.
+	 */
+	public final int peekSkipWs() throws IOException {
+		while(true) {
+			int c = read();
+			boolean isWs = Character.isWhitespace(c);
+			if (c != -1 && ! isWs)
+				unread();
+			if (! isWs)
+				return c;
+		}
+	}
+
+	/**
 	 * Read the specified number of characters off the stream.
 	 *
 	 * @param num The number of characters to read.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java b/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
index e471056..8a4a87b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/parser/ParserSession.java
@@ -20,6 +20,7 @@ import java.nio.charset.*;
 import java.util.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.internal.*;
 
 /**
  * Session object that lives for the duration of a single use of {@link Parser}.
@@ -103,6 +104,8 @@ public class ParserSession extends BeanSession {
 			return (InputStream)input;
 		if (input instanceof byte[])
 			return new ByteArrayInputStream((byte[])input);
+		if (input instanceof String)
+			return new ByteArrayInputStream(StringUtils.fromHex((String)input));
 		if (input instanceof File)
 			try {
 				inputStream = new FileInputStream((File)input);
@@ -269,6 +272,77 @@ public class ParserSession extends BeanSession {
 	}
 
 	/**
+	 * Converts the specified <code>ObjectMap</code> into a bean identified by the <js>"_type"</js>
+	 * property in the map.
+	 *
+	 * @param m The map to convert to a bean.
+	 * @param pMeta The current bean property being parsed.
+	 * @param eType The current expected type being parsed.
+	 * @return The converted bean, or the same map if the <js>"_type"</js> entry wasn't found
+	 * 	or didn't resolve to a bean.
+	 */
+	public final Object cast(ObjectMap m, BeanPropertyMeta pMeta, ClassMeta<?> eType) {
+
+		String btpn = getBeanTypePropertyName();
+
+		Object o = m.get(btpn);
+		if (o == null)
+			return m;
+		String typeName = o.toString();
+
+		ClassMeta<?> cm = getClassMeta(typeName, pMeta, eType);
+
+		if (cm != null) {
+			BeanMap<?> bm = m.getBeanSession().newBeanMap(cm.getInnerClass());
+
+			// Iterate through all the entries in the map and set the individual field values.
+			for (Map.Entry<String,Object> e : m.entrySet()) {
+				String k = e.getKey();
+				Object v = e.getValue();
+				if (! k.equals(btpn)) {
+					// Attempt to recursively cast child maps.
+					if (v instanceof ObjectMap)
+						v = cast((ObjectMap)v, pMeta, eType);
+					bm.put(k, v);
+				}
+			}
+			return bm.getBean();
+		}
+
+		return m;
+	}
+
+	/**
+	 * Give the specified dictionary name, resolve it to a class.
+	 *
+	 * @param typeName The dictionary name to resolve.
+	 * @param pMeta The bean property we're currently parsing.
+	 * @param eType The expected type we're currently parsing.
+	 * @return The resolved class, or <jk>null</jk> if the type name could not be resolved.
+	 */
+	public final ClassMeta<?> getClassMeta(String typeName, BeanPropertyMeta pMeta, ClassMeta<?> eType) {
+		BeanRegistry br = null;
+
+		// Resolve via @BeanProperty(beanDictionary={})
+		if (pMeta != null) {
+			br = pMeta.getBeanRegistry();
+			if (br != null && br.hasName(typeName))
+				return br.getClassMeta(typeName);
+		}
+
+		// Resolve via @Bean(beanDictionary={}) on the expected type where the
+		// expected type is an interface with subclasses.
+		if (eType != null) {
+			br = eType.getBeanRegistry();
+			if (br != null && br.hasName(typeName))
+				return br.getClassMeta(typeName);
+		}
+
+		// Last resort, resolve using the session registry.
+		return getBeanRegistry().getClassMeta(typeName);
+	}
+
+	/**
 	 * Perform cleanup on this context object if necessary.
 	 */
 	@Override

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/serializer/OutputStreamSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/OutputStreamSerializer.java b/juneau-core/src/main/java/org/apache/juneau/serializer/OutputStreamSerializer.java
index 0c8f215..0901c14 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/OutputStreamSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/OutputStreamSerializer.java
@@ -15,6 +15,7 @@ package org.apache.juneau.serializer;
 import java.io.*;
 
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.internal.*;
 
 /**
  * Subclass of {@link Serializer} for byte-based serializers.
@@ -50,7 +51,7 @@ public abstract class OutputStreamSerializer extends Serializer {
 	 * Convenience method for serializing an object to a <code><jk>byte</jk></code>.
 	 *
 	 * @param o The object to serialize.
-	 * @return The output serialized to a string.
+	 * @return The output serialized to a byte array.
 	 * @throws SerializeException If a problem occurred trying to convert the output.
 	 */
 	@Override
@@ -59,4 +60,17 @@ public abstract class OutputStreamSerializer extends Serializer {
 		serialize(createSession(baos), o);
 		return baos.toByteArray();
 	}
+
+	/**
+	 * 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 {
+		ByteArrayOutputStream baos = new ByteArrayOutputStream();
+		serialize(createSession(baos), o);
+		return StringUtils.toHex(baos.toByteArray());
+	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java b/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java
index ac43ecb..313ff47 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/Serializer.java
@@ -413,30 +413,29 @@ public abstract class Serializer extends CoreApi {
 	}
 
 	/**
-	 * <b>Configuration property:</b>  Use indentation.
+	 * <b>Configuration property:</b>  Use whitespace.
 	 * <p>
 	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.useIndentation"</js>
+	 * 	<li><b>Name:</b> <js>"Serializer.useWhitepace"</js>
 	 * 	<li><b>Data type:</b> <code>Boolean</code>
 	 * 	<li><b>Default:</b> <jk>false</jk>
 	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
 	 * </ul>
 	 * <p>
-	 * If <jk>true</jk>, newlines and indentation is added to the output to improve readability.
+	 * If <jk>true</jk>, newlines and indentation and spaces are added to the output to improve readability.
 	 * <p>
 	 * <h5 class='section'>Notes:</h5>
 	 * <ul>
-	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_useIndentation</jsf>, value)</code>.
-	 * 	<li>Checking for recursion can cause a small performance penalty.
+	 * 	<li>This is equivalent to calling <code>setProperty(<jsf>SERIALIZER_useWhitespace</jsf>, value)</code>.
 	 * </ul>
 	 *
 	 * @param value The new value for this property.
 	 * @return This object (for method chaining).
 	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_useIndentation
+	 * @see SerializerContext#SERIALIZER_useWhitespace
 	 */
-	public Serializer setUseIndentation(boolean value) throws LockedException {
-		return setProperty(SERIALIZER_useIndentation, value);
+	public Serializer setUseWhitespace(boolean value) throws LockedException {
+		return setProperty(SERIALIZER_useWhitespace, value);
 	}
 
 	/**

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
index 7abdd45..38fdfef 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerContext.java
@@ -98,18 +98,18 @@ public class SerializerContext extends BeanContext {
 	public static final String SERIALIZER_ignoreRecursions = "Serializer.ignoreRecursions";
 
 	/**
-	 * <b>Configuration property:</b>  Use indentation.
+	 * <b>Configuration property:</b>  Use whitespace.
 	 * <p>
 	 * <ul>
-	 * 	<li><b>Name:</b> <js>"Serializer.useIndentation"</js>
+	 * 	<li><b>Name:</b> <js>"Serializer.useWhitespace"</js>
 	 * 	<li><b>Data type:</b> <code>Boolean</code>
 	 * 	<li><b>Default:</b> <jk>false</jk>
 	 * 	<li><b>Session-overridable:</b> <jk>true</jk>
 	 * </ul>
 	 * <p>
-	 * If <jk>true</jk>, newlines and indentation is added to the output to improve readability.
+	 * If <jk>true</jk>, whitespace is added to the output to improve readability.
 	 */
-	public static final String SERIALIZER_useIndentation = "Serializer.useIndentation";
+	public static final String SERIALIZER_useWhitespace = "Serializer.useWhitespace";
 
 	/**
 	 * <b>Configuration property:</b>  Add <js>"_type"</js> properties when needed.
@@ -318,7 +318,7 @@ public class SerializerContext extends BeanContext {
 	final boolean
 		detectRecursions,
 		ignoreRecursions,
-		useIndentation,
+		useWhitespace,
 		addBeanTypeProperties,
 		trimNulls,
 		trimEmptyCollections,
@@ -340,8 +340,8 @@ public class SerializerContext extends BeanContext {
 		initialDepth = cf.getProperty(SERIALIZER_initialDepth, int.class, 0);
 		detectRecursions = cf.getProperty(SERIALIZER_detectRecursions, boolean.class, false);
 		ignoreRecursions = cf.getProperty(SERIALIZER_ignoreRecursions, boolean.class, false);
-		useIndentation = cf.getProperty(SERIALIZER_useIndentation, boolean.class, false);
-		addBeanTypeProperties = cf.getProperty(SERIALIZER_addBeanTypeProperties, boolean.class, false);
+		useWhitespace = cf.getProperty(SERIALIZER_useWhitespace, boolean.class, false);
+		addBeanTypeProperties = cf.getProperty(SERIALIZER_addBeanTypeProperties, boolean.class, true);
 		trimNulls = cf.getProperty(SERIALIZER_trimNullProperties, boolean.class, true);
 		trimEmptyCollections = cf.getProperty(SERIALIZER_trimEmptyCollections, boolean.class, false);
 		trimEmptyMaps = cf.getProperty(SERIALIZER_trimEmptyMaps, boolean.class, false);
@@ -379,7 +379,7 @@ public class SerializerContext extends BeanContext {
 				.append("initialDepth", initialDepth)
 				.append("detectRecursions", detectRecursions)
 				.append("ignoreRecursions", ignoreRecursions)
-				.append("useIndentation", useIndentation)
+				.append("useWhitespace", useWhitespace)
 				.append("addBeanTypeProperties", addBeanTypeProperties)
 				.append("trimNulls", trimNulls)
 				.append("trimEmptyCollections", trimEmptyCollections)

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
index 63f0400..d2d6847 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerGroup.java
@@ -51,7 +51,7 @@ import org.apache.juneau.*;
  * 	g.append(JsonSerializer.<jk>class</jk>, XmlSerializer.<jk>class</jk>);
  *
  * 	<jc>// Change settings for all serializers in the group and lock it.</jc>
- * 	g.setProperty(SerializerContext.<jsf>SERIALIZER_useIndentation</jsf>, <jk>true</jk>)
+ * 	g.setProperty(SerializerContext.<jsf>SERIALIZER_useWhitespace</jsf>, <jk>true</jk>)
  * 		.addPojoSwaps(CalendarSwap.ISO8601DT.<jk>class</jk>)
  * 		.lock();
  *
@@ -79,7 +79,7 @@ public final class SerializerGroup extends Lockable {
 	 */
 	public SerializerGroup append(Serializer s) {
 		checkLock();
-		synchronized(serializers) {
+		synchronized(this) {
 			cache.clear();
 			serializers.add(0, s);
 		}
@@ -111,7 +111,7 @@ public final class SerializerGroup extends Lockable {
 			append(s.newInstance());
 		} catch (NoClassDefFoundError e) {
 			// Ignore if dependent library not found (e.g. Jena).
-			System.err.println(e);
+			System.err.println(e); // NOT DEBUG
 		}
 		return this;
 	}
@@ -303,17 +303,17 @@ public final class SerializerGroup extends Lockable {
 	}
 
 	/**
-	 * Calls {@link Serializer#setUseIndentation(boolean)} on all serializers in this group.
+	 * Calls {@link Serializer#setUseWhitespace(boolean)} on all serializers in this group.
 	 *
 	 * @param value The new value for this property.
 	 * @return This object (for method chaining).
 	 * @throws LockedException If {@link #lock()} was called on this class.
-	 * @see SerializerContext#SERIALIZER_useIndentation
+	 * @see SerializerContext#SERIALIZER_useWhitespace
 	 */
-	public SerializerGroup setUseIndentation(boolean value) throws LockedException {
+	public SerializerGroup setUseWhitespace(boolean value) throws LockedException {
 		checkLock();
 		for (Serializer s : serializers)
-			s.setUseIndentation(value);
+			s.setUseWhitespace(value);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
index 1ad5ee5..7d499e6 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerSession.java
@@ -20,7 +20,6 @@ import java.lang.reflect.*;
 import java.util.*;
 
 import org.apache.juneau.*;
-import org.apache.juneau.MediaType;
 import org.apache.juneau.internal.*;
 import org.apache.juneau.transform.*;
 
@@ -43,7 +42,7 @@ public class SerializerSession extends BeanSession {
 	private final boolean
 		detectRecursions,
 		ignoreRecursions,
-		useIndentation,
+		useWhitespace,
 		addBeanTypeProperties,
 		trimNulls,
 		trimEmptyCollections,
@@ -103,7 +102,7 @@ public class SerializerSession extends BeanSession {
 			initialDepth = ctx.initialDepth;
 			detectRecursions = ctx.detectRecursions;
 			ignoreRecursions = ctx.ignoreRecursions;
-			useIndentation = ctx.useIndentation;
+			useWhitespace = ctx.useWhitespace;
 			addBeanTypeProperties = ctx.addBeanTypeProperties;
 			trimNulls = ctx.trimNulls;
 			trimEmptyCollections = ctx.trimEmptyCollections;
@@ -119,7 +118,7 @@ public class SerializerSession extends BeanSession {
 			initialDepth = op.getInt(SERIALIZER_initialDepth, ctx.initialDepth);
 			detectRecursions = op.getBoolean(SERIALIZER_detectRecursions, ctx.detectRecursions);
 			ignoreRecursions = op.getBoolean(SERIALIZER_ignoreRecursions, ctx.ignoreRecursions);
-			useIndentation = op.getBoolean(SERIALIZER_useIndentation, ctx.useIndentation);
+			useWhitespace = op.getBoolean(SERIALIZER_useWhitespace, ctx.useWhitespace);
 			addBeanTypeProperties = op.getBoolean(SERIALIZER_addBeanTypeProperties, ctx.addBeanTypeProperties);
 			trimNulls = op.getBoolean(SERIALIZER_trimNullProperties, ctx.trimNulls);
 			trimEmptyCollections = op.getBoolean(SERIALIZER_trimEmptyCollections, ctx.trimEmptyCollections);
@@ -273,12 +272,12 @@ public class SerializerSession extends BeanSession {
 	}
 
 	/**
-	 * Returns the {@link SerializerContext#SERIALIZER_useIndentation} setting value for this session.
+	 * Returns the {@link SerializerContext#SERIALIZER_useWhitespace} setting value for this session.
 	 *
-	 * @return The {@link SerializerContext#SERIALIZER_useIndentation} setting value for this session.
+	 * @return The {@link SerializerContext#SERIALIZER_useWhitespace} setting value for this session.
 	 */
-	public final boolean isUseIndentation() {
-		return useIndentation;
+	public final boolean isUseWhitespace() {
+		return useWhitespace;
 	}
 
 	/**
@@ -682,16 +681,63 @@ public class SerializerSession extends BeanSession {
 	/**
 	 * Create a "_type" property that contains the dictionary name of the bean.
 	 *
-	 * @param m
-	 * 	The bean map to create a class property on.
-	 * @return
-	 * 	A new bean property value.
+	 * @param m The bean map to create a class property on.
+	 * @param typeName The type name of the bean.
+	 * @return A new bean property value.
 	 */
-	public BeanPropertyValue createBeanTypeNameProperty(BeanMap<?> m) {
+	public BeanPropertyValue createBeanTypeNameProperty(BeanMap<?> m, String typeName) {
 		BeanMeta<?> bm = m.getMeta();
-		String name = bm.getClassMeta().getDictionaryName();
-		if (name == null)
+		return new BeanPropertyValue(bm.getTypeProperty(), typeName, null);
+	}
+
+	/**
+	 * Resolves the dictionary name for the actual type.
+	 *
+	 * @param eType The expected type of the bean property.
+	 * @param aType The actual type of the bean property.
+	 * @param pMeta The current bean property being serialized.
+	 * @return The bean dictionary name, or <jk>null</jk> if a name could not be found.
+	 */
+	public String getBeanTypeName(ClassMeta<?> eType, ClassMeta<?> aType, BeanPropertyMeta pMeta) {
+		if (eType == aType)
 			return null;
-		return new BeanPropertyValue(bm.getTypeProperty(), name, null);
+
+		if (! addBeanTypeProperties)
+			return null;
+
+		String eTypeTn = eType.getDictionaryName();
+
+		// First see if it's defined on the actual type.
+		String tn = aType.getDictionaryName();
+		if (tn != null && ! tn.equals(eTypeTn)) {
+			return tn;
+		}
+
+		// Then see if it's defined on the expected type.
+		// The expected type might be an interface with mappings for implementation classes.
+		BeanRegistry br = eType.getBeanRegistry();
+		if (br != null) {
+			tn = br.getTypeName(aType);
+			if (tn != null && ! tn.equals(eTypeTn))
+				return tn;
+		}
+
+		// Then look on the bean property.
+		br = pMeta == null ? null : pMeta.getBeanRegistry();
+		if (br != null) {
+			tn = br.getTypeName(aType);
+			if (tn != null && ! tn.equals(eTypeTn))
+				return tn;
+		}
+
+		// Finally look in the session.
+		br = getBeanRegistry();
+		if (br != null) {
+			tn = br.getTypeName(aType);
+			if (tn != null && ! tn.equals(eTypeTn))
+				return tn;
+		}
+
+		return null;
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerWriter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerWriter.java b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerWriter.java
index 00f8b8b..1e6272b 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerWriter.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/SerializerWriter.java
@@ -33,9 +33,6 @@ public class SerializerWriter extends Writer {
 	/** The underlying writer. */
 	protected final Writer out;
 
-	/** Use-indentation flag. */
-	protected final boolean useIndentation;
-
 	/** Use-whitespace flag. */
 	protected final boolean useWhitespace;
 
@@ -53,16 +50,14 @@ public class SerializerWriter extends Writer {
 
 	/**
 	 * @param out The writer being wrapped.
-	 * @param useIndentation If <jk>true</jk>, calling {@link #cr(int)} will create an indentation.
-	 * @param useWhitespace If <jk>true</jk>, calling {@link #s()} will write a space character.
+	 * @param useWhitespace If <jk>true</jk>, calling {@link #cr(int)} will create an indentation and calling {@link #s()} will write a space character.
 	 * @param trimStrings If <jk>true</jk>, strings should be trimmed before they're serialized.
 	 * @param quoteChar The character to write when {@link #q()} is called.
 	 * @param relativeUriBase The base (e.g. <js>https://localhost:9443/contextPath"</js>) for relative URIs (e.g. <js>"my/path"</js>).
 	 * @param absolutePathUriBase The base (e.g. <js>https://localhost:9443"</js>) for relative URIs with absolute paths (e.g. <js>"/contextPath/my/path"</js>).
 	 */
-	public SerializerWriter(Writer out, boolean useIndentation, boolean useWhitespace, boolean trimStrings, char quoteChar, String relativeUriBase, String absolutePathUriBase) {
+	public SerializerWriter(Writer out, boolean useWhitespace, boolean trimStrings, char quoteChar, String relativeUriBase, String absolutePathUriBase) {
 		this.out = out;
-		this.useIndentation = useIndentation;
 		this.useWhitespace = useWhitespace;
 		this.trimStrings = trimStrings;
 		this.quoteChar = quoteChar;
@@ -73,21 +68,21 @@ public class SerializerWriter extends Writer {
 	/**
 	 * Performs a carriage return.
 	 * <p>
-	 * 	Adds a newline and the specified number of tabs (if the {@code useIndentation} setting is enabled) to the output.
+	 * 	Adds a newline and the specified number of tabs (if the {@code useWhitespace} setting is enabled) to the output.
 	 *
 	 * @param depth The indentation.
 	 * @throws IOException If a problem occurred trying to write to the writer.
 	 * @return This object (for method chaining).
 	 */
 	public SerializerWriter cr(int depth) throws IOException {
-		if (useIndentation)
+		if (useWhitespace)
 			return nl().i(depth);
 		return this;
 	}
 
 	/**
-	 * Writes an indent (if the {@code useIndentation} setting is enabled), followed by text,
-	 * 	followed by a newline (if the {@code useIndentation} setting is enabled).
+	 * Writes an indent (if the {@code useWhitespace} setting is enabled), followed by text,
+	 * 	followed by a newline (if the {@code useWhitespace} setting is enabled).
 	 *
 	 * @param indent The number of tabs to indent.
 	 * @param text The text to write.
@@ -99,7 +94,7 @@ public class SerializerWriter extends Writer {
 	}
 
 	/**
-	 * Writes the specified text followed by a newline (if the {@code useIndentation} setting is enabled).
+	 * Writes the specified text followed by a newline (if the {@code useWhitespace} setting is enabled).
 	 *
 	 * @param text The text to write.
 	 * @throws IOException If a problem occurred trying to write to the writer.
@@ -110,7 +105,7 @@ public class SerializerWriter extends Writer {
 	}
 
 	/**
-	 * Writes an indent (if the {@code useIndentation} setting is enabled), followed by text.
+	 * Writes an indent (if the {@code useWhitespace} setting is enabled), followed by text.
 	 *
 	 * @param indent The number of tabs to indent.
 	 * @param text The text to write.
@@ -122,7 +117,7 @@ public class SerializerWriter extends Writer {
 	}
 
 	/**
-	 * Writes an indent (if the {@code useIndentation} setting is enabled), followed by text.
+	 * Writes an indent (if the {@code useWhitespace} setting is enabled), followed by text.
 	 *
 	 * @param indent The number of tabs to indent.
 	 * @param c The character to write.
@@ -134,8 +129,8 @@ public class SerializerWriter extends Writer {
 	}
 
 	/**
-	 * Writes an indent (if the {@code useIndentation} setting is enabled), followed by text,
-	 * 	optionally followed by a newline (if the {@code useIndentation} setting is enabled).
+	 * Writes an indent (if the {@code useWhitespace} setting is enabled), followed by text,
+	 * 	optionally followed by a newline (if the {@code useWhitespace} setting is enabled).
 	 *
 	 * @param indent The number of tabs to indent.
 	 * @param newline If <jk>true</jk>, then a newline is written.
@@ -222,40 +217,40 @@ public class SerializerWriter extends Writer {
 	}
 
 	/**
-	 * Writes an indent to the writer if the {@code useIndentation} setting is enabled.
+	 * Writes an indent to the writer if the {@code useWhitespace} setting is enabled.
 	 *
 	 * @param indent The number of tabs to indent.
 	 * @throws IOException If a problem occurred trying to write to the writer.
 	 * @return This object (for method chaining).
 	 */
 	public SerializerWriter i(int indent) throws IOException {
-		if (useIndentation)
+		if (useWhitespace)
 			for (int i = 0; i < indent; i++)
 				out.write('\t');
 		return this;
 	}
 
 	/**
-	 * Writes a newline to the writer if the {@code useIndentation} setting is enabled.
+	 * Writes a newline to the writer if the {@code useWhitespace} setting is enabled.
 	 *
 	 * @throws IOException If a problem occurred trying to write to the writer.
 	 * @return This object (for method chaining).
 	 */
 	public SerializerWriter nl() throws IOException {
-		if (useIndentation)
+		if (useWhitespace)
 			out.write('\n');
 		return this;
 	}
 
 	/**
-	 * Writes a newline to the writer if the {@code useIndentation} setting is enabled and the boolean flag is true.
+	 * Writes a newline to the writer if the {@code useWhitespace} setting is enabled and the boolean flag is true.
 	 *
 	 * @param b The boolean flag.
 	 * @return This object (for method chaining).
 	 * @throws IOException If a problem occurred trying to write to the writer.
 	 */
 	public SerializerWriter nlIf(boolean b) throws IOException {
-		if (b && useIndentation)
+		if (b && useWhitespace)
 			out.write('\n');
 		return this;
 	}

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java b/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
index 27aa39c..8a38a88 100644
--- a/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
+++ b/juneau-core/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
@@ -99,7 +99,7 @@ public abstract class WriterSerializer extends Serializer {
 	 * @return This object (for method chaining).
 	 */
 	public final WriterSerializer println(Object o) {
-		System.out.println(toString(o));
+		System.out.println(toString(o));  // NOT DEBUG
 		return this;
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java b/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java
index a194286..76c8dc0 100644
--- a/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/AnnotationBeanFilterBuilder.java
@@ -32,10 +32,10 @@ public final class AnnotationBeanFilterBuilder extends BeanFilterBuilder {
 	 * @param annotations The {@link Bean @Bean} annotations found on the class and all parent classes in child-to-parent order.
 	 * @throws Exception Thrown from property namer constructor.
 	 */
-	public AnnotationBeanFilterBuilder(Class<?> annotatedClass, List<Bean> annotations) throws Exception {
+	public AnnotationBeanFilterBuilder(Class<?> annotatedClass, Map<Class<?>,Bean> annotations) throws Exception {
 		super(annotatedClass);
 
-		ListIterator<Bean> li = annotations.listIterator(annotations.size());
+		ListIterator<Bean> li = new ArrayList<Bean>(annotations.values()).listIterator(annotations.size());
 		while (li.hasPrevious()) {
 			Bean b = li.previous();
 
@@ -60,19 +60,8 @@ public final class AnnotationBeanFilterBuilder extends BeanFilterBuilder {
 			if (b.stopClass() != Object.class)
 				setStopClass(b.stopClass());
 
-			if (b.subTypes().length > 0) {
-				setSubTypeProperty(b.subTypeProperty());
-
-				for (Class<?> bst : b.subTypes()) {
-					Bean b2 = bst.getAnnotation(Bean.class);
-					String name = null;
-					if (! b2.typeName().isEmpty())
-						name = b2.typeName();
-					else
-						name = bst.getSimpleName();
-					addSubType(name, bst);
-				}
-			}
+			if (b.beanDictionary().length > 0)
+				addToBeanDictionary(b.beanDictionary());
 		}
 	}
 }

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilter.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilter.java b/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilter.java
index b4fc90e..3817910 100644
--- a/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilter.java
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilter.java
@@ -12,8 +12,6 @@
 // ***************************************************************************************************************************
 package org.apache.juneau.transform;
 
-import java.util.*;
-
 import org.apache.juneau.*;
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.internal.*;
@@ -31,12 +29,11 @@ public class BeanFilter {
 
 	private final Class<?> beanClass;
 	private final String[] properties, excludeProperties;
-	private final Map<Class<?>, String> subTypes;
-	private final String subTypeAttr;
 	private final PropertyNamer propertyNamer;
 	private final Class<?> interfaceClass, stopClass;
 	private final boolean sortProperties;
 	private final String typeName;
+	private final Class<?>[] beanDictionary;
 
 	/**
 	 * Constructor.
@@ -50,8 +47,7 @@ public class BeanFilter {
 		this.stopClass = builder.stopClass;
 		this.sortProperties = builder.sortProperties;
 		this.propertyNamer = builder.propertyNamer;
-		this.subTypeAttr = builder.subTypeProperty;
-		this.subTypes = builder.subTypes == null ? null : Collections.unmodifiableMap(builder.subTypes);
+		this.beanDictionary = builder.beanDictionary == null ? null : builder.beanDictionary.toArray(new Class<?>[builder.beanDictionary.size()]);
 	}
 
 	/**
@@ -80,6 +76,15 @@ public class BeanFilter {
 	}
 
 	/**
+	 * Returns the bean dictionary defined on this bean.
+	 *
+	 * @return The bean dictionary defined on this bean, or <jk>null</jk> if no bean dictionary is defined.
+	 */
+	public Class<?>[] getBeanDictionary() {
+		return beanDictionary;
+	}
+
+	/**
 	 * Returns <jk>true</jk> if the properties defined on this bean class should be ordered alphabetically.
 	 * <p>
 	 * 	This method is only used when the {@link #getProperties()} method returns <jk>null</jk>.
@@ -110,24 +115,6 @@ public class BeanFilter {
 	}
 
 	/**
-	 * Returns the name of the sub type property associated with the bean class.
-	 *
-	 * @return The sub type property name, or <jk>null</jk> if bean has no subtypes defined.
-	 */
-	public String getSubTypeProperty() {
-		return subTypeAttr;
-	}
-
-	/**
-	 * Returns the subtypes associated with the bean class.
-	 *
-	 * @return The set of sub types associated with this bean class, or <jk>null</jk> if bean has no subtypes defined.
-	 */
-	public Map<Class<?>, String> getSubTypes() {
-		return subTypes;
-	}
-
-	/**
 	 * Returns the interface class associated with this class.
 	 *
 	 * @return The interface class associated with this class, or <jk>null</jk> if no interface class is associated.

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java b/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java
index 6c2928f..b56ce30 100644
--- a/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/BeanFilterBuilder.java
@@ -51,8 +51,7 @@ public abstract class BeanFilterBuilder {
 	Class<?> interfaceClass, stopClass;
 	boolean sortProperties;
 	PropertyNamer propertyNamer;
-	String subTypeProperty;
-	Map<Class<?>,String> subTypes;
+	List<Class<?>> beanDictionary;
 
 	/**
 	 * Constructor.
@@ -205,87 +204,16 @@ public abstract class BeanFilterBuilder {
 	}
 
 	/**
-	 * Defines a virtual property on a superclass that identifies bean subtype classes.
-	 * <p>
-	 * In the following example, the abstract class has two subclasses that are differentiated
-	 * 	by a property called <code>subType</code>
-	 *
-	 * <p class='bcode'>
-	 * 	<jc>// Abstract superclass</jc>
-	 * 	<jk>public abstract class</jk> A {
-	 * 		<jk>public</jk> String <jf>f0</jf> = <js>"f0"</js>;
-	 * 	}
-	 *
-	 * 	<jc>// Subclass 1</jc>
-	 * 	<jk>public class</jk> A1 <jk>extends</jk> A {
-	 * 		<jk>public</jk> String <jf>f1</jf>;
-	 * 	}
-	 *
-	 * 	<jc>// Subclass 2</jc>
-	 * 	<jk>public class</jk> A2 <jk>extends</jk> A {
-	 * 		<jk>public</jk> String <jf>f2</jf>;
-	 * 	}
-	 *
-	 * 	<jc>// Filter for defining subtypes</jc>
-	 * 	<jk>public class</jk> AFilter <jk>extends</jk> BeanFilterBuilder {
-	 * 		<jk>public</jk> AFilter() {
-	 * 			super(A.<jk>class</jk>);
-	 * 			setSubTypeProperty(<js>"subType"</js>);
-	 *				addSubType("A1", A1.<jk>class</jk>);
-	 *				addSubType("A2", A2.<jk>class</jk>);
-	 * 		}
-	 * 	}
-	 * </p>
-	 * <p>
-	 * The following shows what happens when serializing a subclassed object to JSON:
-	 * <p class='bcode'>
-	 * 	JsonSerializer s = <jk>new</jk> JsonSerializer().addBeanFilters(AFilter.<jk>class</jk>);
-	 * 	A1 a1 = <jk>new</jk> A1();
-	 * 	a1.<jf>f1</jf> = <js>"f1"</js>;
-	 * 	String r = s.serialize(a1);
-	 * 	<jsm>assertEquals</jsm>(<js>"{subType:'A1',f1:'f1',f0:'f0'}"</js>, r);
-	 *	</p>
-	 * <p>
-	 * The following shows what happens when parsing back into the original object.
-	 * <p class='bcode'>
-	 * 	JsonParser p = <jk>new</jk> JsonParser().addBeanFilters(AFilter.<jk>class</jk>);
-	 * 	A a = p.parse(r, A.<jk>class</jk>);
-	 * 	<jsm>assertTrue</jsm>(a <jk>instanceof</jk> A1);
-	 * </p>
-	 *
-	 * @param subTypeProperty The name of the subtype property for this bean.
-	 * 	Default is <js>"_subtype"</js>.
-	 * @return This object (for method chaining).
-	 */
-	public BeanFilterBuilder setSubTypeProperty(String subTypeProperty) {
-		this.subTypeProperty = subTypeProperty;
-		return this;
-	}
-
-	/**
-	 * Specifies the subtype mappings for this bean class.
-	 * See {@link #setSubTypeProperty(String)}.
-	 *
-	 * @param subTypes The mappings of subtype classes to subtype names.
-	 * @return This object (for method chaining).
-	 */
-	public BeanFilterBuilder setSubTypes(Map<Class<?>,String> subTypes) {
-		this.subTypes = subTypes;
-		return this;
-	}
-
-	/**
-	 * Adds an entry to the subtype mappings for this bean class.
-	 * See {@link #setSubTypeProperty(String)}.
+	 * Adds a class to this bean's bean dictionary.
 	 *
-	 * @param name The subtype name.
-	 * @param c The subtype class.
+	 * @param c The class to add to this bean dictionary.
 	 * @return This object (for method chaining).
 	 */
-	public BeanFilterBuilder addSubType(String name, Class<?> c) {
-		if (subTypes == null)
-			subTypes = new LinkedHashMap<Class<?>,String>();
-		subTypes.put(c, name);
+	public BeanFilterBuilder addToBeanDictionary(Class<?>...c) {
+		if (beanDictionary == null)
+			beanDictionary = new ArrayList<Class<?>>(Arrays.asList(c));
+		else for (Class<?> cc : c)
+			beanDictionary.add(cc);
 		return this;
 	}
 

http://git-wip-us.apache.org/repos/asf/incubator-juneau/blob/097b8103/juneau-core/src/main/java/org/apache/juneau/transform/package.html
----------------------------------------------------------------------
diff --git a/juneau-core/src/main/java/org/apache/juneau/transform/package.html b/juneau-core/src/main/java/org/apache/juneau/transform/package.html
index 9a9b2a6..f9722e3 100644
--- a/juneau-core/src/main/java/org/apache/juneau/transform/package.html
+++ b/juneau-core/src/main/java/org/apache/juneau/transform/package.html
@@ -210,81 +210,6 @@
 	}
 		</p>
 		
-		<h6 class='topic'>Define bean subtypes</h6>
-		<p>
-			Juneau allows you to losslessly serialize and parse abstract class fields back into the original 
-				concrete objects by defining a subtype attribute and a list of subtypes/ids.
-		</p>
-		<p>
-			For example, let's define the following parent class with two subclasses:
-		</p>
-		<p class='bcode'>
-	<jc>// Abstract parent class</jc>
-	<jk>public abstract class</jk> MyClass {
-		<jk>public</jk> String <jf>foo</jf>=<js>"foo"</js>;
-	}
-
-	<jc>// Subclass 1</jc>
-	<jk>public class</jk> MyClassBar <jk>extends</jk> MyClass {
-		<jk>public</jk> String <jf>bar</jf>=<js>"bar"</js>;
-	}
-	
-	<jc>// Subclass 2</jc>
-	<jk>public class</jk> MyClassBaz <jk>extends</jk> MyClass {
-		<jk>public</jk> String <jf>baz</jf>=<js>"baz"</js>;
-	}
-		</p>
-		<p>
-			Normally, when parsing a serialized <code>MyClass</code> object, the parser does not know what subtype to create.
-			This can be fixed by defining the following bean filter:
-		</p>		
-		<p class='bcode'>
-	<jc>// Define bean filter with our own property namer.</jc>
-	<jk>public class</jk> MyBeanFilter <jk>extends</jk> BeanFilter&lt;MyClass&gt; {
-		<jk>public</jk> MyBeanFilter() {
-			setSubTypeProperty(<js>"subType"</js>);
-			addSubType(MyClassBar.<jk>class</jk>, <js>"BAR"</js>);
-			addSubType(MyClassBaz.<jk>class</jk>, <js>"BAZ"</js>);
-		}
-	}
-		</p>
-		<p>
-			When serialized, the serialized bean will include a <code>"subType"</code> attribute that identifies the subclass, and
-				allows it to be parsed back into the original subclass.
-		</p>
-		<p class='bcode'>
-	<jc>// Serialize to JSON</jc>
-	WriterSerializer s = <jk>new</jk> JsonSerializer().addBeanFilters(MyBeanFilter.<jk>class</jk>);
-	MyClass c = <jk>new</jk> MyClassBar();
-	String json = s.serialize(p);  <jc>// Prints "{subType:'BAR',foo:'foo',bar:'bar'}"</jc>
-	
-	<jc>// Parse back into bean</jc>
-	ReaderParser p = <jk>new</jk> JsonParser().addBeanFilters(MyBeanFilter.<jk>class</jk>);
-	c = p.parse(json, MyClass.<jk>class</jk>); <jc>// c is an instance of MyClassBar</jc>
-		</p>	
-		<p>
-			It should be noted that the sub type attribute is always rendered first in the JSON object so 
-				that the bean object can be instantiated before the real properties are set on it during parsing.  
-			Beans with subtypes are thus 'lazy-instantiated' when the sub type attribute is set.
-			If the sub type attribute is not listed first, the parser will still be able to parse the input,
-			but with reduced efficiency since it must cache the incoming data until the bean can be instantiated.
-		</p>
-		<p>
-			Note that this bean filter is equivalent to specifying the following annotation on the bean class:
-		</p>
-		<p class='bcode'>
-	<ja>@Bean</ja>(
-		subTypeProperty=<js>"subType"</js>,
-		subTypes={
-			<ja>@BeanSubType</ja>(type=MyClassBar.<jk>class</jk>, id=<js>"BAR"</js>),
-			<ja>@BeanSubType</ja>(type=MyClassBaz.<jk>class</jk>, id=<js>"BAZ"</js>)
-		}
-	)
-	<jk>public abstract class</jk> MyClass {
-		...
-	}
-		</p>
-			
 		<h6 class='topic'>Limiting bean properties to parent bean classes</h6>
 		<p>
 			Occassionally, you may want to limit bean properties to some parent interface.