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 e0bb0767af Various toString() improvements
e0bb0767af is described below

commit e0bb0767af2e7c4aadb55bb75dd1a3d6bb411758
Author: James Bognar <[email protected]>
AuthorDate: Mon Dec 15 10:00:13 2025 -0500

    Various toString() improvements
---
 AI.md                                              |  23 ++
 .../commons/annotation/AnnotationObject.java       |  10 +-
 .../juneau/commons/collections/FluentMap.java      |  29 +++
 .../juneau/commons/reflect/AnnotationInfo.java     |  34 +--
 .../juneau/commons/reflect/ReflectionMap.java      | 101 ++++----
 .../juneau/commons/utils/CollectionUtils.java      |  51 +++-
 .../org/apache/juneau/commons/utils/Utils.java     |  65 +++++
 .../src/main/java/org/apache/juneau/BeanMeta.java  |  14 +-
 .../java/org/apache/juneau/BeanPropertyMeta.java   |  13 +-
 .../java/org/apache/juneau/BeanPropertyValue.java  |  21 +-
 .../main/java/org/apache/juneau/BeanRegistry.java  |  14 +-
 .../src/main/java/org/apache/juneau/Context.java   |   2 +-
 .../java/org/apache/juneau/ContextSession.java     |   2 +-
 .../main/java/org/apache/juneau/UriContext.java    | 276 +++++++++++----------
 .../java/org/apache/juneau/cp/BasicFileFinder.java |  25 +-
 .../main/java/org/apache/juneau/cp/BeanStore.java  |  32 ++-
 .../main/java/org/apache/juneau/cp/Messages.java   |  14 +-
 .../org/apache/juneau/httppart/HttpPartSchema.java |  78 +++---
 .../org/apache/juneau/svl/VarResolverSession.java  |  11 +-
 .../java/org/apache/juneau/utils/BeanDiff.java     |  15 +-
 .../main/java/org/apache/juneau/utils/HashKey.java |  19 +-
 .../java/org/apache/juneau/utils/ManifestFile.java |   2 +-
 .../apache/juneau/rest/mock/MockPathResolver.java  |  25 +-
 .../apache/juneau/rest/debug/DebugEnablement.java  |  20 +-
 .../juneau/rest/httppart/RequestAttributes.java    |  10 +-
 .../juneau/rest/httppart/RequestFormParams.java    |  15 +-
 .../juneau/rest/httppart/RequestHeaders.java       |  15 +-
 .../juneau/rest/httppart/RequestPathParams.java    |  13 +-
 .../juneau/rest/httppart/RequestQueryParams.java   |  15 +-
 .../org/apache/juneau/rest/logger/CallLogger.java  |  29 ++-
 .../apache/juneau/rest/logger/CallLoggerRule.java  |  32 +--
 .../juneau/rest/staticfile/BasicStaticFiles.java   |  12 +-
 .../apache/juneau/rest/stats/MethodExecStats.java  |  21 +-
 .../org/apache/juneau/rest/stats/ThrownStats.java  |  19 +-
 .../java/org/apache/juneau/rest/util/UrlPath.java  |  18 +-
 .../org/apache/juneau/rest/util/UrlPathMatch.java  |  16 +-
 .../commons/annotation/AnnotationObject_Test.java  |   6 +-
 .../annotation/AppliedAnnotationObject_Test.java   |   2 +-
 .../AppliedOnClassAnnotationObject_Test.java       |   6 +-
 .../commons/reflect/AnnotationInfo_Test.java       |  10 +-
 .../juneau/commons/reflect/ReflectionMap_Test.java |   2 +-
 .../java/org/apache/juneau/cp/BeanStore_Test.java  |  12 +-
 .../java/org/apache/juneau/cp/Messages_Test.java   |   2 +-
 .../remote/Remote_FormDataAnnotation_Test.java     |  28 +--
 .../http/remote/Remote_HeaderAnnotation_Test.java  |  24 +-
 .../http/remote/Remote_QueryAnnotation_Test.java   |  26 +-
 .../apache/juneau/rest/annotation/Path_Test.java   |  62 ++---
 .../juneau/rest/util/UrlPathMatcher_Test.java      |  86 +++----
 ...t.java => SerializerConfigAnnotation_Test.java} |  26 +-
 .../{BeanDiffTest.java => BeanDiff_Test.java}      |  24 +-
 50 files changed, 882 insertions(+), 545 deletions(-)

diff --git a/AI.md b/AI.md
index 44e562af62..33f4585ef1 100644
--- a/AI.md
+++ b/AI.md
@@ -406,6 +406,29 @@ When adding fluent setter overrides to classes:
   ```
 - **Rationale**: Maintains consistency with existing code style and improves 
readability
 
+#### properties() Method Formatting
+When creating a `properties()` method that uses the fluent map API with `.a()` 
method calls:
+
+1. **Always use `Utils.filteredBeanPropertyMap()`**: Use 
`filteredBeanPropertyMap()` to create the map. This method provides sorted, 
filtered, fluent maps specifically designed for bean property maps.
+2. **Wrap in formatter comments**: Wrap the entire method contents inside `// 
@formatter:off` and `// @formatter:on` comments to preserve formatting
+
+```java
+protected FluentMap<String,Object> properties() {
+       // @formatter:off
+       return filteredBeanPropertyMap()
+               .a("property1", value1)
+               .a("property2", value2)
+               .a("property3", value3);
+       // @formatter:on
+}
+```
+
+**Rationale**: 
+- `filteredBeanPropertyMap()` automatically provides sorted entries, filtered 
values (removes empty/null values), and a fluent API
+- Ensures consistent ordering for deterministic output
+- Provides a clean, dedicated API for building bean property maps
+- Formatter comments preserve the formatting of fluent method chains and 
prevent formatters from reformatting the code in ways that reduce readability
+
 ---
 
 # Documentation Guidelines for Apache Juneau
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/annotation/AnnotationObject.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/annotation/AnnotationObject.java
index 0977eaca9d..48aae6f353 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/annotation/AnnotationObject.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/annotation/AnnotationObject.java
@@ -16,8 +16,8 @@
  */
 package org.apache.juneau.commons.annotation;
 
-import static java.util.Arrays.*;
 import static org.apache.juneau.commons.utils.AssertionUtils.*;
+import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
 
 import java.lang.annotation.*;
