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 f718a4621a refactor: reorder serializer/parser dispatch chains + 
ClassMeta polish (TODO-56)
f718a4621a is described below

commit f718a4621acb5bcfde6d614ba68460e09ce99f99
Author: James Bognar <[email protected]>
AuthorDate: Fri May 22 12:18:23 2026 -0400

    refactor: reorder serializer/parser dispatch chains + ClassMeta polish 
(TODO-56)
---
 .../org/apache/juneau/jena/RdfParserSession.java   | 62 ++++++++--------
 .../apache/juneau/jena/RdfSerializerSession.java   | 38 +++++-----
 .../apache/juneau/jena/RdfStreamParserSession.java | 77 ++++++++++----------
 .../juneau/jena/RdfStreamSerializerSession.java    | 40 ++++++-----
 .../src/main/java/org/apache/juneau/ClassMeta.java | 11 ++-
 .../apache/juneau/bson/BsonSerializerSession.java  | 70 +++++++++---------
 .../org/apache/juneau/cbor/CborParserSession.java  | 54 +++++++-------
 .../apache/juneau/cbor/CborSerializerSession.java  | 32 ++++-----
 .../juneau/hjson/HjsonSerializerSession.java       | 26 +++----
 .../juneau/hocon/HoconSerializerSession.java       | 27 +++----
 .../org/apache/juneau/html/HtmlParserSession.java  |  8 +--
 .../apache/juneau/html/HtmlSerializerSession.java  | 82 ++++++++++-----------
 .../apache/juneau/ini/IniSerializerSession.java    | 12 ++--
 .../org/apache/juneau/json/JsonParserSession.java  | 52 +++++++-------
 .../apache/juneau/json/JsonSerializerSession.java  | 26 +++----
 .../juneau/markdown/MarkdownParserSession.java     |  8 +--
 .../juneau/markdown/MarkdownSerializerSession.java | 14 ++--
 .../juneau/msgpack/MsgPackParserSession.java       | 54 +++++++-------
 .../juneau/msgpack/MsgPackSerializerSession.java   | 32 ++++-----
 .../apache/juneau/proto/ProtoParserSession.java    | 54 +++++++-------
 .../juneau/proto/ProtoSerializerSession.java       |  4 +-
 .../org/apache/juneau/toml/TomlParserSession.java  | 43 +++++------
 .../apache/juneau/toml/TomlSerializerSession.java  | 40 +++++------
 .../org/apache/juneau/uon/UonParserSession.java    | 60 ++++++++--------
 .../apache/juneau/uon/UonSerializerSession.java    | 32 ++++-----
 .../urlencoding/UrlEncodingParserSession.java      |  6 +-
 .../urlencoding/UrlEncodingSerializerSession.java  |  6 +-
 .../org/apache/juneau/xml/XmlParserSession.java    | 48 ++++++-------
 .../apache/juneau/xml/XmlSerializerSession.java    | 29 ++++----
 .../org/apache/juneau/yaml/YamlParserSession.java  | 48 ++++++-------
 .../apache/juneau/yaml/YamlSerializerSession.java  |  8 +--
 ...ISHED-56-serializer-parser-dispatch-cleanup.md} | 84 ++++++++++++++++++++++
 32 files changed, 644 insertions(+), 543 deletions(-)

diff --git 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
index 2f48def313..05faebef32 100644
--- 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
+++ 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java
@@ -402,24 +402,18 @@ public class RdfParserSession extends ReaderParserSession 
{
                        } else {
                                throw new ParseException(this, "Unrecognized 
node type ''{0}'' for object", n);
                        }
-               } else if (sType.isBoolean()) {
-                       o = convertToType(getValue(n, outer), boolean.class);
-               } else if (sType.isCharSequence()) {
-                       o = decodeString(getValue(n, outer));
-               } else if (sType.isChar()) {
-                       o = parseCharacter(decodeString(getValue(n, outer)));
-               } else if (sType.isNumber()) {
-                       o = parseNumber(getValue(n, outer).toString(), (Class<? 
extends Number>)sType.inner());
-               } else if (sType.isDate()) {
-                       o = parseDate(getValue(n, outer).toString(), sType);
-               } else if (sType.isCalendar()) {
-                       o = parseCalendar(getValue(n, outer).toString(), sType);
-               } else if (sType.isTemporal()) {
-                       o = parseTemporal(getValue(n, outer).toString(), sType);
-               } else if (sType.isDuration()) {
-                       o = parseDuration(getValue(n, outer).toString());
-               } else if (sType.isPeriod()) {
-                       o = parsePeriod(getValue(n, outer).toString());
+               } else if (nn(builder)) {
+                       var r = n.asResource();
+                       if (! urisVisited.add(r))
+                               return null;
+                       var bm = toBeanMap(builder.create(this, eType));
+                       o = builder.build(this, parseIntoBeanMap(r, 
bm).getBean(), eType);
+               } else if (sType.canCreateNewBean(outer)) {
+                       var r = n.asResource();
+                       if (! urisVisited.add(r))
+                               return null;
+                       var bm = newBeanMap(outer, sType.inner());
+                       o = parseIntoBeanMap(r, bm).getBean();
                } else if (sType.isMap()) {
                        var r = n.asResource();
                        if (! urisVisited.add(r))
@@ -445,20 +439,28 @@ public class RdfParserSession extends ReaderParserSession 
{
                        }
                        if (sType.isArray() || sType.isArgs())
                                o = toArray(sType, (Collection)o);
-               } else if (nn(builder)) {
-                       var r = n.asResource();
-                       if (! urisVisited.add(r))
-                               return null;
-                       var bm = toBeanMap(builder.create(this, eType));
-                       o = builder.build(this, parseIntoBeanMap(r, 
bm).getBean(), eType);
-               } else if (sType.canCreateNewBean(outer)) {
-                       var r = n.asResource();
-                       if (! urisVisited.add(r))
-                               return null;
-                       var bm = newBeanMap(outer, sType.inner());
-                       o = parseIntoBeanMap(r, bm).getBean();
+               } else if (sType.isCharSequence()) {
+                       o = decodeString(getValue(n, outer));
+               } else if (sType.isChar()) {
+                       o = parseCharacter(decodeString(getValue(n, outer)));
+               } else if (sType.isNumber()) {
+                       o = parseNumber(getValue(n, outer).toString(), (Class<? 
extends Number>)sType.inner());
+               } else if (sType.isBoolean()) {
+                       o = convertToType(getValue(n, outer), boolean.class);
                } else if (sType.isUri() && n.isResource()) {
+                       // RDF URIs must be reconstructed from the resource's 
URI string (not from a literal),
+                       // so this branch is kept here to fire before the 
temporal/scalar coercion fallbacks.
                        o = sType.newInstanceFromString(outer, 
decodeString(n.asResource().getURI()));
+               } else if (sType.isDate()) {
+                       o = parseDate(getValue(n, outer).toString(), sType);
+               } else if (sType.isCalendar()) {
+                       o = parseCalendar(getValue(n, outer).toString(), sType);
+               } else if (sType.isTemporal()) {
+                       o = parseTemporal(getValue(n, outer).toString(), sType);
+               } else if (sType.isDuration()) {
+                       o = parseDuration(getValue(n, outer).toString());
+               } else if (sType.isPeriod()) {
+                       o = parsePeriod(getValue(n, outer).toString());
                } else if (sType.canCreateNewInstanceFromString(outer)) {
                        o = sType.newInstanceFromString(outer, 
decodeString(getValue(n, outer)));
                } else if (n.isResource()) {
diff --git 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
index 3ba2ed5cfc..60b3b89249 100644
--- 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
+++ 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializerSession.java
@@ -375,21 +375,22 @@ public class RdfSerializerSession extends 
WriterSerializerSession {
                        }
 
                } else if (sType.isUri() || isURI) {
-                       // Note that RDF URIs must be absolute to be valid!
+                       // RDF URI gate must come before 
isBean/isMap/isCharSequence: @Uri-annotated values (where sType could be String 
or a bean) need to route through the Resource emission path.  RDF URIs must be 
absolute to be valid.
                        var uri = getUri(o, null);
                        if (isAbsoluteUri(uri))
                                n = m.createResource(uri);
                        else
                                n = 
m.createLiteral(encodeTextInvalidChars(uri));
 
-               } else if (sType.isCharSequence() || sType.isChar()) {
-                       n = m.createLiteral(encodeTextInvalidChars(o));
-
-               } else if (sType.isNumber() || sType.isBoolean()) {
-                       if (! isAddLiteralTypes())
-                               n = m.createLiteral(o.toString());
-                       else
-                               n = m.createTypedLiteral(o);
+               } else if (sType.isBean()) {
+                       var bm = toBeanMap(o);
+                       Object uri = null;
+                       RdfBeanMeta rbm = getRdfBeanMeta(bm.getMeta());
+                       if (rbm.hasBeanUri())
+                               uri = rbm.getBeanUriProperty().get(bm, null);
+                       String uri2 = getUri(uri, null);
+                       n = m.createResource(uri2);
+                       serializeBeanMap(bm, (Resource)n, typeName);
 
                } else if (sType.isMap() || (nn(wType) && wType.isMap())) {
                        if (o instanceof BeanMap o2) {
@@ -406,16 +407,6 @@ public class RdfSerializerSession extends 
WriterSerializerSession {
                                serializeMap(m2, (Resource)n, sType);
                        }
 
-               } else if (sType.isBean()) {
-                       var bm = toBeanMap(o);
-                       Object uri = null;
-                       RdfBeanMeta rbm = getRdfBeanMeta(bm.getMeta());
-                       if (rbm.hasBeanUri())
-                               uri = rbm.getBeanUriProperty().get(bm, null);
-                       String uri2 = getUri(uri, null);
-                       n = m.createResource(uri2);
-                       serializeBeanMap(bm, (Resource)n, typeName);
-
                } else if (sType.isCollectionOrArray() || (nn(wType) && 
wType.isCollection())) {
 
                        var c = sort(sType.isCollection() ? (Collection)o : 
toList(sType.inner(), o));
@@ -438,6 +429,15 @@ public class RdfSerializerSession extends 
WriterSerializerSession {
                                };
                        }
 
+               } else if (sType.isCharSequence() || sType.isChar()) {
+                       n = m.createLiteral(encodeTextInvalidChars(o));
+
+               } else if (sType.isNumber() || sType.isBoolean()) {
+                       if (! isAddLiteralTypes())
+                               n = m.createLiteral(o.toString());
+                       else
+                               n = m.createTypedLiteral(o);
+
                } else if (sType.isReader()) {
                        n = 
m.createLiteral(encodeTextInvalidChars(read((Reader)o, 
SerializerSession::handleThrown)));
                } else if (sType.isInputStream()) {
diff --git 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfStreamParserSession.java
 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfStreamParserSession.java
index 10f2c39ed1..5a6134fc41 100644
--- 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfStreamParserSession.java
+++ 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfStreamParserSession.java
@@ -403,37 +403,34 @@ public class RdfStreamParserSession extends 
InputStreamParserSession {
                        } else {
                                throw new ParseException(this, "Unrecognized 
node type ''{0}'' for object", n);
                        }
-               } else if (sType.isBoolean()) {
-                       o = convertToType(getValue(n, outer), boolean.class);
+               } else if (nn(builder)) {
+                       var r = n.asResource();
+                       if (! urisVisited.add(r))
+                               return null;
+                       var bm = toBeanMap(builder.create(this, eType));
+                       o = builder.build(this, parseIntoBeanMap(r, 
bm).getBean(), eType);
+               } else if (sType.canCreateNewBean(outer)) {
+                       var r = n.asResource();
+                       if (! urisVisited.add(r))
+                               return null;
+                       var bm = newBeanMap(outer, sType.inner());
+                       o = parseIntoBeanMap(r, bm).getBean();
+               } else if (sType.isMap()) {
+                       var r = n.asResource();
+                       if (! urisVisited.add(r))
+                               return null;
+                       var m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : newGenericMap(sType));
+                       o = parseIntoMap(r, m, eType.getKeyType(), 
eType.getValueType(), pMeta);
                } else if (sType.isByteArray()) {
+                       // Correctness gate: byte[] satisfies 
isArray()/isCollectionOrArray() too, but RDF emits
+                       // byte[] as a typed base64 literal (not as a 
Seq/Bag/RDFList of byte resources).  This
+                       // branch MUST stay above isCollectionOrArray so the 
literal path fires first.
                        var v = getValue(n, outer);
                        if (v instanceof byte[] b) {
                                o = b;
                        } else if (v != null) {
                                o = 
java.util.Base64.getDecoder().decode(v.toString());
                        }
