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 2a40bd1ab7 Add view-based projection (@JsonView analog) to bean 
marshalling; adopt isEmpty utility across the reactor.
2a40bd1ab7 is described below

commit 2a40bd1ab7fcfa9faecfa7a29b21c3b31ab90ddd
Author: James Bognar <[email protected]>
AuthorDate: Tue Jun 16 13:11:09 2026 -0400

    Add view-based projection (@JsonView analog) to bean marshalling; adopt 
isEmpty utility across the reactor.
---
 .../bean/jsonschema/JsonSchemaValidator.java       |   4 +-
 .../org/apache/juneau/commons/bean/BeanMap.java    |  32 +-
 .../juneau/commons/bean/BeanPropertyMeta.java      |  18 ++
 .../apache/juneau/commons/bean/BeanSession.java    |  20 ++
 .../org/apache/juneau/commons/lang/CharHolder.java |   2 +-
 .../org/apache/juneau/commons/runtime/Args.java    |   4 +-
 .../juneau/marshall/jena/RdfSerializerSession.java |   2 +-
 .../marshall/jena/RdfStreamSerializerSession.java  |   2 +-
 .../org/apache/juneau/marshall/MarshalledProp.java |  45 +++
 .../juneau/marshall/MarshalledPropAnnotation.java  |  19 ++
 .../marshall/MarshalledPropertyPostProcessor.java  |  34 +-
 .../apache/juneau/marshall/MarshallingContext.java | 149 +++++++--
 .../juneau/marshall/MarshallingContextable.java    |  51 +++
 .../apache/juneau/marshall/MarshallingSession.java |  66 +++-
 .../juneau/marshall/csv/CsvParserSession.java      |   4 +-
 .../juneau/marshall/ini/IniSerializerSession.java  |   2 +-
 .../org/apache/juneau/marshall/ini/IniWriter.java  |   4 +-
 .../juneau/marshall/json/JsonTokenWriter.java      |   3 +-
 .../markdown/MarkdownDocParserSession.java         |   4 +-
 .../marshall/markdown/MarkdownParserSession.java   |   2 +-
 .../marshall/parquet/ParquetParserSession.java     |   2 +-
 .../marshall/parquet/ParquetSchemaBuilder.java     |   5 +-
 .../juneau/marshall/xml/XmlBeanPropertyMeta.java   |   8 +-
 .../org/apache/juneau/ViewProjection_Test.java     | 353 +++++++++++++++++++++
 .../org/apache/juneau/ViewProjection_Test.java     | 294 +++++++++++++++++
 .../microservice/jetty/JettyServerComponent.java   |   2 +-
 .../microservice/tomcat/TomcatServerComponent.java |   4 +-
 .../apache/juneau/microservice/Microservice.java   |   2 +-
 .../juneau/http/resource/HttpResourceBean.java     |   2 +-
 .../juneau/rest/mock/MockServletRequest.java       |   2 +-
 .../micrometer/MicrometerMetricsRecorder.java      |   4 +-
 .../apache/juneau/rest/server/RestOpContext.java   |   8 +-
 .../org/apache/juneau/rest/server/RestRequest.java |   6 +-
 .../apache/juneau/rest/server/RestResponse.java    |   2 +-
 .../rest/server/convention/VersionProvider.java    |   4 +-
 .../rest/server/httppart/RequestFormParamList.java |   2 +-
 .../swagger/BasicSwaggerProviderSession.java       |   4 +-
 37 files changed, 1102 insertions(+), 69 deletions(-)

diff --git 
a/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/JsonSchemaValidator.java
 
