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 1a54c7f  Add FunctionalSwap for function-based swaps.
1a54c7f is described below

commit 1a54c7f549844d31ab5b03d9d77e998cd08aeef4
Author: JamesBognar <[email protected]>
AuthorDate: Sun Oct 31 12:47:19 2021 -0400

    Add FunctionalSwap for function-based swaps.
---
 .../java/org/apache/juneau/jena/RdfParser.java     | 13 ++++
 .../java/org/apache/juneau/jena/RdfSerializer.java | 13 ++++
 .../main/java/org/apache/juneau/BeanContext.java   | 72 +++++++++++++++++---
 .../java/org/apache/juneau/BeanContextable.java    | 47 +++++++++++++
 .../org/apache/juneau/BeanTraverseContext.java     | 12 ++++
 .../main/java/org/apache/juneau/csv/CsvParser.java | 12 ++++
 .../java/org/apache/juneau/csv/CsvSerializer.java  | 12 ++++
 .../org/apache/juneau/html/HtmlDocSerializer.java  | 12 ++++
 .../java/org/apache/juneau/html/HtmlParser.java    | 12 ++++
 .../juneau/html/HtmlSchemaDocSerializer.java       | 13 ++++
 .../apache/juneau/html/HtmlSchemaSerializer.java   | 12 ++++
 .../org/apache/juneau/html/HtmlSerializer.java     | 12 ++++
 .../juneau/html/HtmlStrippedDocSerializer.java     | 12 ++++
 .../main/java/org/apache/juneau/jso/JsoParser.java | 12 ++++
 .../java/org/apache/juneau/jso/JsoSerializer.java  | 12 ++++
 .../java/org/apache/juneau/json/JsonParser.java    | 12 ++++
 .../apache/juneau/json/JsonSchemaSerializer.java   | 12 ++++
 .../org/apache/juneau/json/JsonSerializer.java     | 12 ++++
 .../juneau/jsonschema/JsonSchemaGenerator.java     | 12 ++++
 .../org/apache/juneau/msgpack/MsgPackParser.java   | 12 ++++
 .../apache/juneau/msgpack/MsgPackSerializer.java   | 12 ++++
 .../java/org/apache/juneau/oapi/OpenApiParser.java | 12 ++++
 .../org/apache/juneau/oapi/OpenApiSerializer.java  | 12 ++++
 .../apache/juneau/parser/InputStreamParser.java    | 12 ++++
 .../main/java/org/apache/juneau/parser/Parser.java | 12 ++++
 .../org/apache/juneau/parser/ReaderParser.java     | 12 ++++
 .../apache/juneau/plaintext/PlainTextParser.java   | 12 ++++
 .../juneau/plaintext/PlainTextSerializer.java      | 12 ++++
 .../juneau/serializer/OutputStreamSerializer.java  | 12 ++++
 .../org/apache/juneau/serializer/Serializer.java   | 12 ++++
 .../apache/juneau/serializer/WriterSerializer.java | 12 ++++
 .../org/apache/juneau/soap/SoapXmlSerializer.java  | 12 ++++
 .../org/apache/juneau/swap/FunctionalSwap.java     | 76 ++++++++++++++++++++++
 .../main/java/org/apache/juneau/uon/UonParser.java | 12 ++++
 .../java/org/apache/juneau/uon/UonSerializer.java  | 12 ++++
 .../juneau/urlencoding/UrlEncodingParser.java      | 12 ++++
 .../juneau/urlencoding/UrlEncodingSerializer.java  | 12 ++++
 .../main/java/org/apache/juneau/xml/XmlParser.java | 12 ++++
 .../java/org/apache/juneau/xml/XmlSerializer.java  | 12 ++++
 .../docs/Topics/02.juneau-marshall/11.Swaps.html   | 12 ++++
 .../org/apache/juneau/rest/client/RestClient.java  | 12 ++++
 .../apache/juneau/rest/mock/MockRestClient.java    | 13 ++++
 .../juneau/transforms/FunctionalSwapTest.java      | 72 ++++++++++++++++++++
 .../juneau/transforms/RoundTripObjectSwapTest.java | 68 +++++++++++++++++++
 44 files changed, 797 insertions(+), 10 deletions(-)

diff --git 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
index 53b9e86..8532f3a 100644
--- 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
+++ 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfParser.java
@@ -30,6 +30,7 @@ import org.apache.juneau.internal.FluentSetters;
 import org.apache.juneau.jena.annotation.Rdf;
 import org.apache.juneau.parser.*;
 import org.apache.juneau.utils.HashKey;