@@ -208,21 +208,21 @@ public class AnnotationObject implements Annotation {
         *
         * @return This annotation as a map of key/value pairs.
         */
-       public Map<String,Object> toMap() {
-               var m = new LinkedHashMap<String,Object>();
+       protected Map<String,Object> propertyMap() {
                // @formatter:off
+               var m = mapb_so().sorted().build();
                stream(annotationType().getDeclaredMethods())
                        // Note: isAnnotation() check is defensive code. For 
properly-formed AnnotationObject instances,
                        // annotationType() always returns an annotation 
interface, so this condition is always true.
                        .filter(x->x.getParameterCount() == 0 && 
x.getDeclaringClass().isAnnotation())
                        .sorted(Comparator.comparing(Method::getName))
                        .forEach(x -> m.put(x.getName(), 
safeSupplier(()->x.invoke(this))));
-               // @formatter:on
                return m;
+               // @formatter:on
        }
 
        @Override /* Overridden from Object */
        public String toString() {
-               return toMap().toString();
+               return r(propertyMap());
        }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/FluentMap.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/FluentMap.java
index e7bad56d2c..1687699c8d 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/FluentMap.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/collections/FluentMap.java
@@ -19,6 +19,7 @@ package org.apache.juneau.commons.collections;
 import static org.apache.juneau.commons.utils.AssertionUtils.*;
 
 import java.util.*;
+import java.util.function.Predicate;
 
 /**
  * A fluent wrapper around an arbitrary map that provides convenient methods 
for adding entries.
@@ -172,6 +173,34 @@ public class FluentMap<K,V> extends AbstractMap<K,V> {
                return this;
        }
 
+       /**
+        * Adds a key-value pair to this map if the specified predicate returns 
<jk>true</jk> when applied to the value.
+        *
+        * <p>
+        * This method is useful for conditionally adding entries based on the 
value itself.
+        * The predicate is applied to the value, and if it returns 
<jk>true</jk>, the entry is added.
+        * If the predicate returns <jk>false</jk>, the entry is not added and 
this method returns <c>this</c>
+        * without modifying the map.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      FluentMap&lt;String, String&gt; <jv>map</jv> = <jk>new</jk> 
FluentMap&lt;&gt;(<jk>new</jk> LinkedHashMap&lt;&gt;())
+        *              .a(<js>"host"</js>, <js>"localhost"</js>)
+        *              .ai(s -&gt; !s.isEmpty(), <js>"debug"</js>, 
<js>"true"</js>)   <jc>// Added (value is not empty)</jc>
+        *              .ai(s -&gt; !s.isEmpty(), <js>"test"</js>, 
<js>""</js>);       <jc>// Not added (value is empty)</jc>
+        * </p>
+        *
+        * @param predicate The predicate to test on the value. If it returns 
<jk>true</jk>, the entry is added; if <jk>false</jk>, it is not.
+        * @param key The key to add if the predicate returns <jk>true</jk>.
+        * @param value The value to add if the predicate returns <jk>true</jk>.
+        * @return This object for method chaining.
+        */
+       public FluentMap<K,V> ai(Predicate<V> predicate, K key, V value) {
+               if (predicate.test(value))
+                       map.put(key, value);
+               return this;
+       }
+
        @Override
        public Set<Entry<K,V>> entrySet() {
                return map.entrySet();
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/AnnotationInfo.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/AnnotationInfo.java
index 7c9047e145..f6c0de9da6 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/AnnotationInfo.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/AnnotationInfo.java
@@ -27,6 +27,7 @@ import java.util.*;
 import java.util.function.*;
 
 import org.apache.juneau.commons.annotation.*;
+import org.apache.juneau.commons.collections.*;
 
 /**
  * Encapsulates information about an annotation instance and the element it's 
declared on.
@@ -696,25 +697,26 @@ public class AnnotationInfo<T extends Annotation> {
         *
         * @return A new map showing the attributes of this annotation info.
         */
-       public LinkedHashMap<String,Object> toMap() {
-               var jm = new LinkedHashMap<String,Object>();
-               jm.put(s(annotatable.getAnnotatableType()), 
annotatable.getLabel());
-               var ja = new LinkedHashMap<String,Object>();
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
                var ca = info(a.annotationType());
+               var ja = mapb().sorted().buildFluent();  // NOAI
                ca.getDeclaredMethods().stream().forEach(x -> {
-                       try {
-                               var v = x.invoke(a);
+                       safeOptCatch(() -> {
+                               var val = x.invoke(a);
                                var d = x.inner().getDefaultValue();
-                               if (ne(v, d)) {
-                                       if (! (isArray(v) && length(v) == 0 && 
length(d) == 0))
-                                               ja.put(x.getName(), v);
+                               // Add values only if they're different from 
the default.
+                               if (ne(val, d)) {
+                                       if (! (isArray(val) && length(val) == 0 
&& isArray(d) && length(d) == 0))
+                                               return val;
                                }
-                       } catch (Exception e) {
-                               ja.put(x.getName(), lm(e));
-                       }
+                               return null;
+                       }, e -> lm(e)).ifPresent(v -> ja.a(x.getName(), v));
                });
-               jm.put("@" + ca.getNameSimple(), ja);
-               return jm;
+               return filteredBeanPropertyMap()
+                       .a(s(annotatable.getAnnotatableType()), 
annotatable.getLabel())
+                       .a("@" + ca.getNameSimple(), ja);
+               // @formatter:on
        }
 
        /**
@@ -741,12 +743,12 @@ public class AnnotationInfo<T extends Annotation> {
         * Returns a string representation of this annotation.
         *
         * <p>
-        * Returns the map representation created by {@link #toMap()}.
+        * Returns the map representation created by {@link #properties()}.
         *
         * @return A string representation of this annotation.
         */
        @Override /* Overridden from Object */
        public String toString() {
-               return toMap().toString();
+               return r(properties());
        }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ReflectionMap.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ReflectionMap.java
index bf119be6ef..7f58be65be 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ReflectionMap.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/reflect/ReflectionMap.java
@@ -27,6 +27,7 @@ import java.util.*;
 import java.util.function.*;
 import java.util.stream.*;
 
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.utils.*;
 
 /**
@@ -313,17 +314,19 @@ public class ReflectionMap<V> {
                        return classMatches(simpleName, fullName, c);
                }
 
-               @Override
-               public String toString() {
+               protected FluentMap<String,Object> properties() {
                        // @formatter:off
-                       return mapb().filtered()
-                               .add("simpleName", simpleName)
-                               .add("fullName", fullName)
-                               .add("value", value)
-                               .build()
-                               .toString();
+                       return filteredBeanPropertyMap()
+                               .a("simpleName", simpleName)
+                               .a("fullName", fullName)
+                               .a("value", value);
                        // @formatter:on
                }
+
+               @Override
+               public String toString() {
+                       return r(properties());
+               }
        }
 
        private static class ConstructorEntry<V> {
@@ -350,18 +353,20 @@ public class ReflectionMap<V> {
                        return classMatches(simpleClassName, fullClassName, c) 
&& (argsMatch(args, m.getParameterTypes()));
                }
 
-               @Override
-               public String toString() {
+               protected FluentMap<String,Object> properties() {
                        // @formatter:off
-                       return mapb().filtered()
-                               .add("simpleClassName", simpleClassName)
-                               .add("fullClassName", fullClassName)
-                               .add("args", args)
-                               .add("value", value)
-                               .build()
-                               .toString();
+                       return filteredBeanPropertyMap()
+                               .a("simpleClassName", simpleClassName)
+                               .a("fullClassName", fullClassName)
+                               .a("args", args)
+                               .a("value", value);
                        // @formatter:on
                }
+
+               @Override
+               public String toString() {
+                       return r(properties());
+               }
        }
 
        private static class FieldEntry<V> {
@@ -385,18 +390,20 @@ public class ReflectionMap<V> {
                        return classMatches(simpleClassName, fullClassName, c) 
&& (eq(f.getName(), fieldName));
                }
 
-               @Override
-               public String toString() {
+               protected FluentMap<String,Object> properties() {
                        // @formatter:off
-                       return mapb().filtered()
-                               .add("simpleClassName", simpleClassName)
-                               .add("fullClassName", fullClassName)
-                               .add("fieldName", fieldName)
-                               .add("value", value)
-                               .build()
-                               .toString();
+                       return filteredBeanPropertyMap()
+                               .a("simpleClassName", simpleClassName)
+                               .a("fullClassName", fullClassName)
+                               .a("fieldName", fieldName)
+                               .a("value", value);
                        // @formatter:on
                }
+
+               @Override
+               public String toString() {
+                       return r(properties());
+               }
        }
 
        private static class MethodEntry<V> {
@@ -434,19 +441,21 @@ public class ReflectionMap<V> {
                        // @formatter:on
                }
 
-               @Override
-               public String toString() {
+               protected FluentMap<String,Object> properties() {
                        // @formatter:off
-                       return mapb().filtered()
-                               .add("simpleClassName", simpleClassName)
-                               .add("fullClassName", fullClassName)
-                               .add("methodName", methodName)
-                               .add("args", opt(args).map(x -> '[' + toCdl(x) 
+ "]").orElse(null))
-                               .add("value", value)
-                               .build()
-                               .toString();
+                       return filteredBeanPropertyMap()
+                               .a("simpleClassName", simpleClassName)
+                               .a("fullClassName", fullClassName)
+                               .a("methodName", methodName)
+                               .a("args", opt(args).map(x -> '[' + toCdl(x) + 
"]").orElse(null))
+                               .a("value", value);
                        // @formatter:on
                }
+
+               @Override
+               public String toString() {
+                       return r(properties());
+               }
        }
 
        /**
@@ -709,16 +718,18 @@ public class ReflectionMap<V> {
                return methodEntries.stream().filter(x -> x.matches(m)).map(x 
-> x.value);
        }
 
-       @Override /* Overridden from Object */
-       public String toString() {
+       protected FluentMap<String,Object> properties() {
                // @formatter:off
-               return mapb().filtered()
-                       .add("classEntries", classEntries)
-                       .add("methodEntries", methodEntries)
-                       .add("fieldEntries", fieldEntries)
-                       .add("constructorEntries", constructorEntries)
-                       .build()
-                       .toString();
+               return filteredBeanPropertyMap()
+                       .a("classEntries", classEntries)
+                       .a("methodEntries", methodEntries)
+                       .a("fieldEntries", fieldEntries)
+                       .a("constructorEntries", constructorEntries);
                // @formatter:on
        }
+
+       @Override /* Overridden from Object */
+       public String toString() {
+               return r(properties());
+       }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/CollectionUtils.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/CollectionUtils.java
index 06f75b285d..e770e30db5 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/CollectionUtils.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/CollectionUtils.java
@@ -1524,6 +1524,30 @@ public class CollectionUtils {
                return m;
        }
 
+       /**
+        * Convenience factory for a {@link Maps} builder.
+        *
+        * <p>
+        * This is a shortcut for <c>Maps.create().ordered()</c>.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      Map&lt;String,Object&gt; <jv>map</jv> = mapb()
+        *              .add(<js>"foo"</js>, 1)
+        *              .add(<js>"bar"</js>, 2)
+        *              .build();
+        * </p>
+        *
+        * @param <K> The key type.
+        * @param <V> The value type.
+        * @return A new map builder.
+        * @see Maps
+        */
+       @SuppressWarnings("unchecked")
+       public static <K,V> Maps<K,V> mapb() {
+               return (Maps<K,V>)Maps.create().ordered();
+       }
+
        /**
         * Convenience factory for a {@link Maps} with {@link String} keys and 
{@link Object} values.
         *
@@ -1552,10 +1576,35 @@ public class CollectionUtils {
         * @return A new map builder.
         * @see Maps
         */
-       public static Maps<String,Object> mapb() {
+       public static Maps<String,Object> mapb_so() {
                return Maps.create(String.class, Object.class).ordered();
        }
 
+       /**
+        * Convenience factory for a filtered, sorted, fluent map with {@link 
String} keys and {@link Object} values.
+        *
+        * <p>
+        * This is a shortcut for <c>Maps.create(String.<jk>class</jk>, 
Object.<jk>class</jk>).filtered().sorted().buildFluent()</c>.
+        *
+        * <p>
+        * This is typically used for creating property maps in 
<c>toString()</c> methods that need to be sorted and filtered.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// In a properties() method</jc>
+        *      <jk>return</jk> filteredBeanPropertyMap()
+        *              .a(<js>"name"</js>, <jv>name</jv>)
+        *              .a(<js>"value"</js>, <jv>value</jv>);
+        * </p>
+        *
+        * @return A new filtered, sorted, fluent map builder.
+        * @see FluentMap
+        * @see Maps
+        */
+       public static FluentMap<String,Object> filteredBeanPropertyMap() {
+               return Maps.create(String.class, 
Object.class).filtered().sorted().buildFluent();
+       }
+
        /**
         * Convenience factory for a {@link Maps}.
         *
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/Utils.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/Utils.java
index bc34615325..88fc940286 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/Utils.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/utils/Utils.java
@@ -1543,6 +1543,38 @@ public class Utils {
                }
        }
 
+       /**
+        * Executes a supplier that may throw an exception and returns the 
result or a fallback value.
+        *
+        * <p>
+        * If the supplier executes successfully, returns the result.
+        * If the supplier throws any exception, applies the exception function 
to get a fallback value.
+        *
+        * <p>
+        * This is useful for operations that may fail but you want to handle 
the failure
+        * gracefully by returning a fallback value instead of throwing an 
exception.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Get a value with a fallback if an exception occurs</jc>
+        *      <jk>String</jk> <jv>value</jv> = <jsm>safeCatch</jsm>(() -&gt; 
<jv>riskyOperation</jv>(), <jv>e</jv> -&gt; <js>"default"</js>);
+        * </p>
+        *
+        * @param <T> The return type.
+        * @param s The supplier that may throw an exception.
+        * @param exceptionFunction A function that converts the thrown 
exception into a fallback value.
+        * @return The result of the supplier execution, or the fallback value 
if an exception was thrown.
+        * @see #safe(ThrowingSupplier)
+        * @see #safeOptCatch(ThrowingSupplier, Function)
+        */
+       public static <T> T safeCatch(ThrowingSupplier<T> s, 
Function<Throwable,T> exceptionFunction) {
+               try {
+                       return s.get();
+               } catch (Throwable e) {
+                       return exceptionFunction.apply(e);
+               }
+       }
+
        /**
         * Executes a supplier that may throw an exception and returns an 
Optional.
         *
@@ -1576,6 +1608,39 @@ public class Utils {
                }
        }
 
+       /**
+        * Executes a supplier that may throw an exception and returns an 
Optional with the result or a fallback value.
+        *
+        * <p>
+        * If the supplier executes successfully, returns {@link 
Optional#of(Object)} with the result.
+        * If the supplier throws any exception, applies the exception function 
to get a fallback value and returns it wrapped in an Optional.
+        *
+        * <p>
+        * This is useful for operations that may fail but you want to handle 
the failure
+        * gracefully by returning a fallback value wrapped in an Optional 
instead of throwing an exception.
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jc>// Get a value with a fallback if an exception occurs</jc>
+        *      <jk>Optional</jk>&lt;<jk>String</jk>&gt; <jv>value</jv> = 
<jsm>safeOptCatch</jsm>(() -&gt; <jv>riskyOperation</jv>(), <jv>e</jv> -&gt; 
<js>"default"</js>);
+        * </p>
+        *
+        * @param <T> The return type.
+        * @param s The supplier that may throw an exception.
+        * @param exceptionFunction A function that converts the thrown 
exception into a fallback value.
+        * @return An Optional containing the result if successful, or the 
fallback value wrapped in an Optional if an exception was thrown.
+        * @see #safeOpt(ThrowingSupplier)
+        * @see #safeCatch(ThrowingSupplier, Function)
+        * @see #opt(Object)
+        */
+       public static <T> Optional<T> safeOptCatch(ThrowingSupplier<T> s, 
Function<Throwable,T> exceptionFunction) {
+               try {
+                       return opt(s.get());
+               } catch (Throwable e) {
+                       return opt(exceptionFunction.apply(e));
+               }
+       }
+
        /**
         * Executes a supplier that may throw an exception and returns the 
result or <c>null</c>.
         *
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
index e63daf772e..d228e9e0f8 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanMeta.java
@@ -748,13 +748,17 @@ public class BeanMeta<T> {
                return beanFilter == null ? value : 
beanFilter.writeProperty(bean, name, value);
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               return filteredBeanPropertyMap()
+                       .a("class", classMeta.getName())
+                       .a("properties", properties);
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               var sb = new StringBuilder(classMeta.getName());
-               sb.append(" {\n");
-               properties.values().forEach(x -> 
sb.append('\t').append(x.toString()).append(",\n"));
-               sb.append('}');
-               return sb.toString();
+               return r(properties());
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
index eca9a64a24..6230d1f735 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyMeta.java
@@ -1143,9 +1143,20 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                }
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               return filteredBeanPropertyMap()
+                       .a("name", name)
+                       .a("type", cn(rawTypeMeta))
+                       .a("field", field)
+                       .a("getter", getter)
+                       .a("setter", setter);
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               return name + ": " + cn(this.rawTypeMeta) + ", field=[" + field 
+ "], getter=[" + getter + "], setter=[" + setter + "]";
+               return r(properties());
        }
 
        private Object applyChildPropertiesFilter(BeanSession session, 
ClassMeta cm, Object o) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyValue.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyValue.java
index aefbfc0ee3..d4e5e1021e 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyValue.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanPropertyValue.java
@@ -16,9 +16,10 @@
  */
 package org.apache.juneau;
 
+import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
 
-import org.apache.juneau.collections.*;
+import org.apache.juneau.commons.collections.*;
 
 /**
  * Represents a simple bean property value and the meta-data associated with 
it.
@@ -86,15 +87,17 @@ public class BeanPropertyValue implements 
Comparable<BeanPropertyValue> {
         */
        public final Object getValue() { return value; }
 
-       @Override /* Overridden from Object */
-       public String toString() {
+       protected FluentMap<String,Object> properties() {
                // @formatter:off
-               return JsonMap
-                       .create()
-                       .append("name", name)
-                       .append("value", value)
-                       .append("type", cns(pMeta.getClassMeta()))
-                       .toString();
+               return filteredBeanPropertyMap()
+                       .a("name", name)
+                       .a("value", value)
+                       .a("type", cns(pMeta.getClassMeta()));
                // @formatter:on
        }
+
+       @Override /* Overridden from Object */
+       public String toString() {
+               return r(properties());
+       }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
index c27dce5ce0..7f0edc94fa 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanRegistry.java
@@ -17,6 +17,7 @@
 package org.apache.juneau;
 
 import static org.apache.juneau.commons.reflect.ReflectionUtils.*;
+import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.ThrowableUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
 
@@ -25,6 +26,7 @@ import java.util.*;
 import java.util.concurrent.*;
 
 import org.apache.juneau.annotation.*;
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.reflect.*;
 import org.apache.juneau.commons.utils.*;
 import org.apache.juneau.cp.*;
@@ -115,13 +117,15 @@ public class BeanRegistry {
                return nn(getClassMeta(typeName));
        }
 
+       protected FluentMap<String,Object> properties() {
+               var m = filteredBeanPropertyMap();
+               map.forEach((k, v) -> m.a(k, v.toString(true)));
+               return m;
+       }
+
        @Override
        public String toString() {
-               var sb = new StringBuilder();
-               sb.append('{');
-               map.forEach((k, v) -> 
sb.append(k).append(":").append(v.toString(true)).append(", "));
-               sb.append('}');
-               return sb.toString();
+               return r(properties());
        }
 
        private void addClass(Class<?> c) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
index bbb818f0be..487ed3c279 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/Context.java
@@ -908,7 +908,7 @@ public abstract class Context {
         * @return The properties on this bean as a map for debugging.
         */
        protected FluentMap<String,Object> properties() {
-               return mapb().filtered().sorted().buildFluent()
+               return filteredBeanPropertyMap()
                        .a("annotations", annotations)
                        .a("debug", debug);
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextSession.java
index b494020d7b..bd4e318125 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ContextSession.java
@@ -240,7 +240,7 @@ public abstract class ContextSession {
         * @return The properties on this bean as a map for debugging.
         */
        protected FluentMap<String,Object> properties() {
-               return mapb().sorted().filtered().buildFluent()
+               return filteredBeanPropertyMap()
                        .a("debug", debug);
        }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/UriContext.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/UriContext.java
index 41aa1cf640..89cb6ef970 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/UriContext.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/UriContext.java
@@ -16,13 +16,16 @@
  */
 package org.apache.juneau;
 
+import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.StringUtils.*;
 import static org.apache.juneau.commons.utils.ThrowableUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
 
+import java.util.function.Supplier;
+
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.collections.*;
-import org.apache.juneau.json.*;
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.parser.*;
 
 /**
@@ -95,8 +98,8 @@ public class UriContext {
        @SuppressWarnings("javadoc")
        public final String authority, contextRoot, servletPath, pathInfo, 
parentPath;
 
-       // Lazy-initialized fields.
-       private String aContextRoot, rContextRoot, aServletPath, rResource, 
aPathInfo, rPath;
+       // Memoized suppliers.
+       private final Supplier<String> aContextRoot, rContextRoot, 
aServletPath, rResource, aPathInfo, rPath;
 
        /**
         * Default constructor.
@@ -128,6 +131,12 @@ public class UriContext {
                this.servletPath = 
nullIfEmpty(trimSlashes(m.getString("servletPath")));
                this.pathInfo = 
nullIfEmpty(trimSlashes(m.getString("pathInfo")));
                this.parentPath = this.pathInfo == null || 
this.pathInfo.indexOf('/') == -1 ? null : this.pathInfo.substring(0, 
this.pathInfo.lastIndexOf('/'));
+               this.rContextRoot = memoize(() -> findRContextRoot());
+               this.rResource = memoize(() -> findRResource());
+               this.rPath = memoize(() -> findRPath());
+               this.aContextRoot = memoize(() -> findAContextRoot());
+               this.aServletPath = memoize(() -> findAServletPath());
+               this.aPathInfo = memoize(() -> findAPathInfo());
        }
 
        /**
@@ -155,6 +164,121 @@ public class UriContext {
                this.servletPath = nullIfEmpty(trimSlashes(servletPath));
                this.pathInfo = nullIfEmpty(trimSlashes(pathInfo));
                this.parentPath = this.pathInfo == null || 
this.pathInfo.indexOf('/') == -1 ? null : this.pathInfo.substring(0, 
this.pathInfo.lastIndexOf('/'));
+               this.rContextRoot = memoize(() -> findRContextRoot());
+               this.rResource = memoize(() -> findRResource());
+               this.rPath = memoize(() -> findRPath());
+               this.aContextRoot = memoize(() -> findAContextRoot());
+               this.aServletPath = memoize(() -> findAServletPath());
+               this.aPathInfo = memoize(() -> findAPathInfo());
+       }
+
+       private String findRContextRoot() {
+               return contextRoot == null ? "/" : ('/' + contextRoot);
+       }
+
+       private String findRResource() {
+               // @formatter:off
+               if (contextRoot == null)
+                       return (
+                               servletPath == null
+                               ? "/"
+                               : ('/' + servletPath)
+                       );
+               return (
+                       servletPath == null
+                       ? ('/' + contextRoot)
+                       : ('/' + contextRoot + '/' + servletPath)
+               );
+               // @formatter:on
+       }
+
+       private String findRPath() {
+               // @formatter:off
+               if (contextRoot == null) {
+                       if (servletPath == null)
+                               return (
+                                       pathInfo == null
+                                       ? "/"
+                                       : ('/' + pathInfo)
+                               );
+                       return (
+                               pathInfo == null
+                               ? ('/' + servletPath)
+                               : ('/' + servletPath + '/' + pathInfo)
+                       );
+               }
+               if (servletPath == null)
+                       return (
+                               pathInfo == null
+                               ? ('/' + contextRoot)
+                               : ('/' + contextRoot + '/' + pathInfo)
+                       );
+               return (
+                       pathInfo == null
+                       ? ('/' + contextRoot + '/' + servletPath)
+                       : ('/' + contextRoot + '/' + servletPath + '/' + 
pathInfo)
+               );
+               // @formatter:on
+       }
+
+       private String findAContextRoot() {
+               // @formatter:off
+               if (authority == null)
+                       return rContextRoot.get();
+               return (
+                       contextRoot == null
+                       ? authority
+                       : (authority + '/' + contextRoot)
+               );
+               // @formatter:on
+       }
+
+       private String findAServletPath() {
+               // @formatter:off
+               if (authority == null)
+                       return rResource.get();
+               if (contextRoot == null)
+                       return (
+                               servletPath == null
+                               ? authority
+                               : authority + '/' + servletPath
+                       );
+               return (
+                       servletPath == null
+                       ? (authority + '/' + contextRoot)
+                       : (authority + '/' + contextRoot + '/' + servletPath)
+               );
+               // @formatter:on
+       }
+
+       private String findAPathInfo() {
+               // @formatter:off
+               if (authority == null)
+                       return rPath.get();
+               if (contextRoot == null) {
+                       if (servletPath == null)
+                               return (
+                                       pathInfo == null
+                                       ? authority : (authority + '/' + 
pathInfo)
+                               );
+                       return (
+                               pathInfo == null
+                               ? (authority + '/' + servletPath)
+                               : (authority + '/' + servletPath + '/' + 
pathInfo)
+                       );
+               }
+               if (servletPath == null)
+                       return (
+                               pathInfo == null
+                               ? authority + '/' + contextRoot
+                               : (authority + '/' + contextRoot + '/' + 
pathInfo)
+                       );
+               return (
+                       pathInfo == null
+                       ? (authority + '/' + contextRoot + '/' + servletPath)
+                       : (authority + '/' + contextRoot + '/' + servletPath + 
'/' + pathInfo)
+               );
+               // @formatter:on
        }
 
        /**
@@ -183,19 +307,7 @@ public class UriContext {
         *      Never <jk>null</jk>.
         */
        public String getAbsoluteContextRoot() {
-               if (aContextRoot == null) {
-                       if (authority == null)
-                               aContextRoot = getRootRelativeContextRoot();
-                       else
-                               // @formatter:off
-                               aContextRoot = (
-                                       contextRoot == null
-                                       ? authority
-                                       : (authority + '/' + contextRoot)
-                               );
-                       // @formatter:on
-               }
-               return aContextRoot;
+               return aContextRoot.get();
        }
 
        /**
@@ -209,41 +321,7 @@ public class UriContext {
         *      Never <jk>null</jk>.
         */
        public String getAbsolutePathInfo() {
-               // @formatter:off
-               if (aPathInfo == null) {
-                       if (authority == null)
-                               aPathInfo = getRootRelativePathInfo();
-                       else {
-                               if (contextRoot == null) {
-                                       if (servletPath == null)
-                                               aPathInfo = (
-                                                       pathInfo == null
-                                                       ? authority : 
(authority + '/' + pathInfo)
-                                               );
-                                       else
-                                               aPathInfo = (
-                                                       pathInfo == null
-                                                       ? (authority + '/' + 
servletPath)
-                                                       : (authority + '/' + 
servletPath + '/' + pathInfo)
-                                               );
-                               } else {
-                                       if (servletPath == null)
-                                               aPathInfo = (
-                                                       pathInfo == null
-                                                       ? authority + '/' + 
contextRoot
-                                                       : (authority + '/' + 
contextRoot + '/' + pathInfo)
-                                               );
-                                       else
-                                               aPathInfo = (
-                                                       pathInfo == null
-                                                       ? (authority + '/' + 
contextRoot + '/' + servletPath)
-                                                       : (authority + '/' + 
contextRoot + '/' + servletPath + '/' + pathInfo)
-                                               );
-                               }
-                       }
-               }
-               return aPathInfo;
-               // @formatter:on
+               return aPathInfo.get();
        }
 
        /**
@@ -264,27 +342,7 @@ public class UriContext {
         *      Never <jk>null</jk>.
         */
        public String getAbsoluteServletPath() {
-               // @formatter:off
-               if (aServletPath == null) {
-                       if (authority == null)
-                               aServletPath = getRootRelativeServletPath();
-                       else {
-                               if (contextRoot == null)
-                                       aServletPath = (
-                                               servletPath == null
-                                               ? authority
-                                               : authority + '/' + servletPath
-                                       );
-                               else
-                                       aServletPath = (
-                                               servletPath == null
-                                               ? (authority + '/' + 
contextRoot)
-                                               : (authority + '/' + 
contextRoot + '/' + servletPath)
-                                       );
-                       }
-               }
-               return aServletPath;
-               // @formatter:on
+               return aServletPath.get();
        }
 
        /**
@@ -305,9 +363,7 @@ public class UriContext {
         *      Never <jk>null</jk>.
         */
        public String getRootRelativeContextRoot() {
-               if (rContextRoot == null)
-                       rContextRoot = contextRoot == null ? "/" : ('/' + 
contextRoot);
-               return rContextRoot;
+               return rContextRoot.get();
        }
 
        /**
@@ -321,38 +377,7 @@ public class UriContext {
         *      Never <jk>null</jk>.
         */
        public String getRootRelativePathInfo() {
-               // @formatter:off
-               if (rPath == null) {
-                       if (contextRoot == null) {
-                               if (servletPath == null)
-                                       rPath = (
-                                               pathInfo == null
-                                               ? "/"
-                                               : ('/' + pathInfo)
-                                       );
-                               else
-                                       rPath = (
-                                               pathInfo == null
-                                               ? ('/' + servletPath)
-                                               : ('/' + servletPath + '/' + 
pathInfo)
-                                       );
-                       } else {
-                               if (servletPath == null)
-                                       rPath = (
-                                               pathInfo == null
-                                               ? ('/' + contextRoot)
-                                               : ('/' + contextRoot + '/' + 
pathInfo)
-                                       );
-                               else
-                                       rPath = (
-                                               pathInfo == null
-                                               ? ('/' + contextRoot + '/' + 
servletPath)
-                                               : ('/' + contextRoot + '/' + 
servletPath + '/' + pathInfo)
-                                       );
-                       }
-               }
-               return rPath;
-               // @formatter:on
+               return rPath.get();
        }
 
        /**
@@ -373,23 +398,7 @@ public class UriContext {
         *      Never <jk>null</jk>.
         */
        public String getRootRelativeServletPath() {
-               // @formatter:off
-               if (rResource == null) {
-                       if (contextRoot == null)
-                               rResource = (
-                                       servletPath == null
-                                       ? "/"
-                                       : ('/' + servletPath)
-                               );
-                       else
-                               rResource = (
-                                       servletPath == null
-                                       ? ('/' + contextRoot)
-                                       : ('/' + contextRoot + '/' + 
servletPath)
-                               );
-               }
-               return rResource;
-               // @formatter:on
+               return rResource.get();
        }
 
        /**
@@ -399,8 +408,25 @@ public class UriContext {
         */
        public String getRootRelativeServletPathParent() { return 
getParent(getRootRelativeServletPath()); }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               return filteredBeanPropertyMap()
+                       .a("authority", authority)
+                       .a("contextRoot", contextRoot)
+                       .a("servletPath", servletPath)
+                       .a("pathInfo", pathInfo)
+                       .a("parentPath", parentPath)
+                       .a("aContextRoot", aContextRoot.get())
+                       .a("rContextRoot", rContextRoot.get())
+                       .a("aServletPath", aServletPath.get())
+                       .a("rResource", rResource.get())
+                       .a("aPathInfo", aPathInfo.get())
+                       .a("rPath", rPath.get());
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               return Json5Serializer.DEFAULT.toString(this);
+               return r(properties());
        }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BasicFileFinder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BasicFileFinder.java
index d98f27f1ad..e1b18445f8 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BasicFileFinder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BasicFileFinder.java
@@ -16,7 +16,6 @@
  */
 package org.apache.juneau.cp;
 
-import static org.apache.juneau.collections.JsonMap.*;
 import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.FileUtils.*;
 import static org.apache.juneau.commons.utils.IoUtils.*;
@@ -29,6 +28,7 @@ import java.util.ResourceBundle.*;
 import java.util.concurrent.*;
 import java.util.regex.*;
 
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.io.*;
 
 /**
@@ -115,20 +115,23 @@ public class BasicFileFinder implements FileFinder {
                return hashCode;
        }
 
-       @Override /* Overridden from Object */
-       public String toString() {
+       protected FluentMap<String,Object> properties() {
                // @formatter:off
-               return filteredMap()
-                       .append("class", cns(getClass()))
-                       .append("roots", roots)
-                       .append("cachingLimit", cachingLimit)
-                       .append("include", includePatterns)
-                       .append("exclude", excludePatterns)
-                       .append("hashCode", hashCode)
-                       .asReadableString();
+               return filteredBeanPropertyMap()
+                       .a("class", cns(getClass()))
+                       .a("roots", roots)
+                       .a("cachingLimit", cachingLimit)
+                       .a("include", includePatterns)
+                       .a("exclude", excludePatterns)
+                       .a("hashCode", hashCode);
                // @formatter:on
        }
 
+       @Override /* Overridden from Object */
+       public String toString() {
+               return r(properties());
+       }
+
        /**
         * The main implementation method for finding files.
         *
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
index 31e4e12a2c..841941218d 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/BeanStore.java
@@ -18,7 +18,6 @@ package org.apache.juneau.cp;
 
 import static java.util.stream.Collectors.*;
 import static java.util.stream.Collectors.toList;
-import static org.apache.juneau.collections.JsonMap.*;
 import static org.apache.juneau.commons.reflect.ReflectionUtils.*;
 import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.ThrowableUtils.*;
@@ -30,10 +29,9 @@ import java.util.concurrent.*;
 import java.util.function.*;
 import java.util.stream.*;
 
-import org.apache.juneau.collections.*;
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.reflect.*;
 import org.apache.juneau.commons.utils.*;
-import org.apache.juneau.marshaller.*;
 
 /**
  * Java bean store.
@@ -634,9 +632,21 @@ public class BeanStore {
                return s;
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               return filteredBeanPropertyMap()
+                       .a("identity", identity(this))
+                       .a("entries", 
entries.stream().map(BeanStoreEntry::properties).collect(toList()))
+                       .a("outer", identity(outer.orElse(null)))
+                       .a("parent", 
parent.map(BeanStore::properties).orElse(null))
+                       .ai(readOnly, "readOnly", readOnly)
+                       .ai(threadSafe, "threadSafe", threadSafe);
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               return Json5.of(properties());
+               return r(properties());
        }
 
        private void assertCanWrite() {
@@ -644,20 +654,6 @@ public class BeanStore {
                        throw new IllegalStateException("Method cannot be used 
because BeanStore is read-only.");
        }
 
-       private JsonMap properties() {
-               var nf = (Predicate<Boolean>)Utils::isTrue;
-               // @formatter:off
-               return filteredMap()
-                       .append("identity", identity(this))
-                       .append("entries", 
entries.stream().map(BeanStoreEntry::properties).collect(toList()))
-                       .append("outer", identity(outer.orElse(null)))
-                       .append("parent", 
parent.map(BeanStore::properties).orElse(null))
-                       .appendIf(nf, "readOnly", readOnly)
-                       .appendIf(nf, "threadSafe", threadSafe)
-               ;
-               // @formatter:on
-       }
-
        /**
         * Creates an entry in this store for the specified bean.
         *
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/Messages.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/Messages.java
index 7a1b2da877..1000269cc1 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/Messages.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/cp/Messages.java
@@ -28,6 +28,7 @@ import java.util.concurrent.*;
 
 import org.apache.juneau.*;
 import org.apache.juneau.collections.*;
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.function.*;
 import org.apache.juneau.commons.utils.*;
 import org.apache.juneau.marshaller.*;
@@ -466,12 +467,17 @@ public class Messages extends ResourceBundle {
                return set;
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               var m = filteredBeanPropertyMap();
+               keySet().stream().forEach(x -> m.a(x, getString(x)));
+               return m;
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               var m = new JsonMap();
-               for (var k : new TreeSet<>(keySet()))
-                       m.put(k, getString(k));
-               return Json5.of(m);
+               return r(properties());
        }
 
        @Override /* Overridden from ResourceBundle */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
index e4f6ecc745..6f4828aa1f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/httppart/HttpPartSchema.java
@@ -4120,47 +4120,45 @@ public class HttpPartSchema {
         */
        public boolean isUniqueItems() { return uniqueItems; }
 
-       @Override
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               Predicate<Object> ne = x -> isNotEmpty(s(x));
+               Predicate<Object> nf = x -> x instanceof Boolean && (Boolean)x;
+               Predicate<Object> nm1 = x -> x instanceof Number && 
((Number)x).intValue() != -1;
+               Predicate<Object> nn = Utils::nn;
+               return mapb_so().sorted().buildFluent()
+                       .ai(ne, "name", name)
+                       .ai(ne, "type", type)
+                       .ai(ne, "format", format)
+                       .ai(ne, "default", default_)
+                       .ai(ne, "enum", enum_)
+                       .ai(ne, "properties", properties)
+                       .ai(nf, "allowEmptyValue", allowEmptyValue)
+                       .ai(nf, "exclusiveMaximum", exclusiveMaximum)
+                       .ai(nf, "exclusiveMinimum", exclusiveMinimum)
+                       .ai(nf, "required", required)
+                       .ai(nf, "uniqueItems", uniqueItems)
+                       .ai(nf, "skipIfEmpty", skipIfEmpty)
+                       .ai(x -> x != 
HttpPartCollectionFormat.NO_COLLECTION_FORMAT, "collectionFormat", 
collectionFormat)
+                       .ai(ne, "pattern", pattern)
+                       .ai(nn, "items", items)
+                       .ai(nn, "additionalProperties", additionalProperties)
+                       .ai(nm1, "maximum", maximum)
+                       .ai(nm1, "minimum", minimum)
+                       .ai(nm1, "multipleOf", multipleOf)
+                       .ai(nm1, "maxLength", maxLength)
+                       .ai(nm1, "minLength", minLength)
+                       .ai(nm1, "maxItems", maxItems)
+                       .ai(nm1, "minItems", minItems)
+                       .ai(nm1, "maxProperties", maxProperties)
+                       .ai(nm1, "minProperties", minProperties)
+                       .a("parsedType", parsedType);
+               // @formatter:on
+       }
+
+       @Override /* Overridden from Object */
        public String toString() {
-               try {
-                       Predicate<Object> ne = x -> isNotEmpty(s(x));
-                       Predicate<Boolean> nf = Utils::isTrue;
-                       Predicate<Number> nm1 = Utils::isNotMinusOne;
-                       Predicate<Object> nn = Utils::nn;
-                       // @formatter:off
-                       var m = new JsonMap()
-                               .appendIf(ne, "name", name)
-                               .appendIf(ne, "type", type)
-                               .appendIf(ne, "format", format)
-                               .appendIf(ne, "default", default_)
-                               .appendIf(ne, "enum", enum_)
-                               .appendIf(ne, "properties", properties)
-                               .appendIf(nf, "allowEmptyValue", 
allowEmptyValue)
-                               .appendIf(nf, "exclusiveMaximum", 
exclusiveMaximum)
-                               .appendIf(nf, "exclusiveMinimum", 
exclusiveMinimum)
-                               .appendIf(nf, "required", required)
-                               .appendIf(nf, "uniqueItems", uniqueItems)
-                               .appendIf(nf, "skipIfEmpty", skipIfEmpty)
-                               .appendIf(x -> x != 
HttpPartCollectionFormat.NO_COLLECTION_FORMAT, "collectionFormat", 
collectionFormat)
-                               .appendIf(ne, "pattern", pattern)
-                               .appendIf(nn, "items", items)
-                               .appendIf(nn, "additionalProperties", 
additionalProperties)
-                               .appendIf(nm1, "maximum", maximum)
-                               .appendIf(nm1, "minimum", minimum)
-                               .appendIf(nm1, "multipleOf", multipleOf)
-                               .appendIf(nm1, "maxLength", maxLength)
-                               .appendIf(nm1, "minLength", minLength)
-                               .appendIf(nm1, "maxItems", maxItems)
-                               .appendIf(nm1, "minItems", minItems)
-                               .appendIf(nm1, "maxProperties", maxProperties)
-                               .appendIf(nm1, "minProperties", minProperties)
-                               .append("parsedType", parsedType)
-                       ;
-                       // @formatter:on
-                       return m.toString();
-               } catch (@SuppressWarnings("unused") Exception e) {
-                       return "";
-               }
+               return r(properties());
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverSession.java
index 959a74239e..6b427e7dd0 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/svl/VarResolverSession.java
@@ -430,9 +430,18 @@ public class VarResolverSession {
                return out;
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               return filteredBeanPropertyMap()
+                       .a("var", this.context.getVarMap().keySet())
+                       .a("context.beanStore", this.context.beanStore)
+                       .a("session.beanStore", beanStore);
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               return "var=" + this.context.getVarMap().keySet() + ", 
context.beanStore=" + this.context.beanStore + ", session.beanStore=" + 
beanStore;
+               return r(properties());
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/BeanDiff.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/BeanDiff.java
index 0ee6c44225..092b2a89c8 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/BeanDiff.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/BeanDiff.java
@@ -22,9 +22,8 @@ import static org.apache.juneau.commons.utils.Utils.*;
 import java.util.*;
 
 import org.apache.juneau.*;
-import org.apache.juneau.annotation.*;
 import org.apache.juneau.collections.*;
-import org.apache.juneau.marshaller.*;
+import org.apache.juneau.commons.collections.*;
 
 /**
  * Utility class for comparing two versions of a POJO.
@@ -49,8 +48,8 @@ import org.apache.juneau.marshaller.*;
  * </p>
  *
  */
-@Bean(properties = "v1,v2")
 public class BeanDiff {
+
        /**
         * Builder class.
         *
@@ -229,8 +228,16 @@ public class BeanDiff {
                return v1.size() > 0 || v2.size() > 0;
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               return mapb_so().buildFluent()
+                       .a("v1", v1)
+                       .a("v2", v2);
+               // @formatter:on
+       }
+
        @Override
        public String toString() {
-               return Json5.of(this);
+               return r(properties());
        }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/HashKey.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/HashKey.java
index ce84b3cb4b..30bc2e86e2 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/HashKey.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/HashKey.java
@@ -16,11 +16,13 @@
  */
 package org.apache.juneau.utils;
 
-import static org.apache.juneau.collections.JsonMap.*;
+import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
 
 import java.util.*;
 
+import org.apache.juneau.commons.collections.*;
+
 /**
  * Represents a list of objects used to compare objects for equality.
  *
@@ -60,13 +62,16 @@ public class HashKey {
                return hashCode;
        }
 
-       @Override /* Overridden from Object */
-       public String toString() {
+       protected FluentMap<String,Object> properties() {
                // @formatter:off
-               return filteredMap()
-                       .append("hashCode", hashCode())
-                       .append("array", array)
-                       .asString();
+               return filteredBeanPropertyMap()
+                       .a("hashCode", hashCode())
+                       .a("array", array);
                // @formatter:on
        }
+
+       @Override /* Overridden from Object */
+       public String toString() {
+               return r(properties());
+       }
 }
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ManifestFile.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ManifestFile.java
index 251b14dbb3..a2806be130 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ManifestFile.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/utils/ManifestFile.java
@@ -190,7 +190,7 @@ public class ManifestFile extends JsonMap {
        @Override /* Overridden from Object */
        public String toString() {
                var sb = new StringBuilder();
-               forEach((k, v) -> sb.append(k).append(": ").append(v));
+               forEach((k, v) -> sb.append(k).append(": 
").append(v).append("\n"));
                return sb.toString();
        }
 
diff --git 
a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockPathResolver.java
 
b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockPathResolver.java
index d233a92364..8ab87b05b6 100644
--- 
a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockPathResolver.java
+++ 
b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockPathResolver.java
@@ -24,7 +24,7 @@ import static org.apache.juneau.commons.utils.Utils.*;
 
 import java.util.*;
 
-import org.apache.juneau.collections.*;
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.utils.*;
 import org.apache.juneau.rest.util.*;
 
@@ -118,20 +118,23 @@ class MockPathResolver {
         */
        public String getURI() { return uri; }
 
-       @Override
-       public String toString() {
+       protected FluentMap<String,Object> properties() {
                // @formatter:off
-               return JsonMap.create()
-                       .append("uri", uri)
-                       .append("contextPath", contextPath)
-                       .append("servletPath", servletPath)
-                       .append("remainder", remainder)
-                       .append("target", target)
-                       .append("error", error)
-                       .toString();
+               return filteredBeanPropertyMap()
+                       .a("uri", uri)
+                       .a("contextPath", contextPath)
+                       .a("servletPath", servletPath)
+                       .a("remainder", remainder)
+                       .a("target", target)
+                       .a("error", error);
                // @formatter:on
        }
 
+       @Override
+       public String toString() {
+               return r(properties());
+       }
+
        private void init(String target, String contextPath, String 
servletPath, String pathToResolve, Map<String,Object> pathVars) {
 
                target = trimTrailingSlashes(emptyIfNull(target));
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/debug/DebugEnablement.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/debug/DebugEnablement.java
index e602df3b54..b41fe2277e 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/debug/DebugEnablement.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/debug/DebugEnablement.java
@@ -17,12 +17,13 @@
 package org.apache.juneau.rest.debug;
 
 import static org.apache.juneau.Enablement.*;
-import static org.apache.juneau.collections.JsonMap.*;
+import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
 
 import java.util.function.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.reflect.*;
 import org.apache.juneau.cp.*;
 import org.apache.juneau.http.response.*;
@@ -273,17 +274,20 @@ public abstract class DebugEnablement {
                return e == ALWAYS || (e == CONDITIONAL && 
isConditionallyEnabled(req));
        }
 
-       @Override /* Overridden from Object */
-       public String toString() {
+       protected FluentMap<String,Object> properties() {
                // @formatter:off
-               return filteredMap()
-                       .append("defaultEnablement", defaultEnablement)
-                       .append("enablementMap", enablementMap)
-                       .append("conditionalPredicate", conditionalPredicate)
-                       .asString();
+               return filteredBeanPropertyMap()
+                       .a("defaultEnablement", defaultEnablement)
+                       .a("enablementMap", enablementMap)
+                       .a("conditionalPredicate", conditionalPredicate);
                // @formatter:on
        }
 
+       @Override /* Overridden from Object */
+       public String toString() {
+               return r(properties());
+       }
+
        /**
         * Initializer.
         * <p>
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestAttributes.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestAttributes.java
index 917706b79c..97572fe828 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestAttributes.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestAttributes.java
@@ -23,6 +23,7 @@ import static org.apache.juneau.commons.utils.Utils.*;
 import java.util.*;
 
 import org.apache.juneau.collections.*;
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.rest.*;
 import org.apache.juneau.svl.*;
 
@@ -290,8 +291,15 @@ public class RequestAttributes {
                return this;
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               return filteredBeanPropertyMap()
+                       .a("attributes", asMap());
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               return asMap().toString();
+               return r(properties());
        }
 }
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestFormParams.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestFormParams.java
index 20614645b4..f86e6bf5ea 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestFormParams.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestFormParams.java
@@ -28,7 +28,6 @@ import java.util.*;
 import java.util.stream.*;
 
 import org.apache.http.*;
-import org.apache.juneau.collections.*;
 import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.utils.*;
 import org.apache.juneau.http.*;
@@ -545,12 +544,18 @@ public class RequestFormParams extends 
ArrayList<RequestFormParam> {
                return new RequestFormParams(this, names);
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               var m = filteredBeanPropertyMap();
+               for (var n : getNames())
+                       m.a(n, get(n).asString().orElse(null));
+               return m;
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               var m = new JsonMap();
-               for (var n : getNames())
-                       m.put(n, get(n).asString().orElse(null));
-               return m.asJson();
+               return r(properties());
        }
 
        private boolean eq(String s1, String s2) {
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestHeaders.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestHeaders.java
index b4a61f3a43..314c9df65e 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestHeaders.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestHeaders.java
@@ -27,7 +27,6 @@ import java.util.*;
 import java.util.stream.*;
 
 import org.apache.http.*;
-import org.apache.juneau.collections.*;
 import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.utils.*;
 import org.apache.juneau.http.*;
@@ -484,12 +483,18 @@ public class RequestHeaders extends 
ArrayList<RequestHeader> {
                return new RequestHeaders(this, names);
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               var m = filteredBeanPropertyMap();
+               for (var n : getNames())
+                       m.a(n, get(n).asString().orElse(null));
+               return m;
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               var m = new JsonMap();
-               for (var n : getNames())
-                       m.put(n, get(n).asString().orElse(null));
-               return m.asJson();
+               return r(properties());
        }
 
        private boolean eq(String s1, String s2) {
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestPathParams.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestPathParams.java
index bf50eabc0d..0bc35013be 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestPathParams.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestPathParams.java
@@ -28,7 +28,6 @@ import java.util.*;
 import java.util.stream.*;
 
 import org.apache.http.*;
-import org.apache.juneau.collections.*;
 import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.utils.*;
 import org.apache.juneau.http.*;
@@ -553,12 +552,16 @@ public class RequestPathParams extends 
ArrayList<RequestPathParam> {
                return new RequestPathParams(this, names);
        }
 
+       protected FluentMap<String,Object> properties() {
+               var m = filteredBeanPropertyMap();
+               for (var n : getNames())
+                       m.a(n, get(n).asString().orElse(null));
+               return m;
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               var m = new JsonMap();
-               for (var n : getNames())
-                       m.put(n, get(n).asString().orElse(null));
-               return m.asJson();
+               return r(properties());
        }
 
        private boolean eq(String s1, String s2) {
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestQueryParams.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestQueryParams.java
index 27a5265ceb..e97f89022a 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestQueryParams.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/httppart/RequestQueryParams.java
@@ -28,7 +28,6 @@ import java.util.*;
 import java.util.stream.*;
 
 import org.apache.http.*;
-import org.apache.juneau.collections.*;
 import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.utils.*;
 import org.apache.juneau.http.*;
@@ -550,12 +549,18 @@ public class RequestQueryParams extends 
ArrayList<RequestQueryParam> {
                return new RequestQueryParams(this, names);
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               var m = filteredBeanPropertyMap();
+               for (var n : getNames())
+                       m.a(n, get(n).asString().orElse(null));
+               return m;
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               var m = new JsonMap();
-               for (var n : getNames())
-                       m.put(n, get(n).asString().orElse(null));
-               return m.asJson();
+               return r(properties());
        }
 
        private boolean eq(String s1, String s2) {
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLogger.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLogger.java
index a2a71fe237..7c4d37bcf7 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLogger.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLogger.java
@@ -18,7 +18,6 @@ package org.apache.juneau.rest.logger;
 
 import static java.util.logging.Level.*;
 import static org.apache.juneau.Enablement.*;
-import static org.apache.juneau.collections.JsonMap.*;
 import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.IoUtils.*;
 import static org.apache.juneau.commons.utils.StringUtils.*;
@@ -31,6 +30,7 @@ import java.util.function.*;
 import java.util.logging.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.utils.*;
 import org.apache.juneau.cp.*;
 import org.apache.juneau.rest.annotation.*;
@@ -654,20 +654,23 @@ public class CallLogger {
 
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               return filteredBeanPropertyMap()
+                       .a("logger", logger)
+                       .a("thrownStore", thrownStore)
+                       .a("enabled", enabled)
+                       .a("level", level)
+                       .a("requestDetail", requestDetail)
+                       .a("responseDetail", responseDetail)
+                       .a("normalRules", normalRules)
+                       .a("debugRules", debugRules);
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               // @formatter:off
-               return filteredMap()
-                       .append("logger", logger)
-                       .append("thrownStore", thrownStore)
-                       .append("enabled", enabled)
-                       .append("level", level)
-                       .append("requestDetail", requestDetail)
-                       .append("responseDetail", responseDetail)
-                       .append("normalRules", normalRules.length == 0 ? null : 
normalRules)
-                       .append("debugRules", debugRules.length == 0 ? null : 
debugRules)
-                       .asReadableString();
-               // @formatter:off
+               return r(properties());
        }
 
        private static byte[] getRequestContent(HttpServletRequest req) {
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLoggerRule.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLoggerRule.java
index c8563796ce..e5cf4c7ac4 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLoggerRule.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/logger/CallLoggerRule.java
@@ -16,13 +16,14 @@
  */
 package org.apache.juneau.rest.logger;
 
-import static org.apache.juneau.collections.JsonMap.*;
+import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
 
 import java.util.function.*;
 import java.util.logging.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.cp.*;
 
 import jakarta.servlet.http.*;
@@ -389,20 +390,23 @@ public class CallLoggerRule {
                return true;
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               return filteredBeanPropertyMap()
+                       .a("codeFilter", statusFilter)
+                       .a("enabled", enabled)
+                       .a("enabledTest", enabledTest)
+                       .a("exceptionFilter", exceptionFilter)
+                       .a("level", level)
+                       .a("requestDetail", requestDetail)
+                       .a("requestFilter", requestFilter)
+                       .a("responseDetail", responseDetail)
+                       .a("responseFilter", responseFilter);
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               // @formatter:off
-               return filteredMap()
-                       .append("codeFilter", statusFilter)
-                       .append("enabled", enabled)
-                       .append("enabledTest", enabledTest)
-                       .append("exceptionFilter", exceptionFilter)
-                       .append("level", level)
-                       .append("requestDetail", requestDetail)
-                       .append("requestFilter", requestFilter)
-                       .append("responseDetail", responseDetail)
-                       .append("responseFilter", responseFilter)
-                       .asReadableString();
-               // @formatter:off
+               return r(properties());
        }
 }
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/staticfile/BasicStaticFiles.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/staticfile/BasicStaticFiles.java
index 1a04340f54..2f99aa7a0c 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/staticfile/BasicStaticFiles.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/staticfile/BasicStaticFiles.java
@@ -16,7 +16,7 @@
  */
 package org.apache.juneau.rest.staticfile;
 
-import static org.apache.juneau.collections.JsonMap.*;
+import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.FileUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
 import static org.apache.juneau.http.HttpHeaders.*;
@@ -26,6 +26,7 @@ import java.io.*;
 import java.util.*;
 
 import org.apache.http.*;
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.utils.*;
 import org.apache.juneau.cp.*;
 import org.apache.juneau.http.resource.*;
@@ -150,8 +151,15 @@ public class BasicStaticFiles implements StaticFiles {
                }
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               return filteredBeanPropertyMap()
+                       .a("headers", headers);
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               return filteredMap().append("headers", 
headers).asReadableString();
+               return r(properties());
        }
 }
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/stats/MethodExecStats.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/stats/MethodExecStats.java
index b5ed82bc53..8160fef02b 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/stats/MethodExecStats.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/stats/MethodExecStats.java
@@ -16,6 +16,7 @@
  */
 package org.apache.juneau.rest.stats;
 
+import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
 
 import java.lang.reflect.*;
@@ -23,8 +24,8 @@ import java.util.*;
 import java.util.concurrent.atomic.*;
 
 import org.apache.juneau.*;
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.cp.*;
-import org.apache.juneau.marshaller.*;
 
 /**
  * Method execution statistics.
@@ -239,8 +240,24 @@ public class MethodExecStats {
                return this;
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               return filteredBeanPropertyMap()
+                       .a("avgTime", getAvgTime())
+                       .a("errors", getErrors())
+                       .a("guid", guid)
+                       .a("maxTime", getMaxTime())
+                       .a("method", method)
+                       .a("minTime", getMinTime())
+                       .a("running", getRunning())
+                       .a("runs", getRuns())
+                       .a("thrownStore", thrownStore)
+                       .a("totalTime", getTotalTime());
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               return Json5.of(this);
+               return r(properties());
        }
 }
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/stats/ThrownStats.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/stats/ThrownStats.java
index 72e42724c9..6e8fdafeaf 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/stats/ThrownStats.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/stats/ThrownStats.java
@@ -22,8 +22,8 @@ import static org.apache.juneau.commons.utils.Utils.*;
 import java.util.*;
 import java.util.concurrent.atomic.*;
 
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.cp.*;
-import org.apache.juneau.marshaller.*;
 
 /**
  * Represents an entry in {@link ThrownStore}.
@@ -259,8 +259,23 @@ public class ThrownStats implements Cloneable {
                return this;
        }
 
+       protected FluentMap<String,Object> properties() {
+               // @formatter:off
+               return filteredBeanPropertyMap()
+                       .a("causedBy", causedBy.orElse(null))
+                       .a("count", getCount())
+                       .a("firstMessage", firstMessage)
+                       .a("firstOccurrence", getFirstOccurrence())
+                       .a("guid", guid)
+                       .a("hash", hash)
+                       .a("lastOccurrence", getLastOccurrence())
+                       .a("stackTrace", stackTrace)
+                       .a("thrownClass", thrownClass);
+               // @formatter:on
+       }
+
        @Override /* Overridden from Object */
        public String toString() {
-               return Json5.of(this);
+               return r(properties());
        }
 }
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/UrlPath.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/UrlPath.java
index aa40f92dfe..fcb4127172 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/UrlPath.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/UrlPath.java
@@ -16,13 +16,14 @@
  */
 package org.apache.juneau.rest.util;
 
-import static org.apache.juneau.collections.JsonMap.*;
+import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.StringUtils.*;
 import static org.apache.juneau.commons.utils.ThrowableUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
 
 import java.util.*;
 
+import org.apache.juneau.commons.collections.*;
 import org.apache.juneau.commons.utils.*;
 
 /**
@@ -97,13 +98,16 @@ public class UrlPath {
         */
        public boolean isTrailingSlash() { return nn(path) && 
path.endsWith("/"); }
 
-       @Override /* Overridden from Object */
-       public String toString() {
+       protected FluentMap<String,Object> properties() {
                // @formatter:off
-               return filteredMap()
-                       .append("raw", path)
-                       .append("parts", parts)
-                       .asReadableString();
+               return filteredBeanPropertyMap()
+                       .a("parts", parts)
+                       .a("raw", path);
                // @formatter:on
        }
+
+       @Override /* Overridden from Object */
+       public String toString() {
+               return r(properties());
+       }
 }
\ No newline at end of file
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/UrlPathMatch.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/UrlPathMatch.java
index 871186033e..3a6b7e50c2 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/UrlPathMatch.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/util/UrlPathMatch.java
@@ -16,7 +16,6 @@
  */
 package org.apache.juneau.rest.util;
 
-import static org.apache.juneau.collections.JsonMap.*;
 import static org.apache.juneau.commons.utils.CollectionUtils.*;
 import static org.apache.juneau.commons.utils.StringUtils.*;
 import static org.apache.juneau.commons.utils.Utils.*;
@@ -135,13 +134,16 @@ public class UrlPathMatch {
                return ! vars.isEmpty();
        }
 
-       @Override /* Overridden from Object */
-       public String toString() {
+       protected FluentMap<String,Object> properties() {
                // @formatter:off
-               return filteredMap()
-                       .append("v", getVars())
-                       .append("r", getRemainder())
-                       .asString();
+               return filteredBeanPropertyMap()
+                       .a("r", getRemainder())
+                       .a("v", getVars());
                // @formatter:on
        }
+
+       @Override /* Overridden from Object */
+       public String toString() {
+               return r(properties());
+       }
 }
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/annotation/AnnotationObject_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/annotation/AnnotationObject_Test.java
index e252ee054e..82036e5e19 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/annotation/AnnotationObject_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/annotation/AnnotationObject_Test.java
@@ -200,20 +200,20 @@ class AnnotationObject_Test extends TestBase {
        @Test
        void c01_toMap_defaultValues() {
                var a = T.create().build();
-               assertBean(((T)a).toMap(), "value,number,flag,array", 
",0,false,[]");
+               assertBean(((T)a).propertyMap(), "value,number,flag,array", 
",0,false,[]");
        }
 
        @Test
        void c02_toMap_customValues() {
                var a = T.create().value("a").number(1).flag(true).array("b1", 
"b2").build();
 
-               assertBean(((T)a).toMap(), "value,number,flag,array", 
"a,1,true,[b1,b2]");
+               assertBean(((T)a).propertyMap(), "value,number,flag,array", 
"a,1,true,[b1,b2]");
        }
 
        @Test
        void c03_toMap_keySorted() {
                var a = T.create().build();
-               var map = ((T)a).toMap();
+               var map = ((T)a).propertyMap();
 
                // Map should be ordered by key name
                assertList(map.keySet(), "array", "flag", "number", "value");
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/annotation/AppliedAnnotationObject_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/annotation/AppliedAnnotationObject_Test.java
index 7bd9607b17..f4f4268edf 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/annotation/AppliedAnnotationObject_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/annotation/AppliedAnnotationObject_Test.java
@@ -951,7 +951,7 @@ class AppliedAnnotationObject_Test extends TestBase {
                void k01_withTargets() {
                        var a = TAO.create().on("target1", 
"target2").value("test").build();
 
-                       var map = ((TAO)a).toMap();
+                       var map = ((TAO)a).propertyMap();
                        assertBean(map, "on,value", "[target1,target2],test");
                }
        }
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/annotation/AppliedOnClassAnnotationObject_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/annotation/AppliedOnClassAnnotationObject_Test.java
index 898c29a661..a8091e31f6 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/annotation/AppliedOnClassAnnotationObject_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/annotation/AppliedOnClassAnnotationObject_Test.java
@@ -289,7 +289,7 @@ class AppliedOnClassAnnotationObject_Test extends TestBase {
        @Test
        void e01_toMap_withOnClass() {
                var a = T.create().onClass(TC1.class, 
TC2.class).value("test").build();
-               var map = ((T)a).toMap();
+               var map = ((T)a).propertyMap();
 
                assertBean(map, "value,on,onClass", "test,[],[TC1,TC2]");
        }
@@ -297,7 +297,7 @@ class AppliedOnClassAnnotationObject_Test extends TestBase {
        @Test
        void e02_toMap_withBoth() {
                var a = 
T.create().on("com.example.Class1").onClass(TC1.class).value("test").build();
-               var map = ((T)a).toMap();
+               var map = ((T)a).propertyMap();
 
                assertBean(map, "value,on,onClass", 
"test,[com.example.Class1],[TC1]");
        }
@@ -305,7 +305,7 @@ class AppliedOnClassAnnotationObject_Test extends TestBase {
        @Test
        void e03_toMap_empty() {
                var a = T.create().build();
-               var map = ((T)a).toMap();
+               var map = ((T)a).propertyMap();
 
                assertBean(map, "value,on,onClass", ",[],[]");
        }
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/AnnotationInfo_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/AnnotationInfo_Test.java
index 79f09714b0..4a74d04824 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/AnnotationInfo_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/AnnotationInfo_Test.java
@@ -634,15 +634,15 @@ class AnnotationInfo_Test extends TestBase {
        }
 
        
//====================================================================================================
-       // toMap()
+       // properties()
        
//====================================================================================================
        @Test
-       void a029_toMap() {
+       void a029_properties() {
                var ci = ClassInfo.of(TestClass.class);
                var ai = 
ci.getAnnotations(TestAnnotation.class).findFirst().orElse(null);
                assertNotNull(ai);
 
-               var map = ai.toMap();
+               var map = ai.properties();
                assertNotNull(map);
                assertTrue(map.containsKey("CLASS_TYPE"));
                assertTrue(map.containsKey("@TestAnnotation"));
@@ -656,7 +656,7 @@ class AnnotationInfo_Test extends TestBase {
                var ai2 = 
ci2.getAnnotations(ToMapTestAnnotation.class).findFirst().orElse(null);
                assertNotNull(ai2);
 
-               var map2 = ai2.toMap();
+               var map2 = ai2.properties();
                assertNotNull(map2);
                var annotationMap2 = 
(java.util.Map<String,Object>)map2.get("@ToMapTestAnnotation");
                assertNotNull(annotationMap2);
@@ -706,7 +706,7 @@ class AnnotationInfo_Test extends TestBase {
                var ci3 = ClassInfo.of(ToMapTestClass.class);
                var ai3 = AnnotationInfo.of(ci3, proxyAnnotation);
                
-               var map3 = ai3.toMap();
+               var map3 = ai3.properties();
                assertNotNull(map3);
                var annotationMap3 = 
(java.util.Map<String,Object>)map3.get("@ToMapTestAnnotation");
                assertNotNull(annotationMap3);
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ReflectionMap_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ReflectionMap_Test.java
index 4e2cf06e5a..b8f19914e1 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ReflectionMap_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/commons/reflect/ReflectionMap_Test.java
@@ -629,7 +629,7 @@ class ReflectionMap_Test extends TestBase {
                                .append("F1.myField", 4)            // field
                                .append("F1()", 5)                  // 
constructor
                                .build();
-                       assertString("{classEntries=[{simpleName=F1, 
fullName=F1, value=1}], methodEntries=[{simpleClassName=F1, fullClassName=F1, 
methodName=toString, value=2}, {simpleClassName=F1, fullClassName=F1, 
methodName=toString, args=[String], value=3}, {simpleClassName=F1, 
fullClassName=F1, methodName=myField, value=4}], 
fieldEntries=[{simpleClassName=F1, fullClassName=F1, fieldName=toString, 
value=2}, {simpleClassName=F1, fullClassName=F1, fieldName=myField, value=4}], 
constructorEntries=[{simpleC [...]
+                       
assertString("{classEntries=[{fullName=F1,simpleName=F1,value=1}],constructorEntries=[{fullClassName=F1,simpleClassName=F1,value=5}],fieldEntries=[{fieldName=toString,fullClassName=F1,simpleClassName=F1,value=2},{fieldName=myField,fullClassName=F1,simpleClassName=F1,value=4}],methodEntries=[{fullClassName=F1,methodName=toString,simpleClassName=F1,value=2},{args=[String],fullClassName=F1,methodName=toString,simpleClassName=F1,value=3},{fullClassName=F1,methodName=myField,simpleClassNam
 [...]
                }
        }
 }
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/cp/BeanStore_Test.java 
b/juneau-utest/src/test/java/org/apache/juneau/cp/BeanStore_Test.java
index d7cddb14ca..d1848ec518 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/cp/BeanStore_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/cp/BeanStore_Test.java
@@ -68,8 +68,8 @@ class BeanStore_Test extends TestBase {
        @Test void a01_builderCopyConstructor() {
                var b1p = BeanStore.create().readOnly().threadSafe().build();
                var b1c = BeanStore.create().parent(b1p).build();
-               assertContains("readOnly:true", b1c.toString());
-               assertContains("threadSafe:true", b1c.toString());
+               assertContains("readOnly=true", b1c.toString());
+               assertContains("threadSafe=true", b1c.toString());
        }
 
        @Test void a02_readOnly() {
@@ -163,10 +163,10 @@ class BeanStore_Test extends TestBase {
                        assertList(b.stream(A2.class).map(BeanStoreEntry::get), 
a2a);
                }
 
-               
assertMatchesGlob("{*,entries:[{type:'A1',bean:'"+identity(a1b)+"'},{type:'A1',bean:'"+Utils.identity(a1a)+"'}]}",
 b1p);
-               
assertMatchesGlob("{*,entries:[{type:'A2',bean:'"+identity(a2a)+"'}],parent:{*,entries:[{type:'A1',bean:'"+Utils.identity(a1b)+"'},{type:'A1',bean:'"+Utils.identity(a1a)+"'}]}}",
 b1c);
-               
assertMatchesGlob("{*,entries:[{type:'A1',bean:'"+identity(a1b)+"'},{type:'A1',bean:'"+Utils.identity(a1a)+"'}],threadSafe:true}",
 b2p);
-               
assertMatchesGlob("{*,entries:[{type:'A2',bean:'"+identity(a2a)+"'}],parent:{*,entries:[{type:'A1',bean:'"+Utils.identity(a1b)+"'},{type:'A1',bean:'"+Utils.identity(a1a)+"'}],threadSafe:true},threadSafe:true}",
 b2c);
+               
assertMatchesGlob("{entries=[{type=A1,bean="+identity(a1b)+"},{type=A1,bean="+Utils.identity(a1a)+"}],identity=*}",
 b1p);
+               
assertMatchesGlob("{entries=[{type=A2,bean="+identity(a2a)+"}],identity=*,parent={entries=[{type=A1,bean="+Utils.identity(a1b)+"},{type=A1,bean="+Utils.identity(a1a)+"}],identity=*}}",
 b1c);
+               
assertMatchesGlob("{entries=[{type=A1,bean="+identity(a1b)+"},{type=A1,bean="+Utils.identity(a1a)+"}],identity=*,threadSafe=true}",
 b2p);
+               
assertMatchesGlob("{entries=[{type=A2,bean="+identity(a2a)+"}],identity=*,parent={entries=[{type=A1,bean="+Utils.identity(a1b)+"},{type=A1,bean="+Utils.identity(a1a)+"}],identity=*,threadSafe=true},threadSafe=true}",
 b2c);
 
                b1p.removeBean(A1.class);
                b1c.clear().addBean(A1.class, a1a);
diff --git a/juneau-utest/src/test/java/org/apache/juneau/cp/Messages_Test.java 
b/juneau-utest/src/test/java/org/apache/juneau/cp/Messages_Test.java
index c4e57058dc..f06ad04b19 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/cp/Messages_Test.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/cp/Messages_Test.java
@@ -151,6 +151,6 @@ class Messages_Test extends TestBase {
 
        @Test void a13_toString() {
                var x = Messages.of(Test2.class);
-               assertString("{file:'Test2.properties',yyy:'bar'}", x);
+               assertString("{file=Test2.properties,yyy=bar}", x);
        }
 }
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
index 75eb64f698..78e28f6870 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_FormDataAnnotation_Test.java
@@ -737,9 +737,9 @@ class Remote_FormDataAnnotation_Test extends TestBase {
        @Test void k01_requestBean_simpleVals() {
                var x1 = remote(K.class,K1.class);
                var x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K1.class);
-               
assertEquals("{a:'a1',b:'b1',c:'c1',e:'',g:'true',h:'123',i1:'foo'}",x1.postX1(new
 K1a()));
-               
assertEquals("{a:'a1',b:'b1',c:'c1',e:'',g:'\\'true\\'',h:'\\'123\\'',i1:'foo'}",x2.postX1(new
 K1a()));
-               
assertEquals("{a:'xa1x',b:'xb1x',c:'xc1x',e:'xx',g:'xtruex',h:'x123x',i1:'xfoox'}",x2.postX2(new
 K1a()));
+               
assertEquals("{a=a1,b=b1,c=c1,e=,g=true,h=123,i1=foo}",x1.postX1(new K1a()));
+               
assertEquals("{a=a1,b=b1,c=c1,e=,g='true',h='123',i1=foo}",x2.postX1(new 
K1a()));
+               
assertEquals("{a=xa1x,b=xb1x,c=xc1x,e=xx,g=xtruex,h=x123x,i1=xfoox}",x2.postX2(new
 K1a()));
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
@@ -762,9 +762,9 @@ class Remote_FormDataAnnotation_Test extends TestBase {
        @Test void k02_requestBean_maps() {
                var x1 = remote(K.class,K2.class);
                var x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K2.class);
-               
assertEquals("{a:'a1=v1,a2=123,a3=null,a4=',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:''}",x1.postX1(new
 K2a()));
-               
assertEquals("{a:'(a1=v1,a2=123,a3=null,a4=\\'\\')',b1:'\\'true\\'',b2:'\\'123\\'',b3:'\\'null\\'',c1:'v1',c2:'123',c4:''}",x2.postX1(new
 K2a()));
-               assertEquals("{a:'x{a1=v1, a2=123, a3=null, 
a4=}x',b1:'xtruex',b2:'x123x',b3:'xnullx',c1:'xv1x',c2:'x123x',c4:'xx'}",x2.postX2(new
 K2a()));
+               
assertEquals("{a=a1=v1,a2=123,a3=null,a4=,b1=true,b2=123,b3=null,c1=v1,c2=123,c4=}",x1.postX1(new
 K2a()));
+               
assertEquals("{a=(a1=v1,a2=123,a3=null,a4=''),b1='true',b2='123',b3='null',c1=v1,c2=123,c4=}",x2.postX1(new
 K2a()));
+               assertEquals("{a=x{a1=v1, a2=123, a3=null, 
a4=}x,b1=xtruex,b2=x123x,b3=xnullx,c1=xv1x,c2=x123x,c4=xx}",x2.postX2(new 
K2a()));
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
@@ -788,9 +788,9 @@ class Remote_FormDataAnnotation_Test extends TestBase {
        @Test void k03_requestBean_nameValuePairs() {
                var x1 = remote(K.class,K3.class);
                var x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K3.class);
-               
assertEquals("{a1:'v1',a2:'123',a4:'',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:'',e1:'v1',e2:'123',e4:''}",x1.postX1(new
 K3a()));
-               
assertEquals("{a1:'v1',a2:'123',a4:'',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:'',e1:'v1',e2:'123',e4:''}",x2.postX1(new
 K3a()));
-               
assertEquals("{a1:'v1',a2:'123',a4:'',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:'',e1:'v1',e2:'123',e4:''}",x2.postX2(new
 K3a()));
+               
assertEquals("{a1=v1,a2=123,a4=,b1=true,b2=123,b3=null,c1=v1,c2=123,c4=,e1=v1,e2=123,e4=}",x1.postX1(new
 K3a()));
+               
assertEquals("{a1=v1,a2=123,a4=,b1=true,b2=123,b3=null,c1=v1,c2=123,c4=,e1=v1,e2=123,e4=}",x2.postX1(new
 K3a()));
+               
assertEquals("{a1=v1,a2=123,a4=,b1=true,b2=123,b3=null,c1=v1,c2=123,c4=,e1=v1,e2=123,e4=}",x2.postX2(new
 K3a()));
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
@@ -808,7 +808,7 @@ class Remote_FormDataAnnotation_Test extends TestBase {
 
        @Test void k04_requestBean_charSequence() {
                var x = remote(K.class,K4.class);
-               assertEquals("{foo:'bar',baz:'qux'}",x.post(new C04_Bean()));
+               assertEquals("{baz=qux,foo=bar}",x.post(new C04_Bean()));
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
@@ -826,7 +826,7 @@ class Remote_FormDataAnnotation_Test extends TestBase {
 
        @Test void k05_requestBean_reader() {
                var x = remote(K.class,K5.class);
-               assertEquals("{foo:'bar',baz:'qux'}",x.post(new K5a()));
+               assertEquals("{baz=qux,foo=bar}",x.post(new K5a()));
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
@@ -854,9 +854,9 @@ class Remote_FormDataAnnotation_Test extends TestBase {
        @Test void k06_requestBean_collections() {
                var x1 = remote(K.class,K6.class);
                var x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K6.class);
-               
assertEquals("{a:'foo,,true,123,null,true,123,null',b:'foo,,true,123,null,true,123,null',c:'xfoo||true|123|null|true|123|nullx',d:'',f:'foo,,true,123,null,true,123,null',g:'xfoo||true|123|null|true|123|nullx',h:''}",
 x1.postX1(new K6a()));
-               
assertEquals("{a:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',b:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',c:'xfoo||true|123|null|true|123|nullx',d:'@()',f:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',g:'xfoo||true|123|null|true|123|nullx',h:'@()'}",
 x2.postX1(new K6a()));
-               
assertEquals("{a:'xfoo||true|123|null|true|123|nullx',b:'xfoo||true|123|null|true|123|nullx',c:'xfoo||true|123|null|true|123|nullx',d:'xx',f:'xfoo||true|123|null|true|123|nullx',g:'xfoo||true|123|null|true|123|nullx',h:'xx'}",
 x2.postX2(new K6a()));
+               
assertEquals("{a=foo,,true,123,null,true,123,null,b=foo,,true,123,null,true,123,null,c=xfoo||true|123|null|true|123|nullx,d=,f=foo,,true,123,null,true,123,null,g=xfoo||true|123|null|true|123|nullx,h=}",
 x1.postX1(new K6a()));
+               
assertEquals("{a=@(foo,'','true','123','null',true,123,null),b=@(foo,'','true','123','null',true,123,null),c=xfoo||true|123|null|true|123|nullx,d=@(),f=@(foo,'','true','123','null',true,123,null),g=xfoo||true|123|null|true|123|nullx,h=@()}",
 x2.postX1(new K6a()));
+               
assertEquals("{a=xfoo||true|123|null|true|123|nullx,b=xfoo||true|123|null|true|123|nullx,c=xfoo||true|123|null|true|123|nullx,d=xx,f=xfoo||true|123|null|true|123|nullx,g=xfoo||true|123|null|true|123|nullx,h=xx}",
 x2.postX2(new K6a()));
        }
 
        
//------------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
index e5e7d424e4..9610afd18e 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_HeaderAnnotation_Test.java
@@ -700,9 +700,9 @@ class Remote_HeaderAnnotation_Test extends TestBase {
        @Test void k01_requestBean_simpleVals() {
                var x1 = remote(K.class,K1.class);
                var x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K1.class);
-               
assertEquals("{a:'a1',b:'b1',c:'c1',e:'',g:'true',h:'123',i1:'foo'}",x1.getX1(new
 K1a()));
-               
assertEquals("{a:'a1',b:'b1',c:'c1',e:'',g:'\\'true\\'',h:'\\'123\\'',i1:'foo'}",x2.getX1(new
 K1a()));
-               
assertEquals("{a:'xa1x',b:'xb1x',c:'xc1x',e:'xx',g:'xtruex',h:'x123x',i1:'xfoox'}",x2.getX2(new
 K1a()));
+               
assertEquals("{a=a1,b=b1,c=c1,e=,g=true,h=123,i1=foo}",x1.getX1(new K1a()));
+               
assertEquals("{a=a1,b=b1,c=c1,e=,g='true',h='123',i1=foo}",x2.getX1(new K1a()));
+               
assertEquals("{a=xa1x,b=xb1x,c=xc1x,e=xx,g=xtruex,h=x123x,i1=xfoox}",x2.getX2(new
 K1a()));
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
@@ -725,9 +725,9 @@ class Remote_HeaderAnnotation_Test extends TestBase {
        @Test void k02_requestBean_maps() {
                var x1 = remote(K.class,K2.class);
                var x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K2.class);
-               
assertEquals("{a:'a1=v1,a2=123,a3=null,a4=',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:''}",x1.getX1(new
 K2a()));
-               
assertEquals("{a:'(a1=v1,a2=123,a3=null,a4=\\'\\')',b1:'\\'true\\'',b2:'\\'123\\'',b3:'\\'null\\'',c1:'v1',c2:'123',c4:''}",x2.getX1(new
 K2a()));
-               assertEquals("{a:'x{a1=v1, a2=123, a3=null, 
a4=}x',b1:'xtruex',b2:'x123x',b3:'xnullx',c1:'xv1x',c2:'x123x',c4:'xx'}",x2.getX2(new
 K2a()));
+               
assertEquals("{a=a1=v1,a2=123,a3=null,a4=,b1=true,b2=123,b3=null,c1=v1,c2=123,c4=}",x1.getX1(new
 K2a()));
+               
assertEquals("{a=(a1=v1,a2=123,a3=null,a4=''),b1='true',b2='123',b3='null',c1=v1,c2=123,c4=}",x2.getX1(new
 K2a()));
+               assertEquals("{a=x{a1=v1, a2=123, a3=null, 
a4=}x,b1=xtruex,b2=x123x,b3=xnullx,c1=xv1x,c2=x123x,c4=xx}",x2.getX2(new 
K2a()));
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
@@ -752,9 +752,9 @@ class Remote_HeaderAnnotation_Test extends TestBase {
        @Test void k03_requestBean_headers() {
                var x1 = remote(K.class,K3.class);
                var x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K3.class);
-               
assertEquals("{a1:'v1',a2:'123',a4:'',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:'',e1:'v1',e2:'123',e4:'',f1:'v1',f2:'123',f4:''}",x1.getX1(new
 K3a()));
-               
assertEquals("{a1:'v1',a2:'123',a4:'',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:'',e1:'v1',e2:'123',e4:'',f1:'v1',f2:'123',f4:''}",x2.getX1(new
 K3a()));
-               
assertEquals("{a1:'v1',a2:'123',a4:'',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:'',e1:'v1',e2:'123',e4:'',f1:'v1',f2:'123',f4:''}",x2.getX2(new
 K3a()));
+               
assertEquals("{a1=v1,a2=123,a4=,b1=true,b2=123,b3=null,c1=v1,c2=123,c4=,e1=v1,e2=123,e4=,f1=v1,f2=123,f4=}",x1.getX1(new
 K3a()));
+               
assertEquals("{a1=v1,a2=123,a4=,b1=true,b2=123,b3=null,c1=v1,c2=123,c4=,e1=v1,e2=123,e4=,f1=v1,f2=123,f4=}",x2.getX1(new
 K3a()));
+               
assertEquals("{a1=v1,a2=123,a4=,b1=true,b2=123,b3=null,c1=v1,c2=123,c4=,e1=v1,e2=123,e4=,f1=v1,f2=123,f4=}",x2.getX2(new
 K3a()));
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
@@ -782,9 +782,9 @@ class Remote_HeaderAnnotation_Test extends TestBase {
        @Test void k04_requestBean_collections() {
                var x1 = remote(K.class,K4.class);
                var x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K4.class);
-               
assertEquals("{a:'foo,,true,123,null,true,123,null',b:'foo,,true,123,null,true,123,null',c:'xfoo||true|123|null|true|123|nullx',d:'',f:'foo,,true,123,null,true,123,null',g:'xfoo||true|123|null|true|123|nullx',h:''}",
 x1.getX1(new K4a()));
-               
assertEquals("{a:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',b:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',c:'xfoo||true|123|null|true|123|nullx',d:'@()',f:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',g:'xfoo||true|123|null|true|123|nullx',h:'@()'}",
 x2.getX1(new K4a()));
-               
assertEquals("{a:'xfoo||true|123|null|true|123|nullx',b:'xfoo||true|123|null|true|123|nullx',c:'xfoo||true|123|null|true|123|nullx',d:'xx',f:'xfoo||true|123|null|true|123|nullx',g:'xfoo||true|123|null|true|123|nullx',h:'xx'}",
 x2.getX2(new K4a()));
+               
assertEquals("{a=foo,,true,123,null,true,123,null,b=foo,,true,123,null,true,123,null,c=xfoo||true|123|null|true|123|nullx,d=,f=foo,,true,123,null,true,123,null,g=xfoo||true|123|null|true|123|nullx,h=}",
 x1.getX1(new K4a()));
+               
assertEquals("{a=@(foo,'','true','123','null',true,123,null),b=@(foo,'','true','123','null',true,123,null),c=xfoo||true|123|null|true|123|nullx,d=@(),f=@(foo,'','true','123','null',true,123,null),g=xfoo||true|123|null|true|123|nullx,h=@()}",
 x2.getX1(new K4a()));
+               
assertEquals("{a=xfoo||true|123|null|true|123|nullx,b=xfoo||true|123|null|true|123|nullx,c=xfoo||true|123|null|true|123|nullx,d=xx,f=xfoo||true|123|null|true|123|nullx,g=xfoo||true|123|null|true|123|nullx,h=xx}",
 x2.getX2(new K4a()));
        }
 
        
//------------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
index d933b88e80..759cbb2690 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/http/remote/Remote_QueryAnnotation_Test.java
@@ -731,9 +731,9 @@ class Remote_QueryAnnotation_Test extends TestBase {
        @Test void k01_requestBean_simpleVals() {
                var x1 = remote(K.class,K1.class);
                var x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K1.class);
-               
assertEquals("{a:'a1',b:'b1',c:'c1',e:'',g:'true',h:'123',i1:'foo'}",x1.getX1(new
 K1b()));
-               
assertEquals("{a:'a1',b:'b1',c:'c1',e:'',g:'\\'true\\'',h:'\\'123\\'',i1:'foo'}",x2.getX1(new
 K1b()));
-               
assertEquals("{a:'xa1x',b:'xb1x',c:'xc1x',e:'xx',g:'xtruex',h:'x123x',i1:'xfoox'}",x2.getX2(new
 K1b()));
+               
assertEquals("{a=a1,b=b1,c=c1,e=,g=true,h=123,i1=foo}",x1.getX1(new K1b()));
+               
assertEquals("{a=a1,b=b1,c=c1,e=,g='true',h='123',i1=foo}",x2.getX1(new K1b()));
+               
assertEquals("{a=xa1x,b=xb1x,c=xc1x,e=xx,g=xtruex,h=x123x,i1=xfoox}",x2.getX2(new
 K1b()));
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
@@ -757,9 +757,9 @@ class Remote_QueryAnnotation_Test extends TestBase {
        @Test void k02_requestBean_maps() {
                var x1 = remote(K.class,K2.class);
                var x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K2.class);
-               
assertEquals("{a:'a1=v1,a2=123,a3=null,a4=',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:''}",x1.getX1(new
 K2a()));
-               
assertEquals("{a:'(a1=v1,a2=123,a3=null,a4=\\'\\')',b1:'\\'true\\'',b2:'\\'123\\'',b3:'\\'null\\'',c1:'v1',c2:'123',c4:''}",x2.getX1(new
 K2a()));
-               assertEquals("{a:'x{a1=v1, a2=123, a3=null, 
a4=}x',b1:'xtruex',b2:'x123x',b3:'xnullx',c1:'xv1x',c2:'x123x',c4:'xx'}",x2.getX2(new
 K2a()));
+               
assertEquals("{a=a1=v1,a2=123,a3=null,a4=,b1=true,b2=123,b3=null,c1=v1,c2=123,c4=}",x1.getX1(new
 K2a()));
+               
assertEquals("{a=(a1=v1,a2=123,a3=null,a4=''),b1='true',b2='123',b3='null',c1=v1,c2=123,c4=}",x2.getX1(new
 K2a()));
+               assertEquals("{a=x{a1=v1, a2=123, a3=null, 
a4=}x,b1=xtruex,b2=x123x,b3=xnullx,c1=xv1x,c2=x123x,c4=xx}",x2.getX2(new 
K2a()));
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
@@ -784,8 +784,8 @@ class Remote_QueryAnnotation_Test extends TestBase {
        @Test void k03_requestBean_nameValuePairs() {
                var x1 = remote(K.class,K3.class);
                var x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K3.class);
-               
assertEquals("{a1:'v1',a2:'123',a4:'',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:'',e1:'v1',e2:'123',e4:''}",x1.getX1(new
 K3a()));
-               
assertEquals("{a1:'v1',a2:'123',a4:'',b1:'true',b2:'123',b3:'null',c1:'v1',c2:'123',c4:'',e1:'v1',e2:'123',e4:''}",x2.getX1(new
 K3a()));
+               
assertEquals("{a1=v1,a2=123,a4=,b1=true,b2=123,b3=null,c1=v1,c2=123,c4=,e1=v1,e2=123,e4=}",x1.getX1(new
 K3a()));
+               
assertEquals("{a1=v1,a2=123,a4=,b1=true,b2=123,b3=null,c1=v1,c2=123,c4=,e1=v1,e2=123,e4=}",x2.getX1(new
 K3a()));
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
@@ -803,7 +803,7 @@ class Remote_QueryAnnotation_Test extends TestBase {
 
        @Test void k04_requestBean_charSequence() {
                var x = remote(K.class,K4.class);
-               assertEquals("{foo:'bar',baz:'qux'}",x.get(new K4a()));
+               assertEquals("{baz=qux,foo=bar}",x.get(new K4a()));
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
@@ -821,7 +821,7 @@ class Remote_QueryAnnotation_Test extends TestBase {
 
        @Test void k05_requestBean_reader() {
                var x = remote(K.class,K5.class);
-               assertEquals("{foo:'bar',baz:'qux'}",x.get(new K5a()));
+               assertEquals("{baz=qux,foo=bar}",x.get(new K5a()));
        }
 
        
//-----------------------------------------------------------------------------------------------------------------
@@ -849,9 +849,9 @@ class Remote_QueryAnnotation_Test extends TestBase {
        @Test void k06_requestBean_collections() {
                var x1 = remote(K.class,K6.class);
                var x2 = 
client(K.class).partSerializer(UonSerializer.class).build().getRemote(K6.class);
-               
assertEquals("{a:'foo,,true,123,null,true,123,null',b:'foo,,true,123,null,true,123,null',c:'xfoo||true|123|null|true|123|nullx',d:'',f:'foo,,true,123,null,true,123,null',g:'xfoo||true|123|null|true|123|nullx',h:''}",
 x1.getX1(new K6a()));
-               
assertEquals("{a:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',b:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',c:'xfoo||true|123|null|true|123|nullx',d:'@()',f:'@(foo,\\'\\',\\'true\\',\\'123\\',\\'null\\',true,123,null)',g:'xfoo||true|123|null|true|123|nullx',h:'@()'}",
 x2.getX1(new K6a()));
-               
assertEquals("{a:'xfoo||true|123|null|true|123|nullx',b:'xfoo||true|123|null|true|123|nullx',c:'xfoo||true|123|null|true|123|nullx',d:'xx',f:'xfoo||true|123|null|true|123|nullx',g:'xfoo||true|123|null|true|123|nullx',h:'xx'}",
 x2.getX2(new K6a()));
+               
assertEquals("{a=foo,,true,123,null,true,123,null,b=foo,,true,123,null,true,123,null,c=xfoo||true|123|null|true|123|nullx,d=,f=foo,,true,123,null,true,123,null,g=xfoo||true|123|null|true|123|nullx,h=}",
 x1.getX1(new K6a()));
+               
assertEquals("{a=@(foo,'','true','123','null',true,123,null),b=@(foo,'','true','123','null',true,123,null),c=xfoo||true|123|null|true|123|nullx,d=@(),f=@(foo,'','true','123','null',true,123,null),g=xfoo||true|123|null|true|123|nullx,h=@()}",
 x2.getX1(new K6a()));
+               
assertEquals("{a=xfoo||true|123|null|true|123|nullx,b=xfoo||true|123|null|true|123|nullx,c=xfoo||true|123|null|true|123|nullx,d=xx,f=xfoo||true|123|null|true|123|nullx,g=xfoo||true|123|null|true|123|nullx,h=xx}",
 x2.getX2(new K6a()));
        }
 
        
//------------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Path_Test.java 
b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Path_Test.java
index 7ff64d895c..f58d42cd90 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Path_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/annotation/Path_Test.java
@@ -411,7 +411,7 @@ class Path_Test extends TestBase {
                var f = 
MockRestClient.createLax(F.class).servletPath("/f").defaultRequestConfig(RequestConfig.custom().setNormalizeUri(false).build()).build();
                f.get("http://localhost/f/x1/x2";)
                        .run()
-                       .assertContent("a: {a:'x1',b:'x2'}");
+                       .assertContent("a: {a=x1,b=x2}");
                f.get("http://localhost/f/x1";)
                        .run()
                        .assertStatus(404);
@@ -429,7 +429,7 @@ class Path_Test extends TestBase {
                        .assertStatus(404);
                f.get("http://localhost/f/x1/x2/foo";)
                        .run()
-                       .assertContent("b: 
{a:'x1',b:'x2','/**':'foo','/*':'foo'}");
+                       .assertContent("b: {/*=foo,/**=foo,a=x1,b=x2}");
                f.get("http://localhost/f///foo";)
                        .run()
                        .assertStatus(404);
@@ -441,7 +441,7 @@ class Path_Test extends TestBase {
                        .assertStatus(404);
                f.get("http://localhost/f/x1/x2/fc";)
                        .run()
-                       .assertContent("c: {a:'x1',b:'x2'}");
+                       .assertContent("c: {a=x1,b=x2}");
                f.get("http://localhost/f///a";)
                        .run()
                        .assertStatus(404);
@@ -453,7 +453,7 @@ class Path_Test extends TestBase {
                        .assertStatus(404);
                f.get("http://localhost/f/x1/x2/fd/x3/x4";)
                        .run()
-                       .assertContent("d: {a:'x1',b:'x2',c:'x3',d:'x4'}");
+                       .assertContent("d: {a=x1,b=x2,c=x3,d=x4}");
                f.get("http://localhost/f//x2/b/x3/x4";)
                        .run()
                        .assertStatus(404);
@@ -471,16 +471,16 @@ class Path_Test extends TestBase {
                        .assertStatus(404);
                f.get("http://localhost/f/x1/x2/fe/x3/x4";)
                        .run()
-                       .assertContent("e: {a:'x1, x3',b:'x2, x4'}");
+                       .assertContent("e: {a=x1, x3,b=x2, x4}");
                f.get("http://localhost/f/x1/x2/ff/x3/x4";)
                        .run()
-                       .assertContent("f: {a:'x1',b:'x2',c:'x3',d:'x4'}");
+                       .assertContent("f: {a=x1,b=x2,c=x3,d=x4}");
                f.get("http://localhost/f/x1/x2/ff/x3/x4/";)
                        .run()
-                       .assertContent("f: 
{a:'x1',b:'x2',c:'x3',d:'x4','/**':'','/*':''}");
+                       .assertContent("f: {/*=,/**=,a=x1,b=x2,c=x3,d=x4}");
                f.get("http://localhost/f/x1/x2/ff/x3/x4/foo/bar";)
                        .run()
-                       .assertContent("f: 
{a:'x1',b:'x2',c:'x3',d:'x4','/**':'foo/bar','/*':'foo/bar'}");
+                       .assertContent("f: 
{/*=foo/bar,/**=foo/bar,a=x1,b=x2,c=x3,d=x4}");
        }
 
        
//------------------------------------------------------------------------------------------------------------------
@@ -494,7 +494,7 @@ class Path_Test extends TestBase {
                var g = 
MockRestClient.createLax(G.class).defaultRequestConfig(RequestConfig.custom().setNormalizeUri(false).build()).build();
                g.get("http://localhost/f/x1/x2";)
                        .run()
-                       .assertContent("a: {a:'x1',b:'x2'}");
+                       .assertContent("a: {a=x1,b=x2}");
                g.get("http://localhost/f/x1";)
                        .run()
                        .assertStatus(404);
@@ -512,7 +512,7 @@ class Path_Test extends TestBase {
                        .assertStatus(404);
                g.get("http://localhost/f/x1/x2/fc";)
                        .run()
-                       .assertContent("c: {a:'x1',b:'x2'}");
+                       .assertContent("c: {a=x1,b=x2}");
                g.get("http://localhost/f///a";)
                        .run()
                        .assertStatus(404);
@@ -524,7 +524,7 @@ class Path_Test extends TestBase {
                        .assertStatus(404);
                g.get("http://localhost/f/x1/x2/fd/x3/x4";)
                        .run()
-                       .assertContent("d: {a:'x1',b:'x2',c:'x3',d:'x4'}");
+                       .assertContent("d: {a=x1,b=x2,c=x3,d=x4}");
                g.get("http://localhost/f//x2/b/x3/x4";)
                        .run()
                        .assertStatus(404);
@@ -542,16 +542,16 @@ class Path_Test extends TestBase {
                        .assertStatus(404);
                g.get("http://localhost/f/x1/x2/fe/x3/x4";)
                        .run()
-                       .assertContent("e: {a:'x1, x3',b:'x2, x4'}");
+                       .assertContent("e: {a=x1, x3,b=x2, x4}");
                g.get("http://localhost/f/x1/x2/ff/x3/x4";)
                        .run()
-                       .assertContent("f: {a:'x1',b:'x2',c:'x3',d:'x4'}");
+                       .assertContent("f: {a=x1,b=x2,c=x3,d=x4}");
                g.get("http://localhost/f/x1/x2/ff/x3/x4/";)
                        .run()
-                       .assertContent("f: 
{a:'x1',b:'x2',c:'x3',d:'x4','/**':'','/*':''}");
+                       .assertContent("f: {/*=,/**=,a=x1,b=x2,c=x3,d=x4}");
                g.get("http://localhost/f/x1/x2/ff/x3/x4/foo/bar";)
                        .run()
-                       .assertContent("f: 
{a:'x1',b:'x2',c:'x3',d:'x4','/**':'foo/bar','/*':'foo/bar'}");
+                       .assertContent("f: 
{/*=foo/bar,/**=foo/bar,a=x1,b=x2,c=x3,d=x4}");
        }
 
        
//------------------------------------------------------------------------------------------------------------------
@@ -565,7 +565,7 @@ class Path_Test extends TestBase {
                var h = 
MockRestClient.createLax(H.class).servletPath("/h").defaultRequestConfig(RequestConfig.custom().setNormalizeUri(false).build()).build();
                h.get("http://localhost/h/ha1/hb1/f/x1/x2";)
                        .run()
-                       .assertContent("a: {a:'x1',b:'x2',ha:'ha1',hb:'hb1'}");
+                       .assertContent("a: {a=x1,b=x2,ha=ha1,hb=hb1}");
                // These are 405 instead of 404 because when children don't 
match, we try to find a matching Java method.
                h.get("http://localhost/h/ha1/hb1/f/x1";)
                        .run()
@@ -599,7 +599,7 @@ class Path_Test extends TestBase {
                        .assertStatus(404);
                h.get("http://localhost/h/ha1/hb1/f/x1/x2/foo";)
                        .run()
-                       .assertContent("b: 
{a:'x1',b:'x2',ha:'ha1',hb:'hb1','/**':'foo','/*':'foo'}");
+                       .assertContent("b: 
{/*=foo,/**=foo,a=x1,b=x2,ha=ha1,hb=hb1}");
                h.get("http://localhost/h//hb1/f/x1/x2/foo";)
                        .run()
                        .assertStatus(404);
@@ -617,7 +617,7 @@ class Path_Test extends TestBase {
                        .assertStatus(404);
                h.get("http://localhost/h/ha1/hb1/f/x1/x2/fc";)
                        .run()
-                       .assertContent("c: {a:'x1',b:'x2',ha:'ha1',hb:'hb1'}");
+                       .assertContent("c: {a=x1,b=x2,ha=ha1,hb=hb1}");
                h.get("http://localhost/h//hb1/f/x1/x2/a";)
                        .run()
                        .assertStatus(404);
@@ -635,19 +635,19 @@ class Path_Test extends TestBase {
                        .assertStatus(404);
                h.get("http://localhost/h/ha1/hb1/f/x1/x2/fd/x3/x4";)
                        .run()
-                       .assertContent("d: 
{a:'x1',b:'x2',ha:'ha1',hb:'hb1',c:'x3',d:'x4'}");
+                       .assertContent("d: 
{a=x1,b=x2,c=x3,d=x4,ha=ha1,hb=hb1}");
                h.get("http://localhost/h/ha1/hb1/f/x1/x2/fe/x3/x4";)
                        .run()
-                       .assertContent("e: {a:'x1, x3',b:'x2, 
x4',ha:'ha1',hb:'hb1'}");
+                       .assertContent("e: {a=x1, x3,b=x2, x4,ha=ha1,hb=hb1}");
                h.get("http://localhost/h/ha1/hb1/f/x1/x2/ff/x3/x4";)
                        .run()
-                       .assertContent("f: 
{a:'x1',b:'x2',ha:'ha1',hb:'hb1',c:'x3',d:'x4'}");
+                       .assertContent("f: 
{a=x1,b=x2,c=x3,d=x4,ha=ha1,hb=hb1}");
                h.get("http://localhost/h/ha1/hb1/f/x1/x2/ff/x3/x4/";)
                        .run()
-                       .assertContent("f: 
{a:'x1',b:'x2',ha:'ha1',hb:'hb1',c:'x3',d:'x4','/**':'','/*':''}");
+                       .assertContent("f: 
{/*=,/**=,a=x1,b=x2,c=x3,d=x4,ha=ha1,hb=hb1}");
                h.get("http://localhost/h/ha1/hb1/f/x1/x2/ff/x3/x4/foo/bar";)
                        .run()
-                       .assertContent("f: 
{a:'x1',b:'x2',ha:'ha1',hb:'hb1',c:'x3',d:'x4','/**':'foo/bar','/*':'foo/bar'}");
+                       .assertContent("f: 
{/*=foo/bar,/**=foo/bar,a=x1,b=x2,c=x3,d=x4,ha=ha1,hb=hb1}");
        }
 
        
//------------------------------------------------------------------------------------------------------------------
@@ -661,7 +661,7 @@ class Path_Test extends TestBase {
                var i = 
MockRestClient.createLax(I.class).servletPath("/i").build();
                i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2";)
                        .run()
-                       .assertContent("a: 
{a:'x1',b:'x2',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
+                       .assertContent("a: 
{a=x1,b=x2,ha=ha1,hb=hb1,ia=ia1,ib=ib1}");
                i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1";)
                        .run()
                        .assertStatus(404);
@@ -709,25 +709,25 @@ class Path_Test extends TestBase {
                        .assertStatus(404);
                i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/foo";)
                        .run()
-                       .assertContent("b: 
{a:'x1',b:'x2',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1','/**':'foo','/*':'foo'}");
+                       .assertContent("b: 
{/*=foo,/**=foo,a=x1,b=x2,ha=ha1,hb=hb1,ia=ia1,ib=ib1}");
                i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/fc";)
                        .run()
-                       .assertContent("c: 
{a:'x1',b:'x2',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
+                       .assertContent("c: 
{a=x1,b=x2,ha=ha1,hb=hb1,ia=ia1,ib=ib1}");
                i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/fd/x3/x4";)
                        .run()
-                       .assertContent("d: 
{a:'x1',b:'x2',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1',c:'x3',d:'x4'}");
+                       .assertContent("d: 
{a=x1,b=x2,c=x3,d=x4,ha=ha1,hb=hb1,ia=ia1,ib=ib1}");
                i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/fe/x3/x4";)
                        .run()
-                       .assertContent("e: {a:'x1, x3',b:'x2, 
x4',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1'}");
+                       .assertContent("e: {a=x1, x3,b=x2, 
x4,ha=ha1,hb=hb1,ia=ia1,ib=ib1}");
                i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/ff/x3/x4";)
                        .run()
-                       .assertContent("f: 
{a:'x1',b:'x2',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1',c:'x3',d:'x4'}");
+                       .assertContent("f: 
{a=x1,b=x2,c=x3,d=x4,ha=ha1,hb=hb1,ia=ia1,ib=ib1}");
                i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/ff/x3/x4/";)
                        .run()
-                       .assertContent("f: 
{a:'x1',b:'x2',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1',c:'x3',d:'x4','/**':'','/*':''}");
+                       .assertContent("f: 
{/*=,/**=,a=x1,b=x2,c=x3,d=x4,ha=ha1,hb=hb1,ia=ia1,ib=ib1}");
                
i.get("http://localhost/i/ia1/ib1/h/ha1/hb1/f/x1/x2/ff/x3/x4/foo/bar";)
                        .run()
-                       .assertContent("f: 
{a:'x1',b:'x2',ha:'ha1',hb:'hb1',ia:'ia1',ib:'ib1',c:'x3',d:'x4','/**':'foo/bar','/*':'foo/bar'}");
+                       .assertContent("f: 
{/*=foo/bar,/**=foo/bar,a=x1,b=x2,c=x3,d=x4,ha=ha1,hb=hb1,ia=ia1,ib=ib1}");
        }
 
        
//------------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/rest/util/UrlPathMatcher_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/rest/util/UrlPathMatcher_Test.java
index 67bcb0b193..20bc78791c 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/rest/util/UrlPathMatcher_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/rest/util/UrlPathMatcher_Test.java
@@ -104,7 +104,7 @@ class UrlPathMatcher_Test extends TestBase {
        @Test void b01_simple_match() {
                var p = of("/foo");
                check(p, "/foo", "{}");
-               check(p, "/foo/", "{r:''}");
+               check(p, "/foo/", "{r=}");
        }
 
        @Test void b02_simple_noMatch() {
@@ -115,7 +115,7 @@ class UrlPathMatcher_Test extends TestBase {
        @Test void b03_simple_match_2parts() {
                var p = of("/foo/bar");
                check(p, "/foo/bar", "{}");
-               check(p, "/foo/bar/", "{r:''}");
+               check(p, "/foo/bar/", "{r=}");
        }
 
        @Test void b04_simple_noMatch_2parts() {
@@ -125,7 +125,7 @@ class UrlPathMatcher_Test extends TestBase {
 
        @Test void b05_simple_match_0parts() {
                var p = of("/");
-               check(p, "/", "{r:''}");
+               check(p, "/", "{r=}");
        }
 
        @Test void b06_simple_noMatch_0parts() {
@@ -135,7 +135,7 @@ class UrlPathMatcher_Test extends TestBase {
 
        @Test void b07_simple_match_blank() {
                var p = of("");
-               check(p, "/", "{r:''}");
+               check(p, "/", "{r=}");
        }
 
        @Test void b08_simple_noMatch_blank() {
@@ -150,10 +150,10 @@ class UrlPathMatcher_Test extends TestBase {
        @Test void c01_simple_withRemainder_match() {
                var p = of("/foo/*");
                check(p, "/foo", "{}");
-               check(p, "/foo/", "{r:''}");
-               check(p, "/foo/bar", "{r:'bar'}");
-               check(p, "/foo/bar/", "{r:'bar/'}");
-               check(p, "/foo/bar/baz", "{r:'bar/baz'}");
+               check(p, "/foo/", "{r=}");
+               check(p, "/foo/bar", "{r=bar}");
+               check(p, "/foo/bar/", "{r=bar/}");
+               check(p, "/foo/bar/baz", "{r=bar/baz}");
        }
 
        @Test void c02_simple_withRemainder_noMatch() {
@@ -164,8 +164,8 @@ class UrlPathMatcher_Test extends TestBase {
        @Test void c03_simple_withRemainder_match_2parts() {
                var p = of("/foo/bar/*");
                check(p, "/foo/bar", "{}");
-               check(p, "/foo/bar/baz", "{r:'baz'}");
-               check(p, "/foo/bar/baz/", "{r:'baz/'}");
+               check(p, "/foo/bar/baz", "{r=baz}");
+               check(p, "/foo/bar/baz/", "{r=baz/}");
        }
 
        @Test void c04_simple_withRemainder_noMatch_2parts() {
@@ -175,16 +175,16 @@ class UrlPathMatcher_Test extends TestBase {
 
        @Test void c05_simple_withRemainder_match_0parts() {
                var p = of("/*");
-               check(p, "/", "{r:''}");
-               check(p, "/foo", "{r:'foo'}");
-               check(p, "/foo/bar", "{r:'foo/bar'}");
+               check(p, "/", "{r=}");
+               check(p, "/foo", "{r=foo}");
+               check(p, "/foo/bar", "{r=foo/bar}");
        }
 
        @Test void c06_simple_withRemainder_match_blank() {
                var p = of("*");
-               check(p, "/", "{r:''}");
-               check(p, "/foo", "{r:'foo'}");
-               check(p, "/foo/bar", "{r:'foo/bar'}");
+               check(p, "/", "{r=}");
+               check(p, "/foo", "{r=foo}");
+               check(p, "/foo/bar", "{r=foo/bar}");
        }
 
        
//------------------------------------------------------------------------------------------------------------------
@@ -193,8 +193,8 @@ class UrlPathMatcher_Test extends TestBase {
 
        @Test void d01_1part1vars_match() {
                var p = of("/{foo}");
-               check(p, "/bar", "{v:{foo:'bar'}}");
-               check(p, "/bar/", "{v:{foo:'bar'},r:''}");
+               check(p, "/bar", "{v={foo=bar}}");
+               check(p, "/bar/", "{r=,v={foo=bar}}");
        }
 
        @Test void d02_1part1var_noMatch() {
@@ -204,8 +204,8 @@ class UrlPathMatcher_Test extends TestBase {
 
        @Test void d03_2parts1var_match() {
                var p = of("/foo/{bar}");
-               check(p, "/foo/baz", "{v:{bar:'baz'}}");
-               check(p, "/foo/baz/", "{v:{bar:'baz'},r:''}");
+               check(p, "/foo/baz", "{v={bar=baz}}");
+               check(p, "/foo/baz/", "{r=,v={bar=baz}}");
        }
 
        @Test void d04_2parts1var_noMatch() {
@@ -215,8 +215,8 @@ class UrlPathMatcher_Test extends TestBase {
 
        @Test void d05_3vars_match() {
                var p = of("/{a}/{b}/{c}");
-               check(p, "/A/B/C", "{v:{a:'A',b:'B',c:'C'}}");
-               check(p, "/A/B/C/", "{v:{a:'A',b:'B',c:'C'},r:''}");
+               check(p, "/A/B/C", "{v={a=A,b=B,c=C}}");
+               check(p, "/A/B/C/", "{r=,v={a=A,b=B,c=C}}");
        }
 
        @Test void d06_3vars_noMatch() {
@@ -226,8 +226,8 @@ class UrlPathMatcher_Test extends TestBase {
 
        @Test void d07_7parts3vars_match() {
                var p = of("/a/{a}/b/{b}/c/{c}/d");
-               check(p, "/a/A/b/B/c/C/d", "{v:{a:'A',b:'B',c:'C'}}");
-               check(p, "/a/A/b/B/c/C/d/", "{v:{a:'A',b:'B',c:'C'},r:''}");
+               check(p, "/a/A/b/B/c/C/d", "{v={a=A,b=B,c=C}}");
+               check(p, "/a/A/b/B/c/C/d/", "{r=,v={a=A,b=B,c=C}}");
        }
 
        @Test void d08_6parts3vars_noMatch() {
@@ -241,10 +241,10 @@ class UrlPathMatcher_Test extends TestBase {
 
        @Test void e01_1part1vars_withRemainder_match() {
                var p = of("/{foo}/*");
-               check(p, "/bar", "{v:{foo:'bar'}}");
-               check(p, "/bar/", "{v:{foo:'bar'},r:''}");
-               check(p, "/bar/baz", "{v:{foo:'bar'},r:'baz'}");
-               check(p, "/bar/baz/qux", "{v:{foo:'bar'},r:'baz/qux'}");
+               check(p, "/bar", "{v={foo=bar}}");
+               check(p, "/bar/", "{r=,v={foo=bar}}");
+               check(p, "/bar/baz", "{r=baz,v={foo=bar}}");
+               check(p, "/bar/baz/qux", "{r=baz/qux,v={foo=bar}}");
        }
 
        @Test void e02_1part1var_withRemainder_noMatch() {
@@ -254,9 +254,9 @@ class UrlPathMatcher_Test extends TestBase {
 
        @Test void e03_2parts1var_withRemainder_match() {
                var p = of("/foo/{bar}/*");
-               check(p, "/foo/baz", "{v:{bar:'baz'}}");
-               check(p, "/foo/baz/", "{v:{bar:'baz'},r:''}");
-               check(p, "/foo/baz/qux/", "{v:{bar:'baz'},r:'qux/'}");
+               check(p, "/foo/baz", "{v={bar=baz}}");
+               check(p, "/foo/baz/", "{r=,v={bar=baz}}");
+               check(p, "/foo/baz/qux/", "{r=qux/,v={bar=baz}}");
        }
 
        @Test void e04_2parts1var_withRemainder_noMatch() {
@@ -271,9 +271,9 @@ class UrlPathMatcher_Test extends TestBase {
        @Test void f01_innerMeta_withRemainder_match() {
                var p = of("/*/*");
                check(p, "/bar", "{}");
-               check(p, "/bar/", "{r:''}");
-               check(p, "/bar/baz", "{r:'baz'}");
-               check(p, "/bar/baz/qux", "{r:'baz/qux'}");
+               check(p, "/bar/", "{r=}");
+               check(p, "/bar/baz", "{r=baz}");
+               check(p, "/bar/baz/qux", "{r=baz/qux}");
        }
 
        @Test void f02_innerMeta_withRemainder_noMatch() {
@@ -284,8 +284,8 @@ class UrlPathMatcher_Test extends TestBase {
        @Test void f03_innerMeta_withRemainder_match() {
                var p = of("/foo/*/bar/*");
                check(p, "/foo/baz/bar", "{}");
-               check(p, "/foo/baz/bar/", "{r:''}");
-               check(p, "/foo/baz/bar/qux/", "{r:'qux/'}");
+               check(p, "/foo/baz/bar/", "{r=}");
+               check(p, "/foo/baz/bar/qux/", "{r=qux/}");
        }
 
        @Test void f04_innerMeta_withRemainder_noMatch() {
@@ -299,10 +299,10 @@ class UrlPathMatcher_Test extends TestBase {
 
        @Test void g01_encodedVars() {
                var p = of("/foo/{bar}/*");
-               check(p, "/foo/baz%2Fqux", "{v:{bar:'baz/qux'}}");
-               check(p, "/foo/baz+qux", "{v:{bar:'baz qux'}}");
-               check(p, "/foo/baz%2Fqux/quux%2Fquuux", 
"{v:{bar:'baz/qux'},r:'quux%2Fquuux'}");
-               check(p, "/foo/baz+qux/quux+quuux", "{v:{bar:'baz 
qux'},r:'quux+quuux'}");
+               check(p, "/foo/baz%2Fqux", "{v={bar=baz/qux}}");
+               check(p, "/foo/baz+qux", "{v={bar=baz qux}}");
+               check(p, "/foo/baz%2Fqux/quux%2Fquuux", 
"{r=quux%2Fquuux,v={bar=baz/qux}}");
+               check(p, "/foo/baz+qux/quux+quuux", "{r=quux+quuux,v={bar=baz 
qux}}");
        }
 
        
//------------------------------------------------------------------------------------------------------------------
@@ -312,19 +312,19 @@ class UrlPathMatcher_Test extends TestBase {
        @Test void h01_notVars() {
                var p = of("/foo/{bar/*");
                check(p, "/foo/{bar", "{}");
-               check(p, "/foo/{bar/{baz", "{r:'{baz'}");
+               check(p, "/foo/{bar/{baz", "{r={baz}");
        }
 
        @Test void h02_notVars() {
                var p = of("/foo/bar}/*");
                check(p, "/foo/bar}", "{}");
-               check(p, "/foo/bar}/baz}", "{r:'baz}'}");
+               check(p, "/foo/bar}/baz}", "{r=baz}}");
        }
 
        @Test void h03_notVars() {
                var p = of("/foo/x{bar}x/*");
                check(p, "/foo/x{bar}x", "{}");
-               check(p, "/foo/x{bar}x/x{baz}x", "{r:'x{baz}x'}");
+               check(p, "/foo/x{bar}x/x{baz}x", "{r=x{baz}x}");
        }
 
        
//------------------------------------------------------------------------------------------------------------------
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/serializer/SerializerConfigAnnotationTest.java
 
b/juneau-utest/src/test/java/org/apache/juneau/serializer/SerializerConfigAnnotation_Test.java
similarity index 76%
rename from 
juneau-utest/src/test/java/org/apache/juneau/serializer/SerializerConfigAnnotationTest.java
rename to 
juneau-utest/src/test/java/org/apache/juneau/serializer/SerializerConfigAnnotation_Test.java
index 30b860ecf0..8dc652b81b 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/serializer/SerializerConfigAnnotationTest.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/serializer/SerializerConfigAnnotation_Test.java
@@ -32,7 +32,7 @@ import org.junit.jupiter.api.*;
 /**
  * Tests the @SerializerConfig annotation.
  */
-class SerializerConfigAnnotationTest extends TestBase {
+class SerializerConfigAnnotation_Test extends TestBase {
 
        private static void check(String expected, Object o) {
                assertEquals(expected, TO_STRING.apply(o));
@@ -79,7 +79,7 @@ class SerializerConfigAnnotationTest extends TestBase {
        static class A {}
        static ClassInfo a = ClassInfo.of(A.class);
 
-       @Test void basicWriterSerializer() {
+       @Test void a01_basicWriterSerializer() {
                var al = AnnotationWorkList.of(sr, rstream(a.getAnnotations()));
                var x = JsonSerializer.create().apply(al).build().getSession();
                check("true", ((SerializerSession)x).isAddBeanTypes());
@@ -97,13 +97,13 @@ class SerializerConfigAnnotationTest extends TestBase {
                check("true", x.isTrimEmptyMaps());
                check("false", x.isKeepNullProperties());
                check("true", x.isTrimStrings());
-               
check("{absoluteAuthority:'/',absoluteContextRoot:'/',absolutePathInfo:'/',absolutePathInfoParent:'/',absoluteServletPath:'/',absoluteServletPathParent:'/',rootRelativeContextRoot:'/',rootRelativePathInfo:'/',rootRelativePathInfoParent:'/',rootRelativeServletPath:'/',rootRelativeServletPathParent:'/'}",
 x.getUriContext());
+               
check("{aContextRoot=/,aPathInfo=/,aServletPath=/,rContextRoot=/,rPath=/,rResource=/}",
 x.getUriContext());
                check("RESOURCE", x.getUriRelativity());
                check("ABSOLUTE", x.getUriResolution());
                check("true", x.isUseWhitespace());
        }
 
-       @Test void basicOutputStreamSerializer() {
+       @Test void a02_basicOutputStreamSerializer() {
                var al = AnnotationWorkList.of(sr, rstream(a.getAnnotations()));
                var x = 
MsgPackSerializer.create().apply(al).build().getSession();
                check("true", ((SerializerSession)x).isAddBeanTypes());
@@ -120,7 +120,7 @@ class SerializerConfigAnnotationTest extends TestBase {
                check("true", x.isTrimEmptyMaps());
                check("false", x.isKeepNullProperties());
                check("true", x.isTrimStrings());
-               
check("{absoluteAuthority:'/',absoluteContextRoot:'/',absolutePathInfo:'/',absolutePathInfoParent:'/',absoluteServletPath:'/',absoluteServletPathParent:'/',rootRelativeContextRoot:'/',rootRelativePathInfo:'/',rootRelativePathInfoParent:'/',rootRelativeServletPath:'/',rootRelativeServletPathParent:'/'}",
 x.getUriContext());
+               
check("{aContextRoot=/,aPathInfo=/,aServletPath=/,rContextRoot=/,rPath=/,rResource=/}",
 x.getUriContext());
                check("RESOURCE", x.getUriRelativity());
                check("ABSOLUTE", x.getUriResolution());
        }
@@ -133,7 +133,7 @@ class SerializerConfigAnnotationTest extends TestBase {
        static class B {}
        static ClassInfo b = ClassInfo.of(B.class);
 
-       @Test void noValuesWriterSerializer() {
+       @Test void b01_noValuesWriterSerializer() {
                var al = AnnotationWorkList.of(sr, rstream(b.getAnnotations()));
                var x = JsonSerializer.create().apply(al).build().getSession();
                check("false", ((SerializerSession)x).isAddBeanTypes());
@@ -147,13 +147,13 @@ class SerializerConfigAnnotationTest extends TestBase {
                check("false", x.isTrimEmptyMaps());
                check("false", x.isKeepNullProperties());
                check("false", x.isTrimStrings());
-               
check("{absoluteAuthority:'/',absoluteContextRoot:'/',absolutePathInfo:'/',absolutePathInfoParent:'/',absoluteServletPath:'/',absoluteServletPathParent:'/',rootRelativeContextRoot:'/',rootRelativePathInfo:'/',rootRelativePathInfoParent:'/',rootRelativeServletPath:'/',rootRelativeServletPathParent:'/'}",
 x.getUriContext());
+               
check("{aContextRoot=/,aPathInfo=/,aServletPath=/,rContextRoot=/,rPath=/,rResource=/}",
 x.getUriContext());
                check("RESOURCE", x.getUriRelativity());
                check("NONE", x.getUriResolution());
                check("false", x.isUseWhitespace());
        }
 
-       @Test void noValuesOutputStreamSerializer() {
+       @Test void b02_noValuesOutputStreamSerializer() {
                var al = AnnotationWorkList.of(sr, rstream(b.getAnnotations()));
                var x = 
MsgPackSerializer.create().apply(al).build().getSession();
                check("false", ((SerializerSession)x).isAddBeanTypes());
@@ -166,7 +166,7 @@ class SerializerConfigAnnotationTest extends TestBase {
                check("false", x.isTrimEmptyMaps());
                check("false", x.isKeepNullProperties());
                check("false", x.isTrimStrings());
-               
check("{absoluteAuthority:'/',absoluteContextRoot:'/',absolutePathInfo:'/',absolutePathInfoParent:'/',absoluteServletPath:'/',absoluteServletPathParent:'/',rootRelativeContextRoot:'/',rootRelativePathInfo:'/',rootRelativePathInfoParent:'/',rootRelativeServletPath:'/',rootRelativeServletPathParent:'/'}",
 x.getUriContext());
+               
check("{aContextRoot=/,aPathInfo=/,aServletPath=/,rContextRoot=/,rPath=/,rResource=/}",
 x.getUriContext());
                check("RESOURCE", x.getUriRelativity());
                check("NONE", x.getUriResolution());
        }
@@ -178,7 +178,7 @@ class SerializerConfigAnnotationTest extends TestBase {
        static class C {}
        static ClassInfo c = ClassInfo.of(C.class);
 
-       @Test void noAnnotationWriterSerializer() {
+       @Test void c01_noAnnotationWriterSerializer() {
                var al = AnnotationWorkList.of(sr, rstream(c.getAnnotations()));
                var x = JsonSerializer.create().apply(al).build().getSession();
                check("false", ((SerializerSession)x).isAddBeanTypes());
@@ -192,13 +192,13 @@ class SerializerConfigAnnotationTest extends TestBase {
                check("false", x.isTrimEmptyMaps());
                check("false", x.isKeepNullProperties());
                check("false", x.isTrimStrings());
-               
check("{absoluteAuthority:'/',absoluteContextRoot:'/',absolutePathInfo:'/',absolutePathInfoParent:'/',absoluteServletPath:'/',absoluteServletPathParent:'/',rootRelativeContextRoot:'/',rootRelativePathInfo:'/',rootRelativePathInfoParent:'/',rootRelativeServletPath:'/',rootRelativeServletPathParent:'/'}",
 x.getUriContext());
+               
check("{aContextRoot=/,aPathInfo=/,aServletPath=/,rContextRoot=/,rPath=/,rResource=/}",
 x.getUriContext());
                check("RESOURCE", x.getUriRelativity());
                check("NONE", x.getUriResolution());
                check("false", x.isUseWhitespace());
        }
 
-       @Test void noAnnotationOutputStreamSerializer() {
+       @Test void c02_noAnnotationOutputStreamSerializer() {
                var al = AnnotationWorkList.of(sr, rstream(c.getAnnotations()));
                var x = 
MsgPackSerializer.create().apply(al).build().getSession();
                check("false", ((SerializerSession)x).isAddBeanTypes());
@@ -211,7 +211,7 @@ class SerializerConfigAnnotationTest extends TestBase {
                check("false", x.isTrimEmptyMaps());
                check("false", x.isKeepNullProperties());
                check("false", x.isTrimStrings());
-               
check("{absoluteAuthority:'/',absoluteContextRoot:'/',absolutePathInfo:'/',absolutePathInfoParent:'/',absoluteServletPath:'/',absoluteServletPathParent:'/',rootRelativeContextRoot:'/',rootRelativePathInfo:'/',rootRelativePathInfoParent:'/',rootRelativeServletPath:'/',rootRelativeServletPathParent:'/'}",
 x.getUriContext());
+               
check("{aContextRoot=/,aPathInfo=/,aServletPath=/,rContextRoot=/,rPath=/,rResource=/}",
 x.getUriContext());
                check("RESOURCE", x.getUriRelativity());
                check("NONE", x.getUriResolution());
        }
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/utils/BeanDiffTest.java 
b/juneau-utest/src/test/java/org/apache/juneau/utils/BeanDiff_Test.java
similarity index 80%
rename from juneau-utest/src/test/java/org/apache/juneau/utils/BeanDiffTest.java
rename to juneau-utest/src/test/java/org/apache/juneau/utils/BeanDiff_Test.java
index d7a781c6ea..89f566cfcb 100644
--- a/juneau-utest/src/test/java/org/apache/juneau/utils/BeanDiffTest.java
+++ b/juneau-utest/src/test/java/org/apache/juneau/utils/BeanDiff_Test.java
@@ -22,7 +22,7 @@ import static org.junit.jupiter.api.Assertions.*;
 import org.apache.juneau.*;
 import org.junit.jupiter.api.*;
 
-class BeanDiffTest extends TestBase {
+class BeanDiff_Test extends TestBase {
 
        public static class A {
                public int f1;
@@ -39,66 +39,66 @@ class BeanDiffTest extends TestBase {
        @Test void a01_same() {
                var bd = BeanDiff.create(A.create(1, "a"), A.create(1, 
"a")).build();
                assertFalse(bd.hasDiffs());
-               assertEquals("{v1:{},v2:{}}", bd.toString());
+               assertEquals("{v1={},v2={}}", bd.toString());
        }
 
        @Test void a02_different() {
                var bd = BeanDiff.create(A.create(1, "a"), A.create(2, 
"b")).build();
                assertTrue(bd.hasDiffs());
-               assertEquals("{v1:{f1:1,f2:'a'},v2:{f1:2,f2:'b'}}", 
bd.toString());
+               assertEquals("{v1={f1=1,f2=a},v2={f1=2,f2=b}}", bd.toString());
        }
 
        @Test void a03_firstNull() {
                var bd = BeanDiff.create(null, A.create(2, "b")).build();
                assertTrue(bd.hasDiffs());
-               assertEquals("{v1:{},v2:{f1:2,f2:'b'}}", bd.toString());
+               assertEquals("{v1={},v2={f1=2,f2=b}}", bd.toString());
        }
 
        @Test void a04_secondNull() {
                var bd = BeanDiff.create(A.create(1, "a"), null).build();
                assertTrue(bd.hasDiffs());
-               assertEquals("{v1:{f1:1,f2:'a'},v2:{}}", bd.toString());
+               assertEquals("{v1={f1=1,f2=a},v2={}}", bd.toString());
        }
 
        @Test void a05_bothNull() {
                var bd = BeanDiff.create(null, null).build();
                assertFalse(bd.hasDiffs());
-               assertEquals("{v1:{},v2:{}}", bd.toString());
+               assertEquals("{v1={},v2={}}", bd.toString());
        }
 
        @Test void a06_nullFields() {
                var bd = BeanDiff.create(A.create(1, null), A.create(2, 
"b")).build();
                assertTrue(bd.hasDiffs());
-               assertEquals("{v1:{f1:1},v2:{f1:2,f2:'b'}}", bd.toString());
+               assertEquals("{v1={f1=1},v2={f1=2,f2=b}}", bd.toString());
        }
 
        @Test void a07_includes() {
                var bd = BeanDiff.create(A.create(1, null), A.create(2, 
"b")).include("f1").build();
                assertTrue(bd.hasDiffs());
-               assertEquals("{v1:{f1:1},v2:{f1:2}}", bd.toString());
+               assertEquals("{v1={f1=1},v2={f1=2}}", bd.toString());
        }
 
        @Test void a08_includesSet() {
                var bd = BeanDiff.create(A.create(1, null), A.create(2, 
"b")).include(set("f1")).build();
                assertTrue(bd.hasDiffs());
-               assertEquals("{v1:{f1:1},v2:{f1:2}}", bd.toString());
+               assertEquals("{v1={f1=1},v2={f1=2}}", bd.toString());
        }
 
        @Test void a09_excludes() {
                var bd = BeanDiff.create(A.create(1, null), A.create(2, 
"b")).exclude("f2").build();
                assertTrue(bd.hasDiffs());
-               assertEquals("{v1:{f1:1},v2:{f1:2}}", bd.toString());
+               assertEquals("{v1={f1=1},v2={f1=2}}", bd.toString());
        }
 
        @Test void a10_excludesSet() {
                var bd = BeanDiff.create(A.create(1, null), A.create(2, 
"b")).exclude(set("f2")).build();
                assertTrue(bd.hasDiffs());
-               assertEquals("{v1:{f1:1},v2:{f1:2}}", bd.toString());
+               assertEquals("{v1={f1=1},v2={f1=2}}", bd.toString());
        }
 
        @Test void a11_differentBeanContext() {
                var bd = BeanDiff.create(A.create(1, null), A.create(2, 
"b")).beanContext(BeanContext.DEFAULT_SORTED).build();
                assertTrue(bd.hasDiffs());
-               assertEquals("{v1:{f1:1},v2:{f1:2,f2:'b'}}", bd.toString());
+               assertEquals("{v1={f1=1},v2={f1=2,f2=b}}", bd.toString());
        }
 }
\ No newline at end of file

Reply via email to