-               } else if (sType.isCharSequence()) {
-                       o = decodeString(getValue(n, outer));
-               } else if (sType.isChar()) {
-                       o = parseCharacter(decodeString(getValue(n, outer)));
-               } else if (sType.isNumber()) {
-                       o = parseNumber(getValue(n, outer).toString(), (Class<? 
extends Number>)sType.inner());
-               } else if (sType.isDate()) {
-                       o = parseDate(getValue(n, outer).toString(), sType);
-               } else if (sType.isCalendar()) {
-                       o = parseCalendar(getValue(n, outer).toString(), sType);
-               } else if (sType.isTemporal()) {
-                       o = parseTemporal(getValue(n, outer).toString(), sType);
-               } else if (sType.isDuration()) {
-                       o = parseDuration(getValue(n, outer).toString());
-               } else if (sType.isPeriod()) {
-                       o = parsePeriod(getValue(n, outer).toString());
-               } else if (sType.isMap()) {
-                       var r = n.asResource();
-                       if (! urisVisited.add(r))
-                               return null;
-                       var m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : newGenericMap(sType));
-                       o = parseIntoMap(r, m, eType.getKeyType(), 
eType.getValueType(), pMeta);
                } else if (sType.isCollectionOrArray() || sType.isArgs()) {
                        if (sType.isArray() || sType.isArgs())
                                o = list();
@@ -453,20 +450,28 @@ public class RdfStreamParserSession extends 
InputStreamParserSession {
                        }
                        if (sType.isArray() || sType.isArgs())
                                o = toArray(sType, (Collection)o);
-               } else if (nn(builder)) {
-                       var r = n.asResource();
-                       if (! urisVisited.add(r))
-                               return null;
-                       var bm = toBeanMap(builder.create(this, eType));
-                       o = builder.build(this, parseIntoBeanMap(r, 
bm).getBean(), eType);
-               } else if (sType.canCreateNewBean(outer)) {
-                       var r = n.asResource();
-                       if (! urisVisited.add(r))
-                               return null;
-                       var bm = newBeanMap(outer, sType.inner());
-                       o = parseIntoBeanMap(r, bm).getBean();
+               } else if (sType.isCharSequence()) {
+                       o = decodeString(getValue(n, outer));
+               } else if (sType.isChar()) {
+                       o = parseCharacter(decodeString(getValue(n, outer)));
+               } else if (sType.isNumber()) {
+                       o = parseNumber(getValue(n, outer).toString(), (Class<? 
extends Number>)sType.inner());
+               } else if (sType.isBoolean()) {
+                       o = convertToType(getValue(n, outer), boolean.class);
                } else if (sType.isUri() && n.isResource()) {
+                       // RDF URIs must be reconstructed from the resource's 
URI string (not from a literal),
+                       // so this branch is kept here to fire before the 
temporal/scalar coercion fallbacks.
                        o = sType.newInstanceFromString(outer, 
decodeString(n.asResource().getURI()));
+               } else if (sType.isDate()) {
+                       o = parseDate(getValue(n, outer).toString(), sType);
+               } else if (sType.isCalendar()) {
+                       o = parseCalendar(getValue(n, outer).toString(), sType);
+               } else if (sType.isTemporal()) {
+                       o = parseTemporal(getValue(n, outer).toString(), sType);
+               } else if (sType.isDuration()) {
+                       o = parseDuration(getValue(n, outer).toString());
+               } else if (sType.isPeriod()) {
+                       o = parsePeriod(getValue(n, outer).toString());
                } else if (sType.canCreateNewInstanceFromString(outer)) {
                        o = sType.newInstanceFromString(outer, 
decodeString(getValue(n, outer)));
                } else if (n.isResource()) {
diff --git 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfStreamSerializerSession.java
 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfStreamSerializerSession.java
index 50dc5ef960..d1c3a63c23 100644
--- 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfStreamSerializerSession.java
+++ 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfStreamSerializerSession.java
@@ -320,21 +320,21 @@ public class RdfStreamSerializerSession extends 
OutputStreamSerializerSession {
                                n = m.createResource(RDF_NIL);
                        }
                } else if (sType.isUri() || isURI) {
+                       // RDF URI gate must come before 
isBean/isMap/isCharSequence: @Uri-annotated values need Resource emission, not 
literal text.
                        var uri = getUri(o, null);
                        if (isAbsoluteUri(uri))
                                n = m.createResource(uri);
                        else
                                n = 
m.createLiteral(encodeTextInvalidChars(uri));
-               } else if (sType.isCharSequence() || sType.isChar()) {
-                       n = m.createLiteral(encodeTextInvalidChars(o));
-               } else if (sType.isNumber() || sType.isBoolean()) {
-                       if (!ctx.isAddLiteralTypes())
-                               n = m.createLiteral(o.toString());
-                       else
-                               n = m.createTypedLiteral(o);
-               } else if (sType.isByteArray()) {
-                       var b64 = Base64.getEncoder().encodeToString((byte[]) 
o);
-                       n = m.createTypedLiteral(b64, 
XSDDatatype.XSDbase64Binary);
+               } else if (sType.isBean()) {
+                       var bm = toBeanMap(o);
+                       Object uri = null;
+                       var rbm = ctx.getRdfBeanMeta(bm.getMeta());
+                       if (rbm.hasBeanUri())
+                               uri = rbm.getBeanUriProperty().get(bm, null);
+                       var uri2 = getUri(uri, null);
+                       n = m.createResource(uri2);
+                       serializeBeanMap(bm, (Resource)n, typeName);
                } else if (sType.isMap() || (nn(wType) && wType.isMap())) {
                        if (o instanceof BeanMap o2) {
                                Object uri = null;
@@ -348,15 +348,10 @@ public class RdfStreamSerializerSession extends 
OutputStreamSerializerSession {
                                n = m.createResource();
                                serializeMap((Map)o, (Resource)n, sType);
                        }
-               } else if (sType.isBean()) {
-                       var bm = toBeanMap(o);
-                       Object uri = null;
-                       var rbm = ctx.getRdfBeanMeta(bm.getMeta());
-                       if (rbm.hasBeanUri())
-                               uri = rbm.getBeanUriProperty().get(bm, null);
-                       var uri2 = getUri(uri, null);
-                       n = m.createResource(uri2);
-                       serializeBeanMap(bm, (Resource)n, typeName);
+               } else if (sType.isByteArray()) {
+                       // byte[] gate must come before isCollectionOrArray: 
byte[] satisfies isArray() but RDF emits it as a typed base64 literal, not as a 
Seq of bytes.
+                       var b64 = Base64.getEncoder().encodeToString((byte[]) 
o);
+                       n = m.createTypedLiteral(b64, 
XSDDatatype.XSDbase64Binary);
                } else if (sType.isCollectionOrArray() || (nn(wType) && 
wType.isCollection())) {
                        var c = sort(sType.isCollection() ? (Collection)o : 
toList(sType.inner(), o));
                        var f = ctx.getCollectionFormat();
@@ -375,6 +370,13 @@ public class RdfStreamSerializerSession extends 
OutputStreamSerializerSession {
                                        default -> serializeToContainer(c, 
eType, m.createSeq());
                                };
                        }
+               } else if (sType.isCharSequence() || sType.isChar()) {
+                       n = m.createLiteral(encodeTextInvalidChars(o));
+               } else if (sType.isNumber() || sType.isBoolean()) {
+                       if (!ctx.isAddLiteralTypes())
+                               n = m.createLiteral(o.toString());
+                       else
+                               n = m.createTypedLiteral(o);
                } else if (sType.isReader()) {
                        n = 
m.createLiteral(encodeTextInvalidChars(read((Reader)o, 
SerializerSession::handleThrown)));
                } else if (sType.isInputStream()) {
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 0aedd97241..f6635e9d9e 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
@@ -73,7 +73,7 @@ import org.apache.juneau.swap.*;
        "java:S1452",  // Wildcard required - ClassMeta<?>, ObjectSwap<T,?>, 
etc. for element/component types
        "java:S6539"   // Monster Class: ClassMeta is a focused 
reflection-metadata cache; splitting would increase coupling
 })