+import org.apache.juneau.utils.ThrowingFunction;
 import org.apache.juneau.xml.*;
 
 /**
@@ -1323,6 +1324,18 @@ public class RdfParser extends ReaderParser implements 
RdfMetaProvider {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
index a8fae3e..444481e 100644
--- 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
+++ 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/jena/RdfSerializer.java
@@ -31,6 +31,7 @@ import org.apache.juneau.internal.FluentSetters;
 import org.apache.juneau.jena.annotation.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.utils.HashKey;
+import org.apache.juneau.utils.ThrowingFunction;
 import org.apache.juneau.xml.*;
 import org.apache.juneau.xml.annotation.*;
 
@@ -1551,6 +1552,18 @@ public class RdfSerializer extends WriterSerializer 
implements RdfMetaProvider {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
index 71869c7..4a00cfc 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContext.java
@@ -231,7 +231,8 @@ public class BeanContext extends Context {
                Locale locale;
                TimeZone timeZone;
                Class<? extends PropertyNamer> propertyNamer;
-               List<Class<?>> beanDictionary, swaps;
+               List<Class<?>> beanDictionary;
+               List<Object> swaps;
                Set<Class<?>> notBeanClasses;
                Set<String> notBeanPackages;
 
@@ -3051,6 +3052,52 @@ public class BeanContext extends Context {
                }
 
                /**
+                * A shortcut for defining a {@link FunctionalSwap}.
+                *
+                * <h5 class='section'>Example:</h5>
+                * <p class='bcode w800'>
+                *      <jc>// Create a serializer that performs a custom 
format for DAte objects.</jc>
+                *      WriterSerializer <jv>serializer</jv> = JsonSerializer
+                *              .<jsm>create</jsm>()
+                *              .swap(Date.<jk>class</jk>, 
String.<jk>class</jk>, <jv>x</jv> -&gt; <jsm>format</jsm>(<jv>x</jv>))
+                *              .build();
+                * </p>
+                *
+                * @param normalClass The object type being swapped out.
+                * @param swappedClass The object type being swapped in.
+                * @param swapFunction The function to convert the object.
+                * @return This object.
+                */
+               @FluentSetter
+               public <T,S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       return swap(normalClass, swappedClass, swapFunction, 
null);
+               }
+
+               /**
+                * A shortcut for defining a {@link FunctionalSwap}.
+                *
+                * <h5 class='section'>Example:</h5>
+                * <p class='bcode w800'>
+                *      <jc>// Create a serializer that performs a custom 
format for DAte objects.</jc>
+                *      WriterSerializer <jv>serializer</jv> = JsonSerializer
+                *              .<jsm>create</jsm>()
+                *              .swap(Date.<jk>class</jk>, 
String.<jk>class</jk>, <jv>x</jv> -&gt; <jsm>format</jsm>(<jv>x</jv>), 
<jv>x</jv> -&gt; <jsm>parse</jsm>(<jv>x</jv>))
+                *              .build();
+                * </p>
+                *
+                * @param normalClass The object type being swapped out.
+                * @param swappedClass The object type being swapped in.
+                * @param swapFunction The function to convert the object 
during serialization.
+                * @param unswapFunction The function to convert the object 
during parsing.
+                * @return This object.
+                */
+               @FluentSetter
+               public <T,S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       swaps().add(0, new FunctionalSwap<>(normalClass, 
swappedClass, swapFunction, unswapFunction));
+                       return this;
+               }
+
+               /**
                 * Returns the bean swaps list.
                 *
                 * <p>
@@ -3059,7 +3106,7 @@ public class BeanContext extends Context {
                 * @return The bean swaps list.
                 * @see #swaps(Class...)
                 */