b/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/JsonSchemaValidator.java
index 513ea65389..1031f6a161 100644
--- 
a/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/JsonSchemaValidator.java
+++ 
b/juneau-bean/juneau-bean-jsonschema/src/main/java/org/apache/juneau/bean/jsonschema/JsonSchemaValidator.java
@@ -192,7 +192,7 @@ public final class JsonSchemaValidator implements 
PropertyValidator {
 
        private static void validateEnum(JsonSchema s, Object value) {
                var enums = s.getEnum();
-               if (enums == null || enums.isEmpty())
+               if (e(enums))
                        return;
                for (var e : enums) {
                        if (jsonEquals(e, value))
@@ -217,7 +217,7 @@ public final class JsonSchemaValidator implements 
PropertyValidator {
                        return;
                }
                var arr = s.getTypeAsJsonTypeArray();
-               if (arr == null || arr.isEmpty())
+               if (e(arr))
                        return;
                for (var t : arr) {
                        if (matchesType(t, value))
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanMap.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanMap.java
index 897c12a980..e98d286431 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanMap.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanMap.java
@@ -266,15 +266,32 @@ public class BeanMap<T> extends 
AbstractMap<String,Object> implements Delegate<T
        /**
         * Performs an action on each property in this bean map.
         *
+        * <p>
+        * If a {@link BeanSession} is attached and has an active view, only 
properties that are visible under
+        * that view (as determined by {@link 
BeanSession#isPropertyInActiveView(BeanPropertyMeta)}) are visited.
+        *
         * @param filter The filter to apply to properties.
         * @param action The action.
         * @return This object.
         */
        public BeanMap<T> forEachProperty(Predicate<BeanPropertyMeta> filter, 
Consumer<BeanPropertyMeta> action) {
-               
meta.getProperties().values().stream().filter(filter).forEach(action);
+               
meta.getProperties().values().stream().filter(filter).filter(this::isInActiveView).forEach(action);
                return this;
        }
 
+       /**
+        * Returns <jk>true</jk> if the property is visible under the active 
view on this bean map's session.
+        *
+        * <p>
+        * When no session is attached, or no active view is set, all 
properties are visible.
+        *
+        * @param pMeta The property to test.
+        * @return <jk>true</jk> if the property is in-view.
+        */
+       protected boolean isInActiveView(BeanPropertyMeta pMeta) {
+               return session == null || session.isPropertyInActiveView(pMeta);
+       }
+
        /**
         * Invokes all the getters on this bean and consumes the results.
         *
@@ -599,11 +616,20 @@ public class BeanMap<T> extends 
AbstractMap<String,Object> implements Delegate<T
        /**
         * Returns the metadata on the specified property.
         *
+        * <p>
+        * Returns <jk>null</jk> if the property does not exist on the bean 
<em>or</em> if the property exists but is
+        * excluded by the current active view.  The latter allows the caller 
(e.g. {@link #put(String, Object)}) to
+        * route out-of-view input through the existing 
unknown/ignored-property path governed by
+        * {@link 
org.apache.juneau.commons.bean.BeanConfigContext#isIgnoreUnknownBeanProperties()}.
+        *
         * @param propertyName The name of the bean property.
-        * @return Metadata on the specified property, or <jk>null</jk> if that 
property does not exist.
+        * @return Metadata on the specified property, or <jk>null</jk> if that 
property does not exist or is out of view.
         */
        public BeanPropertyMeta getPropertyMeta(String propertyName) {
-               return meta.getPropertyMeta(propertyName);
+               var p = meta.getPropertyMeta(propertyName);
+               if (p != null && ! isInActiveView(p))
+                       return null;
+               return p;
        }
 
        /**
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanPropertyMeta.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanPropertyMeta.java
index 2757c4bcab..78e37cd0cd 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanPropertyMeta.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanPropertyMeta.java
@@ -95,6 +95,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                public BiFunction<BeanSession,Object,Object> readTransform;  // 
Package-private; defaults to identity if null.  Typed against the commons.bean 
SPI seam; marshalling-side installers cast the session argument back to {@code 
MarshallingSession} where needed (see {@code 
MarshalledPropertyPostProcessor#installSwapAwareTransforms}).
                public BiFunction<BeanSession,Object,Object> writeTransform; // 
Package-private; defaults to identity if null.  Typed against the commons.bean 
SPI seam (see readTransform note).
                public List<ClassInfo> dictionaryClasses;  // Package-private 
for BeanMeta access; @MarshalledProp(dictionary={}) classes scanned during 
validate().
+               public Set<String> views;  // Named views this property belongs 
to; null = untagged (in all views when defaultViewInclusion is enabled). Set 
via MarshalledPropertyPostProcessor.
                private boolean isConstructorArg;
                public boolean isUri;  // Package-private so 
MarshalledPropertyPostProcessor can set @Uri-derived flag.  Mirrors 
rawTypeMeta.isUri() plus @Uri annotation reads on field/getter/setter.
                private boolean isDyna;
@@ -520,6 +521,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
        private final BeanInfo<?> typeMeta;                              // The 
transformed class type of the bean property.  Concrete instances are always 
{@code ClassMeta}; typed against the bean-modeling SPI seam.
        private final BiFunction<BeanSession,Object,Object> writeTransform; // 
Applied to incoming value before raw setter; identity by default.  Typed 
against the commons.bean SPI seam.
        private final boolean writeOnly;                                 // 
True if this property is write-only.
+       private final Set<String> views;                                 // 
Named views this property belongs to; null = untagged (included in all views 
when defaultViewInclusion is enabled).
 
        /**
         * Creates a new BeanPropertyMeta using the contents of the specified 
builder.
@@ -548,6 +550,7 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
                setter = b.setter;
                typeMeta = b.typeMeta;
                writeOnly = b.writeOnly;
+               views = b.views != null ? Collections.unmodifiableSet(b.views) 
: null;
                readTransform = b.readTransform != null ? b.readTransform : 
(session, o) -> o;
                writeTransform = b.writeTransform != null ? b.writeTransform : 
(session, o) -> o;
 
@@ -1044,6 +1047,21 @@ public class BeanPropertyMeta implements 
Comparable<BeanPropertyMeta> {
         */
        public boolean isUri() { return isUri; }
 
+       /**
+        * Returns the set of named views this property belongs to, or 
<jk>null</jk> if the property is untagged.
+        *
+        * <p>
+        * An untagged property (one with no {@code @MarshalledProp(view=...)} 
annotation) follows the
+        * default-view-inclusion policy: it is included under every active 
view when the policy is enabled
+        * (the default behavior), or excluded from all views when the policy 
is disabled.
+        *
+        * <p>
+        * A tagged property is included only when the active view name is 
contained in this set.
+        *
+        * @return The set of named views, or <jk>null</jk> if no view 
membership was declared.
+        */
+       public Set<String> getViews() { return views; }
+
        /**
         * Equivalent to calling {@link BeanMap#put(String, Object)}, but is 
faster since it avoids looking up the property
         * meta.
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanSession.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanSession.java
index 7fde720c7a..e949e4dc65 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanSession.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/bean/BeanSession.java
@@ -131,4 +131,24 @@ public interface BeanSession {
         * @return A new bean map (typically a {@code BeanMap}) wrapping the 
supplied bean.
         */
        <T> Object toBeanMap(T bean);
+
+       /**
+        * Returns <jk>true</jk> if the specified bean property is visible 
under the current active view.
+        *
+        * <p>
+        * When no active view is set on the session, this method always 
returns <jk>true</jk> (all properties visible).
+        * The marshalling-side {@code MarshallingSession} overrides this to 
implement the actual view-membership check
+        * using the property's declared view set and the active view name.
+        *
+        * <p>
+        * Default-view-inclusion policy (configurable): an untagged property — 
one whose view set is empty — is
+        * considered in-view under every active view unless the
+        * {@link 
org.apache.juneau.marshall.MarshallingContext.Builder#disableDefaultViewInclusion()}
 flag is set.
+        *
+        * @param pMeta The property metadata. Must not be <jk>null</jk>.
+        * @return <jk>true</jk> if the property should be included under the 
current active view.
+        */
+       default boolean isPropertyInActiveView(BeanPropertyMeta pMeta) {
+               return true; // HTT — default SPI method; MarshallingSession 
always overrides, so this body is unreachable in practice.
+       }
 }
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/lang/CharHolder.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/lang/CharHolder.java
index 360e6fe8a0..d789b4f730 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/lang/CharHolder.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/lang/CharHolder.java
@@ -275,7 +275,7 @@ public class CharHolder extends Holder<Character> {
         * @return <jk>true</jk> if the current value matches any character in 
the string.
         */
        public boolean isAny(String values) {
-               if (values == null || values.isEmpty())
+               if (e(values))
                        return false;
                var current = get();
                if (current == null)
diff --git 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/runtime/Args.java
 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/runtime/Args.java
index c40906415e..60c8061c55 100644
--- 
a/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/runtime/Args.java
+++ 
b/juneau-core/juneau-commons/src/main/java/org/apache/juneau/commons/runtime/Args.java
@@ -138,7 +138,7 @@ public class Args {
         */
        public Optional<String> get(String key) {
                var v = options.get(normalize(key));
-               if (v == null || v.isEmpty())
+               if (e(v))
                        return opte();
                return opt(v.get(0));
        }
@@ -379,7 +379,7 @@ public class Args {
                                if (allowShortFlags)
                                        p.add("-");
                        }
-                       p.removeIf(x -> x == null || x.isEmpty());
+                       p.removeIf(x -> e(x));
                        p.sort((a,b) -> Integer.compare(b.length(), 
a.length()));
                        return p;
                }
diff --git 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/marshall/jena/RdfSerializerSession.java
 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/marshall/jena/RdfSerializerSession.java
index 224ca67da2..16b50a19a5 100644
--- 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/marshall/jena/RdfSerializerSession.java
+++ 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/marshall/jena/RdfSerializerSession.java
@@ -189,7 +189,7 @@ public class RdfSerializerSession extends 
WriterSerializerSession {
                String s = null;
                if (nn(uri))
                        s = uri.toString();
-               if ((s == null || s.isEmpty()) && nn(uri2))
+               if (e(s) && nn(uri2))
                        s = uri2.toString();
                if (s == null)
                        return null;
diff --git 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/marshall/jena/RdfStreamSerializerSession.java
 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/marshall/jena/RdfStreamSerializerSession.java
index 4f495de54c..4f57bfd4f7 100644
--- 
a/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/marshall/jena/RdfStreamSerializerSession.java
+++ 
b/juneau-core/juneau-marshall-rdf/src/main/java/org/apache/juneau/marshall/jena/RdfStreamSerializerSession.java
@@ -264,7 +264,7 @@ public class RdfStreamSerializerSession extends 
OutputStreamSerializerSession {
                String s = null;
                if (nn(uri))
                        s = uri.toString();
-               if ((s == null || s.isEmpty()) && nn(uri2))
+               if (e(s) && nn(uri2))
                        s = uri2.toString();
                if (s == null)
                        return null;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshalledProp.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshalledProp.java
index 9b255d3909..186975d3e8 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshalledProp.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshalledProp.java
@@ -61,6 +61,51 @@ public @interface MarshalledProp {
         */
        String[] description() default {};
 
+       /**
+        * Declares the named views this property belongs to.
+        *
+        * <p>
+        * When an active view is selected (via
+        * {@link 
org.apache.juneau.marshall.MarshallingContext.Builder#activeView(String)} or 
the per-call session
+        * override), this property is included only when its declared view set 
contains the active view name.
+        *
+        * <p>
+        * If this member is empty (the default), the property follows the 
default-view-inclusion policy:
+        * by default an untagged property is included under every active view 
(matching Jackson's
+        * {@code DEFAULT_VIEW_INCLUSION} behavior). The policy can be flipped 
via
+        * {@link 
org.apache.juneau.marshall.MarshallingContext.Builder#disableDefaultViewInclusion()}.
+        *
+        * <p>
+        * Multiple view names are supported — a property tagged {@code 
view={"summary","detail"}} is included
+        * when <em>either</em> {@code "summary"} or {@code "detail"} is the 
active view (union semantics).
+        *
+        * <h5 class='section'>Example:</h5>
+        * <p class='bjava'>
+        *      <jk>public class</jk> MyBean {
+        *
+        *              <jc>// Included in all views (untagged = default 
inclusion)</jc>
+        *              <jk>public</jk> String <jf>id</jf>;
+        *
+        *              <jc>// Included only in the "summary" and "detail" 
views</jc>
+        *              <ja>@MarshalledProp</ja>(view={<js>"summary"</js>, 
<js>"detail"</js>})
+        *              <jk>public</jk> String <jf>name</jf>;
+        *
+        *              <jc>// Included only in the "detail" view</jc>
+        *              <ja>@MarshalledProp</ja>(view=<js>"detail"</js>)
+        *              <jk>public</jk> String <jf>description</jf>;
+        *      }
+        * </p>
+        *
+        * <h5 class='section'>See Also:</h5><ul>
+        *      <li class='jm'>{@link 
org.apache.juneau.marshall.MarshallingContext.Builder#activeView(String)}
+        *      <li class='link'><a class="doclink" 
href="https://juneau.apache.org/docs/topics/ViewProjection";>View-based 
Projection</a>
+        * </ul>
+        *
+        * @return The annotation value.
+        * @since 10.0.0
+        */
+       String[] view() default {};
+
        /**
         * Bean dictionary.
         *
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshalledPropAnnotation.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshalledPropAnnotation.java
index aeae3e56c7..7fba4e6a60 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshalledPropAnnotation.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshalledPropAnnotation.java
@@ -45,6 +45,7 @@ public class MarshalledPropAnnotation {
                private String[] description = {};
                private Class<?>[] dictionary = new Class[0];
                private String format = "";
+               private String[] view = {};
                private DurationFormat durationFormat = DurationFormat.NOT_SET;
                private PeriodFormat periodFormat = PeriodFormat.NOT_SET;
                private CalendarFormat calendarFormat = CalendarFormat.NOT_SET;
@@ -275,6 +276,17 @@ public class MarshalledPropAnnotation {
                        return this;
                }
 
+               /**
+                * Sets the {@link MarshalledProp#view()} property on this 
annotation.
+                *
+                * @param value The new value for this property.
+                * @return This object.
+                */
+               public Builder view(String...value) {
+                       view = value;
+                       return this;
+               }
+
        }
 
        @SuppressWarnings({
@@ -285,6 +297,7 @@ public class MarshalledPropAnnotation {
                private final String[] description;
                private final Class<?>[] dictionary;
                private final String format;
+               private final String[] view;
                private final DurationFormat durationFormat;
                private final PeriodFormat periodFormat;
                private final CalendarFormat calendarFormat;
@@ -306,6 +319,7 @@ public class MarshalledPropAnnotation {
                        description = copyOf(b.description);
                        dictionary = copyOf(b.dictionary);
                        format = b.format;
+                       view = copyOf(b.view);
                        durationFormat = b.durationFormat;
                        periodFormat = b.periodFormat;
                        calendarFormat = b.calendarFormat;
@@ -412,6 +426,11 @@ public class MarshalledPropAnnotation {
                public String[] description() {
                        return description;
                }
+
+               @Override /* Overridden from MarshalledProp */
+               public String[] view() {
+                       return view;
+               }
        }
 
        /** Default value */
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshalledPropertyPostProcessor.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshalledPropertyPostProcessor.java
index 033a24731d..662750cafe 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshalledPropertyPostProcessor.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshalledPropertyPostProcessor.java
@@ -105,6 +105,7 @@ final class MarshalledPropertyPostProcessor implements 
BeanPropertyPostProcessor
        static void process(MarshallingContext bc, BeanPropertyMeta.Builder b) {
                var ap = bc.getAnnotationProvider();
                var bdClasses = new ArrayList<Class<?>>();
+               Set<String> viewNames = null;
                var propertyClass = propertyClass(b);
 
                // XMLGregorianCalendar always uses XML format regardless of 
any CalendarFormat setting.
@@ -122,6 +123,8 @@ final class MarshalledPropertyPostProcessor implements 
BeanPropertyPostProcessor
                        });
                        ap.find(Swap.class, 
b.innerField).stream().findFirst().ifPresent(x -> b.swap = swapSwap(x));
                        b.isUri |= ap.has(Uri.class, b.innerField);
+                       for (var ai : ap.find(MarshalledProp.class, 
b.innerField))
+                               viewNames = addViews(viewNames, 
ai.inner().view());
                }
 
                if (nn(b.getter)) {
@@ -134,6 +137,8 @@ final class MarshalledPropertyPostProcessor implements 
BeanPropertyPostProcessor
                        });
                        ap.find(Swap.class, b.getter).forEach(x -> b.swap = 
swapSwap(x));
                        b.isUri |= ap.has(Uri.class, b.getter);
+                       for (var ai : ap.find(MarshalledProp.class, b.getter))
+                               viewNames = addViews(viewNames, 
ai.inner().view());
                }
 
                if (nn(b.setter)) {
@@ -146,8 +151,13 @@ final class MarshalledPropertyPostProcessor implements 
BeanPropertyPostProcessor
                        });
                        ap.find(Swap.class, b.setter).forEach(x -> b.swap = 
swapSwap(x));
                        b.isUri |= ap.has(Uri.class, b.setter);
+                       for (var ai : ap.find(MarshalledProp.class, b.setter))
+                               viewNames = addViews(viewNames, 
ai.inner().view());
                }
 
+               if (viewNames != null)
+                       b.views = viewNames;
+
                ClassInfo ownerClass = owningClass(b);
                if (nn(ownerClass)) {
                        ap.find(Marshalled.class, 
ownerClass).stream().findFirst().ifPresent(x -> {
@@ -311,7 +321,7 @@ final class MarshalledPropertyPostProcessor implements 
BeanPropertyPostProcessor
                if (nn(b.setter))
                        for (var ai : ap.find(Schema.class, b.setter))
                                merged = applyToMap(merged, ai.inner());
-               if (merged == null || merged.isEmpty())
+               if (e(merged))
                        return;
                var validator = factory.create(merged, propertyClass(b));
                if (validator == null)
@@ -353,7 +363,7 @@ final class MarshalledPropertyPostProcessor implements 
BeanPropertyPostProcessor
                } catch (ParseException e) {
                        throw new RuntimeException(e);
                }
-               if (m == null || m.isEmpty())
+               if (e(m))
                        return acc;
                if (acc == null)
                        return new JsonMap(m);
@@ -1054,6 +1064,26 @@ final class MarshalledPropertyPostProcessor implements 
BeanPropertyPostProcessor
                return (Class) Class.class;
        }
 
+       /**
+        * Accumulates non-empty view names into a set, creating it lazily on 
first use.
+        *
+        * @param acc The current accumulator (may be null on first call).
+        * @param views The view names to add (may be empty array).
+        * @return The updated accumulator (non-null if any names were added).
+        */
+       private static Set<String> addViews(Set<String> acc, String[] views) {
+               if (views == null || views.length == 0) // HTT — views==null 
branch: annotation arrays are never null in Java; defensive guard only.
+                       return acc;
+               for (var v : views) {
+                       if (v != null && ! v.isEmpty()) { // HTT — v==null 
branch: annotation String[] elements are never null in Java; defensive guard 
only.
+                               if (acc == null)
+                                       acc = new LinkedHashSet<>();
+                               acc.add(v);
+                       }
+               }
+               return acc;
+       }
+
        @SuppressWarnings({
                "java:S112" // Rewrap DatatypeConfigurationException as 
RuntimeException; we cannot recover at the swap level
        })
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshallingContext.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshallingContext.java
index 8858170e85..8c063de659 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshallingContext.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshallingContext.java
@@ -302,7 +302,9 @@ public class MarshallingContext extends Context implements 
ConversionFinder, Bea
                private Set<ClassInfo> notBeanClasses;
                private Set<String> notBeanPackages;
                private BeanStore beanStore;
-               
+               private String activeView;
+               private boolean disableDefaultViewInclusion;
+
                /**
                 * Constructor.
                 *
@@ -411,6 +413,8 @@ public class MarshallingContext extends Context implements 
ConversionFinder, Bea
                        useJavaBeanIntrospector = 
copyFrom.useJavaBeanIntrospector;
                        validateSchema = copyFrom.validateSchema;
                        beanStore = copyFrom.beanStore;
+                       activeView = copyFrom.activeView;
+                       disableDefaultViewInclusion = ! 
copyFrom.defaultViewInclusion;
                }
 
                /**
@@ -467,6 +471,8 @@ public class MarshallingContext extends Context implements 
ConversionFinder, Bea
                        useJavaBeanIntrospector = 
copyFrom.useJavaBeanIntrospector;
                        validateSchema = copyFrom.validateSchema;
                        beanStore = copyFrom.beanStore;
+                       activeView = copyFrom.activeView;
+                       disableDefaultViewInclusion = 
copyFrom.disableDefaultViewInclusion;
                }
 
                /**
@@ -2315,25 +2321,27 @@ public class MarshallingContext extends Context 
implements ConversionFinder, Bea
                                swaps,
                                notBeanClasses,
                                notBeanPackages,
-                               integer(
-                                       disableBeansRequireSomeProperties,
-                                       beanMapPutReturnsOldValue,
-                                       beansRequireDefaultConstructor,
-                                       beansRequireSerializable,
-                                       beansRequireSettersForGetters,
-                                       disableIgnoreTransientFields,
-                                       disableIgnoreUnknownNullBeanProperties,
-                                       disableIgnoreMissingSetters,
-                                       disableInterfaceProxies,
-                                       findFluentSetters,
-                                       ignoreInvocationExceptionsOnGetters,
-                                       ignoreInvocationExceptionsOnSetters,
-                                       ignoreUnknownBeanProperties,
-                                       ignoreUnknownEnumValues,
-                                       unsortedProperties,
-                                       useJavaBeanIntrospector,
-                                       validateSchema
-                               ),
+                       integer(
+                               disableBeansRequireSomeProperties,
+                               beanMapPutReturnsOldValue,
+                               beansRequireDefaultConstructor,
+                               beansRequireSerializable,
+                               beansRequireSettersForGetters,
+                               disableIgnoreTransientFields,
+                               disableIgnoreUnknownNullBeanProperties,
+                               disableIgnoreMissingSetters,
+                               disableInterfaceProxies,
+                               findFluentSetters,
+                               ignoreInvocationExceptionsOnGetters,
+                               ignoreInvocationExceptionsOnSetters,
+                               ignoreUnknownBeanProperties,
+                               ignoreUnknownEnumValues,
+                               unsortedProperties,
+                               useJavaBeanIntrospector,
+                               validateSchema,
+                               disableDefaultViewInclusion
+                       ),
+                       activeView,
                                typePropertyName,
                                mediaType,
                                timeZone,
@@ -2360,6 +2368,77 @@ public class MarshallingContext extends Context 
implements ConversionFinder, Bea
                        // @formatter:on
                }
 
+               /**
+                * Sets the default active view name for all sessions created 
from this context.
+                *
+                * <p>
+                * When set, only bean properties whose declared {@link 
MarshalledProp#view()} set contains this view name
+                * will be included during serialization.  On the parse side, 
properties outside the active view are routed
+                * through the existing unknown/ignored-property mechanism 
governed by
+                * {@link #ignoreUnknownBeanProperties()}.
+                *
+                * <p>
+                * Untagged properties (those whose declared view set is empty) 
follow the default-view-inclusion policy:
+                * included under every active view unless {@link 
#disableDefaultViewInclusion()} has been called.
+                *
+                * <p>
+                * This value can be overridden per serialization or parse call 
via the session builder (e.g.
+                * {@link MarshallingSession.Builder#activeView(String)}).
+                *
+                * <h5 class='section'>Example:</h5>
+                * <p class='bjava'>
+                *      JsonSerializer <jv>serializer</jv> = 
JsonSerializer.<jsm>create</jsm>()
+                *              .activeView(<js>"summary"</js>)
+                *              .build();
+                * </p>
+                *
+                * <h5 class='section'>See Also:</h5><ul>
+                *      <li class='ja'>{@link MarshalledProp#view()}
+                *      <li class='jm'>{@link 
MarshallingSession.Builder#activeView(String)}
+                * </ul>
+                *
+                * @param value The active view name.  Use <jk>null</jk> to 
disable view filtering.
+                * @return This object.
+                * @since 10.0.0
+                */
+               public Builder activeView(String value) {
+                       activeView = value;
+                       return this;
+               }
+
+               /**
+                * Disables the default-view-inclusion policy.
+                *
+                * <p>
+                * By default, bean properties that carry no {@link 
MarshalledProp#view()} declaration are included under
+                * every active view (matching Jackson's {@code 
DEFAULT_VIEW_INCLUSION} behavior).
+                * Calling this method reverses the policy: untagged properties 
are <em>excluded</em> when any active view
+                * is set.
+                *
+                * <h5 class='section'>See Also:</h5><ul>
+                *      <li class='ja'>{@link MarshalledProp#view()}
+                *      <li class='jm'>{@link #activeView(String)}
+                * </ul>
+                *
+                * @return This object.
+                * @since 10.0.0
+                */
+               public Builder disableDefaultViewInclusion() {
+                       return disableDefaultViewInclusion(true);
+               }
+
+               /**
+                * Same as {@link #disableDefaultViewInclusion()} but allows 
you to explicitly specify the value.
+                *
+                * @param value The value for this setting.
+                * @return This object.
+                * @since 10.0.0
+                */
+               public Builder disableDefaultViewInclusion(boolean value) {
+                       disableDefaultViewInclusion = value;
+                       return this;
+               }
+
                /**
                 * Ignore invocation errors on getters.
                 *
@@ -3977,6 +4056,8 @@ public class MarshallingContext extends Context 
implements ConversionFinder, Bea
        private final Visibility beanFieldVisibility;
        private final Visibility beanMethodVisibility;
        private final BeanStore beanStore;
+       private final String activeView;
+       private final boolean defaultViewInclusion;
 
        /**
         * Constructor.
@@ -4033,6 +4114,8 @@ public class MarshallingContext extends Context 
implements ConversionFinder, Bea
                useJavaBeanIntrospector = builder.useJavaBeanIntrospector;
                validateSchema = builder.validateSchema;
                beanStore = builder.beanStore;
+               activeView = builder.activeView;
+               defaultViewInclusion = ! builder.disableDefaultViewInclusion;
 
                var builderNotBeanClasses = new 
ArrayList<>(builder.notBeanClasses);
                notBeanClasses = builderNotBeanClasses.isEmpty() ? 
DEFAULT_NOTBEAN_CLASSES : Stream.concat(builderNotBeanClasses.stream(), 
DEFAULT_NOTBEAN_CLASSES.stream()).distinct().toList();
@@ -5105,6 +5188,32 @@ public class MarshallingContext extends Context 
implements ConversionFinder, Bea
         */
        protected final Locale getLocale() { return locale; }
 
+       /**
+        * The default active view for sessions created from this context.
+        *
+        * <p>
+        * Returns the view name set via {@link Builder#activeView(String)}, or 
<jk>null</jk> if no default
+        * active view has been configured (all properties visible).
+        *
+        * @return The default active view, or <jk>null</jk>.
+        * @since 10.0.0
+        */
+       public final String getActiveView() { return activeView; }
+
+       /**
+        * Default-view-inclusion policy.
+        *
+        * <p>
+        * Returns <jk>true</jk> (the default) when untagged properties — those 
carrying no
+        * {@link MarshalledProp#view()} declaration — are included under every 
active view.
+        * Returns <jk>false</jk> when {@link 
Builder#disableDefaultViewInclusion()} has been called,
+        * in which case untagged properties are excluded when any active view 
is in effect.
+        *
+        * @return <jk>true</jk> if untagged properties are included under 
every active view.
+        * @since 10.0.0
+        */
+       public final boolean isDefaultViewInclusion() { return 
defaultViewInclusion; }
+
        /**
         * Media type.
         *
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshallingContextable.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshallingContextable.java
index 2f955dea12..bb103a06c4 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshallingContextable.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshallingContextable.java
@@ -1655,6 +1655,57 @@ public abstract class MarshallingContextable extends 
Context {
                        return self();
                }
 
+               /**
+                * Sets the default active view name for serializer/parser 
sessions created from this context.
+                *
+                * <p>
+                * When set, only bean properties whose declared {@link 
MarshalledProp#view()} set contains this view name
+                * will be included during serialization.  On the parse side, 
out-of-view properties are routed through
+                * the existing unknown/ignored-property mechanism governed by 
{@link #ignoreUnknownBeanProperties()}.
+                *
+                * <p>
+                * Untagged properties follow the default-view-inclusion 
policy: included under every active view unless
+                * {@link #disableDefaultViewInclusion()} has been called.
+                *
+                * <p>
+                * This value can be overridden per call via {@link 
MarshallingSession.Builder#activeView(String)}.
+                *
+                * <h5 class='section'>See Also:</h5><ul>
+                *      <li class='ja'>{@link MarshalledProp#view()}
+                *      <li class='jm'>{@link 
MarshallingContext.Builder#activeView(String)}
+                *      <li class='jm'>{@link 
MarshallingSession.Builder#activeView(String)}
+                * </ul>
+                *
+                * @param value The active view name.  Use <jk>null</jk> to 
disable view filtering.
+                * @return This object.
+                * @since 10.0.0
+                */
+               public SELF activeView(String value) {
+                       bcBuilder.activeView(value);
+                       return self();
+               }
+
+               /**
+                * Disables the default-view-inclusion policy.
+                *
+                * <p>
+                * By default, bean properties that carry no {@link 
MarshalledProp#view()} declaration are included under
+                * every active view.  Calling this method reverses the policy: 
untagged properties are <em>excluded</em>
+                * when any active view is set.
+                *
+                * <h5 class='section'>See Also:</h5><ul>
+                *      <li class='ja'>{@link MarshalledProp#view()}
+                *      <li class='jm'>{@link 
MarshallingContext.Builder#disableDefaultViewInclusion()}
+                * </ul>
+                *
+                * @return This object.
+                * @since 10.0.0
+                */
+               public SELF disableDefaultViewInclusion() {
+                       bcBuilder.disableDefaultViewInclusion();
+                       return self();
+               }
+
                /**
                 * POJO example.
                 *
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshallingSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshallingSession.java
index 9765c2404d..71db8444c4 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshallingSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/MarshallingSession.java
@@ -60,9 +60,11 @@ public class MarshallingSession extends ContextSession 
implements ConverterSessi
        private static final String PROP_locale = "locale";
        private static final String PROP_mediaType = "mediaType";
        private static final String PROP_timeZone = "timeZone";
+       private static final String PROP_activeView = "activeView";
        private static final String PROP_BeanSession_locale = 
"MarshallingSession.locale";
        private static final String PROP_BeanSession_mediaType = 
"MarshallingSession.mediaType";
        private static final String PROP_BeanSession_timeZone = 
"MarshallingSession.timeZone";
+       private static final String PROP_BeanSession_activeView = 
"MarshallingSession.activeView";
 
        // Argument name constants for assertArgNotNull
        private static final String ARG_ctx = "ctx";
@@ -82,6 +84,7 @@ public class MarshallingSession extends ContextSession 
implements ConverterSessi
                private Locale locale;
                private MediaType mediaType;
                private TimeZone timeZone;
+               private String activeView;
 
                /**
                 * Constructor
@@ -94,6 +97,7 @@ public class MarshallingSession extends ContextSession 
implements ConverterSessi
                        this.ctx = ctx;
                        mediaType = ctx.getMediaType();
                        timeZone = ctx.getTimeZone();
+                       activeView = ctx.getActiveView();
                }
 
                /**
@@ -168,6 +172,32 @@ public class MarshallingSession extends ContextSession 
implements ConverterSessi
                        return self();
                }
 
+               /**
+                * Overrides the active view for this session.
+                *
+                * <p>
+                * When set, only bean properties whose declared {@link 
MarshalledProp#view()} set contains this view name
+                * will be included during serialization.  On the parse side, 
out-of-view properties are routed through
+                * the existing unknown/ignored-property mechanism.
+                *
+                * <p>
+                * This is a per-call override.  If not set, the value from
+                * {@link MarshallingContext.Builder#activeView(String)} is 
used.
+                *
+                * <h5 class='section'>See Also:</h5><ul>
+                *      <li class='ja'>{@link MarshalledProp#view()}
+                *      <li class='jm'>{@link 
MarshallingContext.Builder#activeView(String)}
+                * </ul>
+                *
+                * @param value The active view name.  Use <jk>null</jk> to 
disable view filtering for this call.
+                * @return This object.
+                * @since 10.0.0
+                */
+               public SELF activeView(String value) {
+                       activeView = value;
+                       return self();
+               }
+
                @Override /* Overridden from Builder */
                public SELF property(String key, Object value) {
                        if (key == null) {
@@ -181,6 +211,8 @@ public class MarshallingSession extends ContextSession 
implements ConverterSessi
                                        return mediaType(cvt(value, 
MediaType.class));
                                case PROP_timeZone, PROP_BeanSession_timeZone:
                                        return timeZone(cvt(value, 
TimeZone.class));
+                               case PROP_activeView, 
PROP_BeanSession_activeView:
+                                       return activeView(cvt(value, 
String.class));
                                default:
                                        super.property(key, value);
                                        return self();
@@ -261,8 +293,8 @@ public class MarshallingSession extends ContextSession 
implements ConverterSessi
        private final MarshallingContext ctx;
        private final Locale locale;
        private final MediaType mediaType;
-
        private final TimeZone timeZone;
+       private final String activeView;
 
        /**
         * Constructor.
@@ -275,6 +307,7 @@ public class MarshallingSession extends ContextSession 
implements ConverterSessi
                locale = opt(builder.locale).orElse(ctx.getLocale());
                mediaType = opt(builder.mediaType).orElse(builder.mediaType);
                timeZone = opt(builder.timeZone).orElse(builder.timeZone);
+               activeView = builder.activeView;
        }
 
        @Override /* ConverterSession */
@@ -686,6 +719,34 @@ public class MarshallingSession extends ContextSession 
implements ConverterSessi
         */
        public Locale getLocale() { return locale; }
 
+       /**
+        * Active view.
+        *
+        * <p>
+        * Returns the active view name for this session.  When 
non-<jk>null</jk>, only bean properties whose
+        * declared {@link MarshalledProp#view()} set contains this name are 
included during serialization, and
+        * out-of-view properties encountered during parsing are treated as 
unknown.
+        *
+        * <p>
+        * This is the per-call override value, which defaults to {@link 
MarshallingContext#getActiveView()}.
+        *
+        * @see MarshallingContext.Builder#activeView(String)
+        * @see MarshallingSession.Builder#activeView(String)
+        * @return The active view for this session, or <jk>null</jk> if view 
filtering is not active.
+        * @since 10.0.0
+        */
+       public final String getActiveView() { return activeView; }
+
+       @Override /* BeanSession */
+       public boolean isPropertyInActiveView(BeanPropertyMeta pMeta) {
+               if (activeView == null)
+                       return true;
+               var views = pMeta.getViews();
+               if (e(views))
+                       return ctx.isDefaultViewInclusion();
+               return views.contains(activeView);
+       }
+
        /**
         * Media type.
         *
@@ -1281,7 +1342,8 @@ public class MarshallingSession extends ContextSession 
implements ConverterSessi
                return super.properties()
                        .a(PROP_locale, locale)
                        .a(PROP_mediaType, mediaType)
-                       .a(PROP_timeZone, timeZone);
+                       .a(PROP_timeZone, timeZone)
+                       .a(PROP_activeView, activeView);
        }
 
        /**
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/csv/CsvParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/csv/CsvParserSession.java
index 712eb550a2..4a19afe2d1 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/csv/CsvParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/csv/CsvParserSession.java
@@ -160,7 +160,7 @@ public class CsvParserSession extends ReaderParserSession 
implements RecordReada
 
                // Read header row
                var headers = r.readRow();
-               if (headers == null || headers.isEmpty())
+               if (e(headers))
                        return null;
 
                Object o = null;
@@ -366,7 +366,7 @@ public class CsvParserSession extends ReaderParserSession 
implements RecordReada
         * CSV-specific parsing for byte[] and primitive arrays. Returns null 
if not applicable.
         */
        private Object parseCsvCellValue(String val, ClassMeta<?> eType) throws 
ParseException {
-               if (val == null || val.isEmpty())
+               if (e(val))
                        return null;
                if (eType.isByteArray()) {
                        if (byteArrayFormat == 
CsvByteArrayCellFormat.SEMICOLON_DELIMITED) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/ini/IniSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/ini/IniSerializerSession.java
index 90fd0719df..ec3c5bcc58 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/ini/IniSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/ini/IniSerializerSession.java
@@ -302,7 +302,7 @@ public class IniSerializerSession extends 
WriterSerializerSession implements Rec
        }
 
        private static boolean needsQuoting(String s) {
-               if (s == null || s.isEmpty())
+               if (e(s))
                        return true;
                if (s.equals("null") || s.equalsIgnoreCase("true") || 
s.equalsIgnoreCase("false"))
                        return true;
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/ini/IniWriter.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/ini/IniWriter.java
index 0d6c40dfbe..b59497e3fd 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/ini/IniWriter.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/ini/IniWriter.java
@@ -16,6 +16,8 @@
  */
 package org.apache.juneau.marshall.ini;
 
+import static org.apache.juneau.commons.utils.Utils.*;
+
 import java.io.*;
 
 import org.apache.juneau.marshall.*;
@@ -84,7 +86,7 @@ public class IniWriter extends SerializerWriter {
         */
        public IniWriter comment(String text) {
                w("# ");
-               if (text != null && !text.isEmpty()) {
+               if (ne(text)) {
                        var lines = text.split("\n");
                        for (var i = 0; i < lines.length; i++) {
                                if (i > 0)
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/json/JsonTokenWriter.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/json/JsonTokenWriter.java
index 7a72c13fcc..0321e3045b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/json/JsonTokenWriter.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/json/JsonTokenWriter.java
@@ -17,6 +17,7 @@
 package org.apache.juneau.marshall.json;
 
 import static org.apache.juneau.commons.utils.AssertionUtils.*;
+import static org.apache.juneau.commons.utils.Utils.*;
 
 import java.io.*;
 import java.math.*;
@@ -230,7 +231,7 @@ public class JsonTokenWriter implements TokenWriter {
         * and must not be one of a small set of JavaScript reserved words.
         */
        private static boolean isSafeBareIdentifier(String s) {
-               if (s == null || s.isEmpty())
+               if (e(s))
                        return false;
                var first = s.charAt(0);
                if (!(Character.isLetter(first) || first == '_'))
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/markdown/MarkdownDocParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/markdown/MarkdownDocParserSession.java
index 57048dd2fb..051d0147f0 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/markdown/MarkdownDocParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/markdown/MarkdownDocParserSession.java
@@ -16,6 +16,8 @@
  */
 package org.apache.juneau.marshall.markdown;
 
+import static org.apache.juneau.commons.utils.Utils.*;
+
 import java.io.*;
 import java.util.*;
 
@@ -176,7 +178,7 @@ public class MarkdownDocParserSession extends 
MarkdownParserSession {
 
                // The "root" section (before any sub-heading) holds the 
key/value table
                var rootLines = sections.get("");
-               if (rootLines != null && !rootLines.isEmpty()) {
+               if (ne(rootLines)) {
                        // Filter out the top-level heading (level)
                        var tableLines = rootLines.stream()
                                .filter(l -> !isHeadingLine(l, level))
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/markdown/MarkdownParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/markdown/MarkdownParserSession.java
index fe6dc4ff83..916a840642 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/markdown/MarkdownParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/markdown/MarkdownParserSession.java
@@ -421,7 +421,7 @@ public class MarkdownParserSession extends 
ReaderParserSession implements Record
                int typeColIndex = headers.indexOf(CONST_type);
                if (typeColIndex >= 0 && typeColIndex < cells.size()) {
                        var typeName = cells.get(typeColIndex);
-                       if (typeName != null && !typeName.isEmpty()) {
+                       if (ne(typeName)) {
                                var registry = eType != null ? 
eType.getBeanRegistry() : null;
                                var resolved = registry != null ? 
registry.getClassMeta(typeName) : null;
                                if (resolved != null)
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/parquet/ParquetParserSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/parquet/ParquetParserSession.java
index 4671ad5cb0..9961649444 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/parquet/ParquetParserSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/parquet/ParquetParserSession.java
@@ -610,7 +610,7 @@ public class ParquetParserSession extends 
InputStreamParserSession implements Re
 
        /** Returns true if rows are key-value pairs (Map with non-String keys 
format). */
        private static boolean isKeyValuePairFormat(List<?> rows) {
-               if (rows == null || rows.isEmpty())
+               if (e(rows))
                        return false;
                var first = rows.get(0);
                if (!(first instanceof Map<?, ?> m))
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/parquet/ParquetSchemaBuilder.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/parquet/ParquetSchemaBuilder.java
index 7e50077f57..36c58c7bfa 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/parquet/ParquetSchemaBuilder.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/parquet/ParquetSchemaBuilder.java
@@ -17,6 +17,7 @@
 package org.apache.juneau.marshall.parquet;
 
 import static org.apache.juneau.commons.utils.ThrowableUtils.*;
+import static org.apache.juneau.commons.utils.Utils.*;
 import static org.apache.juneau.marshall.parquet.ParquetSchemaElement.*;
 
 import java.util.*;
@@ -232,7 +233,7 @@ public final class ParquetSchemaBuilder {
                // Resolve element type from sample when generics are erased 
(et is Object) for proper list-of-bean
                // expansion into leaf columns (e.g. members.list.element.name, 
members.list.element.age)
                var sampleCollection = extractSampleCollection(sampleBean);
-               if (sampleCollection != null && !sampleCollection.isEmpty()) {
+               if (ne(sampleCollection)) {
                        var first = sampleCollection.iterator().next();
                        if (first != null)
                                et = 
marshallingContext.getClassMeta(first.getClass());
@@ -241,7 +242,7 @@ public final class ParquetSchemaBuilder {
                elements.add(new ParquetSchemaElement(name, null, null, isRoot 
? null : OPTIONAL, 1, CONVERTED_LIST, null, null, null, null));
                elements.add(new ParquetSchemaElement("list", null, null, 
REPEATED, 1, null, null, null, null, null));
                Object elementSample = null;
-               if (sampleCollection != null && !sampleCollection.isEmpty())
+               if (ne(sampleCollection))
                        elementSample = sampleCollection.iterator().next();
                addSchemaElements(elements, et, "element", listPath + ".list", 
false, elementSample, typesInProgress);
        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/xml/XmlBeanPropertyMeta.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/xml/XmlBeanPropertyMeta.java
index 197f7d14da..f762b989d1 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/xml/XmlBeanPropertyMeta.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/marshall/xml/XmlBeanPropertyMeta.java
@@ -138,10 +138,10 @@ public class XmlBeanPropertyMeta extends 
ExtendedBeanPropertyMeta {
                        if (isCollection) {
                                if (cen.isEmpty() && nn(xmlMetaProvider))
                                        cen = 
xmlMetaProvider.getXmlClassMeta(cmProperty).getChildName();
-                               if (cen == null || cen.isEmpty())
-                                       cen = 
cmProperty.getElementType().getBeanDictionaryName();
-                               if (cen == null || cen.isEmpty())
-                                       cen = name;
+                       if (e(cen))
+                               cen = 
cmProperty.getElementType().getBeanDictionaryName();
+                       if (e(cen))
+                               cen = name;
                        } else {
                                throw bex(cmBean.inner(), "Annotation error on 
property ''{0}''.  @Xml.format=COLLAPSED can only be specified on collections 
and arrays.", name);
                        }
diff --git 
a/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/ViewProjection_Test.java
 
b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/ViewProjection_Test.java
new file mode 100644
index 0000000000..740fb1f026
--- /dev/null
+++ 
b/juneau-core/juneau-marshall/src/test/java/org/apache/juneau/ViewProjection_Test.java
@@ -0,0 +1,353 @@
+/*
+ * 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;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.apache.juneau.commons.bean.*;
+import org.apache.juneau.marshall.*;
+import org.apache.juneau.marshall.json5.*;
+import org.apache.juneau.marshall.msgpack.*;
+import org.apache.juneau.marshall.xml.*;
+import org.junit.jupiter.api.*;
+
+/**
+ * Tests for view-based property projection.
+ *
+ * <p>
+ * Covers: property-level view membership via {@link MarshalledProp#view()}, 
active-view selector on
+ * {@link MarshallingContext.Builder} and per-call {@link 
MarshallingSession.Builder}, default-view-inclusion
+ * policy, multi-view union semantics, interaction with read-only/write-only 
and {@link MarshalledIgnore},
+ * the {@code *Config}/{@code @ContextApply} path for unmodifiable classes, 
and cross-format spot checks.
+ */
+class ViewProjection_Test extends TestBase {
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // A: baseline — no active view → all properties visible
+       
//------------------------------------------------------------------------------------------------------------------
+
+       public static class A {
+               public String id = "1";
+
+               @MarshalledProp(view = "summary")
+               public String name = "Alice";
+
+               @MarshalledProp(view = "detail")
+               public String description = "A person";
+
+               static A create() {
+                       return new A();
+               }
+       }
+
+       @Test void a01_noActiveView_allPropertiesVisible() {
+               assertJson("{description:'A person',id:'1',name:'Alice'}", 
A.create());
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // B: summary view — tagged summary + untagged
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test void b01_summaryView_serializer() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               assertSerialized(A.create(), s, "{id:'1',name:'Alice'}");
+       }
+
+       @Test void b02_summaryView_parser_outOfViewIgnored() {
+               var p = 
Json5Parser.DEFAULT.copy().activeView("summary").ignoreUnknownBeanProperties().build();
+               var x = p.parse("{id:'2',name:'Bob',description:'ignored'}", 
A.class);
+               assertEquals("2", x.id);
+               assertEquals("Bob", x.name);
+               assertEquals("A person", x.description); // unchanged — never 
set
+       }
+
+       @Test void b03_detailView_serializer() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("detail").build();
+               assertSerialized(A.create(), s, "{description:'A 
person',id:'1'}");
+       }
+
+       @Test void b04_unknownView_onlyUntaggedProperties() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("other").build();
+               assertSerialized(A.create(), s, "{id:'1'}");
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // C: multi-view union membership
+       
//------------------------------------------------------------------------------------------------------------------
+
+       public static class C {
+               public String id = "1";
+
+               @MarshalledProp(view = {"summary", "detail"})
+               public String name = "Alice";
+
+               @MarshalledProp(view = "detail")
+               public String description = "A person";
+
+               static C create() {
+                       return new C();
+               }
+       }
+
+       @Test void c01_summaryView_unionIncludesNameNotDescription() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               assertSerialized(C.create(), s, "{id:'1',name:'Alice'}");
+       }
+
+       @Test void c02_detailView_unionIncludesBoth() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("detail").build();
+               assertSerialized(C.create(), s, "{description:'A 
person',id:'1',name:'Alice'}");
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // D: disableDefaultViewInclusion — untagged properties excluded when 
view active
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test void d01_disableDefaultViewInclusion_summaryView() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").disableDefaultViewInclusion().build();
+               assertSerialized(A.create(), s, "{name:'Alice'}");
+       }
+
+       @Test void d02_disableDefaultViewInclusion_detailView() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("detail").disableDefaultViewInclusion().build();
+               assertSerialized(A.create(), s, "{description:'A person'}");
+       }
+
+       @Test void d03_disableDefaultViewInclusion_unknownView_nothingVisible() 
{
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("other").disableDefaultViewInclusion().build();
+               assertSerialized(A.create(), s, "{}");
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // E: per-session override — context sets default, session overrides 
per-call
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test void e01_perSessionOverride_overridesContextDefault() throws 
Exception {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+
+               // default from context: summary
+               assertEquals("{id:'1',name:'Alice'}", s.serialize(A.create()));
+
+               // per-call override to detail
+               assertEquals("{description:'A person',id:'1'}", 
s.createSession().activeView("detail").build().serialize(A.create()));
+
+               // per-call override to null → all properties
+               assertEquals("{description:'A person',id:'1',name:'Alice'}", 
s.createSession().activeView(null).build().serialize(A.create()));
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // F: precedence — @MarshalledIgnore overrides view
+       
//------------------------------------------------------------------------------------------------------------------
+
+       public static class F {
+               public String id = "1";
+
+               @BeanIgnore
+               @MarshalledProp(view = "summary")
+               public String ignored = "x";
+
+               static F create() {
+                       return new F();
+               }
+       }
+
+       @Test void f01_beanIgnore_precedenceOverView() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               assertSerialized(F.create(), s, "{id:'1'}");
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // G: precedence — readOnly/writeOnly compose with view
+       
//------------------------------------------------------------------------------------------------------------------
+
+       public static class G {
+               @BeanProp(ro = "true")
+               @MarshalledProp(view = "summary")
+               public String name = "Alice";
+
+               @BeanProp(wo = "true")
+               @MarshalledProp(view = "detail")
+               public String description = "A person";
+
+               static G create() {
+                       return new G();
+               }
+       }
+
+       @Test void g01_readOnlyPlusView_serializer_onlyNameVisible() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               assertSerialized(G.create(), s, "{name:'Alice'}");
+       }
+
+       @Test void g02_writeOnlyPlusView_serializer_notVisible() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("detail").build();
+               assertSerialized(G.create(), s, "{}");
+       }
+
+       @Test void g03_readOnlyPlusView_parser_nameIgnored_descriptionSet() {
+               var p = 
Json5Parser.DEFAULT.copy().activeView("detail").ignoreUnknownBeanProperties().build();
+               var x = p.parse("{name:'Bob',description:'New'}", G.class);
+               assertEquals("Alice", x.name);  // read-only: not written
+               assertEquals("New", x.description);  // in detail view and 
write-only
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // H: view via *Config / @ContextApply on unmodifiable class
+       
//------------------------------------------------------------------------------------------------------------------
+
+       public static class H {
+               public String id = "1";
+               public String name = "Alice";
+               public String description = "A person";
+
+               static H create() {
+                       return new H();
+               }
+       }
+
+       @MarshalledPropApply(on = "H.name", value = @MarshalledProp(view = 
"summary"))
+       @MarshalledPropApply(on = "H.description", value = @MarshalledProp(view 
= "detail"))
+       private static class HConfig {}
+
+       @Test void h01_configApply_summaryView() {
+               var s = 
Json5Serializer.DEFAULT.copy().applyAnnotations(HConfig.class).activeView("summary").build();
+               assertSerialized(H.create(), s, "{id:'1',name:'Alice'}");  // i 
before n alphabetically
+       }
+
+       @Test void h02_configApply_detailView() {
+               var s = 
Json5Serializer.DEFAULT.copy().applyAnnotations(HConfig.class).activeView("detail").build();
+               assertSerialized(H.create(), s, "{description:'A 
person',id:'1'}");
+       }
+
+       @Test void h03_configApply_parser_outOfView() {
+               var p = 
Json5Parser.DEFAULT.copy().applyAnnotations(HConfig.class).activeView("summary").ignoreUnknownBeanProperties().build();
+               var x = p.parse("{id:'2',name:'Bob',description:'ignored'}", 
H.class);
+               assertEquals("2", x.id);
+               assertEquals("Bob", x.name);
+               assertEquals("A person", x.description); // unchanged
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // I: cross-format — XML spot check
+       
//------------------------------------------------------------------------------------------------------------------
+
+       public static class I {
+               public String id = "1";
+
+               @MarshalledProp(view = "summary")
+               public String name = "Alice";
+
+               static I create() {
+                       return new I();
+               }
+       }
+
+       @Test void i01_xmlFormat_summaryView() {
+               var s = 
XmlSerializer.DEFAULT_NS_SQ.copy().activeView("summary").build();
+               var xml = s.serialize(I.create());
+               // id (untagged, always included) and name (in summary) should 
appear
+               assertTrue(xml.contains("1"), "Expected id value in XML: " + 
xml);
+               assertTrue(xml.contains("Alice"), "Expected name value in XML: 
" + xml);
+       }
+
+       @Test void i02_xmlFormat_detailView_nameNotVisible() {
+               var s = 
XmlSerializer.DEFAULT_NS_SQ.copy().activeView("detail").build();
+               var xml = s.serialize(I.create());
+               // name is only in summary view, not detail → should not appear
+               assertFalse(xml.contains("Alice"), "name should not appear in 
detail view: " + xml);
+               assertTrue(xml.contains("1"), "Expected id value in XML: " + 
xml);
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // J: cross-format — MsgPack binary spot check
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test void j01_msgpackFormat_summaryView_serializer() {
+               // MsgPack with summary view — only id (untagged) and name (in 
summary) should appear
+               var s = 
MsgPackSerializer.DEFAULT.copy().activeView("summary").build();
+               // Serialize to hex string and verify it's shorter than a full 
serialization (fewer properties)
+               var fullBytes = MsgPackSerializer.DEFAULT.serialize(A.create());
+               var summaryBytes = s.serialize(A.create());
+               // The summary view should produce fewer bytes (omits 
description)
+               assertNotEquals(fullBytes, summaryBytes);
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // K: view interacts with beanProperties* (intersection: view ∩ filter)
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test void k01_viewAndBeanPropertiesFilter_onlyUntaggedSurvivesBoth() {
+               // beanProperties restricts visible set to {id, name}
+               // view "detail" restricts to {id (untagged), description (in 
detail)}
+               // intersection: only id (untagged, in beanProperties) survives 
both filters
+               var s = Json5Serializer.DEFAULT.copy()
+                       .beanProperties(A.class, "id,name")
+                       .activeView("detail")
+                       .build();
+               assertSerialized(A.create(), s, "{id:'1'}");
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // L: parse-side — out-of-view property with 
ignoreUnknownBeanProperties=false throws
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test void l01_parseSide_outOfViewThrowsWhenIgnoreDisabled() {
+               var p = 
Json5Parser.DEFAULT.copy().activeView("summary").build();
+               assertThrows(Exception.class, () -> 
p.parse("{id:'1',description:'x'}", A.class));
+       }
+
+       @Test void l02_parseSide_outOfViewIgnoredWhenIgnoreEnabled() {
+               var p = 
Json5Parser.DEFAULT.copy().activeView("summary").ignoreUnknownBeanProperties().build();
+               assertDoesNotThrow(() -> p.parse("{id:'1',description:'x'}", 
A.class));
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // M: context-level default view is part of hashKey (different contexts 
cached separately)
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test void m01_differentActiveViews_differentContexts() {
+               var s1 = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               var s2 = 
Json5Serializer.DEFAULT.copy().activeView("detail").build();
+               var s3 = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               // same active view → same output (different instances, but 
same serialization result)
+               assertEquals(s1.serialize(A.create()), 
s3.serialize(A.create()));
+               // different active view → different output
+               assertNotEquals(s1.serialize(A.create()), 
s2.serialize(A.create()));
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // N: MarshalledIgnore annotation on a field with no view tag — never 
visible
+       
//------------------------------------------------------------------------------------------------------------------
+
+       public static class N {
+               public String id = "1";
+
+               @BeanIgnore
+               public String secret = "x";
+
+               static N create() {
+                       return new N();
+               }
+       }
+
+       @Test void n01_beanIgnoreNoView_neverVisible() {
+               assertJson("{id:'1'}", N.create());
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               assertSerialized(N.create(), s, "{id:'1'}");
+       }
+}
diff --git 
a/juneau-integration-tests/src/test/java/org/apache/juneau/ViewProjection_Test.java
 
b/juneau-integration-tests/src/test/java/org/apache/juneau/ViewProjection_Test.java
new file mode 100644
index 0000000000..df62c78d46
--- /dev/null
+++ 
b/juneau-integration-tests/src/test/java/org/apache/juneau/ViewProjection_Test.java
@@ -0,0 +1,294 @@
+/*
+ * 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;
+
+import static org.apache.juneau.TestUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+import org.apache.juneau.commons.bean.*;
+import org.apache.juneau.marshall.*;
+import org.apache.juneau.marshall.json5.*;
+import org.junit.jupiter.api.*;
+
+import static org.apache.juneau.marshall.MarshalledPropApplyAnnotation.create;
+
+/**
+ * Integration-suite coverage tests for view-based property projection.
+ *
+ * <p>
+ * These tests mirror the unit-level {@code ViewProjection_Test} (in 
juneau-core/juneau-marshall) and are
+ * placed here so their execution is captured by the integration-tests JaCoCo 
exec file, making coverage
+ * of {@link MarshalledProp#view()}, {@link 
MarshallingContext.Builder#activeView(String)},
+ * {@link MarshallingContext.Builder#disableDefaultViewInclusion()},
+ * {@link MarshallingSession#isPropertyInActiveView}, and
+ * {@code MarshalledPropertyPostProcessor.addViews()} visible to the coverage 
reporter.
+ */
+class ViewProjection_Test extends TestBase {
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // A: baseline — no active view → all properties visible
+       
//------------------------------------------------------------------------------------------------------------------
+
+       public static class A {
+               public String id = "1";
+
+               @MarshalledProp(view = "summary")
+               public String name = "Alice";
+
+               @MarshalledProp(view = "detail")
+               public String description = "A person";
+
+               static A create() {
+                       return new A();
+               }
+       }
+
+       @Test void a01_noActiveView_allPropertiesVisible() {
+               assertJson("{description:'A person',id:'1',name:'Alice'}", 
A.create());
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // B: summary / detail / unknown views — covers 
MarshallingContextable.activeView(),
+       //    MarshallingContext.Builder.activeView(), 
MarshallingSession.isPropertyInActiveView() non-null path,
+       //    and MarshalledPropertyPostProcessor.addViews() loop body.
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test void b01_summaryView_includesTaggedAndUntagged() {
+               // MarshallingContextable.Builder.activeView() at line 1684 and
+               // MarshallingContext.Builder.activeView() at line 2405 are 
exercised here.
+               // MarshallingSession.isPropertyInActiveView() non-null 
activeView path (lines 744-747)
+               // is exercised for: untagged 'id' (views==null → 
ctx.isDefaultViewInclusion()),
+               // 'name' tagged summary (views.contains → true), 'description' 
tagged detail (views.contains → false).
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               assertSerialized(A.create(), s, "{id:'1',name:'Alice'}");
+       }
+
+       @Test void b02_detailView_includesTaggedAndUntagged() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("detail").build();
+               assertSerialized(A.create(), s, "{description:'A 
person',id:'1'}");
+       }
+
+       @Test void b03_unknownView_onlyUntaggedProperties() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("other").build();
+               assertSerialized(A.create(), s, "{id:'1'}");
+       }
+
+       @Test void b04_activeView_null_resetToAll() {
+               // Explicitly passing null disables view filtering — same as no 
activeView.
+               var s = Json5Serializer.DEFAULT.copy().activeView(null).build();
+               assertSerialized(A.create(), s, "{description:'A 
person',id:'1',name:'Alice'}");
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // C: disableDefaultViewInclusion — covers 
MarshallingContextable.Builder.disableDefaultViewInclusion()
+       //    at line 1705 and 
MarshallingContext.Builder.disableDefaultViewInclusion() / 
defaultViewInclusion=false path.
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test void c01_disableDefaultViewInclusion_summaryView() {
+               // MarshallingContextable.Builder.disableDefaultViewInclusion() 
at line 1705 is exercised here.
+               // isDefaultViewInclusion() returns false → untagged 'id' 
excluded.
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").disableDefaultViewInclusion().build();
+               assertSerialized(A.create(), s, "{name:'Alice'}");
+       }
+
+       @Test void c02_disableDefaultViewInclusion_detailView() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("detail").disableDefaultViewInclusion().build();
+               assertSerialized(A.create(), s, "{description:'A person'}");
+       }
+
+       @Test void c03_disableDefaultViewInclusion_unknownView_nothingVisible() 
{
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("other").disableDefaultViewInclusion().build();
+               assertSerialized(A.create(), s, "{}");
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // D: multi-view union membership — covers addViews() 'acc non-null' 
branch (accumulator is reused
+       //    across multiple view names on the same property) and covers 
acc.add(v) with acc != null.
+       
//------------------------------------------------------------------------------------------------------------------
+
+       public static class D {
+               public String id = "1";
+
+               @MarshalledProp(view = {"summary", "detail"})
+               public String name = "Alice";
+
+               @MarshalledProp(view = "detail")
+               public String description = "A person";
+
+               static D create() {
+                       return new D();
+               }
+       }
+
+       @Test void d01_multiView_summaryViewIncludesName() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               assertSerialized(D.create(), s, "{id:'1',name:'Alice'}");
+       }
+
+       @Test void d02_multiView_detailViewIncludesBoth() {
+               // addViews() is called twice for 'name': once for "summary" 
(acc becomes non-null),
+               // once for "detail" (acc != null branch taken — adds to 
existing set).
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("detail").build();
+               assertSerialized(D.create(), s, "{description:'A 
person',id:'1',name:'Alice'}");
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // E: MarshalledPropAnnotation programmatic builder — covers 
MarshalledPropAnnotation.create(),
+       //    Builder.view(), Object.view(), Builder.build(), and Object 
constructor.
+       
//------------------------------------------------------------------------------------------------------------------
+
+       public static class E {
+               public String id = "1";
+               public String name = "Alice";
+               public String description = "A person";
+
+               static E create() {
+                       return new E();
+               }
+       }
+
+       @Test void e01_programmaticAnnotation_summaryView() {
+               // MarshalledPropAnnotation.create() at line 444, 
Builder.view() at line 285,
+               // Object.view() at line 431, and Builder.build() / Object 
constructor are all exercised here
+               // via 
MarshalledPropApplyAnnotation.Builder.value(MarshalledProp).
+               var applyName = 
create("ViewProjection_Test$E.name").value(MarshalledPropAnnotation.create().view("summary").build()).build();
+               var applyDesc = 
create("ViewProjection_Test$E.description").value(MarshalledPropAnnotation.create().view("detail").build()).build();
+               var s = Json5Serializer.DEFAULT.copy()
+                       .annotations(applyName, applyDesc)
+                       .activeView("summary")
+                       .build();
+               assertSerialized(E.create(), s, "{id:'1',name:'Alice'}");
+       }
+
+       @Test void e02_programmaticAnnotation_detailView() {
+               var applyName = 
create("ViewProjection_Test$E.name").value(MarshalledPropAnnotation.create().view("summary").build()).build();
+               var applyDesc = 
create("ViewProjection_Test$E.description").value(MarshalledPropAnnotation.create().view("detail").build()).build();
+               var s = Json5Serializer.DEFAULT.copy()
+                       .annotations(applyName, applyDesc)
+                       .activeView("detail")
+                       .build();
+               assertSerialized(E.create(), s, "{description:'A 
person',id:'1'}");
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // F: addViews() edge case — empty-string view name is silently ignored.
+       //    Covers the v.isEmpty() → T branch inside the addViews() for-loop.
+       
//------------------------------------------------------------------------------------------------------------------
+
+       public static class F {
+               public String id = "1";
+
+               @MarshalledProp(view = {"", "summary"})
+               public String name = "Alice";
+
+               static F create() {
+                       return new F();
+               }
+       }
+
+       @Test void f01_emptyStringViewName_ignored() {
+               // @MarshalledProp(view = {"", "summary"}) — the empty string 
is ignored by addViews(),
+               // exercising the v.isEmpty() → true branch (skips the empty 
entry, adds "summary").
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               assertSerialized(F.create(), s, "{id:'1',name:'Alice'}");
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // G: per-session override — context default overridden per-call via 
MarshallingSession.Builder.activeView().
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test void g01_perSessionOverride_overridesContextDefault() throws 
Exception {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+
+               // Default from context: summary view.
+               assertEquals("{id:'1',name:'Alice'}", s.serialize(A.create()));
+
+               // Per-call override to detail view.
+               assertEquals("{description:'A person',id:'1'}", 
s.createSession().activeView("detail").build().serialize(A.create()));
+
+               // Per-call override to null → all properties visible.
+               assertEquals("{description:'A person',id:'1',name:'Alice'}", 
s.createSession().activeView(null).build().serialize(A.create()));
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // H: parser-side view — out-of-view properties treated as unknown 
during parsing.
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test void h01_parseSide_summaryView_outOfViewIgnored() {
+               var p = 
Json5Parser.DEFAULT.copy().activeView("summary").ignoreUnknownBeanProperties().build();
+               var x = p.parse("{id:'2',name:'Bob',description:'ignored'}", 
A.class);
+               assertEquals("2", x.id);
+               assertEquals("Bob", x.name);
+               assertEquals("A person", x.description); // unchanged — 
out-of-view during parse
+       }
+
+       @Test void h02_parseSide_outOfViewThrowsWhenIgnoreDisabled() {
+               var p = 
Json5Parser.DEFAULT.copy().activeView("summary").build();
+               assertThrows(Exception.class, () -> 
p.parse("{id:'1',description:'x'}", A.class));
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // I: hashKey isolation — different activeView settings produce 
different contexts (are cached separately).
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test void i01_differentActiveViews_differentContexts() {
+               var s1 = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               var s2 = 
Json5Serializer.DEFAULT.copy().activeView("detail").build();
+               var s3 = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               // Same active view → same serialization result.
+               assertEquals(s1.serialize(A.create()), 
s3.serialize(A.create()));
+               // Different active view → different serialization result.
+               assertNotEquals(s1.serialize(A.create()), 
s2.serialize(A.create()));
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // I2: MarshallingSession.getActiveView() — covers the getter body 
(line 738 in MarshallingSession).
+       
//------------------------------------------------------------------------------------------------------------------
+
+       @Test void i02_getActiveView_returnsConfiguredValue() throws Exception {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               var session = (MarshallingSession) s.createSession().build();
+               assertEquals("summary", session.getActiveView());
+       }
+
+       @Test void i03_getActiveView_nullByDefault() throws Exception {
+               var s = Json5Serializer.DEFAULT.copy().build();
+               var session = (MarshallingSession) s.createSession().build();
+               assertNull(session.getActiveView());
+       }
+
+       
//------------------------------------------------------------------------------------------------------------------
+       // J: BeanIgnore precedence — @BeanIgnore overrides view membership.
+       
//------------------------------------------------------------------------------------------------------------------
+
+       public static class J {
+               public String id = "1";
+
+               @BeanIgnore
+               @MarshalledProp(view = "summary")
+               public String ignored = "x";
+
+               static J create() {
+                       return new J();
+               }
+       }
+
+       @Test void j01_beanIgnore_precedenceOverView() {
+               var s = 
Json5Serializer.DEFAULT.copy().activeView("summary").build();
+               assertSerialized(J.create(), s, "{id:'1'}");
+       }
+}
diff --git 
a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyServerComponent.java
 
b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyServerComponent.java
index 55f292ea9d..0cb615bb68 100644
--- 
a/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyServerComponent.java
+++ 
b/juneau-microservice/juneau-microservice-jetty/src/main/java/org/apache/juneau/microservice/jetty/JettyServerComponent.java
@@ -108,7 +108,7 @@ public class JettyServerComponent implements 
MicroserviceListener {
        Optional<String> serverPortEnv = opte();
 
        private static int[] parseIntArray(String csv) {
-               if (csv == null || csv.isEmpty())
+               if (e(csv))
                        return new int[0];
                var parts = csv.split(",");
                var out = new int[parts.length];
diff --git 
a/juneau-microservice/juneau-microservice-tomcat/src/main/java/org/apache/juneau/microservice/tomcat/TomcatServerComponent.java
 
b/juneau-microservice/juneau-microservice-tomcat/src/main/java/org/apache/juneau/microservice/tomcat/TomcatServerComponent.java
index 3e910be388..d7da247d65 100644
--- 
a/juneau-microservice/juneau-microservice-tomcat/src/main/java/org/apache/juneau/microservice/tomcat/TomcatServerComponent.java
+++ 
b/juneau-microservice/juneau-microservice-tomcat/src/main/java/org/apache/juneau/microservice/tomcat/TomcatServerComponent.java
@@ -117,7 +117,7 @@ public class TomcatServerComponent implements 
MicroserviceListener {
        Optional<String> serverPortEnv = opte();
 
        private static int[] parseIntArray(String csv) {
-               if (csv == null || csv.isEmpty())
+               if (e(csv))
                        return new int[0];
                var parts = csv.split(",");
                var out = new int[parts.length];
@@ -509,7 +509,7 @@ public class TomcatServerComponent implements 
MicroserviceListener {
        public URI getURI() {
                var cp = getContextPath();
                try {
-                       return new URI(getProtocol(), null, getHostName(), 
getPort(), (cp == null || cp.isEmpty()) ? null : cp, null, null);
+                       return new URI(getProtocol(), null, getHostName(), 
getPort(), e(cp) ? null : cp, null, null);
                } catch (URISyntaxException e) {
                        throw toRex(e);
                }
diff --git 
a/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java
 
b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java
index d630a4dbff..c39b9627f9 100755
--- 
a/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java
+++ 
b/juneau-microservice/juneau-microservice/src/main/java/org/apache/juneau/microservice/Microservice.java
@@ -145,7 +145,7 @@ public class Microservice implements ConfigEventListener {
                 */
                @Inject
                public void 
initWorkingDirFromEnv(@Value("${juneau.workingDir}") String workingDirEnv) {
-                       if (workingDir == null && workingDirEnv != null && 
!workingDirEnv.isEmpty())
+                       if (workingDir == null && ne(workingDirEnv))
                                workingDir = new File(workingDirEnv);
                }
 
diff --git 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/resource/HttpResourceBean.java
 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/resource/HttpResourceBean.java
index c5dad6c493..b5f1eb49c6 100644
--- 
a/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/resource/HttpResourceBean.java
+++ 
b/juneau-rest/juneau-rest-common/src/main/java/org/apache/juneau/http/resource/HttpResourceBean.java
@@ -134,7 +134,7 @@ public final class HttpResourceBean implements HttpResource 
{
         * @return A new instance. Never <jk>null</jk>.
         */
        public HttpResourceBean withHeaders(List<HttpHeader> toAdd) {
-               if (toAdd == null || toAdd.isEmpty())
+               if (e(toAdd))
                        return this;
                var newHeaders = new ArrayList<>(headers);
                for (var h : toAdd)
diff --git 
a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockServletRequest.java
 
b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockServletRequest.java
index c87911c602..8cd35bf84e 100644
--- 
a/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockServletRequest.java
+++ 
b/juneau-rest/juneau-rest-mock/src/main/java/org/apache/juneau/rest/mock/MockServletRequest.java
@@ -375,7 +375,7 @@ public class MockServletRequest implements 
HttpServletRequest {
        @Override /* Overridden from HttpServletRequest */
        public int getIntHeader(String name) {
                var s = getHeader(name);
-               return s == null || s.isEmpty() ? 0 : Integer.parseInt(s);
+               return e(s) ? 0 : Integer.parseInt(s);
        }
 
        @Override /* Overridden from HttpServletRequest */
diff --git 
a/juneau-rest/juneau-rest-server-metrics-micrometer/src/main/java/org/apache/juneau/rest/server/metrics/micrometer/MicrometerMetricsRecorder.java
 
b/juneau-rest/juneau-rest-server-metrics-micrometer/src/main/java/org/apache/juneau/rest/server/metrics/micrometer/MicrometerMetricsRecorder.java
index 5294285d3e..b8d49d23fb 100644
--- 
a/juneau-rest/juneau-rest-server-metrics-micrometer/src/main/java/org/apache/juneau/rest/server/metrics/micrometer/MicrometerMetricsRecorder.java
+++ 
b/juneau-rest/juneau-rest-server-metrics-micrometer/src/main/java/org/apache/juneau/rest/server/metrics/micrometer/MicrometerMetricsRecorder.java
@@ -159,13 +159,13 @@ public class MicrometerMetricsRecorder implements 
MetricsRecorder {
        })
        @Override /* MetricsRecorder */
        public void record(String opName, String httpMethod, String 
uriTemplate, int statusCode, Duration elapsed, Throwable error, String 
metricName, String metricTags) {
-               var effectiveName = (metricName != null && 
!metricName.isEmpty()) ? metricName : timerName;
+               var effectiveName = ne(metricName) ? metricName : timerName;
                var builder = Timer.builder(effectiveName)
                        .tag(TAG_METHOD, defaultIfBlank(httpMethod, ""))
                        .tag(TAG_URI, defaultIfBlank(uriTemplate, ""))
                        .tag(TAG_STATUS, Integer.toString(statusCode))
                        .tag(TAG_EXCEPTION, exceptionTag(error));
-               if (metricTags != null && !metricTags.isEmpty())
+               if (ne(metricTags))
                        for (var pair : metricTags.split(",")) {
                                var kv = pair.split("=", 2);
                                if (kv.length == 2)
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestOpContext.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestOpContext.java
index 8998e78ebf..a79959efb3 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestOpContext.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestOpContext.java
@@ -296,7 +296,7 @@ public class RestOpContext extends Context implements 
Comparable<RestOpContext>
                        return Charset.forName(v.get());
                if (isInherited(PROPERTY_defaultCharset)) {
                        var rv = 
restContext().mergeReplacedStringAttribute(PROPERTY_defaultCharset, null);
-                       if (rv != null && !rv.isEmpty())
+                       if (ne(rv))
                                return Charset.forName(rv);
                }
                return Charset.forName(defaultCharsetName);
@@ -558,7 +558,7 @@ public class RestOpContext extends Context implements 
Comparable<RestOpContext>
                var vr = varResolver();
                for (var ai : getRestOpAnnotations()) {
                        var v = httpMethodFromAnnotation(ai.inner(), vr);
-                       if (v != null && !v.isEmpty())
+                       if (ne(v))
                                return normalizeHttpMethod(v);
                }
                return normalizeHttpMethod(HttpUtils.detectHttpMethod(method(), 
true, "GET"));
@@ -627,7 +627,7 @@ public class RestOpContext extends Context implements 
Comparable<RestOpContext>
                        return parseLongWithSuffix(v.get());
                if (isInherited(PROPERTY_maxInput)) {
                        var rv = 
restContext().mergeReplacedStringAttribute(PROPERTY_maxInput, null);
-                       if (rv != null && !rv.isEmpty())
+                       if (ne(rv))
                                return parseLongWithSuffix(rv);
                }
                return parseLongWithSuffix(defaultMaxInputString);
@@ -1240,7 +1240,7 @@ public class RestOpContext extends Context implements 
Comparable<RestOpContext>
                        return "options";
                if (a instanceof RestOp r) {
                        var m = vr.resolve(r.method());
-                       if (m != null && !m.isEmpty())
+                       if (ne(m))
                                return m;
                        var s = vr.resolve(r.value());
                        if (s != null) {
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestRequest.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestRequest.java
index 0030bb3fa9..198615d41b 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestRequest.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestRequest.java
@@ -1714,7 +1714,7 @@ public class RestRequest extends 
HttpServletRequestWrapper {
         * @return This object.
         */
        public RestRequest setSerializerSessionProperties(Map<String,Object> 
values) {
-               if (values != null && !values.isEmpty()) {
+               if (ne(values)) {
                        if (serializerSessionProperties == null)
                                serializerSessionProperties = new 
LinkedHashMap<>();
                        serializerSessionProperties.putAll(values);
@@ -1729,7 +1729,7 @@ public class RestRequest extends 
HttpServletRequestWrapper {
         * @return This object.
         */
        public RestRequest setParserSessionProperties(Map<String,Object> 
values) {
-               if (values != null && !values.isEmpty()) {
+               if (ne(values)) {
                        if (parserSessionProperties == null)
                                parserSessionProperties = new LinkedHashMap<>();
                        parserSessionProperties.putAll(values);
@@ -1831,7 +1831,7 @@ public class RestRequest extends 
HttpServletRequestWrapper {
        private static Map<String,Object> 
mergeSessionMaps(Map<String,Object>...maps) {
                Map<String,Object> result = null;
                for (var map : maps) {
-                       if (map != null && !map.isEmpty()) {
+                       if (ne(map)) {
                                if (result == null)
                                        result = new LinkedHashMap<>(map);
                                else
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestResponse.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestResponse.java
index aae6d44c54..706267b92a 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestResponse.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/RestResponse.java
@@ -402,7 +402,7 @@ public class RestResponse extends 
HttpServletResponseWrapper {
                        var encoders = request.getOpContext().getEncoders();
 
                        var ae = 
request.getHeaderParam("Accept-Encoding").orElse(null);
-                       if (! (ae == null || ae.isEmpty())) {
+                       if (ne(ae)) {
                                var match = encoders.getEncoderMatch(ae);
                                if (match == null) {
                                        // Identity should always match unless 
"identity;q=0" or "*;q=0" is specified.
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/convention/VersionProvider.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/convention/VersionProvider.java
index d5df7a6aee..7fc7d3d708 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/convention/VersionProvider.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/convention/VersionProvider.java
@@ -341,12 +341,12 @@ public class VersionProvider {
 
                private static void ifNotEmpty(Map<String,String> attrs, String 
key, Consumer<String> sink) {
                        var v = attrs.get(key);
-                       if (v != null && !v.isEmpty())
+                       if (ne(v))
                                sink.accept(v);
                }
 
                private static void ifNotEmptyValue(String v, Consumer<String> 
sink) {
-                       if (v != null && !v.isEmpty())
+                       if (ne(v))
                                sink.accept(v);
                }
        }
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/httppart/RequestFormParamList.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/httppart/RequestFormParamList.java
index 1addc4d4e3..25b23c19fd 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/httppart/RequestFormParamList.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/httppart/RequestFormParamList.java
@@ -165,7 +165,7 @@ public class RequestFormParamList extends 
ArrayList<RequestFormParam> {
                        }
                } else {
                        c = req.getHttpServletRequest().getParts();
-                       if (c == null || c.isEmpty())
+                       if (e(c))
                                m = 
req.getHttpServletRequest().getParameterMap();
                }
 
diff --git 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/swagger/BasicSwaggerProviderSession.java
 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/swagger/BasicSwaggerProviderSession.java
index b8793fcf46..c5abbfcf83 100644
--- 
a/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/swagger/BasicSwaggerProviderSession.java
+++ 
b/juneau-rest/juneau-rest-server/src/main/java/org/apache/juneau/rest/server/swagger/BasicSwaggerProviderSession.java
@@ -163,11 +163,11 @@ public class BasicSwaggerProviderSession {
        }
 
        private static MarshalledList nullIfEmpty(MarshalledList l) {
-               return (l == null || l.isEmpty() ? null : l);
+               return e(l) ? null : l;
        }
 
        private static MarshalledMap nullIfEmpty(MarshalledMap m) {
-               return (m == null || m.isEmpty() ? null : m);
+               return e(m) ? null : m;
        }
 
        static String joinnl(String[]...s) {


Reply via email to