-public class ClassMeta<T> extends BeanInfo<T> {
+public final class ClassMeta<T> extends BeanInfo<T> {
 
        private static class Categories {
                int bits;
@@ -1044,7 +1044,7 @@ public class ClassMeta<T> extends BeanInfo<T> {
         * @return <jk>true</jk> if this class is a subclass of {@link 
Collection}.
         */
        @Override
-       public boolean isCollection() { return cat != null && 
cat.is(COLLECTION); }
+       public boolean isCollection() { return cat.is(COLLECTION); }
 
        /**
         * Returns <jk>true</jk> if this class is a subclass of {@link 
Collection} or is an array or {@link Optional}.
@@ -1168,10 +1168,7 @@ public class ClassMeta<T> extends BeanInfo<T> {
         * @return <jk>true</jk> if this class is a subclass of {@link Map}.
         */
        @Override
-       public boolean isMap() {
-               // Defensive null-guard: category is expected to be set, but 
keep this check for safety.
-               return cat != null && cat.is(MAP);
-       }
+       public boolean isMap() { return cat.is(MAP); }
 
        /**
         * Returns <jk>true</jk> if this class is a subclass of {@link Map} or 
it's a bean.
@@ -1274,7 +1271,7 @@ public class ClassMeta<T> extends BeanInfo<T> {
         * @return <jk>true</jk> if this class is a {@link URI} or {@link URL}.
         */
        @Override
-       public boolean isUri() { return cat != null && cat.is(URI); }
+       public boolean isUri() { return cat.is(URI); }
 
        /**
         * Converts the specified object into an instance of this class.
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/bson/BsonSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/bson/BsonSerializerSession.java
index 848150eb81..dade47be23 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/bson/BsonSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/bson/BsonSerializerSession.java
@@ -137,6 +137,38 @@ public class BsonSerializerSession extends 
OutputStreamSerializerSession {
 
                if (o == null || (sType.isChar() && ((Character)o).charValue() 
== 0)) {
                        out.writeElement(NULL.value, name);
+               } else if (sType.isBean()) {
+                       out.writeElement(DOCUMENT.value, name);
+                       var child = out.createChild();
+                       child.startDocument();
+                       serializeBeanMap(child, toBeanMap(o), 
getBeanTypeName(this, eType, aType, pMeta));
+                       out.writeChildDocument(child);
+               } else if (sType.isMap()) {
+                       if (o instanceof BeanMap o2) {
+                               out.writeElement(DOCUMENT.value, name);
+                               var child = out.createChild();
+                               child.startDocument();
+                               serializeBeanMap(child, o2, 
getBeanTypeName(this, eType, aType, pMeta));
+                               out.writeChildDocument(child);
+                       } else {
+                               out.writeElement(DOCUMENT.value, name);
+                               var child = out.createChild();
+                               child.startDocument();
+                               serializeMap(child, (Map)o, eType);
+                               out.writeChildDocument(child);
+                       }
+               } else if (sType.isByteArray()) {
+                       out.writeElement(BINARY.value, name);
+                       out.writeBinary((byte[])o);
+               } else if (sType.isCollection() || sType.isArray()) {
+                       out.writeElement(ARRAY.value, name);
+                       var child = out.createChild();
+                       child.startDocument();
+                       serializeArray(child, sType.isArray() ? 
toList(sType.inner(), o) : (Collection)o, eType);
+                       out.writeChildDocument(child);
+               } else if (sType.isCharSequence() || sType.isChar() || 
sType.isEnum()) {
+                       out.writeElement(STRING.value, name);
+                       out.writeString(trim(o));
                } else if (sType.isBoolean()) {
                        out.writeElement(BOOLEAN.value, name);
                        out.writeBoolean((Boolean)o);
@@ -158,6 +190,9 @@ public class BsonSerializerSession extends 
OutputStreamSerializerSession {
                                out.writeElement(DOUBLE.value, name);
                                out.writeDouble(((Number)o).doubleValue());
                        }
+               } else if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
+                       out.writeElement(STRING.value, name);
+                       out.writeString(resolveUri(o.toString()));
                } else if (sType.isDate()) {
                        if (ctx.writeDatesAsDatetime) {
                                out.writeElement(DATETIME.value, name);
@@ -187,47 +222,12 @@ public class BsonSerializerSession extends 
OutputStreamSerializerSession {
                } else if (sType.isPeriod()) {
                        out.writeElement(STRING.value, name);
                        out.writeString(serializePeriod((Period)o));
-               } else if (sType.isBean()) {
-                       out.writeElement(DOCUMENT.value, name);
-                       var child = out.createChild();
-                       child.startDocument();
-                       serializeBeanMap(child, toBeanMap(o), 
getBeanTypeName(this, eType, aType, pMeta));
-                       out.writeChildDocument(child);
-               } else if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
-                       out.writeElement(STRING.value, name);
-                       out.writeString(resolveUri(o.toString()));
-               } else if (sType.isMap()) {
-                       if (o instanceof BeanMap o2) {
-                               out.writeElement(DOCUMENT.value, name);
-                               var child = out.createChild();
-                               child.startDocument();
-                               serializeBeanMap(child, o2, 
getBeanTypeName(this, eType, aType, pMeta));
-                               out.writeChildDocument(child);
-                       } else {
-                               out.writeElement(DOCUMENT.value, name);
-                               var child = out.createChild();
-                               child.startDocument();
-                               serializeMap(child, (Map)o, eType);
-                               out.writeChildDocument(child);
-                       }
-               } else if (sType.isByteArray()) {
-                       out.writeElement(BINARY.value, name);
-                       out.writeBinary((byte[])o);
-               } else if (sType.isCollection() || sType.isArray()) {
-                       out.writeElement(ARRAY.value, name);
-                       var child = out.createChild();
-                       child.startDocument();
-                       serializeArray(child, sType.isArray() ? 
toList(sType.inner(), o) : (Collection)o, eType);
-                       out.writeChildDocument(child);
                } else if (sType.isStreamable()) {
                        out.writeElement(ARRAY.value, name);
                        var child = out.createChild();
                        child.startDocument();
                        serializeArray(child, toListFromStreamable(o, sType), 
eType);
                        out.writeChildDocument(child);
-               } else if (sType.isCharSequence() || sType.isChar() || 
sType.isEnum()) {
-                       out.writeElement(STRING.value, name);
-                       out.writeString(trim(o));
                } else {
                        out.writeElement(STRING.value, name);
                        out.writeString(toString(o));
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cbor/CborParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cbor/CborParserSession.java
index 47abf51f8c..1bbe5a678b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cbor/CborParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cbor/CborParserSession.java
@@ -246,32 +246,6 @@ public class CborParserSession extends 
InputStreamParserSession {
 
                        if (sType.isObject()) {
                                // Do nothing.
-                       } else if (sType.isBoolean() || sType.isCharSequence() 
|| sType.isChar() || sType.isNumber() || sType.isByteArray()) {
-                               o = convertToType(o, sType);
-                       } else if (sType.isDate()) {
-                               o = parseDate(String.valueOf(o), sType);
-                       } else if (sType.isCalendar()) {
-                               o = parseCalendar(String.valueOf(o), sType);
-                       } else if (sType.isTemporal()) {
-                               o = parseTemporal(String.valueOf(o), sType);
-                       } else if (sType.isDuration()) {
-                               o = parseDuration(String.valueOf(o));
-                       } else if (sType.isPeriod()) {
-                               o = parsePeriod(String.valueOf(o));
-                       } else if (sType.isMap()) {
-                               if (dt == MAP) {
-                                       Map m = 
(sType.canCreateNewInstance(outer) ? (Map)sType.newInstance(outer) : 
newGenericMap(sType));
-                                       for (var i = 0; i < len; i++) {
-                                               Object key = 
parseAnything(sType.getKeyType(), is, outer, pMeta);
-                                               var vt = sType.getValueType();
-                                               Object value = 
parseAnything(vt, is, m, pMeta);
-                                               setName(vt, value, key);
-                                               m.put(key, value);
-                                       }
-                                       o = m;
-                               } else {
-                                       throw new ParseException(this, "Invalid 
data type {0} encountered for parse type {1}", dt, sType);
-                               }
                        } else if (nn(builder) || 
sType.canCreateNewBean(outer)) {
                                if (dt == MAP) {
                                        BeanMap m = builder == null ? 
newBeanMap(outer, sType.inner()) : toBeanMap(builder.create(this, eType));
@@ -299,6 +273,34 @@ public class CborParserSession extends 
InputStreamParserSession {
                                } else {
                                        throw new ParseException(this, "Invalid 
data type {0} encountered for parse type {1}", dt, sType);
                                }
+                       } else if (sType.isMap()) {
+                               if (dt == MAP) {
+                                       Map m = 
(sType.canCreateNewInstance(outer) ? (Map)sType.newInstance(outer) : 
newGenericMap(sType));
+                                       for (var i = 0; i < len; i++) {
+                                               Object key = 
parseAnything(sType.getKeyType(), is, outer, pMeta);
+                                               var vt = sType.getValueType();
+                                               Object value = 
parseAnything(vt, is, m, pMeta);
+                                               setName(vt, value, key);
+                                               m.put(key, value);
+                                       }
+                                       o = m;
+                               } else {
+                                       throw new ParseException(this, "Invalid 
data type {0} encountered for parse type {1}", dt, sType);
+                               }
+                       } else if (sType.isBoolean() || sType.isCharSequence() 
|| sType.isChar() || sType.isNumber() || sType.isByteArray()) {
+                               // Merged scalar tier: one CBOR data type 
(BOOLEAN/UINT/NINT/FLOAT/STRING/BINARY) covers
+                               // many scalar Java types — the read already 
happened above and convertToType narrows.
+                               o = convertToType(o, sType);
+                       } else if (sType.isDate()) {
+                               o = parseDate(String.valueOf(o), sType);
+                       } else if (sType.isCalendar()) {
+                               o = parseCalendar(String.valueOf(o), sType);
+                       } else if (sType.isTemporal()) {
+                               o = parseTemporal(String.valueOf(o), sType);
+                       } else if (sType.isDuration()) {
+                               o = parseDuration(String.valueOf(o));
+                       } else if (sType.isPeriod()) {
+                               o = parsePeriod(String.valueOf(o));
                        } else if (sType.canCreateNewInstanceFromString(outer) 
&& dt == STRING) {
                                o = sType.newInstanceFromString(outer, o == 
null ? "" : o.toString());
                        } else if (sType.isCollection()) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cbor/CborSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cbor/CborSerializerSession.java
index eb0f894c04..2607e497eb 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cbor/CborSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cbor/CborSerializerSession.java
@@ -255,24 +255,8 @@ public class CborSerializerSession extends 
OutputStreamSerializerSession {
 
                if (o == null || (sType.isChar() && ((Character)o).charValue() 
== 0))
                        out.appendNull();
-               else if (sType.isBoolean())
-                       out.appendBoolean((Boolean)o);
-               else if (sType.isNumber())
-                       out.appendNumber((Number)o);
-               else if (sType.isDate())
-                       out.appendString(serializeDate((Date)o, sType));
-               else if (sType.isCalendar())
-                       out.appendString(serializeCalendar(o, sType));
-               else if (sType.isTemporal())
-                       out.appendString(serializeTemporal((TemporalAccessor)o, 
sType));
-               else if (sType.isDuration())
-                       appendDuration(out, (Duration)o);
-               else if (sType.isPeriod())
-                       out.appendString(serializePeriod((Period)o));
                else if (sType.isBean())
                        serializeBeanMap(out, toBeanMap(o), typeName);
-               else if (sType.isUri() || (nn(pMeta) && pMeta.isUri()))
-                       out.appendString(resolveUri(o.toString()));
                else if (sType.isMap()) {
                        if (o instanceof BeanMap o2)
                                serializeBeanMap(out, o2, typeName);
@@ -284,6 +268,22 @@ public class CborSerializerSession extends 
OutputStreamSerializerSession {
                        out.appendBinary((byte[])o);
                } else if (sType.isArray()) {
                        serializeCollection(out, toList(sType.inner(), o), 
eType);
+               } else if (sType.isBoolean()) {
+                       out.appendBoolean((Boolean)o);
+               } else if (sType.isNumber()) {
+                       out.appendNumber((Number)o);
+               } else if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
+                       out.appendString(resolveUri(o.toString()));
+               } else if (sType.isDate()) {
+                       out.appendString(serializeDate((Date)o, sType));
+               } else if (sType.isCalendar()) {
+                       out.appendString(serializeCalendar(o, sType));
+               } else if (sType.isTemporal()) {
+                       out.appendString(serializeTemporal((TemporalAccessor)o, 
sType));
+               } else if (sType.isDuration()) {
+                       appendDuration(out, (Duration)o);
+               } else if (sType.isPeriod()) {
+                       out.appendString(serializePeriod((Period)o));
                } else if (sType.isStreamable()) {
                        serializeCollection(out, toListFromStreamable(o, 
sType), eType);
                } else if (sType.isReader()) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hjson/HjsonSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hjson/HjsonSerializerSession.java
index 38f70777c4..32a7721991 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hjson/HjsonSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hjson/HjsonSerializerSession.java
@@ -241,8 +241,21 @@ public class HjsonSerializerSession extends 
WriterSerializerSession {
 
                if (o == null || (sType.isChar() && ((Character) o).charValue() 
== 0)) {
                        out.w("null");
+               } else if (sType.isBean()) {
+                       serializeBeanMap(out, toBeanMap(o), 
getBeanTypeName(this, eType, aType, pMeta), false);
+               } else if (sType.isMap()) {
+                       if (o instanceof BeanMap o2)
+                               serializeBeanMap(out, o2, getBeanTypeName(this, 
eType, aType, pMeta), false);
+                       else
+                               serializeMap(out, (Map) o, eType, false);
+               } else if (sType.isCollection()) {
+                       serializeCollection(out, (Collection) o, eType);
+               } else if (sType.isArray()) {
+                       serializeCollection(out, toList(sType.inner(), o), 
eType);
                } else if (sType.isNumber() || sType.isBoolean()) {
                        out.append(o);
+               } else if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
+                       serializeString(out, getUriResolver().resolve(o));
                } else if (sType.isDate()) {
                        serializeString(out, serializeDate((Date)o, sType));
                } else if (sType.isCalendar()) {
@@ -257,19 +270,6 @@ public class HjsonSerializerSession extends 
WriterSerializerSession {
                                serializeString(out, value);
                } else if (sType.isPeriod()) {
                        serializeString(out, serializePeriod((Period)o));
-               } else if (sType.isBean()) {
-                       serializeBeanMap(out, toBeanMap(o), 
getBeanTypeName(this, eType, aType, pMeta), false);
-               } else if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
-                       serializeString(out, getUriResolver().resolve(o));
-               } else if (sType.isMap()) {
-                       if (o instanceof BeanMap o2)
-                               serializeBeanMap(out, o2, getBeanTypeName(this, 
eType, aType, pMeta), false);
-                       else
-                               serializeMap(out, (Map) o, eType, false);
-               } else if (sType.isCollection()) {
-                       serializeCollection(out, (Collection) o, eType);
-               } else if (sType.isArray()) {
-                       serializeCollection(out, toList(sType.inner(), o), 
eType);
                } else if (sType.isStreamable()) {
                        serializeStreamable(out, o, sType, eType);
                } else if (sType.isReader()) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hocon/HoconSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hocon/HoconSerializerSession.java
index ab87213f33..7815e0ae39 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hocon/HoconSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hocon/HoconSerializerSession.java
@@ -266,9 +266,23 @@ public class HoconSerializerSession extends 
WriterSerializerSession {
                if (o == null || (sType.isChar() && ((Character) o).charValue() 
== 0)) {
                        hw.w("null");
                } else if (o instanceof byte[] bytes) {
+                       // byte[] gate: encode as Base64 before isArray would 
otherwise route it as a generic array.
                        serializeString(hw, 
Base64.getEncoder().encodeToString(bytes));
+               } else if (sType.isBean()) {
+                       serializeBeanMap(hw, toBeanMap(o), 
getBeanTypeName(this, eType, aType, pMeta), false);
+               } else if (sType.isMap()) {
+                       if (o instanceof BeanMap o2)
+                               serializeBeanMap(hw, o2, getBeanTypeName(this, 
eType, aType, pMeta), false);
+                       else
+                               serializeMap(hw, (Map) o, eType, false);
+               } else if (sType.isCollection()) {
+                       serializeCollection(hw, (Collection) o, eType);
+               } else if (sType.isArray()) {
+                       serializeCollection(hw, toList(sType.inner(), o), 
eType);
                } else if (sType.isNumber() || sType.isBoolean()) {
                        hw.append(o);
+               } else if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
+                       serializeString(hw, getUriResolver().resolve(o));
                } else if (sType.isDate()) {
                        serializeString(hw, serializeDate((Date)o, sType));
                } else if (sType.isCalendar()) {
@@ -283,19 +297,6 @@ public class HoconSerializerSession extends 
WriterSerializerSession {
                                serializeString(hw, value);
                } else if (sType.isPeriod()) {
                        serializeString(hw, serializePeriod((Period)o));
-               } else if (sType.isBean()) {
-                       serializeBeanMap(hw, toBeanMap(o), 
getBeanTypeName(this, eType, aType, pMeta), false);
-               } else if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
-                       serializeString(hw, getUriResolver().resolve(o));
-               } else if (sType.isMap()) {
-                       if (o instanceof BeanMap o2)
-                               serializeBeanMap(hw, o2, getBeanTypeName(this, 
eType, aType, pMeta), false);
-                       else
-                               serializeMap(hw, (Map) o, eType, false);
-               } else if (sType.isCollection()) {
-                       serializeCollection(hw, (Collection) o, eType);
-               } else if (sType.isArray()) {
-                       serializeCollection(hw, toList(sType.inner(), o), 
eType);
                } else if (sType.isStreamable()) {
                        serializeStreamable(hw, o, sType, eType);
                } else if (sType.isReader()) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java
index 1d47cf1c0c..0a36efdf03 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java
@@ -351,10 +351,10 @@ public class HtmlParserSession extends XmlParserSession {
                                o = text;
                        else if (sType.isChar())
                                o = parseCharacter(text);
-                       else if (sType.isBoolean())
-                               o = Boolean.parseBoolean(text);
                        else if (sType.isNumber())
                                o = parseNumber(text, (Class<? extends 
Number>)eType.inner());
+                       else if (sType.isBoolean())
+                               o = Boolean.parseBoolean(text);
                        else if (sType.isDate())
                                o = parseDate(text, sType);
                        else if (sType.isCalendar())
@@ -440,14 +440,14 @@ public class HtmlParserSession extends XmlParserSession {
                        if (typeName.equals(TAG_object)) {
                                if (sType.isObject()) {
                                        o = parseIntoMap(r, 
newGenericMap(sType), sType.getKeyType(), sType.getValueType(), pMeta);
-                               } else if (sType.isMap()) {
-                                       o = parseIntoMap(r, 
(Map)(sType.canCreateNewInstance(outer) ? sType.newInstance(outer) : 
newGenericMap(sType)), sType.getKeyType(), sType.getValueType(), pMeta);
                                } else if (nn(builder)) {
                                        BeanMap m = 
toBeanMap(builder.create(this, eType));
                                        o = builder.build(this, 
parseIntoBean(r, m).getBean(), eType);
                                } else if (sType.canCreateNewBean(outer)) {
                                        BeanMap m = newBeanMap(outer, 
sType.inner());
                                        o = parseIntoBean(r, m).getBean();
+                               } else if (sType.isMap()) {
+                                       o = parseIntoMap(r, 
(Map)(sType.canCreateNewInstance(outer) ? sType.newInstance(outer) : 
newGenericMap(sType)), sType.getKeyType(), sType.getValueType(), pMeta);
                                } else if 
(nn(sType.getProxyInvocationHandler())) {
                                        BeanMap m = newBeanMap(outer, 
sType.inner());
                                        o = parseIntoBean(r, m).getBean();
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 54cf4c0e86..5c36c81c75 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
@@ -1049,6 +1049,40 @@ public class HtmlSerializerSession extends 
XmlSerializerSession {
                                        out.tag("null");
                                cr = CR_MIXED;
 
+                       } else if (sType.isBean()) {
+                               BeanMap m = toBeanMap(o);
+                               if (getAnnotationProvider().has(HtmlLink.class, 
aType)) {
+                                       var uriProperty = Value.<String>empty();
+                                       var nameProperty = 
Value.<String>empty();
+                                       aType.forEachAnnotation(HtmlLink.class, 
x -> ne(x.uriProperty()), x -> uriProperty.set(x.uriProperty()));
+                                       aType.forEachAnnotation(HtmlLink.class, 
x -> ne(x.nameProperty()), x -> nameProperty.set(x.nameProperty()));
+                                       Object urlProp = 
m.get(uriProperty.orElse(""));
+                                       Object nameProp = 
m.get(nameProperty.orElse(""));
+
+                                       out.oTag("a").attrUri("href", 
urlProp).w('>').text(nameProp).eTag("a");
+                                       cr = CR_MIXED;
+                               } else {
+                                       out.nlIf(! isRoot, xIndent + 2);
+                                       serializeBeanMap(out, m, eType, pMeta);
+                               }
+
+                       } else if (sType.isMap() || (nn(wType) && 
wType.isMap())) {
+                               out.nlIf(! isRoot, xIndent + 1);
+                               if (o instanceof BeanMap o2)
+                                       serializeBeanMap(out, o2, eType, pMeta);
+                               else
+                                       serializeMap(out, (Map)o, sType, 
eType.getKeyType(), eType.getValueType(), typeName, pMeta);
+
+                       } else if (sType.isCollection() || sType.isArray() || 
(nn(wType) && wType.isCollection())) {
+                               out.nlIf(! isRoot, xIndent + 1);
+                               serializeCollection(out, o, sType, eType, name, 
pMeta);
+
+                       } else if (sType.isStreamable()) {
+                               // HTML must inspect elements to decide table 
vs. list layout (getTableHeaders), so materialization is unavoidable.
+                               out.nlIf(! isRoot, xIndent + 1);
+                               var list = toListFromStreamable(o, sType);
+                               serializeCollection(out, list, 
getClassMeta(List.class), eType, name, pMeta);
+
                        } else if (sType.isNumber()) {
                                if (eType.isNumber() && ! (isRoot && 
addJsonTags))
                                        out.append(o);
@@ -1063,6 +1097,13 @@ public class HtmlSerializerSession extends 
XmlSerializerSession {
                                        
out.sTag("boolean").append(o).eTag("boolean");
                                cr = CR_MIXED;
 
+                       } else if (isUri(sType, pMeta, o)) {
+                               String label = getAnchorText(pMeta, o);
+                               out.oTag("a").attrUri("href", o).w('>');
+                               out.text(label);
+                               out.eTag("a");
+                               cr = CR_MIXED;
+
                        } else if (sType.isDate()) {
                                String s = serializeDate((Date)o, sType);
                                if (isRoot && addJsonTags)
@@ -1103,47 +1144,6 @@ public class HtmlSerializerSession extends 
XmlSerializerSession {
                                        out.text(s);
                                cr = CR_MIXED;
 
-                       } else if (sType.isMap() || (nn(wType) && 
wType.isMap())) {
-                               out.nlIf(! isRoot, xIndent + 1);
-                               if (o instanceof BeanMap o2)
-                                       serializeBeanMap(out, o2, eType, pMeta);
-                               else
-                                       serializeMap(out, (Map)o, sType, 
eType.getKeyType(), eType.getValueType(), typeName, pMeta);
-
-                       } else if (sType.isBean()) {
-                               BeanMap m = toBeanMap(o);
-                               if (getAnnotationProvider().has(HtmlLink.class, 
aType)) {
-                                       var uriProperty = Value.<String>empty();
-                                       var nameProperty = 
Value.<String>empty();
-                                       aType.forEachAnnotation(HtmlLink.class, 
x -> ne(x.uriProperty()), x -> uriProperty.set(x.uriProperty()));
-                                       aType.forEachAnnotation(HtmlLink.class, 
x -> ne(x.nameProperty()), x -> nameProperty.set(x.nameProperty()));
-                                       Object urlProp = 
m.get(uriProperty.orElse(""));
-                                       Object nameProp = 
m.get(nameProperty.orElse(""));
-
-                                       out.oTag("a").attrUri("href", 
urlProp).w('>').text(nameProp).eTag("a");
-                                       cr = CR_MIXED;
-                               } else {
-                                       out.nlIf(! isRoot, xIndent + 2);
-                                       serializeBeanMap(out, m, eType, pMeta);
-                               }
-
-                       } else if (sType.isCollection() || sType.isArray() || 
(nn(wType) && wType.isCollection())) {
-                               out.nlIf(! isRoot, xIndent + 1);
-                               serializeCollection(out, o, sType, eType, name, 
pMeta);
-
-                       } else if (sType.isStreamable()) {
-                               // HTML must inspect elements to decide table 
vs. list layout (getTableHeaders), so materialization is unavoidable.
-                               out.nlIf(! isRoot, xIndent + 1);
-                               var list = toListFromStreamable(o, sType);
-                               serializeCollection(out, list, 
getClassMeta(List.class), eType, name, pMeta);
-
-                       } else if (isUri(sType, pMeta, o)) {
-                               String label = getAnchorText(pMeta, o);
-                               out.oTag("a").attrUri("href", o).w('>');
-                               out.text(label);
-                               out.eTag("a");
-                               cr = CR_MIXED;
-
                        } else {
                                if (isRoot && addJsonTags)
                                        
out.sTag(CONST_string).text(toString(o)).eTag(CONST_string);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ini/IniSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ini/IniSerializerSession.java
index 186974204b..8acf67922d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ini/IniSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ini/IniSerializerSession.java
@@ -263,10 +263,16 @@ public class IniSerializerSession extends 
WriterSerializerSession {
        }
 
        private String formatSimpleValue(Object value, ClassMeta<?> aType) 
throws SerializeException {
+               if (aType.isCharSequence() || aType.isUri()) {
+                       var s = toString(value);
+                       return needsQuoting(s) ? "'" + s.replace("'", "''") + 
"'" : s;
+               }
                if (aType.isNumber())
                        return value.toString();
                if (aType.isBoolean())
                        return ((Boolean)value).toString();
+               if (aType.isEnum())
+                       return ((Enum<?>)value).name();
                if (aType.isDate())
                        return serializeDate((Date)value, aType);
                if (aType.isCalendar())
@@ -277,12 +283,6 @@ public class IniSerializerSession extends 
WriterSerializerSession {
                        return serializeDuration((Duration)value);
                if (aType.isPeriod())
                        return serializePeriod((Period)value);
-               if (aType.isEnum())
-                       return ((Enum<?>)value).name();
-               if (aType.isCharSequence() || aType.isUri()) {
-                       var s = toString(value);
-                       return needsQuoting(s) ? "'" + s.replace("'", "''") + 
"'" : s;
-               }
                return toString(value);
        }
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java
index 1bb5dcfb0e..df094f3a1a 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java
@@ -283,24 +283,12 @@ public class JsonParserSession extends 
ReaderParserSession {
                                parseKeyword("false", r);
                                o = Boolean.FALSE;
                        }
-               } else if (sType.isBoolean()) {
-                       o = parseBoolean(r);
-               } else if (sType.isCharSequence()) {
-                       o = parseString(r);
-               } else if (sType.isChar()) {
-                       o = parseCharacter(parseString(r));
-               } else if (sType.isNumber()) {
-                       o = parseNumber(r, (Class<? extends 
Number>)sType.inner());
-               } else if (sType.isDate()) {
-                       o = parseDate(parseString(r), sType);
-               } else if (sType.isCalendar()) {
-                       o = parseCalendar(parseString(r), sType);
-               } else if (sType.isTemporal()) {
-                       o = parseTemporal(parseString(r), sType);
-               } else if (sType.isDuration()) {
-                       o = parseDuration(parseString(r));
-               } else if (sType.isPeriod()) {
-                       o = parsePeriod(parseString(r));
+               } else if (nn(builder)) {
+                       var m = toBeanMap(builder.create(this, eType));
+                       o = builder.build(this, parseIntoBeanMap2(r, 
m).getBean(), eType);
+               } else if (sType.canCreateNewBean(outer)) {
+                       var m = newBeanMap(outer, sType.inner());
+                       o = parseIntoBeanMap2(r, m).getBean();
                } else if (sType.isMap()) {
                        Map m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : newGenericMap(sType));
                        o = parseIntoMap2(r, m, sType.getKeyType(), 
sType.getValueType(), pMeta);
@@ -313,14 +301,6 @@ public class JsonParserSession extends ReaderParserSession 
{
                                Collection l = 
(sType.canCreateNewInstance(outer) ? (Collection)sType.newInstance() : 
newGenericList());
                                o = parseIntoCollection2(r, l, sType, pMeta);
                        }
-               } else if (nn(builder)) {
-                       var m = toBeanMap(builder.create(this, eType));
-                       o = builder.build(this, parseIntoBeanMap2(r, 
m).getBean(), eType);
-               } else if (sType.canCreateNewBean(outer)) {
-                       var m = newBeanMap(outer, sType.inner());
-                       o = parseIntoBeanMap2(r, m).getBean();
-               } else if (sType.canCreateNewInstanceFromString(outer) && (c == 
'\'' || c == '"')) {
-                       o = sType.newInstanceFromString(outer, parseString(r));
                } else if (sType.isArray() || sType.isArgs()) {
                        if (c == '{') {
                                var m = newGenericMap();
@@ -330,6 +310,26 @@ public class JsonParserSession extends ReaderParserSession 
{
                                var l = (ArrayList)parseIntoCollection2(r, 
list(), sType, pMeta);
                                o = toArray(sType, l);
                        }
+               } else if (sType.isCharSequence()) {
+                       o = parseString(r);
+               } else if (sType.isChar()) {
+                       o = parseCharacter(parseString(r));
+               } else if (sType.isNumber()) {
+                       o = parseNumber(r, (Class<? extends 
Number>)sType.inner());
+               } else if (sType.isBoolean()) {
+                       o = parseBoolean(r);
+               } else if (sType.isDate()) {
+                       o = parseDate(parseString(r), sType);
+               } else if (sType.isCalendar()) {
+                       o = parseCalendar(parseString(r), sType);
+               } else if (sType.isTemporal()) {
+                       o = parseTemporal(parseString(r), sType);
+               } else if (sType.isDuration()) {
+                       o = parseDuration(parseString(r));
+               } else if (sType.isPeriod()) {
+                       o = parsePeriod(parseString(r));
+               } else if (sType.canCreateNewInstanceFromString(outer) && (c == 
'\'' || c == '"')) {
+                       o = sType.newInstanceFromString(outer, parseString(r));
                } else if (c == '{') {
                        Map m = newGenericMap();
                        parseIntoMap2(r, m, sType.getKeyType(), 
sType.getValueType(), pMeta);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
index 3d54b02020..c213124b70 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
@@ -446,8 +446,21 @@ public class JsonSerializerSession extends 
WriterSerializerSession {
                // '\0' characters are considered null.
                if (o == null || (sType.isChar() && ((Character)o).charValue() 
== 0)) {
                        out.append("null");
+               } else if (sType.isBean()) {
+                       serializeBeanMap(out, toBeanMap(o), typeName);
+               } else if (sType.isMap()) {
+                       if (o instanceof BeanMap o2)
+                               serializeBeanMap(out, o2, typeName);
+                       else
+                               serializeMap(out, (Map)o, eType);
+               } else if (sType.isCollection()) {
+                       serializeCollection(out, (Collection)o, eType);
+               } else if (sType.isArray()) {
+                       serializeCollection(out, toList(sType.inner(), o), 
eType);
                } else if (sType.isNumber() || sType.isBoolean()) {
                        out.append(o);
+               } else if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
+                       out.uriValue(o);
                } else if (sType.isDate()) {
                        out.stringValue(serializeDate((Date)o, sType));
                } else if (sType.isCalendar()) {
@@ -462,19 +475,6 @@ public class JsonSerializerSession extends 
WriterSerializerSession {
                                out.stringValue(value);
                } else if (sType.isPeriod()) {
                        out.stringValue(serializePeriod((Period)o));
-               } else if (sType.isBean()) {
-                       serializeBeanMap(out, toBeanMap(o), typeName);
-               } else if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
-                       out.uriValue(o);
-               } else if (sType.isMap()) {
-                       if (o instanceof BeanMap o2)
-                               serializeBeanMap(out, o2, typeName);
-                       else
-                               serializeMap(out, (Map)o, eType);
-               } else if (sType.isCollection()) {
-                       serializeCollection(out, (Collection)o, eType);
-               } else if (sType.isArray()) {
-                       serializeCollection(out, toList(sType.inner(), o), 
eType);
                } else if (sType.isStreamable()) {
                        serializeStreamable(out, o, sType, eType);
                } else if (sType.isReader()) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/markdown/MarkdownParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/markdown/MarkdownParserSession.java
index 1e490f2fc8..f63ebc1b2f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/markdown/MarkdownParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/markdown/MarkdownParserSession.java
@@ -678,16 +678,16 @@ public class MarkdownParserSession extends 
ReaderParserSession {
                // MarshallingContext.get<Format>() hint reaches the wire-form 
coercion.  Without this the
                // fall-through to convertToType(val, eType) below would route 
a bare numeric cell through a
                // generic Number → T coercion (e.g. Duration.ofMillis(long)) 
that drops the format hint.
-               if (eType.isDuration())
-                       return (T) parseDuration(val);
-               if (eType.isPeriod())
-                       return (T) parsePeriod(val);
                if (eType.isDate())
                        return parseDate(val, eType);
                if (eType.isCalendar())
                        return parseCalendar(val, eType);
                if (eType.isTemporal())
                        return parseTemporal(val, eType);
+               if (eType.isDuration())
+                       return (T) parseDuration(val);
+               if (eType.isPeriod())
+                       return (T) parsePeriod(val);
 
                try {
                        return convertToType(val, eType);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/markdown/MarkdownSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/markdown/MarkdownSerializerSession.java
index 6352dcb0de..4b15c6bb59 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/markdown/MarkdownSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/markdown/MarkdownSerializerSession.java
@@ -546,6 +546,13 @@ public class MarkdownSerializerSession extends 
WriterSerializerSession {
                        cm = swap.getSwapClassMeta(this);
                }
 
+               if (cm.isCharSequence() || cm.isEnum()) {
+                       var s = toString(o);
+                       if (isAmbiguousString(s, nullValue))
+                               return "`'" + escapeJson5String(s) + "'`";
+                       return MarkdownWriter.escapeCell(s);
+               }
+
                if (cm.isNumber() || cm.isBoolean())
                        return o.toString();
 
@@ -564,13 +571,6 @@ public class MarkdownSerializerSession extends 
WriterSerializerSession {
                if (cm.isPeriod())
                        return 
MarkdownWriter.escapeCell(serializePeriod((Period)o));
 
-               if (cm.isCharSequence() || cm.isEnum()) {
-                       var s = toString(o);
-                       if (isAmbiguousString(s, nullValue))
-                               return "`'" + escapeJson5String(s) + "'`";
-                       return MarkdownWriter.escapeCell(s);
-               }
-
                // Complex value: serialize as JSON5 in backticks — use 
context-aware serializer for swaps
                try {
                        var json5 = getJson5Serializer().serialize(o);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
index b42e2bfe85..bbb0faf272 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java
@@ -241,32 +241,6 @@ public class MsgPackParserSession extends 
InputStreamParserSession {
 
                        if (sType.isObject()) {
                                // Do nothing.
-                       } else if (sType.isBoolean() || sType.isCharSequence() 
|| sType.isChar() || sType.isNumber() || sType.isByteArray()) {
-                               o = convertToType(o, sType);
-                       } else if (sType.isDate()) {
-                               o = parseDate(String.valueOf(o), sType);
-                       } else if (sType.isCalendar()) {
-                               o = parseCalendar(String.valueOf(o), sType);
-                       } else if (sType.isTemporal()) {
-                               o = parseTemporal(String.valueOf(o), sType);
-                       } else if (sType.isDuration()) {
-                               o = parseDuration(String.valueOf(o));
-                       } else if (sType.isPeriod()) {
-                               o = parsePeriod(String.valueOf(o));
-                       } else if (sType.isMap()) {
-                               if (dt == MAP) {
-                                       Map m = 
(sType.canCreateNewInstance(outer) ? (Map)sType.newInstance(outer) : 
newGenericMap(sType));
-                                       for (var i = 0; i < length; i++) {
-                                               Object key = 
parseAnything(sType.getKeyType(), is, outer, pMeta);
-                                               var vt = sType.getValueType();
-                                               Object value = 
parseAnything(vt, is, m, pMeta);
-                                               setName(vt, value, key);
-                                               m.put(key, value);
-                                       }
-                                       o = m;
-                               } else {
-                                       throw new ParseException(this, "Invalid 
data type {0} encountered for parse type {1}", dt, sType);
-                               }
                        } else if (nn(builder) || 
sType.canCreateNewBean(outer)) {
                                if (dt == MAP) {
                                        BeanMap m = builder == null ? 
newBeanMap(outer, sType.inner()) : toBeanMap(builder.create(this, eType));
@@ -294,6 +268,34 @@ public class MsgPackParserSession extends 
InputStreamParserSession {
                                } else {
                                        throw new ParseException(this, "Invalid 
data type {0} encountered for parse type {1}", dt, sType);
                                }
+                       } else if (sType.isMap()) {
+                               if (dt == MAP) {
+                                       Map m = 
(sType.canCreateNewInstance(outer) ? (Map)sType.newInstance(outer) : 
newGenericMap(sType));
+                                       for (var i = 0; i < length; i++) {
+                                               Object key = 
parseAnything(sType.getKeyType(), is, outer, pMeta);
+                                               var vt = sType.getValueType();
+                                               Object value = 
parseAnything(vt, is, m, pMeta);
+                                               setName(vt, value, key);
+                                               m.put(key, value);
+                                       }
+                                       o = m;
+                               } else {
+                                       throw new ParseException(this, "Invalid 
data type {0} encountered for parse type {1}", dt, sType);
+                               }
+                       } else if (sType.isBoolean() || sType.isCharSequence() 
|| sType.isChar() || sType.isNumber() || sType.isByteArray()) {
+                               // Merged scalar tier: one wire-type 
(BOOLEAN/INT/LONG/FLOAT/DOUBLE/STRING/BIN) covers
+                               // many scalar Java types — the read already 
happened above and convertToType narrows.
+                               o = convertToType(o, sType);
+                       } else if (sType.isDate()) {
+                               o = parseDate(String.valueOf(o), sType);
+                       } else if (sType.isCalendar()) {
+                               o = parseCalendar(String.valueOf(o), sType);
+                       } else if (sType.isTemporal()) {
+                               o = parseTemporal(String.valueOf(o), sType);
+                       } else if (sType.isDuration()) {
+                               o = parseDuration(String.valueOf(o));
+                       } else if (sType.isPeriod()) {
+                               o = parsePeriod(String.valueOf(o));
                        } else if (sType.canCreateNewInstanceFromString(outer) 
&& dt == STRING) {
                                o = sType.newInstanceFromString(outer, o == 
null ? "" : o.toString());
                        } else if (sType.isCollection()) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
index 87cef9b4a1..51bbb7bdf2 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
@@ -262,24 +262,8 @@ public class MsgPackSerializerSession extends 
OutputStreamSerializerSession {
                // '\0' characters are considered null.
                if (o == null || (sType.isChar() && ((Character)o).charValue() 
== 0))
                        out.appendNull();
-               else if (sType.isBoolean())
-                       out.appendBoolean((Boolean)o);
-               else if (sType.isNumber())
-                       out.appendNumber((Number)o);
-               else if (sType.isDate())
-                       out.appendString(serializeDate((Date)o, sType));
-               else if (sType.isCalendar())
-                       out.appendString(serializeCalendar(o, sType));
-               else if (sType.isTemporal())
-                       out.appendString(serializeTemporal((TemporalAccessor)o, 
sType));
-               else if (sType.isDuration())
-                       appendDuration(out, (Duration)o);
-               else if (sType.isPeriod())
-                       out.appendString(serializePeriod((Period)o));
                else if (sType.isBean())
                        serializeBeanMap(out, toBeanMap(o), typeName);
-               else if (sType.isUri() || (nn(pMeta) && pMeta.isUri()))
-                       out.appendString(resolveUri(o.toString()));
                else if (sType.isMap()) {
                        if (o instanceof BeanMap o2)
                                serializeBeanMap(out, o2, typeName);
@@ -291,6 +275,22 @@ public class MsgPackSerializerSession extends 
OutputStreamSerializerSession {
                        out.appendBinary((byte[])o);
                } else if (sType.isArray()) {
                        serializeCollection(out, toList(sType.inner(), o), 
eType);
+               } else if (sType.isBoolean()) {
+                       out.appendBoolean((Boolean)o);
+               } else if (sType.isNumber()) {
+                       out.appendNumber((Number)o);
+               } else if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
+                       out.appendString(resolveUri(o.toString()));
+               } else if (sType.isDate()) {
+                       out.appendString(serializeDate((Date)o, sType));
+               } else if (sType.isCalendar()) {
+                       out.appendString(serializeCalendar(o, sType));
+               } else if (sType.isTemporal()) {
+                       out.appendString(serializeTemporal((TemporalAccessor)o, 
sType));
+               } else if (sType.isDuration()) {
+                       appendDuration(out, (Duration)o);
+               } else if (sType.isPeriod()) {
+                       out.appendString(serializePeriod((Period)o));
                } else if (sType.isStreamable()) {
                        // MsgPack protocol requires array size in header 
(startArray(size)), so materialization is unavoidable.
                        serializeCollection(out, toListFromStreamable(o, 
sType), eType);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/proto/ProtoParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/proto/ProtoParserSession.java
index 16a89252a7..c3fa4f7c45 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/proto/ProtoParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/proto/ProtoParserSession.java
@@ -311,28 +311,30 @@ public class ProtoParserSession extends 
ReaderParserSession {
        private Object convertValue(Object val, ClassMeta<?> targetType) throws 
ParseException, ExecutableException {
                if (val == null)
                        return null;
-               if (val instanceof Map val2 && 
JsonMap.class.isAssignableFrom(targetType.inner()))
-                       return toJsonMap(val2);
-               if (val instanceof Map val2 && targetType.isBean()) {
-                       var typeName = (String) 
val2.get(getBeanTypePropertyName(targetType));
-                       var beanType = targetType;
-                       if (typeName != null && !typeName.isEmpty()) {
-                               var resolved = getClassMeta(typeName, null, 
targetType);
-                               if (resolved != null)
-                                       beanType = resolved;
+               if (val instanceof Map val2) {
+                       if (JsonMap.class.isAssignableFrom(targetType.inner()))
+                               return toJsonMap(val2);
+                       if (targetType.isBean()) {
+                               var typeName = (String) 
val2.get(getBeanTypePropertyName(targetType));
+                               var beanType = targetType;
+                               if (typeName != null && !typeName.isEmpty()) {
+                                       var resolved = getClassMeta(typeName, 
null, targetType);
+                                       if (resolved != null)
+                                               beanType = resolved;
+                               }
+                               var child = 
toBeanMap(beanType.newInstance(getOuter()));
+                               populateBeanMap(child, val2);
+                               return child.getBean();
+                       }
+                       if (targetType.isMap()) {
+                               // When the bean property's declared key type 
is non-String (e.g. Map<TestEnum,String>),
+                               // route through the converter's Map→Map path 
so keys are coerced to the declared type.
+                               // toJsonMap unconditionally toString-keys the 
entries which loses the enum/typed key (Bug #7b).
+                               var keyType = targetType.getKeyType();
+                               if (keyType != null && !keyType.isObject() && 
!keyType.isString())
+                                       return convertToMemberType(null, val2, 
targetType);
+                               return toJsonMap(val2);
                        }
-                       var child = toBeanMap(beanType.newInstance(getOuter()));
-                       populateBeanMap(child, val2);
-                       return child.getBean();
-               }
-               if (val instanceof Map val2 && targetType.isMap()) {
-                       // When the bean property's declared key type is 
non-String (e.g. Map<TestEnum,String>),
-                       // route through the converter's Map→Map path so keys 
are coerced to the declared type.
-                       // toJsonMap unconditionally toString-keys the entries 
which loses the enum/typed key (Bug #7b).
-                       var keyType = targetType.getKeyType();
-                       if (keyType != null && !keyType.isObject() && 
!keyType.isString())
-                               return convertToMemberType(null, val2, 
targetType);
-                       return toJsonMap(val2);
                }
                if (val instanceof List val2 && 
targetType.isCollectionOrArray()) {
                        var elType = targetType.getElementType();
@@ -341,8 +343,12 @@ public class ProtoParserSession extends 
ReaderParserSession {
                                result.add(convertValue(item, elType));
                        return targetType.isArray() ? toArray(targetType, 
result) : result;
                }
-               if (val instanceof Number val2 && targetType.isNumber())
-                       return convertToMemberType(null, val2, targetType);
+               if (val instanceof Number val2) {
+                       if (targetType.isNumber())
+                               return convertToMemberType(null, val2, 
targetType);
+                       if (targetType.isDateOrCalendarOrTemporal())
+                               return 
Iso8601Utils.fromEpochMillis(val2.longValue(), targetType, getTimeZone());
+               }
                if (val instanceof CharSequence val2) {
                        if (targetType.isDate())
                                return parseDate(val2.toString(), targetType);
@@ -375,8 +381,6 @@ public class ProtoParserSession extends ReaderParserSession 
{
                                bytes[i] = (byte) s.charAt(i);
                        return bytes;
                }
-               if (val instanceof Number val2 && 
targetType.isDateOrCalendarOrTemporal())
-                       return Iso8601Utils.fromEpochMillis(val2.longValue(), 
targetType, getTimeZone());
                return convertToMemberType(null, val, targetType);
        }
 }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/proto/ProtoSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/proto/ProtoSerializerSession.java
index 25521f4bd3..71eb94bfbd 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/proto/ProtoSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/proto/ProtoSerializerSession.java
@@ -449,6 +449,8 @@ public class ProtoSerializerSession extends 
WriterSerializerSession {
                                out.integerValue(((Number) value).longValue());
                } else if (type.isBoolean()) {
                        out.booleanValue((Boolean) value);
+               } else if (type.isEnum()) {
+                       out.enumValue(((Enum<?>) value).name());
                } else if (type.isDate()) {
                        out.stringValue(serializeDate((Date)value, type));
                } else if (type.isCalendar()) {
@@ -459,8 +461,6 @@ public class ProtoSerializerSession extends 
WriterSerializerSession {
                        out.stringValue(serializeDuration((Duration)value));
                } else if (type.isPeriod()) {
                        out.stringValue(serializePeriod((Period)value));
-               } else if (type.isEnum()) {
-                       out.enumValue(((Enum<?>) value).name());
                } else if (value instanceof byte[] value2) {
                        out.bytesValue(value2);
                } else {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/toml/TomlParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/toml/TomlParserSession.java
index b4871df958..95bdbe95f7 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/toml/TomlParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/toml/TomlParserSession.java
@@ -392,13 +392,14 @@ public class TomlParserSession extends 
ReaderParserSession {
                String nv = ctx != null ? ctx.getNullValue() : null;
                if (val instanceof String s && nv != null && s.equals(nv))
                        return null;
-               if (val instanceof Map map && 
JsonMap.class.isAssignableFrom(targetType.inner())) {
-                       return toJsonMap(map);
-               }
-               if (val instanceof Map map && targetType.isBean()) {
-                       BeanMap<?> child = 
toBeanMap(targetType.newInstance(getOuter()));
-                       populateBeanMap(child, map);
-                       return child.getBean();
+               if (val instanceof Map map) {
+                       if (JsonMap.class.isAssignableFrom(targetType.inner()))
+                               return toJsonMap(map);
+                       if (targetType.isBean()) {
+                               BeanMap<?> child = 
toBeanMap(targetType.newInstance(getOuter()));
+                               populateBeanMap(child, map);
+                               return child.getBean();
+                       }
                }
                if (val instanceof List list && 
targetType.isCollectionOrArray()) {
                        ClassMeta<?> elType = targetType.getElementType();
@@ -408,26 +409,14 @@ public class TomlParserSession extends 
ReaderParserSession {
                        }
                        return targetType.isArray() ? toArray(targetType, 
result) : result;
                }
-               if (val instanceof Number && targetType.isNumber())
-                       return convertToMemberType(null, val, targetType);
-               if (val instanceof String string) {
-                       if (targetType.isDate())
-                               return parseDate(string, targetType);
-                       if (targetType.isCalendar())
-                               return parseCalendar(string, targetType);
-                       if (targetType.isTemporal())
-                               return parseTemporal(string, targetType);
-                       if (targetType.isDuration())
-                               return parseDuration(string);
-                       if (targetType.isPeriod())
-                               return parsePeriod(string);
-               }
                // Bare numeric wire literals (e.g. "2024", "8100000000000") 
arrive here as Number values
                // from the TOML tokenizer.  Route them through the 
format-aware parsers so the configured
                // MarshallingContext.get<Format>() hint (NANOS, ISO_YEAR, 
MILLIS, …) reaches the coercion.
                // Without this routing the generic Number → T coercion below 
would silently drop the hint
                // (e.g. treating Long(2024) as epoch-millis → 
1970-01-01T00:00:02.024Z instead of year 2024).
                if (val instanceof Number num) {
+                       if (targetType.isNumber())
+                               return convertToMemberType(null, num, 
targetType);
                        if (targetType.isDuration())
                                return parseDuration(num.toString());
                        if (targetType.isPeriod())
@@ -439,6 +428,18 @@ public class TomlParserSession extends ReaderParserSession 
{
                        if (targetType.isTemporal())
                                return parseTemporal(num.toString(), 
targetType);
                }
+               if (val instanceof String string) {
+                       if (targetType.isDate())
+                               return parseDate(string, targetType);
+                       if (targetType.isCalendar())
+                               return parseCalendar(string, targetType);
+                       if (targetType.isTemporal())
+                               return parseTemporal(string, targetType);
+                       if (targetType.isDuration())
+                               return parseDuration(string);
+                       if (targetType.isPeriod())
+                               return parsePeriod(string);
+               }
                // Native TOML datetime literals (Z-zoned / offset / local) are 
returned by TomlTokenizer as
                // java.time.OffsetDateTime / LocalDateTime / LocalDate / 
LocalTime objects.  Re-stringify
                // through the temporal's own ISO toString() and route through 
parseTemporal so the
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/toml/TomlSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/toml/TomlSerializerSession.java
index 82ff3c188f..0ae9f722cf 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/toml/TomlSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/toml/TomlSerializerSession.java
@@ -285,13 +285,32 @@ public class TomlSerializerSession extends 
WriterSerializerSession {
                        w.stringValue(ctx.getNullValue());
                        return;
                }
-               if (aType.isNumber()) {
+               if (aType.isBean()) {
+                       BeanMap<?> bm = toBeanMap(value);
+                       if (shouldUseInlineTable(bm)) {
+                               w.inlineTableStart();
+                               boolean[] first = {true};
+                               Predicate<Object> checkNull = x -> 
isKeepNullProperties() || nn(x);
+                               bm.forEachValue(checkNull, (pm, k, v, th) -> {
+                                       if (!first[0]) w.w(", ");
+                                       first[0] = false;
+                                       writeKey(w, k);
+                                       w.w(" = ");
+                               writeValue(w, v, (ClassMeta<?>) 
pm.getBeanInfo(), pm);
+                               });
+                               w.inlineTableEnd();
+                       } else {
+                               serializeBean(w, bm, "");
+                       }
+               } else if (aType.isNumber()) {
                        if (value instanceof Float || value instanceof Double)
                                w.floatValue(((Number)value).doubleValue());
                        else
                                w.integerValue(((Number)value).longValue());
                } else if (aType.isBoolean()) {
                        w.booleanValue((Boolean)value);
+               } else if (aType.isEnum()) {
+                       w.stringValue(((Enum<?>)value).name());
                } else if (aType.isDate()) {
                        w.w(serializeDate((Date)value, aType));
                } else if (aType.isCalendar()) {
@@ -306,25 +325,6 @@ public class TomlSerializerSession extends 
WriterSerializerSession {
                        w.stringValue(serializeDuration((Duration)value));
                } else if (aType.isPeriod()) {
                        w.stringValue(serializePeriod((Period)value));
-               } else if (aType.isEnum()) {
-                       w.stringValue(((Enum<?>)value).name());
-               } else if (aType.isBean()) {
-                       BeanMap<?> bm = toBeanMap(value);
-                       if (shouldUseInlineTable(bm)) {
-                               w.inlineTableStart();
-                               boolean[] first = {true};
-                               Predicate<Object> checkNull = x -> 
isKeepNullProperties() || nn(x);
-                               bm.forEachValue(checkNull, (pm, k, v, th) -> {
-                                       if (!first[0]) w.w(", ");
-                                       first[0] = false;
-                                       writeKey(w, k);
-                                       w.w(" = ");
-                               writeValue(w, v, (ClassMeta<?>) 
pm.getBeanInfo(), pm);
-                               });
-                               w.inlineTableEnd();
-                       } else {
-                               serializeBean(w, bm, "");
-                       }
                } else if (value.getClass().isArray()) {
                        // Bug #11/#12 a04 residual (generalized): when aType 
arrives erased — most commonly
                        // because the value is a typed List<T[]> bean-property 
element and the parent List's
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java
index 0da857a8c3..f2ef15d15e 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java
@@ -392,24 +392,14 @@ public class UonParserSession extends ReaderParserSession 
implements HttpPartPar
                                        o = s;
                                }
                        }
-               } else if (sType.isBoolean()) {
-                       o = parseBoolean(r);
-               } else if (sType.isCharSequence()) {
-                       o = parseString(r, isUrlParamValue);
-               } else if (sType.isChar()) {
-                       o = parseCharacter(parseString(r, isUrlParamValue));
-               } else if (sType.isNumber()) {
-                       o = parseNumber(r, (Class<? extends 
Number>)sType.inner());
-               } else if (sType.isDate()) {
-                       o = parseDate(parseString(r, isUrlParamValue), sType);
-               } else if (sType.isCalendar()) {
-                       o = parseCalendar(parseString(r, isUrlParamValue), 
sType);
-               } else if (sType.isTemporal()) {
-                       o = parseTemporal(parseString(r, isUrlParamValue), 
sType);
-               } else if (sType.isDuration()) {
-                       o = parseDuration(parseString(r, isUrlParamValue));
-               } else if (sType.isPeriod()) {
-                       o = parsePeriod(parseString(r, isUrlParamValue));
+               } else if (nn(builder)) {
+                       var m = toBeanMap(builder.create(this, eType));
+                       m = parseIntoBeanMap(r, m);
+                       o = m == null ? null : builder.build(this, m.getBean(), 
eType);
+               } else if (sType.canCreateNewBean(outer)) {
+                       var m = newBeanMap(outer, sType.inner());
+                       m = parseIntoBeanMap(r, m);
+                       o = m == null ? null : m.getBean();
                } else if (sType.isMap()) {
                        var m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : newGenericMap(sType));
                        o = parseIntoMap(r, m, sType.getKeyType(), 
sType.getValueType(), pMeta);
@@ -430,18 +420,6 @@ public class UonParserSession extends ReaderParserSession 
implements HttpPartPar
                                var l = (sType.canCreateNewInstance(outer) ? 
(Collection)sType.newInstance(outer) : newGenericList());
                                o = parseIntoCollection(r, l, sType, 
isUrlParamValue, pMeta);
                        }
-               } else if (nn(builder)) {
-                       var m = toBeanMap(builder.create(this, eType));
-                       m = parseIntoBeanMap(r, m);
-                       o = m == null ? null : builder.build(this, m.getBean(), 
eType);
-               } else if (sType.canCreateNewBean(outer)) {
-                       var m = newBeanMap(outer, sType.inner());
-                       m = parseIntoBeanMap(r, m);
-                       o = m == null ? null : m.getBean();
-               } else if (sType.canCreateNewInstanceFromString(outer)) {
-                       var s = parseString(r, isUrlParamValue);
-                       if (nn(s))
-                               o = sType.newInstanceFromString(outer, s);
                } else if (sType.isArray() || sType.isArgs()) {
                        if (c == '(') {
                                var m = newGenericMap();
@@ -459,6 +437,28 @@ public class UonParserSession extends ReaderParserSession 
implements HttpPartPar
                                var l = (ArrayList)parseIntoCollection(r, 
list(), sType, isUrlParamValue, pMeta);
                                o = toArray(sType, l);
                        }
+               } else if (sType.isCharSequence()) {
+                       o = parseString(r, isUrlParamValue);
+               } else if (sType.isChar()) {
+                       o = parseCharacter(parseString(r, isUrlParamValue));
+               } else if (sType.isNumber()) {
+                       o = parseNumber(r, (Class<? extends 
Number>)sType.inner());
+               } else if (sType.isBoolean()) {
+                       o = parseBoolean(r);
+               } else if (sType.isDate()) {
+                       o = parseDate(parseString(r, isUrlParamValue), sType);
+               } else if (sType.isCalendar()) {
+                       o = parseCalendar(parseString(r, isUrlParamValue), 
sType);
+               } else if (sType.isTemporal()) {
+                       o = parseTemporal(parseString(r, isUrlParamValue), 
sType);
+               } else if (sType.isDuration()) {
+                       o = parseDuration(parseString(r, isUrlParamValue));
+               } else if (sType.isPeriod()) {
+                       o = parsePeriod(parseString(r, isUrlParamValue));
+               } else if (sType.canCreateNewInstanceFromString(outer)) {
+                       var s = parseString(r, isUrlParamValue);
+                       if (nn(s))
+                               o = sType.newInstanceFromString(outer, s);
                } else if (c == '(') {
                        // It could be a non-bean with _type attribute.
                        var m = newGenericMap();
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
index f277aa4aff..e73352ed13 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
@@ -507,24 +507,8 @@ public class UonSerializerSession extends 
WriterSerializerSession implements Htt
                // '\0' characters are considered null.
                if (o == null || (sType.isChar() && ((Character)o).charValue() 
== 0))
                        out.appendObject(null, false);
-               else if (sType.isBoolean())
-                       out.appendBoolean(o);
-               else if (sType.isNumber())
-                       out.appendNumber(o);
-               else if (sType.isDate())
-                       out.appendObject(serializeDate((Date)o, sType), false);
-               else if (sType.isCalendar())
-                       out.appendObject(serializeCalendar(o, sType), false);
-               else if (sType.isTemporal())
-                       out.appendObject(serializeTemporal((TemporalAccessor)o, 
sType), false);
-               else if (sType.isDuration())
-                       out.appendObject(serializeDuration((Duration)o), false);
-               else if (sType.isPeriod())
-                       out.appendObject(serializePeriod((Period)o), false);
                else if (sType.isBean())
                        serializeBeanMap(out, toBeanMap(o), typeName);
-               else if (sType.isUri() || (nn(pMeta) && pMeta.isUri()))
-                       out.appendUri(o);
                else if (sType.isMap()) {
                        if (o instanceof BeanMap o2)
                                serializeBeanMap(out, o2, typeName);
@@ -534,6 +518,22 @@ public class UonSerializerSession extends 
WriterSerializerSession implements Htt
                        serializeCollection(out, (Collection)o, eType);
                } else if (sType.isArray()) {
                        serializeCollection(out, toList(sType.inner(), o), 
eType);
+               } else if (sType.isBoolean()) {
+                       out.appendBoolean(o);
+               } else if (sType.isNumber()) {
+                       out.appendNumber(o);
+               } else if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
+                       out.appendUri(o);
+               } else if (sType.isDate()) {
+                       out.appendObject(serializeDate((Date)o, sType), false);
+               } else if (sType.isCalendar()) {
+                       out.appendObject(serializeCalendar(o, sType), false);
+               } else if (sType.isTemporal()) {
+                       out.appendObject(serializeTemporal((TemporalAccessor)o, 
sType), false);
+               } else if (sType.isDuration()) {
+                       out.appendObject(serializeDuration((Duration)o), false);
+               } else if (sType.isPeriod()) {
+                       out.appendObject(serializePeriod((Period)o), false);
                } else if (sType.isStreamable()) {
                        serializeStreamable(out, o, sType, eType);
                } else if (sType.isReader()) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
index 063e84c7da..a1f3c243c3 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java
@@ -276,9 +276,6 @@ public class UrlEncodingParserSession extends 
UonParserSession {
                                o = m.get(CONST_value);
                        else
                                o = cast(m, null, eType);
-               } else if (sType.isMap()) {
-                       var m = (sType.canCreateNewInstance() ? 
(Map)sType.newInstance() : newGenericMap(sType));
-                       o = parseIntoMap2(r, m, sType, m);
                } else if (nn(builder)) {
                        var m = toBeanMap(builder.create(this, eType));
                        m = parseIntoBeanMap(r, m);
@@ -287,6 +284,9 @@ public class UrlEncodingParserSession extends 
UonParserSession {
                        var m = newBeanMap(outer, sType.inner());
                        m = parseIntoBeanMap(r, m);
                        o = m == null ? null : m.getBean();
+               } else if (sType.isMap()) {
+                       var m = (sType.canCreateNewInstance() ? 
(Map)sType.newInstance() : newGenericMap(sType));
+                       o = parseIntoMap2(r, m, sType, m);
                } else if (sType.isCollection() || sType.isArray() || 
sType.isArgs()) {
                        // ?1=foo&2=bar...
                        var c2 = ((sType.isArray() || sType.isArgs()) || ! 
sType.canCreateNewInstance(outer)) ? newGenericList() : 
(Collection)sType.newInstance();
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
index 9e2a5e248d..276d3bb19d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
@@ -284,13 +284,13 @@ public class UrlEncodingSerializerSession extends 
UonSerializerSession {
                                sType = getClassMetaForObject(o);
                }
 
-               if (sType.isMap()) {
+               if (sType.isBean()) {
+                       serializeBeanMap(out, toBeanMap(o), typeName);
+               } else if (sType.isMap()) {
                        if (o instanceof BeanMap o2)
                                serializeBeanMap(out, o2, typeName);
                        else
                                serializeMap(out, (Map)o, sType);
-               } else if (sType.isBean()) {
-                       serializeBeanMap(out, toBeanMap(o), typeName);
                } else if (sType.isCollection() || sType.isArray()) {
                        var m = sType.isCollection() ? 
getCollectionMap((Collection)o) : getCollectionMap(o);
                        serializeCollectionMap(out, m, getClassMeta(Map.class, 
Integer.class, Object.class));
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java
index 7e8fa7faf1..873d55cbe7 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java
@@ -902,12 +902,21 @@ public class XmlParserSession extends ReaderParserSession 
{
                                o = Boolean.parseBoolean(getElementText(r));
                        else if (jsonType == UNKNOWN)
                                o = getUnknown(r);
-               } else if (sType.isBoolean()) {
-                       o = Boolean.parseBoolean(getElementText(r));
-               } else if (sType.isCharSequence()) {
-                       o = getElementText(r);
-               } else if (sType.isChar()) {
-                       o = parseCharacter(getElementText(r));
+               } else if (nn(builder) || sType.canCreateNewBean(outer)) {
+                       if (getXmlClassMeta(sType).getFormat() == COLLAPSED) {
+                               var fieldName = r.getLocalName();
+                               var m = nn(builder) ? 
toBeanMap(builder.create(this, eType)) : newBeanMap(outer, sType.inner());
+                               var bpm = 
getXmlBeanMeta(m.getMeta()).getPropertyMeta(fieldName);
+                               var cm = (ClassMeta<?>) 
m.getMeta().getBeanInfo();
+                               Object value = parseAnything(cm, currAttr, r, 
m.getBean(false), false, null);
+                               setName(cm, value, currAttr);
+                               bpm.set(m, currAttr, value);
+                               o = nn(builder) ? builder.build(this, 
m.getBean(), eType) : m.getBean();
+                       } else {
+                               var m = nn(builder) ? 
toBeanMap(builder.create(this, eType)) : newBeanMap(outer, sType.inner());
+                               m = parseIntoBean(r, m, isNil);
+                               o = nn(builder) ? builder.build(this, 
m.getBean(), eType) : m.getBean();
+                       }
                } else if (sType.isMap()) {
                        var m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : newGenericMap(sType));
                        o = parseIntoMap(r, m, sType.getKeyType(), 
sType.getValueType(), pMeta);
@@ -919,8 +928,17 @@ public class XmlParserSession extends ReaderParserSession {
                } else if (sType.isCollection()) {
                        var l = (sType.canCreateNewInstance(outer) ? 
(Collection)sType.newInstance(outer) : newGenericList());
                        o = parseIntoCollection(r, l, sType, pMeta);
+               } else if (sType.isArray() || sType.isArgs()) {
+                       var l = (ArrayList)parseIntoCollection(r, list(), 
sType, pMeta);
+                       o = toArray(sType, l);
+               } else if (sType.isCharSequence()) {
+                       o = getElementText(r);
+               } else if (sType.isChar()) {
+                       o = parseCharacter(getElementText(r));
                } else if (sType.isNumber()) {
                        o = parseNumber(getElementText(r), (Class<? extends 
Number>)sType.inner());
+               } else if (sType.isBoolean()) {
+                       o = Boolean.parseBoolean(getElementText(r));
                } else if (sType.isDate()) {
                        o = parseDate(getElementText(r), sType);
                } else if (sType.isCalendar()) {
@@ -931,24 +949,6 @@ public class XmlParserSession extends ReaderParserSession {
                        o = parseDuration(getElementText(r));
                } else if (sType.isPeriod()) {
                        o = parsePeriod(getElementText(r));
-               } else if (nn(builder) || sType.canCreateNewBean(outer)) {
-                       if (getXmlClassMeta(sType).getFormat() == COLLAPSED) {
-                               var fieldName = r.getLocalName();
-                               var m = nn(builder) ? 
toBeanMap(builder.create(this, eType)) : newBeanMap(outer, sType.inner());
-                               var bpm = 
getXmlBeanMeta(m.getMeta()).getPropertyMeta(fieldName);
-                               var cm = (ClassMeta<?>) 
m.getMeta().getBeanInfo();
-                               Object value = parseAnything(cm, currAttr, r, 
m.getBean(false), false, null);
-                               setName(cm, value, currAttr);
-                               bpm.set(m, currAttr, value);
-                               o = nn(builder) ? builder.build(this, 
m.getBean(), eType) : m.getBean();
-                       } else {
-                               var m = nn(builder) ? 
toBeanMap(builder.create(this, eType)) : newBeanMap(outer, sType.inner());
-                               m = parseIntoBean(r, m, isNil);
-                               o = nn(builder) ? builder.build(this, 
m.getBean(), eType) : m.getBean();
-                       }
-               } else if (sType.isArray() || sType.isArgs()) {
-                       var l = (ArrayList)parseIntoCollection(r, list(), 
sType, pMeta);
-                       o = toArray(sType, l);
                } else if (sType.canCreateNewInstanceFromString(outer)) {
                        o = sType.newInstanceFromString(outer, 
getElementText(r));
                } else if (nn(sType.getProxyInvocationHandler())) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
index d058428eb6..e153c7f850 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
@@ -1090,7 +1090,21 @@ public class XmlSerializerSession extends 
WriterSerializerSession {
 
                // Render the tag contents.
                if (nn(o)) {
-                       if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
+                       if (sType.isBean()) {
+                               rc = serializeBeanMap(out, toBeanMap(o), 
elementNamespace, isCollapsed, isMixedOrText);
+                       } else if (sType.isMap() || (nn(wType) && 
wType.isMap())) {
+                               if (o instanceof BeanMap o2)
+                                       rc = serializeBeanMap(out, o2, 
elementNamespace, isCollapsed, isMixedOrText);
+                               else
+                                       rc = serializeMap(out, (Map)o, sType, 
eType.getKeyType(), eType.getValueType(), isMixedOrText);
+                       } else if (sType.isCollection() || sType.isArray() || 
(nn(wType) && (wType.isCollection() || wType.isArray()))) {
+                               if (isCollapsed)
+                                       indent--;
+                               serializeCollection(out, o, sType, eType, 
pMeta, isMixedOrText);
+                               if (isCollapsed)
+                                       indent++;
+                       } else if (sType.isUri() || (nn(pMeta) && 
pMeta.isUri())) {
+                               // Must come before isCharSequence/isChar: 
@Uri-annotated String properties (where sType is String but pMeta.isUri() is 
true) need to route here for URI text emission.
                                out.textUri(o);
                        } else if (sType.isCharSequence() || sType.isChar()) {
                                if (isXmlText(format, sType))
@@ -1109,19 +1123,6 @@ public class XmlSerializerSession extends 
WriterSerializerSession {
                                out.text(serializeDuration((Duration)o));
                        } else if (sType.isPeriod()) {
                                out.text(serializePeriod((Period)o));
-                       } else if (sType.isMap() || (nn(wType) && 
wType.isMap())) {
-                               if (o instanceof BeanMap o2)
-                                       rc = serializeBeanMap(out, o2, 
elementNamespace, isCollapsed, isMixedOrText);
-                               else
-                                       rc = serializeMap(out, (Map)o, sType, 
eType.getKeyType(), eType.getValueType(), isMixedOrText);
-                       } else if (sType.isBean()) {
-                               rc = serializeBeanMap(out, toBeanMap(o), 
elementNamespace, isCollapsed, isMixedOrText);
-                       } else if (sType.isCollection() || sType.isArray() || 
(nn(wType) && (wType.isCollection() || wType.isArray()))) {
-                               if (isCollapsed)
-                                       indent--;
-                               serializeCollection(out, o, sType, eType, 
pMeta, isMixedOrText);
-                               if (isCollapsed)
-                                       indent++;
                        } else if (sType.isStreamable()) {
                                if (isCollapsed)
                                        indent--;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlParserSession.java
index 2d0a777b62..043efabf83 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlParserSession.java
@@ -274,6 +274,12 @@ public class YamlParserSession extends ReaderParserSession 
{
                                var m2 = newGenericMap();
                                parseFlowMapping(r, m2, string(), object(), 
pMeta);
                                o = cast(m2, pMeta, eType);
+                       } else if (nn(builder)) {
+                               var m = toBeanMap(builder.create(this, eType));
+                               o = builder.build(this, parseIntoBeanMap(r, 
m).getBean(), eType);
+                       } else if (sType.canCreateNewBean(outer)) {
+                               var m = newBeanMap(outer, sType.inner());
+                               o = parseIntoBeanMap(r, m).getBean();
                        } else if (sType.isMap()) {
                                Map m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : newGenericMap(sType));
                                o = parseFlowMapping(r, m, sType.getKeyType(), 
sType.getValueType(), pMeta);
@@ -281,12 +287,6 @@ public class YamlParserSession extends ReaderParserSession 
{
                                var m = newGenericMap();
                                parseFlowMapping(r, m, string(), object(), 
pMeta);
                                o = cast(m, pMeta, eType);
-                       } else if (nn(builder)) {
-                               var m = toBeanMap(builder.create(this, eType));
-                               o = builder.build(this, parseIntoBeanMap(r, 
m).getBean(), eType);
-                       } else if (sType.canCreateNewBean(outer)) {
-                               var m = newBeanMap(outer, sType.inner());
-                               o = parseIntoBeanMap(r, m).getBean();
                        } else if (sType.isArray() || sType.isArgs()) {
                                var m = newGenericMap();
                                parseFlowMapping(r, m, string(), object(), 
pMeta);
@@ -377,14 +377,6 @@ public class YamlParserSession extends ReaderParserSession 
{
                                m2.put(ts, value);
                                parseBlockMappingRemainder(r, m2, string(), 
object(), pMeta, keyIndent);
                                return cast(m2, pMeta, eType);
-                       } else if (sType.isMap()) {
-                               Map m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : newGenericMap(sType));
-                               Object value = 
parseAnything(sType.getValueType(), r, m, pMeta);
-                               Object key = convertAttrToType(m, trim(s), 
sType.getKeyType());
-                               setName(sType.getValueType(), value, key);
-                               m.put(key, value);
-                               parseBlockMappingRemainder(r, m, 
sType.getKeyType(), sType.getValueType(), pMeta, keyIndent);
-                               return m;
                        } else if (nn(builder)) {
                                var m = toBeanMap(builder.create(this, eType));
                                parseBeanProperty(r, m, s);
@@ -395,6 +387,14 @@ public class YamlParserSession extends ReaderParserSession 
{
                                parseBeanProperty(r, m, s);
                                parseIntoBeanMapBlockRemainder(r, m, keyIndent);
                                return m.getBean();
+                       } else if (sType.isMap()) {
+                               Map m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : newGenericMap(sType));
+                               Object value = 
parseAnything(sType.getValueType(), r, m, pMeta);
+                               Object key = convertAttrToType(m, trim(s), 
sType.getKeyType());
+                               setName(sType.getValueType(), value, key);
+                               m.put(key, value);
+                               parseBlockMappingRemainder(r, m, 
sType.getKeyType(), sType.getValueType(), pMeta, keyIndent);
+                               return m;
                        } else {
                                var m2 = newGenericMap();
                                Object value = parseAnything(object(), r, m2, 
pMeta);
@@ -435,14 +435,6 @@ public class YamlParserSession extends ReaderParserSession 
{
                                m2.put(keyStr, value);
                                parseBlockMappingRemainder(r, m2, string(), 
object(), pMeta, keyIndent);
                                return cast(m2, pMeta, eType);
-                       } else if (sType.isMap()) {
-                               Map m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : newGenericMap(sType));
-                               Object value = 
parseAnything(sType.getValueType(), r, m, pMeta);
-                               Object key = convertAttrToType(m, keyStr, 
sType.getKeyType());
-                               setName(sType.getValueType(), value, key);
-                               m.put(key, value);
-                               parseBlockMappingRemainder(r, m, 
sType.getKeyType(), sType.getValueType(), pMeta, keyIndent);
-                               return m;
                        } else if (nn(builder)) {
                                var m = toBeanMap(builder.create(this, eType));
                                parseBeanProperty(r, m, s);
@@ -453,6 +445,14 @@ public class YamlParserSession extends ReaderParserSession 
{
                                parseBeanProperty(r, m, s);
                                parseIntoBeanMapBlockRemainder(r, m, keyIndent);
                                return m.getBean();
+                       } else if (sType.isMap()) {
+                               Map m = (sType.canCreateNewInstance(outer) ? 
(Map)sType.newInstance(outer) : newGenericMap(sType));
+                               Object value = 
parseAnything(sType.getValueType(), r, m, pMeta);
+                               Object key = convertAttrToType(m, keyStr, 
sType.getKeyType());
+                               setName(sType.getValueType(), value, key);
+                               m.put(key, value);
+                               parseBlockMappingRemainder(r, m, 
sType.getKeyType(), sType.getValueType(), pMeta, keyIndent);
+                               return m;
                        } else {
                                var m2 = newGenericMap();
                                Object value = parseAnything(object(), r, m2, 
pMeta);
@@ -485,14 +485,14 @@ public class YamlParserSession extends 
ReaderParserSession {
        private Object convertToType(String s, ClassMeta<?> sType, ClassMeta<?> 
eType, Object outer, BeanPropertyMeta pMeta) throws ParseException {
                if (sType.isObject()) {
                        return resolveScalarType(trim(s));
-               } else if (sType.isBoolean()) {
-                       return bool(s);
                } else if (sType.isCharSequence()) {
                        return trim(s);
                } else if (sType.isChar()) {
                        return parseCharacter(s);
                } else if (sType.isNumber()) {
                        return StringUtils.parseNumber(s, (Class<? extends 
Number>)sType.inner());
+               } else if (sType.isBoolean()) {
+                       return bool(s);
                } else if (sType.isDate()) {
                        return parseDate(s, sType);
                } else if (sType.isCalendar()) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlSerializerSession.java
index 178b53719e..c0f722c2ae 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlSerializerSession.java
@@ -285,12 +285,8 @@ public class YamlSerializerSession extends 
WriterSerializerSession {
 
                if (o == null || (sType.isChar() && ((Character)o).charValue() 
== 0)) {
                        out.append("null");
-               } else if (sType.isNumber() || sType.isBoolean()) {
-                       out.append(o);
                } else if (sType.isBean()) {
                        serializeBeanMap(out, toBeanMap(o), typeName);
-               } else if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
-                       out.uriValue(o);
                } else if (sType.isMap()) {
                        if (o instanceof BeanMap o2)
                                serializeBeanMap(out, o2, typeName);
@@ -300,6 +296,10 @@ public class YamlSerializerSession extends 
WriterSerializerSession {
                        serializeCollection(out, (Collection)o, eType, asField);
                } else if (sType.isArray()) {
                        serializeCollection(out, toList(sType.inner(), o), 
eType, asField);
+               } else if (sType.isNumber() || sType.isBoolean()) {
+                       out.append(o);
+               } else if (sType.isUri() || (nn(pMeta) && pMeta.isUri())) {
+                       out.uriValue(o);
                } else if (sType.isReader()) {
                        pipe((Reader)o, out, SerializerSession::handleThrown);
                } else if (sType.isInputStream()) {
diff --git a/todo/TODO-56-serializer-parser-dispatch-cleanup.md 
b/todo/FINISHED-56-serializer-parser-dispatch-cleanup.md
similarity index 74%
rename from todo/TODO-56-serializer-parser-dispatch-cleanup.md
rename to todo/FINISHED-56-serializer-parser-dispatch-cleanup.md
index 4540504032..ada9b4f864 100644
--- a/todo/TODO-56-serializer-parser-dispatch-cleanup.md
+++ b/todo/FINISHED-56-serializer-parser-dispatch-cleanup.md
@@ -4,6 +4,90 @@ Source: filed 2026-05-21 in response to the recent 
JIT/dispatch analysis on `Cla
 
 ---
 
+## Status (2026-05-22, final closeout)
+
+**Phase 1 parser-side, this pass — all in-scope `*ParserSession` chains 
reordered to canonical order, with wire-token-driven correctness gates 
preserved.**
+
+Files touched this pass (parser-side):
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParserSession.java`
 — `parseAnything` reordered; structural branches (builder → bean → map → 
collection → array → charSeq → char → number → boolean → temporal cluster) 
follow the canonical sequence after the `isObject` peek-char dispatch and the 
wire-token (`c == '{' / '[' / 'n'`) gates.
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParserSession.java`
 — `parseAnything` reordered; `isVoid` and the URL-blank-param pre-check stay 
at top, `builder` / `canCreateNewBean` promoted above `isMap` / `isCollection` 
/ `isArray`.
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParserSession.java`
 — `parseAnything` reordered; `builder` and `canCreateNewBean` promoted before 
`isMap` / `isCollection`.
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParserSession.java`
 — `parseAnything` structural tail reordered; the `isObject` jsonType-driven 
branch stays at top.
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParserSession.java`
 — both the text-content cascade (`tag == null || tag.isOneOf(BR, BS, FF, SP)`) 
scalar order and the TABLE/object cascade structural tail reordered. Outer 
tag-first dispatch left alone (correctness-load-bearing per the inventory note).
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/yaml/YamlParserSession.java`
 — `parseAnything` (the `c == '{'` cascade), `handleQuotedScalar`, 
`handlePlainScalar`, and `convertToType` reordered.
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/markdown/MarkdownParserSession.java`
 — `parseCellValue` temporal cluster reordered to canonical sequence (`isDate` 
→ `isCalendar` → `isTemporal` → `isDuration` → `isPeriod`).
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParserSession.java`
 — `parseAnything` structural tail reordered, keeping the merged-scalar tier 
and wire-type pre-dispatch in place.
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cbor/CborParserSession.java`
 — mirror of MsgPack reorder.
+- 
`juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParserSession.java`
 — `parseAnything` structural tail reordered, after the RDF_NIL guard and 
`isObject` literal/resource/Seq pre-dispatch.
+- 
`juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfStreamParserSession.java`
 — `parseAnything` structural tail reordered. **Important:** `isByteArray` 
deliberately stays *adjacent to the scalar tier* (after `isCharSequence`) — and 
crucially *below* `isCollectionOrArray` — because the RDF byte-array node is a 
typed base64 literal that's read through the same scalar-path helper 
(`getValue(n, outer)`); moving `isByteArray` earlier (above 
`isCollectionOrArray`) caused [...]
+
+Files reviewed but unchanged (already in canonical order, wire-token-shaped, 
or not a reorder candidate):
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hjson/HjsonParserSession.java`
 — no top-level canonical chain; piecemeal sites already in order.
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/hocon/HoconParserSession.java`
 — same as Hjson.
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ini/IniParserSession.java`
 — `parseValue` is wire-token-driven and the type branches are already 
structural-first; no reorder needed.
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/toml/TomlParserSession.java`
 — `convertValue` already addressed in Phase 2.
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/proto/ProtoParserSession.java`
 — `convertValue` already addressed in Phase 2; `parseAnything` delegates.
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/bson/BsonParserSession.java`
 — no canonical chain (convertToType-driven).
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParserSession.java`
 — highly specialized row-shape parser; `parseAnything` and `parseCellValue` 
are structural-first already, no reorder candidate.
+- 
`juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parquet/ParquetParserSession.java`
 — out of scope per the Phase-1 carve-out (row-oriented, schema-driven).
+
+**Verification (final, this pass):**
+- `mvn -pl juneau-utest -am 
-Dtest='Proto*Test,Hjson*Test,Hocon*Test,Bson*Test,Toml*Test,Csv*Test,Markdown*Test,Yaml*Test,Ini*Test,Json5*Test,JsonParser*Test,XmlParser*Test,UrlEncodingParser*Test,UonParser*Test'
 …` — green.
+- `./scripts/test.py -v` (clean build + tests) — **126,680 tests pass, 0 
failures, 0 errors, 20 skipped** (baseline restored after the 
`RdfStreamParserSession` byte[] ordering regression was fixed mid-pass).
+- `./scripts/test.py -b` (mvn clean install) — green.
+
+**Latent bugs surfaced this pass:** none net-net. One *self-inflicted* 
regression was caught and fixed during testing: an earlier attempt at 
reordering `RdfStreamParserSession.parseAnything` put `isByteArray` above 
`isCollectionOrArray` for symmetry with the canonical order, which broke 
base64-typed-literal parsing (`ResourceRequiredException` on 
`"AQ=="^^xsd:base64Binary`). The ordering constraint is now commented in the 
file.
+
+**Phase 4 / Phase 5 disposition:**
+- **Phase 4** (`Category primaryCategory()` switch pilot) — punted as 
**explicitly optional** per the plan's own "Roll-out decision" note. Not gating 
completion.
+- **Phase 5** (`MarshallDispatchBenchmark` JMH) — punted as **explicitly 
optional** per the plan's "sanity check, not a pre-commit blocker" framing. Not 
gating completion.
+
+Phase 1 (both sides), Phase 2, and Phase 3 are now complete; that satisfies 
the readability + behavior-preserving goal the plan was filed to deliver. Plan 
archived to `FINISHED-56-serializer-parser-dispatch-cleanup.md`.
+
+---
+
+## Status (2026-05-22 worker pass — prior serializer-side pass)
+
+**Done:**
+- **Phase 2** — both files hoisted:
+  - `ProtoParserSession.convertValue` — three `Map val2` and two `Number val2` 
checks collapsed into single outer pattern-match blocks; `CharSequence val2` 
left as-is (already hoisted).
+  - `TomlParserSession.convertValue` — two `Map map` checks hoisted into one 
outer block; two `Number num` checks (separated only by a `String` block that 
can never match a Number) merged into a single outer `Number` block with 
`isNumber` checked first.
+- **Phase 3** — `ClassMeta` polish:
+  - Marked `ClassMeta<T>` class `final` (no `extends ClassMeta` consumers 
found in `juneau-marshall`, `juneau-marshall-rdf`, `juneau-utest`, 
`juneau-rest-*`, `juneau-microservice-*`, `juneau-bean-*`, or `juneau-docs`).
+  - Dropped the defensive `cat != null &&` guards from `isCollection()`, 
`isMap()`, and `isUri()`; removed the obsolete "Defensive null-guard …" comment 
from `isMap()`.
+  - Did **not** add `final` to individual `isXxx` methods (class-level `final` 
already covers them per the plan).
+- **Phase 1 — serializer-side reorders applied** (canonical bean → map → 
collection → array → charSeq → number/boolean → uri → temporal cluster → 
streamable/reader/inputstream → tail, with pre-dispatch correctness gates 
preserved):
+  - `JsonSerializerSession.serializeAnything` — the canonical "winner" file; 
reorder applied.
+  - `UonSerializerSession.serializeAnything` — same shape as JSON, reordered.
+  - `UrlEncodingSerializerSession.serializeAnything` — minor swap of `isMap` ↔ 
`isBean` to align with canonical order.
+  - `HjsonSerializerSession.serializeAnything` — same shape as JSON, reordered.
+  - `HoconSerializerSession.serializeAnything` — same shape as JSON, 
reordered; `byte[]` Base64 gate preserved at top after the null gate.
+  - `YamlSerializerSession.serializeAnything` — reordered; YAML omits the 
temporal cluster (falls through to `toString`) per the inventory note.
+  - `MarkdownSerializerSession.serializeInlineValue` — scalar-tail polish: 
`isCharSequence || isEnum` lifted above the temporal cluster. Main 
`serializeAnything` was already structural-first and was left as-is.
+  - `HtmlSerializerSession.serializeAnything` (write pass) — reordered; 
`isReader || isInputStream` short-circuit and HTML-specific `isXml` / 
`isPlainText` gates preserved at the top.
+  - `XmlSerializerSession.serializeAnything` (write pass at 1093-1133) — 
reordered; classify pass at 988-1004 left alone (correctness-load-bearing). 
**Important:** `isUri || pMeta.isUri()` deliberately stays *before* 
`isCharSequence || isChar` because `@Uri`-annotated `String` properties (where 
`sType` is `String` but `pMeta.isUri()` is true) must route through the URI 
text-emission path; a comment was added at the branch.
+  - `IniSerializerSession.formatSimpleValue` — scalar-tail polish: 
`isCharSequence || isUri` lifted above number/temporal.
+  - `TomlSerializerSession.writeValue` — `isBean` promoted to the top of the 
leaf-value chain; rest left in place (the runtime `value.getClass().isArray()` 
gate stays *before* `isCollection() || isArray()` so erased-array values still 
hit the inline-array emission path).
+  - `MsgPackSerializerSession.serializeAnything` — reordered; the 
binary-format `isByteArray` branch stays adjacent to `isCollection` (between 
collection and generic array dispatch).
+  - `CborSerializerSession.serializeAnything` — mirror of MsgPack reorder.
+  - `BsonSerializerSession.writeElement` — reordered; `isCharSequence || 
isChar || isEnum` lifted from near the bottom to its canonical slot.
+  - `ProtoSerializerSession.serializeScalarValue` — chain was essentially 
already in canonical order at the scalar-leaf level; only `isEnum` ordering 
verified. Top-level `serializeAnything` (131-237) untouched (already 
structural-first per the inventory note).
+  - `RdfSerializerSession.serializeAnything` and 
`RdfStreamSerializerSession.serializeAnything` — `isBean` / `isMap` / 
`isCollectionOrArray` promoted above `isCharSequence` / `isNumber`. 
**Important:** `isUri || isURI` deliberately stays at the top (after the null 
gate) because RDF URIs must emit as `Resource`s, not literals; a comment was 
added. For `RdfStreamSerializerSession`, `isByteArray` was kept *before* 
`isCollectionOrArray` (byte[] satisfies `isArray()` but RDF emits it as a typ 
[...]
+
+**Verification:**
+- Baseline `mvn -pl juneau-utest -am 
-Dtest='Proto*Test,Hjson*Test,Hocon*Test,Bson*Test,Toml*Test,Csv*Test,Markdown*Test,Yaml*Test,Ini*Test,Json5*Test,JsonParser*Test,XmlParser*Test,UrlEncodingParser*Test,UonParser*Test'
 …` — green (1315 tests).
+- Per-format target tests run incrementally during each file's edit — all 
green.
+- Final `./scripts/test.py -v` — **126,680 tests pass, 0 failures, 0 errors, 
20 skipped** (the skipped count is the baseline; no regressions).
+- Final `./scripts/test.py -b` (mvn clean install) — green.
+
+**Deferred — picked up in the 2026-05-22 final closeout above:**
+- **Phase 1, parser-side chains** — done in the closeout pass. See the file 
list at the top of this status section.
+- **Phase 4** and **Phase 5** — both remain explicitly optional and are punted 
per the plan's own optional-marker language. Not gating completion.
+
+**Latent bugs surfaced:** none. All reorders were behavior-preserving; the 
comments added on `XmlSerializerSession`, `RdfSerializerSession`, 
`RdfStreamSerializerSession`, and `HoconSerializerSession` document the 
ordering constraints that prevent a future reorder from regressing them.
+
+---
+
 ## Background
 
 ### Why the dispatch chains came up

Reply via email to