-               public List<Class<?>> swaps() {
+               public List<Object> swaps() {
                        if (swaps == null)
                                swaps = new ArrayList<>();
                        return swaps;
@@ -3480,7 +3527,8 @@ public class BeanContext extends Context {
        final TimeZone timeZone;
        final MediaType mediaType;
        final Class<? extends PropertyNamer> propertyNamer;
-       final List<Class<?>> beanDictionary, swaps, notBeanClasses;
+       final List<Class<?>> beanDictionary, notBeanClasses;
+       final List<Object> swaps;
        final List<String> notBeanPackages;
        final HashKey hashKey;
 
@@ -3552,13 +3600,17 @@ public class BeanContext extends Context {
 
                LinkedList<ObjectSwap<?,?>> _swaps = new LinkedList<>();
                for (Object o : ofNullable(swaps).orElse(emptyList())) {
-                       ClassInfo ci = ClassInfo.of((Class<?>)o);
-                       if (ci.isChildOf(ObjectSwap.class))
-                               _swaps.add(castOrCreate(ObjectSwap.class, 
ci.inner()));
-                       else if (ci.isChildOf(Surrogate.class))
-                               
_swaps.addAll(SurrogateSwap.findObjectSwaps(ci.inner(), this));
-                       else
-                               throw runtimeException("Invalid class {0} 
specified in BeanContext.swaps property.  Must be a subclass of ObjectSwap or 
Surrogate.", ci.inner());
+                       if (o instanceof ObjectSwap) {
+                               _swaps.add((ObjectSwap<?,?>)o);
+                       } else {
+                               ClassInfo ci = ClassInfo.of((Class<?>)o);
+                               if (ci.isChildOf(ObjectSwap.class))
+                                       
_swaps.add(castOrCreate(ObjectSwap.class, ci.inner()));
+                               else if (ci.isChildOf(Surrogate.class))
+                                       
_swaps.addAll(SurrogateSwap.findObjectSwaps(ci.inner(), this));
+                               else
+                                       throw runtimeException("Invalid class 
{0} specified in BeanContext.swaps property.  Must be a subclass of ObjectSwap 
or Surrogate.", ci.inner());
+                       }
                }
                swapArray = _swaps.toArray(new ObjectSwap[_swaps.size()]);
 
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextable.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextable.java
index 21d6df0..afb25e4 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextable.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanContextable.java
@@ -2603,6 +2603,53 @@ public abstract class BeanContextable extends Context {
                }
 
                /**
+                * A shortcut for defining a {@link FunctionalSwap}.
+                *
+                * <h5 class='section'>Example:</h5>
+                * <p class='bcode w800'>
+                *      <jc>// Create a serializer that performs a custom 
format for DAte objects.</jc>
+                *      WriterSerializer <jv>serializer</jv> = JsonSerializer
+                *              .<jsm>create</jsm>()
+                *              .swap(Date.<jk>class</jk>, 
String.<jk>class</jk>, <jv>x</jv> -&gt; <jsm>format</jsm>(<jv>x</jv>))
+                *              .build();
+                * </p>
+                *
+                * @param normalClass The object type being swapped out.
+                * @param swappedClass The object type being swapped in.
+                * @param swapFunction The function to convert the object.
+                * @return This object.
+                */
+               @FluentSetter
+               public <T,S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       bcBuilder.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               /**
+                * A shortcut for defining a {@link FunctionalSwap}.
+                *
+                * <h5 class='section'>Example:</h5>
+                * <p class='bcode w800'>
+                *      <jc>// Create a serializer that performs a custom 
format for DAte objects.</jc>
+                *      WriterSerializer <jv>serializer</jv> = JsonSerializer
+                *              .<jsm>create</jsm>()
+                *              .swap(Date.<jk>class</jk>, 
String.<jk>class</jk>, <jv>x</jv> -&gt; <jsm>format</jsm>(<jv>x</jv>), 
<jv>x</jv> -&gt; <jsm>parse</jsm>(<jv>x</jv>))
+                *              .build();
+                * </p>
+                *
+                * @param normalClass The object type being swapped out.
+                * @param swappedClass The object type being swapped in.
+                * @param swapFunction The function to convert the object 
during serialization.
+                * @param unswapFunction The function to convert the object 
during parsing.
+                * @return This object.
+                */
+               @FluentSetter
+               public <T,S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       bcBuilder.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               /**
                 * <i><l>Context</l> configuration property:&emsp;</i>  
TimeZone.
                 *
                 * <p>
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseContext.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseContext.java
index 9be4f25..415d681 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseContext.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/BeanTraverseContext.java
@@ -637,6 +637,18 @@ public abstract class BeanTraverseContext extends 
BeanContextable {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParser.java
index 395368e..7f2ed33 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvParser.java
@@ -454,6 +454,18 @@ public class CsvParser extends ReaderParser implements 
CsvMetaProvider {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializer.java
index 752a5a1..26cdaa4 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializer.java
@@ -454,6 +454,18 @@ public final class CsvSerializer extends WriterSerializer 
implements CsvMetaProv
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
index 1985eb0..84e0e43 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlDocSerializer.java
@@ -1149,6 +1149,18 @@ public class HtmlDocSerializer extends 
HtmlStrippedDocSerializer {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParser.java
index d89fa8a..a5073a5 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlParser.java
@@ -464,6 +464,18 @@ public class HtmlParser extends XmlParser implements 
HtmlMetaProvider {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
index 8b405ef..0542f70 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaDocSerializer.java
@@ -25,6 +25,7 @@ import org.apache.juneau.internal.*;
 import org.apache.juneau.json.*;
 import org.apache.juneau.jsonschema.*;
 import org.apache.juneau.jsonschema.annotation.*;
+import org.apache.juneau.utils.*;
 import org.apache.juneau.xml.*;
 
 /**
@@ -625,6 +626,18 @@ public final class HtmlSchemaDocSerializer extends 
HtmlDocSerializer {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializer.java
index c7bc490..07b7955 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSchemaSerializer.java
@@ -693,6 +693,18 @@ public class HtmlSchemaSerializer extends HtmlSerializer {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
index 4b31ff3..672179b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializer.java
@@ -1061,6 +1061,18 @@ public class HtmlSerializer extends XmlSerializer 
implements HtmlMetaProvider {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlStrippedDocSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlStrippedDocSerializer.java
index 53ea0fd..dda2b72 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlStrippedDocSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlStrippedDocSerializer.java
@@ -466,6 +466,18 @@ public class HtmlStrippedDocSerializer extends 
HtmlSerializer {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoParser.java
index 5fa172f..3ee9160 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoParser.java
@@ -458,6 +458,18 @@ public final class JsoParser extends InputStreamParser 
implements JsoMetaProvide
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoSerializer.java
index da8aec9..9320d9c 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jso/JsoSerializer.java
@@ -460,6 +460,18 @@ public class JsoSerializer extends OutputStreamSerializer 
implements JsoMetaProv
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParser.java
index 6405170..a46f47b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonParser.java
@@ -605,6 +605,18 @@ public class JsonParser extends ReaderParser implements 
JsonMetaProvider {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializer.java
index c4624e3..9d3b0ff 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSchemaSerializer.java
@@ -685,6 +685,18 @@ public class JsonSchemaSerializer extends JsonSerializer 
implements JsonSchemaMe
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
index 0ece723..55bffec 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializer.java
@@ -754,6 +754,18 @@ public class JsonSerializer extends WriterSerializer 
implements JsonMetaProvider
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGenerator.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGenerator.java
index 7ebde96..e6da1cb 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGenerator.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/jsonschema/JsonSchemaGenerator.java
@@ -766,6 +766,18 @@ public class JsonSchemaGenerator extends 
BeanTraverseContext implements JsonSche
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
index 2dcd2dc..a6e8a27 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackParser.java
@@ -496,6 +496,18 @@ public class MsgPackParser extends InputStreamParser 
implements MsgPackMetaProvi
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
index a766df6..80e158c 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializer.java
@@ -536,6 +536,18 @@ public class MsgPackSerializer extends 
OutputStreamSerializer implements MsgPack
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParser.java
index 74674e1..a433c1c 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiParser.java
@@ -578,6 +578,18 @@ public class OpenApiParser extends UonParser implements 
OpenApiMetaProvider {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializer.java
index 13cc23c..8d07dda 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializer.java
@@ -589,6 +589,18 @@ public class OpenApiSerializer extends UonSerializer 
implements OpenApiMetaProvi
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
index 20c6b62..91b2352 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/InputStreamParser.java
@@ -479,6 +479,18 @@ public abstract class InputStreamParser extends Parser {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
index eec6d33..7baf9f3 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/Parser.java
@@ -912,6 +912,18 @@ public abstract class Parser extends BeanContextable {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
index 2dd9545..0916d69 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/parser/ReaderParser.java
@@ -517,6 +517,18 @@ public abstract class ReaderParser extends Parser {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
index ab94bc0..8aabec1 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextParser.java
@@ -473,6 +473,18 @@ public class PlainTextParser extends ReaderParser 
implements PlainTextMetaProvid
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
index e3b67fd..fa7fcd2 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/plaintext/PlainTextSerializer.java
@@ -469,6 +469,18 @@ public class PlainTextSerializer extends WriterSerializer 
implements PlainTextMe
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializer.java
index d669425..d265640 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/OutputStreamSerializer.java
@@ -473,6 +473,18 @@ public abstract class OutputStreamSerializer extends 
Serializer {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
index 672ce6b..6eecb75 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/Serializer.java
@@ -1165,6 +1165,18 @@ public abstract class Serializer extends 
BeanTraverseContext {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
index 649a147..2f806f1 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/WriterSerializer.java
@@ -727,6 +727,18 @@ public abstract class WriterSerializer extends Serializer {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java
index 88b10c0..4855134 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/soap/SoapXmlSerializer.java
@@ -487,6 +487,18 @@ public class SoapXmlSerializer extends XmlSerializer 
implements SoapXmlMetaProvi
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swap/FunctionalSwap.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swap/FunctionalSwap.java
new file mode 100644
index 0000000..4711b34
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swap/FunctionalSwap.java
@@ -0,0 +1,76 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau.swap;
+
+import org.apache.juneau.*;
+import org.apache.juneau.utils.*;
+
+/**
+ * A subclass of {@link ObjectSwap} that allows swap and unswap methods to be 
defined as functions.
+ *
+ * <p class='bcode w800'>
+ *     <jc>// Example</jc>
+ *     <jk>public class</jk> MyBeanSwap <jk>extends</jk> 
FunctionalSwap<MyBean,String> {
+ *             <jk>public</jk> MyBeanSwap() {
+ *                     <jk>super</jk>(MyBean.<jk>class</jk>, 
String.<jk>class</jk>, <jv>x</jv> -&gt; <jsm>myStringifyier</jsm>(<jv>x</jv>), 
<jv>x</jv> -&gt; <jsm>myDeStringifier</jsm>(<jv>x</jv>));
+ *             }
+ *     }
+ * </p>
+ *
+ * @param <T> The normal form of the class.
+ * @param <S> The swapped form of the class.
+ */
+public class FunctionalSwap<T,S> extends ObjectSwap<T,S> {
+
+       private final ThrowingFunction<T,S> swapFunction;
+       private final ThrowingFunction<S,T> unswapFunction;
+
+       /**
+        * Constructor.
+        *
+        * @param normalClass The normal class.
+        * @param swappedClass The swapped class.
+        * @param swapFunction The function for converting from normal to 
swapped.
+        */
+       public FunctionalSwap(Class<T> normalClass, Class<S> swappedClass, 
ThrowingFunction<T,S> swapFunction) {
+               this(normalClass, swappedClass, swapFunction, null);
+       }
+
+       /**
+        * Constructor.
+        *
+        * @param normalClass The normal class.
+        * @param swappedClass The swapped class.
+        * @param swapFunction The function for converting from normal to 
swapped.
+        * @param unswapFunction The function for converting swapped to normal.
+        */
+       public FunctionalSwap(Class<T> normalClass, Class<S> swappedClass, 
ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> unswapFunction) {
+               super(normalClass, swappedClass);
+               this.swapFunction = swapFunction;
+               this.unswapFunction = unswapFunction;
+       }
+
+       @Override
+       public S swap(BeanSession session, T o, String template) throws 
Exception {
+               if (swapFunction == null)
+                       return super.swap(session, o, template);
+               return swapFunction.applyThrows(o);
+       }
+
+       @Override
+       public T unswap(BeanSession session, S f, ClassMeta<?> hint, String 
template) throws Exception {
+               if (unswapFunction == null)
+                       return super.unswap(session, f, hint, template);
+               return unswapFunction.applyThrows(f);
+       }
+}
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParser.java
index a3d5063..1cf8863 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonParser.java
@@ -577,6 +577,18 @@ public class UonParser extends ReaderParser implements 
HttpPartParser, UonMetaPr
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializer.java
index ff1a49e..9eb1a91 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializer.java
@@ -810,6 +810,18 @@ public class UonSerializer extends WriterSerializer 
implements HttpPartSerialize
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
index 941cd3c..9c0a2c0 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingParser.java
@@ -536,6 +536,18 @@ public class UrlEncodingParser extends UonParser 
implements UrlEncodingMetaProvi
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
index baf8a44..a8e25b6 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializer.java
@@ -673,6 +673,18 @@ public class UrlEncodingSerializer extends UonSerializer 
implements UrlEncodingM
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParser.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParser.java
index 97e2086..6ee2878 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParser.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlParser.java
@@ -620,6 +620,18 @@ public class XmlParser extends ReaderParser implements 
XmlMetaProvider {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializer.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializer.java
index ce94730..1759b3f 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializer.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializer.java
@@ -860,6 +860,18 @@ public class XmlSerializer extends WriterSerializer 
implements XmlMetaProvider {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git a/juneau-doc/docs/Topics/02.juneau-marshall/11.Swaps.html 
b/juneau-doc/docs/Topics/02.juneau-marshall/11.Swaps.html
index 9393958..0bc490f 100644
--- a/juneau-doc/docs/Topics/02.juneau-marshall/11.Swaps.html
+++ b/juneau-doc/docs/Topics/02.juneau-marshall/11.Swaps.html
@@ -108,3 +108,15 @@
        <jv>json</jv> = <jv>serializer</jv>.serialize(<jv>bytes2d</jv>);        
   <jc>// Produces "['AQID','BAUG',null]"</jc>
        <jv>bytes2d</jv> = <jv>parser</jv>.parse(<jv>json</jv>, 
<jk>byte</jk>[][].<jk>class</jk>);   <jc>// Reproduces 
{{1,2,3},{4,5,6},null}</jc>
 </p>
+<p>
+       The {@link 
oaj.BeanContextable.Builder#swap(Class,Class,ThrowableFunction)} and {@link 
oaj.BeanContextable.Builder#swap(Class,Class,ThrowableFunction,ThrowableFunction)}
+       methods are another way to define swaps by using functions.
+</p>
+<p class='bpcode w800'>
+       <jc>// Use a function to convert beans to strings.</jc>
+       WriterSerializer <jv>serializer</jv> = JsonSerializer
+               .<jsm>create</jsm>()
+               .simple()
+               .swap(MyBean.<jk>class</jk>, String.<jk>class</jk>, <jv>x</jv> 
-&gt; <jsm>myBeanStringifier</jsm>(<jv>x</jv>))
+               .build();
+</p>
diff --git 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
index 4c45366..eb1ef22 100644
--- 
a/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
+++ 
b/juneau-rest/juneau-rest-client/src/main/java/org/apache/juneau/rest/client/RestClient.java
@@ -6017,6 +6017,18 @@ public class RestClient extends BeanContextable 
implements HttpClient, Closeable
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
 
b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
index 4d9ee8d..7fd90a9 100644
--- 
a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
+++ 
b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockRestClient.java
@@ -66,6 +66,7 @@ import org.apache.juneau.http.header.ContentType;
 import org.apache.juneau.rest.logging.*;
 import org.apache.juneau.serializer.*;
 import org.apache.juneau.uon.*;
+import org.apache.juneau.utils.*;
 
 /**
  * Mocked {@link RestClient}.
@@ -927,6 +928,18 @@ public class MockRestClient extends RestClient implements 
HttpClientConnection {
                }
 
                @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
+               public <T, S> Builder swap(Class<T> normalClass, Class<S> 
swappedClass, ThrowingFunction<T,S> swapFunction, ThrowingFunction<S,T> 
unswapFunction) {
+                       super.swap(normalClass, swappedClass, swapFunction, 
unswapFunction);
+                       return this;
+               }
+
+               @Override /* GENERATED - 
org.apache.juneau.BeanContextable.Builder */
                public Builder swaps(java.lang.Class<?>...values) {
                        super.swaps(values);
                        return this;
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/transforms/FunctionalSwapTest.java
 
b/juneau-utest/src/test/java/org/apache/juneau/transforms/FunctionalSwapTest.java
new file mode 100644
index 0000000..18a4927
--- /dev/null
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/transforms/FunctionalSwapTest.java
@@ -0,0 +1,72 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau.transforms;
+
+import java.util.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.swap.*;
+import org.apache.juneau.swaps.*;
+import org.junit.runner.*;
+import org.junit.runners.*;
+
+@RunWith(Parameterized.class)
+public class FunctionalSwapTest extends RoundTripObjectSwapTest<Locale,String> 
{
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Setup
+       
//------------------------------------------------------------------------------------------------------------------
+
+       private static BeanSession BS = BeanContext.DEFAULT_SESSION;
+       private static final LocaleSwap localeSwap = new LocaleSwap();
+       private static FunctionalSwap<Locale,String> SWAP = new 
FunctionalSwap<>(Locale.class, String.class, x->localeSwap.swap(BS, x), 
x->localeSwap.unswap(BS, x, null));
+
+       public FunctionalSwapTest(String label, Locale o, 
FunctionalSwap<Locale,String> s, String r, BeanSession bs) throws Exception {
+               super(label, o, s, r, bs);
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // Parameters
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Parameterized.Parameters
+       public static Collection<Object[]> getPairs() {
+               return Arrays.asList(new Object[][] {
+
+                       
//----------------------------------------------------------------------------------------------------------
+                       // Basic tests
+                       
//----------------------------------------------------------------------------------------------------------
+                       {
+                               "[0] Language only ",
+                               Locale.ENGLISH,
+                               SWAP,
+                               "en",
+                               BS
+                       },
+                       {
+                               "[1] Language and country",
+                               Locale.JAPAN,
+                               SWAP,
+                               "ja-JP",
+                               BS
+                       },
+                       {
+                               "[2] null",
+                               null,
+                               SWAP,
+                               null,
+                               BS
+                       },
+               });
+       }
+}
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/transforms/RoundTripObjectSwapTest.java
 
b/juneau-utest/src/test/java/org/apache/juneau/transforms/RoundTripObjectSwapTest.java
new file mode 100644
index 0000000..3f8a9a7
--- /dev/null
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/transforms/RoundTripObjectSwapTest.java
@@ -0,0 +1,68 @@
+// 
***************************************************************************************************************************
+// * Licensed to the Apache Software Foundation (ASF) under one or more 
contributor license agreements.  See the NOTICE file *
+// * distributed with this work for additional information regarding copyright 
ownership.  The ASF licenses this file        *
+// * to you under the Apache License, Version 2.0 (the "License"); you may not 
use this file except in compliance            *
+// * with the License.  You may obtain a copy of the License at                
                                              *
+// *                                                                           
                                              *
+// *  http://www.apache.org/licenses/LICENSE-2.0                               
                                              *
+// *                                                                           
                                              *
+// * Unless required by applicable law or agreed to in writing, software 
distributed under the License is distributed on an  *
+// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either 
express or implied.  See the License for the        *
+// * specific language governing permissions and limitations under the 
License.                                              *
+// 
***************************************************************************************************************************
+package org.apache.juneau.transforms;
+
+import static org.apache.juneau.internal.StringUtils.*;
+import static org.junit.runners.MethodSorters.*;
+
+import org.apache.jena.ext.com.google.common.base.*;
+import org.apache.juneau.*;
+import org.apache.juneau.swap.*;
+import org.junit.*;
+
+/**
+ * Tests designed to serialize and parse objects to make sure we end up
+ * with the same objects for all serializers and parsers.
+ */
+@FixMethodOrder(NAME_ASCENDING)
+public abstract class RoundTripObjectSwapTest<T,S> {
+
+       private final String label;
+       private final T o;
+       private final ObjectSwap<T,S> ss;
+       private final S expected;
+       private final BeanSession bs;
+
+       public RoundTripObjectSwapTest(String label, T o, ObjectSwap<T,S> ss, S 
expected, BeanSession bs) throws Exception {
+               this.label = label;
+               this.o = o;
+               this.ss = ss;
+               this.expected = expected;
+               this.bs = bs;
+       }
+
+       @Test
+       public void testSwap() throws Exception {
+               S s = ss.swap(bs, o);
+               if (! Objects.equal(expected, s)) {
+                       fail("Test [{0} swap] failed.  Expected=[{1}], 
Actual=[{2}]", label, expected, s);
+               }
+       }
+
+       @Test
+       public void testUnswap() throws Exception {
+               S s = ss.swap(bs, o);
+               T o2 = ss.unswap(bs, s, bs.getClassMetaForObject(o));
+               S s2 = ss.swap(bs, o2);
+               if (! Objects.equal(s, s2)) {
+                       System.err.println("s=["+s+"], o=["+o+"], 
o.type=["+o.getClass().getName()+"], o2=["+o2+"], 
o2.type=["+o2.getClass().getName()+"]");  // NOT DEBUG
+                       fail("Test [{0} unswap] failed.  Expected=[{1}], 
Actual=[{2}]", label, s, s2);
+               }
+       }
+
+       private void fail(String msg, Object...args) {
+               String s = format(msg, args);
+               System.err.println(s);  // NOT DEBUG
+               Assert.fail(s);
+       }
+}

Reply via email to