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 b9ec9884e4 Built-in support for Iterator/Stream objects with 
load-as-you-serialize
b9ec9884e4 is described below

commit b9ec9884e4b6e1aca266f82c453b2c526fd36604
Author: James Bognar <[email protected]>
AuthorDate: Sat Feb 28 07:46:21 2026 -0500

    Built-in support for Iterator/Stream objects with load-as-you-serialize
---
 .gitignore                                         |   1 +
 RELEASE-NOTES.txt                                  |  26 +++
 TODO.md                                            |   7 +-
 .../src/main/java/org/apache/juneau/ClassMeta.java |  53 ++++-
 .../apache/juneau/csv/CsvSerializerSession.java    |   3 +
 .../apache/juneau/html/HtmlSerializerSession.java  |   6 +
 .../apache/juneau/json/JsonSerializerSession.java  |  17 ++
 .../juneau/msgpack/MsgPackSerializerSession.java   |   3 +
 .../juneau/oapi/OpenApiSerializerSession.java      |   4 +
 .../juneau/serializer/SerializerSession.java       |  52 +++++
 .../java/org/apache/juneau/swap/DefaultSwaps.java  |   2 -
 .../org/apache/juneau/swaps/EnumerationSwap.java   |  51 -----
 .../java/org/apache/juneau/swaps/IteratorSwap.java |  51 -----
 .../apache/juneau/uon/UonSerializerSession.java    |  23 ++
 .../urlencoding/UrlEncodingSerializerSession.java  |  13 ++
 .../apache/juneau/xml/XmlSerializerSession.java    |  41 +++-
 .../org/apache/juneau/examples/rest/TestUtils.java |   3 -
 .../juneau/examples/rest/RequestEchoResource.java  |   7 -
 .../juneau/transforms/DefaultSwaps_Test.java       |   4 +-
 .../juneau/transforms/EnumerationSwapTest.java     |  40 ----
 .../apache/juneau/transforms/IteratorSwapTest.java |  42 ----
 .../transforms/StreamableSerializationTest.java    | 241 +++++++++++++++++++++
 22 files changed, 484 insertions(+), 206 deletions(-)

diff --git a/.gitignore b/.gitignore
index d2fb04dec0..d16c40f54f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -24,3 +24,4 @@ cursor-*
 scripts/release-history-*.json
 /SONARQUBE_ISSUES.txt
 /AISESSION.md
+/plans/
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index bd9239129e..c231a807f3 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -26,6 +26,32 @@ Release Notes - Juneau - Version 9.2.1 - YYYY-MM-DD
     * Bump Bump org.apache.maven.plugins:maven-compiler-plugin from 3.14.1 to 
3.15.0 #314.
     * Bump Bump jetty.version from 12.1.5 to 12.1.6 #312.
 
+<<<<<<< Updated upstream
+** New Features - Direct Iterator/Iterable/Stream/Enumeration Serialization
+
+    * Iterators, Iterables (non-Collection), Enumerations, and 
java.util.stream.Streams
+      are now serialized directly as arrays without requiring intermediate 
List materialization.
+    * Text-based serializers (JSON, XML, UON, URL Encoding, OpenAPI) write 
elements lazily
+      to the output one at a time via forEachStreamableEntry().
+    * Binary/layout-dependent serializers (MsgPack, HTML, CSV) collect to a 
List internally
+      since the format requires knowing the size or inspecting elements 
upfront.
+    * New ClassMeta methods: isIterator(), isIterable(), isStream(), 
isStreamable().
+    * New ClassMeta.Category enum values: ITERATOR, ITERABLE, STREAM.
+=======
+** New Features - Direct Iterator/Iterable/Stream Serialization
+
+    * Iterators, Iterables (non-Collection), Enumerations, and 
java.util.stream.Streams
+      are now serialized directly as arrays without requiring intermediate 
List materialization.
+    * For text-based serializers (JSON, XML, UON), elements are written lazily 
one at a
+      time for improved memory efficiency with large datasets.
+    * For binary/structured serializers (MsgPack, HTML, CSV), elements are 
collected to a
+      List internally since the format requires knowing the size or inspecting 
elements upfront.
+    * New ClassMeta methods: isIterator(), isIterable(), isStream(), 
isStreamable().
+>>>>>>> Stashed changes
+    * New SerializerSession methods: forEachStreamableEntry(), 
toListFromStreamable().
+    * IteratorSwap and EnumerationSwap classes have been removed; Iterator, 
Enumeration, Iterable,
+      and Stream types are now handled natively by all serializers.
+
 Release Notes - Juneau - Version 9.2.0 - 2025-12-30
 
 ** Changes
diff --git a/TODO.md b/TODO.md
index 98c2469549..5b6f7e5210 100644
--- a/TODO.md
+++ b/TODO.md
@@ -11,4 +11,9 @@
 - JsonSchemaGenerator should return JsonSchema beans.
 - Create full-fledged CSV serializer/parser support.
 - Add YAML serializer/parser support.
-- Update REST server API to use new BeanStore2.
\ No newline at end of file
+- Update REST server API to use new BeanStore2.
+- ClassInfo should have a findGetter(String propertyName) convenience method.
+- Make sure @Beanp("*") works on plain fields.
+- Add schema validation to beans during parsing.
+- Duration objects should be supported for serialization by default.
+
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
index 00b8ecdf15..42b94cb662 100644
--- a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
+++ b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/ClassMeta.java
@@ -32,6 +32,7 @@ import java.util.*;
 import java.util.List;
 import java.util.concurrent.*;
 import java.util.function.*;
+import java.util.stream.*;
 
 import org.apache.juneau.annotation.*;
 import org.apache.juneau.commons.collections.*;
@@ -112,7 +113,10 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                LIST(17),
                SET(18),
                DELEGATE(19),
-               BEAN(20);
+               BEAN(20),
+               ITERATOR(21),
+               ITERABLE(22),
+               STREAM(23);
 
                private final int mask;
 
@@ -215,6 +219,12 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                        } else if (isAssignableTo(List.class)) {
                                cat.set(LIST);
                        }
+               } else if (isAssignableTo(Iterable.class)) {
+                       cat.set(ITERABLE);
+               } else if (isAssignableTo(Iterator.class) || 
isAssignableTo(Enumeration.class)) {
+                       cat.set(ITERATOR);
+               } else if (isAssignableTo(BaseStream.class)) {
+                       cat.set(STREAM);
                } else if (isAssignableTo(Map.class)) {
                        cat.set(MAP);
                        if (isAssignableTo(BeanMap.class)) {
@@ -1019,6 +1029,33 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         */
        public boolean isInteger() { return isAny(Integer.class, int.class); }
 
+       /**
+        * Returns <jk>true</jk> if this class implements {@link Iterable} but 
is not a {@link Collection}.
+        *
+        * @return <jk>true</jk> if this class implements {@link Iterable} but 
is not a {@link Collection}.
+        * @since 9.2.1
+        */
+       public boolean isIterable() { return cat.is(ITERABLE); }
+
+       /**
+        * Returns <jk>true</jk> if this class implements {@link Iterator} or 
{@link Enumeration}.
+        *
+        * @return <jk>true</jk> if this class implements {@link Iterator} or 
{@link Enumeration}.
+        * @since 9.2.1
+        */
+       public boolean isIterator() { return cat.is(ITERATOR); }
+
+       /**
+        * Returns <jk>true</jk> if this class is an {@link Iterator}, {@link 
Iterable} (non-Collection), or {@link BaseStream}.
+        *
+        * <p>
+        * These types represent lazily-evaluated sequences that can be 
serialized as arrays.
+        *
+        * @return <jk>true</jk> if this class is a streamable type.
+        * @since 9.2.1
+        */
+       public boolean isStreamable() { return cat.is(ITERATOR) || 
cat.is(ITERABLE) || cat.is(STREAM); }
+
        /**
         * Returns <jk>true</jk> if this class extends from {@link List}.
         *
@@ -1114,6 +1151,14 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
         */
        public boolean isShort() { return isAny(Short.class, short.class); }
 
+       /**
+        * Returns <jk>true</jk> if this class is a subclass of {@link 
BaseStream} (includes {@link java.util.stream.Stream}).
+        *
+        * @return <jk>true</jk> if this class is a subclass of {@link 
BaseStream}.
+        * @since 9.2.1
+        */
+       public boolean isStream() { return cat.is(STREAM); }
+
        /**
         * Returns <jk>true</jk> if this class is a {@link String}.
         *
@@ -1361,8 +1406,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                        return null;
                if (cat.is(ARRAY)) {
                        return 
beanContext.getClassMeta(inner().getComponentType());
-               } else if (cat.is(COLLECTION) || is(Optional.class)) {
-                       // If this is a COLLECTION, see if it's parameterized 
(e.g. AddressBook extends LinkedList<Person>)
+               } else if (cat.is(COLLECTION) || cat.is(ITERABLE) || 
cat.is(ITERATOR) || cat.is(STREAM) || is(Optional.class)) {
                        var parameters = beanContext.findParameters(inner(), 
inner());
                        if (nn(parameters) && parameters.length == 1) {
                                return parameters[0];
@@ -1401,7 +1445,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                var ap = beanContext.getAnnotationProvider();
                ap.find(Swap.class, 
this).stream().map(AnnotationInfo::inner).forEach(x -> list.add(createSwap(x)));
                var ds = DefaultSwaps.find(this);
-               if (ds == null)
+               if (ds == null && !isStreamable()) {
                        ds = AutoObjectSwap.find(beanContext, this);
                if (ds == null)
                        ds = AutoNumberSwap.find(beanContext, this);
@@ -1409,6 +1453,7 @@ public class ClassMeta<T> extends ClassInfoTyped<T> {
                        ds = AutoMapSwap.find(beanContext, this);
                if (ds == null)
                        ds = AutoListSwap.find(beanContext, this);
+               }
 
                if (nn(ds))
                        list.add((ObjectSwap<T,?>)ds);
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
index 4ed4ebeba8..bf52621b77 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/csv/CsvSerializerSession.java
@@ -236,6 +236,9 @@ public class CsvSerializerSession extends 
WriterSerializerSession {
                                l = l((Object[])o);
                        } else if (cm.isCollection()) {
                                l = (Collection<?>)o;
+                       } else if (cm.isStreamable()) {
+                               // CSV must inspect first element for column 
headers, so materialization is unavoidable.
+                               l = toListFromStreamable(o, cm);
                        } else {
                                l = Collections.singleton(o);
                        }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
index fc59e1722f..72da37ad01 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/html/HtmlSerializerSession.java
@@ -991,6 +991,12 @@ public class HtmlSerializerSession extends 
XmlSerializerSession {
                                out.nlIf(! isRoot, xIndent + 1);
                                serializeCollection(out, o, sType, eType, name, 
pMeta);
 
+                       } else if (sType.isStreamable()) {
+                               // HTML must inspect elements to decide table 
vs. list layout (getTableHeaders), so materialization is unavoidable.
+                               out.nlIf(! isRoot, xIndent + 1);
+                               var list = toListFromStreamable(o, sType);
+                               serializeCollection(out, list, 
getClassMeta(List.class), eType, name, pMeta);
+
                        } else if (isUri(sType, pMeta, o)) {
                                String label = getAnchorText(pMeta, o);
                                out.oTag("a").attrUri("href", o).w('>');
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
index 03606154f0..0fe6b80c6b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/json/JsonSerializerSession.java
@@ -261,6 +261,21 @@ public class JsonSerializerSession extends 
WriterSerializerSession {
                return out;
        }
 
+       private SerializerWriter serializeStreamable(JsonWriter out, Object o, 
ClassMeta<?> sType, ClassMeta<?> type) throws SerializeException {
+               var elementType = type.getElementType();
+
+               out.w('[');
+               var addComma = Flag.create();
+               forEachStreamableEntry(o, sType, x -> {
+                       addComma.ifSet(() -> out.w(',').smi(indent)).set();
+                       out.cr(indent);
+                       serializeAnything(out, x, elementType, "<iterator>", 
null);
+               });
+
+               out.cre(indent - 1).w(']');
+               return out;
+       }
+
        
        @SuppressWarnings({
                "rawtypes", // Raw types necessary for generic collection/map 
serialization
@@ -434,6 +449,8 @@ public class JsonSerializerSession extends 
WriterSerializerSession {
                        serializeCollection(out, (Collection)o, eType);
                } else if (sType.isArray()) {
                        serializeCollection(out, toList(sType.inner(), o), 
eType);
+               } else if (sType.isStreamable()) {
+                       serializeStreamable(out, o, sType, eType);
                } else if (sType.isReader()) {
                        pipe((Reader)o, out, SerializerSession::handleThrown);
                } else if (sType.isInputStream()) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
index b5ffd72297..47cbaed3d0 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/msgpack/MsgPackSerializerSession.java
@@ -281,6 +281,9 @@ public class MsgPackSerializerSession extends 
OutputStreamSerializerSession {
                        out.appendBinary((byte[])o);
                } else if (sType.isArray()) {
                        serializeCollection(out, toList(sType.inner(), o), 
eType);
+               } else if (sType.isStreamable()) {
+                       // MsgPack protocol requires array size in header 
(startArray(size)), so materialization is unavoidable.
+                       serializeCollection(out, toListFromStreamable(o, 
sType), eType);
                } else if (sType.isReader()) {
                        pipe((Reader)o, out, SerializerSession::handleThrown);
                } else if (sType.isInputStream()) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerSession.java
index bf23d6c59c..687e3674b8 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/oapi/OpenApiSerializerSession.java
@@ -406,6 +406,8 @@ public class OpenApiSerializerSession extends 
UonSerializerSession {
                                                        
sb.append(serialize(partType, items, Array.get(value, i)));
                                        } else if (type.isCollection()) {
                                                
((Collection<?>)value).forEach(x -> sb.append(serialize(partType, items, x)));
+                                       } else if (type.isStreamable()) {
+                                               forEachStreamableEntry(value, 
type, x -> sb.append(serialize(partType, items, x)));
                                        } else if 
(vt.hasMutaterTo(String[].class)) {
                                                String[] ss = toType(value, 
CM_StringArray);
                                                for (var element : ss)
@@ -475,6 +477,8 @@ public class OpenApiSerializerSession extends 
UonSerializerSession {
                                l.add(toObject(partType, Array.get(o, i), 
items));
                } else if (type.isCollection()) {
                        ((Collection<?>)o).forEach(x -> 
l.add(toObject(partType, x, items)));
+               } else if (type.isStreamable()) {
+                       forEachStreamableEntry(o, type, x -> 
l.add(toObject(partType, x, items)));
                } else {
                        l.add(toObject(partType, o, items));
                }
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
index ea57a7eac8..2b1079ec20 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/serializer/SerializerSession.java
@@ -27,6 +27,7 @@ import java.lang.reflect.*;
 import java.text.*;
 import java.util.*;
 import java.util.function.*;
+import java.util.stream.*;
 import org.apache.juneau.*;
 import org.apache.juneau.commons.collections.FluentMap;
 import org.apache.juneau.commons.reflect.*;
@@ -431,6 +432,57 @@ public class SerializerSession extends BeanTraverseSession 
{
                        m.entrySet().forEach(consumer);
        }
 
+       /**
+        * Iterates over a streamable object (Iterator, Iterable, or Stream), 
consuming each entry.
+        *
+        * <p>
+        * For collections, delegates to {@link #forEachEntry(Collection, 
Consumer)} which supports sorting.
+        * For other streamable types, iterates lazily without materializing 
into a List.
+        *
+        * @param o The streamable object.
+        * @param type The class meta for the object.
+        * @param consumer The entry consumer.
+        * @since 9.2.1
+        */
+       @SuppressWarnings({
+               "rawtypes",  // Raw types necessary for generic streamable 
handling
+               "unchecked"  // Type erasure requires unchecked operations
+       })
+       public final void forEachStreamableEntry(Object o, ClassMeta<?> type, 
Consumer consumer) {
+               if (o == null)
+                       return;
+               if (type.isCollection()) {
+                       forEachEntry((Collection)o, consumer);
+               } else if (type.isIterable()) {
+                       ((Iterable)o).forEach(consumer);
+               } else if (type.isIterator()) {
+                       if (o instanceof Enumeration e)
+                               e.asIterator().forEachRemaining(consumer);
+                       else
+                               ((Iterator)o).forEachRemaining(consumer);
+               } else if (type.isStream()) {
+                       ((Stream)o).forEach(consumer);
+               }
+       }
+
+       /**
+        * Converts a streamable object (Iterator, Iterable, or Stream) to a 
List.
+        *
+        * <p>
+        * Used by serializers that need to know the collection size or inspect 
elements before serializing
+        * (e.g. MsgPack, HTML, CSV).
+        *
+        * @param o The streamable object.
+        * @param type The class meta for the object.
+        * @return A new list containing all elements.
+        * @since 9.2.1
+        */
+       public final List<?> toListFromStreamable(Object o, ClassMeta<?> type) {
+               var list = new ArrayList<>();
+               forEachStreamableEntry(o, type, list::add);
+               return list;
+       }
+
        /**
         * Returns the listener associated with this session.
         *
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swap/DefaultSwaps.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swap/DefaultSwaps.java
index bbcd132667..e223c20d0b 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swap/DefaultSwaps.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swap/DefaultSwaps.java
@@ -46,8 +46,6 @@ public class DefaultSwaps {
 
        private static final Map<Class<?>,ObjectSwap<?,?>> SWAPS = new 
ConcurrentHashMap<>();
        static {
-               SWAPS.put(Enumeration.class, new EnumerationSwap());
-               SWAPS.put(Iterator.class, new IteratorSwap());
                SWAPS.put(Locale.class, new LocaleSwap());
                SWAPS.put(Class.class, new ClassSwap());
                SWAPS.put(Calendar.class, new 
TemporalCalendarSwap.IsoOffsetDateTime());
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swaps/EnumerationSwap.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swaps/EnumerationSwap.java
deleted file mode 100644
index b07011ebe3..0000000000
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swaps/EnumerationSwap.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.swaps;
-
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.swap.*;
-
-/**
- * Transforms {@link Enumeration Enumerations} to {@code List<Object>} objects.
- *
- * <p>
- * This is a one-way transform, since {@code Enumerations} cannot be 
reconstituted.
- *
- * <h5 class='section'>See Also:</h5><ul>
- *     <li class='link'><a class="doclink" 
href="https://juneau.apache.org/docs/topics/SwapBasics";>Swap Basics</a>
-
- * </ul>
- */
-@SuppressWarnings({
-       "unchecked", // Type erasure requires unchecked casts in ObjectSwap 
operations
-       "rawtypes", // Raw types necessary for ObjectSwap implementation
-})
-public class EnumerationSwap extends ObjectSwap<Enumeration,List> {
-
-       /**
-        * Converts the specified {@link Enumeration} to a {@link List}.
-        */
-       @Override /* Overridden from ObjectSwap */
-       public List swap(BeanSession session, Enumeration o) {
-               var l = new LinkedList();
-               while (o.hasMoreElements())
-                       l.add(o.nextElement());
-               return l;
-       }
-}
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swaps/IteratorSwap.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swaps/IteratorSwap.java
deleted file mode 100644
index 641b1b8002..0000000000
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/swaps/IteratorSwap.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.swaps;
-
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.swap.*;
-
-/**
- * Transforms {@link Iterator Iterators} to {@code List<Object>} objects.
- *
- * <p>
- * This is a one-way transform, since {@code Iterators} cannot be 
reconstituted.
- *
- * <h5 class='section'>See Also:</h5><ul>
- *     <li class='link'><a class="doclink" 
href="https://juneau.apache.org/docs/topics/SwapBasics";>Swap Basics</a>
-
- * </ul>
- */
-@SuppressWarnings({
-       "unchecked", // Type erasure requires unchecked casts in ObjectSwap 
operations
-       "rawtypes", // Raw types necessary for ObjectSwap implementation
-})
-public class IteratorSwap extends ObjectSwap<Iterator,List> {
-
-       /**
-        * Converts the specified {@link Iterator} to a {@link List}.
-        */
-       @Override /* Overridden from ObjectSwap */
-       public List swap(BeanSession session, Iterator o) {
-               var l = new LinkedList();
-               while (o.hasNext())
-                       l.add(o.next());
-               return l;
-       }
-}
\ No newline at end of file
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
index 50d5c0f81a..fc3cd01be3 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/uon/UonSerializerSession.java
@@ -302,6 +302,27 @@ public class UonSerializerSession extends 
WriterSerializerSession implements Htt
                return out;
        }
 
+       private SerializerWriter serializeStreamable(UonWriter out, Object o, 
ClassMeta<?> sType, ClassMeta<?> type) throws SerializeException {
+
+               var elementType = type.getElementType();
+
+               if (! plainTextParams)
+                       out.append('@').append('(');
+
+               var addComma = Flag.create();
+               forEachStreamableEntry(o, sType, x -> {
+                       addComma.ifSet(() -> out.append(',')).set();
+                       out.cr(indent);
+                       serializeAnything(out, x, elementType, "<iterator>", 
null);
+               });
+
+               addComma.ifSet(() -> out.cre(indent - 1));
+               if (! plainTextParams)
+                       out.append(')');
+
+               return out;
+       }
+
        @SuppressWarnings({
                "rawtypes", // Raw types necessary for generic collection/map 
serialization
                "unchecked", // Type erasure requires unchecked casts in 
collection/map serialization
@@ -475,6 +496,8 @@ public class UonSerializerSession extends 
WriterSerializerSession implements Htt
                        serializeCollection(out, (Collection)o, eType);
                } else if (sType.isArray()) {
                        serializeCollection(out, toList(sType.inner(), o), 
eType);
+               } else if (sType.isStreamable()) {
+                       serializeStreamable(out, o, sType, eType);
                } else if (sType.isReader()) {
                        pipe((Reader)o, out, SerializerSession::handleThrown);
                } else if (sType.isInputStream()) {
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
index 6cd622ac49..fd89a59fec 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/urlencoding/UrlEncodingSerializerSession.java
@@ -266,6 +266,8 @@ public class UrlEncodingSerializerSession extends 
UonSerializerSession {
                } else if (sType.isCollection() || sType.isArray()) {
                        var m = sType.isCollection() ? 
getCollectionMap((Collection)o) : getCollectionMap(o);
                        serializeCollectionMap(out, m, getClassMeta(Map.class, 
Integer.class, Object.class));
+               } else if (sType.isStreamable()) {
+                       serializeStreamableAsCollectionMap(out, o, sType);
                } else if (sType.isReader()) {
                        pipe((Reader)o, out);
                } else if (sType.isInputStream()) {
@@ -349,6 +351,17 @@ public class UrlEncodingSerializerSession extends 
UonSerializerSession {
                return out;
        }
 
+       private SerializerWriter serializeStreamableAsCollectionMap(UonWriter 
out, Object o, ClassMeta<?> sType) throws SerializeException {
+               var addAmp = Flag.create();
+               var i = IntegerValue.create();
+               forEachStreamableEntry(o, sType, v -> {
+                       addAmp.ifSet(() -> out.cr(indent).append('&')).set();
+                       out.append(i.getAndIncrement()).append('=');
+                       super.serializeAnything(out, v, null, null, null);
+               });
+               return out;
+       }
+
        @SuppressWarnings({
                "java:S1213" // Method name matches private method in parent 
class by design for override behavior
        })
diff --git 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
index 5402c4b613..bf132d8152 100644
--- 
a/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
+++ 
b/juneau-core/juneau-marshall/src/main/java/org/apache/juneau/xml/XmlSerializerSession.java
@@ -556,6 +556,35 @@ public class XmlSerializerSession extends 
WriterSerializerSession {
                return out;
        }
 
+       private XmlWriter serializeStreamable(XmlWriter out, Object in, 
ClassMeta<?> sType, ClassMeta<?> eType, BeanPropertyMeta ppMeta, boolean 
isMixed) throws SerializeException {
+
+               var eeType = eType.getElementType();
+
+               var eName = Value.<String>empty();
+               var eNs = Value.<Namespace>empty();
+
+               if (nn(ppMeta)) {
+                       XmlBeanPropertyMeta bpXml = 
getXmlBeanPropertyMeta(ppMeta);
+                       eName.set(bpXml.getChildName());
+                       eNs.set(bpXml.getNamespace());
+               }
+
+               var previousWasTextNode = Value.of(false);
+
+               forEachStreamableEntry(in, sType, x -> {
+                       var currentIsTextNode = isTextNode(x);
+
+                       if (isTrue(previousWasTextNode.get()) && 
currentIsTextNode && nn(textNodeDelimiter) && ! textNodeDelimiter.isEmpty()) {
+                               out.append(textNodeDelimiter);
+                       }
+
+                       serializeAnything(out, x, eeType, null, eName.get(), 
eNs.get(), false, XmlFormat.DEFAULT, isMixed, false, null);
+                       previousWasTextNode.set(currentIsTextNode);
+               });
+
+               return out;
+       }
+
        private ContentResult serializeMap(XmlWriter out, Map m, ClassMeta<?> 
sType, ClassMeta<?> eKeyType, ClassMeta<?> eValueType, boolean isMixed) throws 
SerializeException {
 
                var keyType = eKeyType == null ? sType.getKeyType() : eKeyType;
@@ -831,8 +860,8 @@ public class XmlSerializerSession extends 
WriterSerializerSession {
                                isExpectedType = aType.isNumber();
                        else if (eType.isMap())
                                isExpectedType = aType.isMap();
-                       else if (eType.isCollectionOrArray())
-                               isExpectedType = aType.isCollectionOrArray();
+                       else if (eType.isCollectionOrArray() || 
eType.isStreamable())
+                               isExpectedType = aType.isCollectionOrArray() || 
aType.isStreamable();
                        else
                                isExpectedType = false;
                }
@@ -864,7 +893,7 @@ public class XmlSerializerSession extends 
WriterSerializerSession {
                } else if (sType.isMapOrBean()) {
                        isCollapsed = getXmlClassMeta(sType).getFormat() == 
COLLAPSED;
                        type = OBJECT;
-               } else if (sType.isCollectionOrArray()) {
+               } else if (sType.isCollectionOrArray() || sType.isStreamable()) 
{
                        isCollapsed = (format == COLLAPSED && ! 
addNamespaceUris);
                        type = ARRAY;
                } else {
@@ -980,6 +1009,12 @@ public class XmlSerializerSession extends 
WriterSerializerSession {
                                serializeCollection(out, o, sType, eType, 
pMeta, isMixedOrText);
                                if (isCollapsed)
                                        indent++;
+                       } else if (sType.isStreamable()) {
+                               if (isCollapsed)
+                                       indent--;
+                               serializeStreamable(out, o, sType, eType, 
pMeta, isMixedOrText);
+                               if (isCollapsed)
+                                       indent++;
                        } else if (sType.isReader()) {
                                pipe((Reader)o, out, 
SerializerSession::handleThrown);
                        } else if (sType.isInputStream()) {
diff --git 
a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/TestUtils.java
 
b/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/TestUtils.java
index 63857c276d..24f65fdb63 100644
--- 
a/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/TestUtils.java
+++ 
b/juneau-examples/juneau-examples-rest-jetty-ftest/src/test/java/org/apache/juneau/examples/rest/TestUtils.java
@@ -24,7 +24,6 @@ import java.util.regex.*;
 
 import org.apache.juneau.json.*;
 import org.apache.juneau.serializer.*;
-import org.apache.juneau.swaps.*;
 import org.apache.juneau.xml.*;
 import org.junit.*;
 
@@ -45,12 +44,10 @@ public class TestUtils {
 
        private static JsonSerializer js2 = JsonSerializer.create()
                .json5()
-               .swaps(IteratorSwap.class, EnumerationSwap.class)
                .build();
 
        private static JsonSerializer js3 = JsonSerializer.create()
                .json5()
-               .swaps(IteratorSwap.class, EnumerationSwap.class)
                .sortProperties()
                .build();
        // @formatter:on
diff --git 
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
 
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
index 1099b8a2f2..46a5f06e2f 100644
--- 
a/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
+++ 
b/juneau-examples/juneau-examples-rest/src/main/java/org/apache/juneau/examples/rest/RequestEchoResource.java
@@ -25,7 +25,6 @@ import org.apache.juneau.rest.converter.*;
 import org.apache.juneau.rest.servlet.*;
 import org.apache.juneau.rest.widget.*;
 import org.apache.juneau.serializer.annotation.*;
-import org.apache.juneau.swaps.*;
 
 import jakarta.servlet.*;
 import jakarta.servlet.http.*;
@@ -65,12 +64,6 @@ import jakarta.servlet.http.*;
        },
        nowrap="false"
 )
-@BeanConfig(
-       swaps={
-               // Add a special filter for Enumerations
-               EnumerationSwap.class
-       }
-)
 @SerializerConfig(
        maxDepth="5",
        detectRecursions="true"
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/transforms/DefaultSwaps_Test.java
 
b/juneau-utest/src/test/java/org/apache/juneau/transforms/DefaultSwaps_Test.java
index 1c1b43ea8f..1c8fd0da76 100644
--- 
a/juneau-utest/src/test/java/org/apache/juneau/transforms/DefaultSwaps_Test.java
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/transforms/DefaultSwaps_Test.java
@@ -68,7 +68,7 @@ class DefaultSwaps_Test extends TestBase {
        }
 
        
//------------------------------------------------------------------------------------------------------------------
-       //      POJO_SWAPS.put(Enumeration.class, new EnumerationSwap())
+       //      Enumeration - natively serialized as array
        
//------------------------------------------------------------------------------------------------------------------
        private static final Vector<String> A = new Vector<>();
        static {
@@ -138,7 +138,7 @@ class DefaultSwaps_Test extends TestBase {
        }
 
        
//------------------------------------------------------------------------------------------------------------------
-       //      POJO_SWAPS.put(Iterator.class, new IteratorSwap())
+       //      Iterator - natively serialized as array
        
//------------------------------------------------------------------------------------------------------------------
        private static final List<String> B = l("foo","bar");
 
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/transforms/EnumerationSwapTest.java
 
b/juneau-utest/src/test/java/org/apache/juneau/transforms/EnumerationSwapTest.java
deleted file mode 100755
index e4382de8c2..0000000000
--- 
a/juneau-utest/src/test/java/org/apache/juneau/transforms/EnumerationSwapTest.java
+++ /dev/null
@@ -1,40 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.transforms;
-
-import static org.apache.juneau.commons.utils.CollectionUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.json.*;
-import org.apache.juneau.swaps.*;
-import org.junit.jupiter.api.*;
-
-class EnumerationSwapTest extends TestBase {
-
-       
//====================================================================================================
-       // test
-       
//====================================================================================================
-       @Test void a01_test() throws Exception {
-               var s = 
JsonSerializer.create().json5().swaps(EnumerationSwap.class).build();
-               var v = new Vector<>(l(a("foo","bar","baz")));
-               var e = v.elements();
-               assertEquals("['foo','bar','baz']", s.serialize(e));
-       }
-}
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/transforms/IteratorSwapTest.java 
b/juneau-utest/src/test/java/org/apache/juneau/transforms/IteratorSwapTest.java
deleted file mode 100755
index f987a5e133..0000000000
--- 
a/juneau-utest/src/test/java/org/apache/juneau/transforms/IteratorSwapTest.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.apache.juneau.transforms;
-
-import static org.apache.juneau.commons.utils.CollectionUtils.*;
-import static org.junit.jupiter.api.Assertions.*;
-
-import java.util.*;
-
-import org.apache.juneau.*;
-import org.apache.juneau.json.*;
-import org.apache.juneau.swaps.*;
-import org.junit.jupiter.api.*;
-
-class IteratorSwapTest extends TestBase {
-
-       
//====================================================================================================
-       // test
-       
//====================================================================================================
-       @Test void a01_test() throws Exception {
-               var s = 
JsonSerializer.create().json5().swaps(IteratorSwap.class).build();
-
-               // Iterators
-               var l = new ArrayList<>(l(a("foo","bar","baz")));
-               var i = l.iterator();
-               assertEquals("['foo','bar','baz']", s.serialize(i));
-       }
-}
\ No newline at end of file
diff --git 
a/juneau-utest/src/test/java/org/apache/juneau/transforms/StreamableSerializationTest.java
 
b/juneau-utest/src/test/java/org/apache/juneau/transforms/StreamableSerializationTest.java
new file mode 100644
index 0000000000..704b9f2b7a
--- /dev/null
+++ 
b/juneau-utest/src/test/java/org/apache/juneau/transforms/StreamableSerializationTest.java
@@ -0,0 +1,241 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.juneau.transforms;
+
+import static org.junit.jupiter.api.Assertions.*;
+
+import java.util.*;
+import java.util.stream.*;
+
+import org.apache.juneau.*;
+import org.apache.juneau.csv.*;
+import org.apache.juneau.html.*;
+import org.apache.juneau.json.*;
+import org.apache.juneau.msgpack.*;
+import org.apache.juneau.uon.*;
+import org.apache.juneau.xml.*;
+import org.junit.jupiter.api.*;
+
+class StreamableSerializationTest extends TestBase {
+
+       static final JsonSerializer JSON = 
JsonSerializer.create().json5().build();
+       static final XmlSerializer XML = 
XmlSerializer.create().sq().ns().build();
+       static final UonSerializer UON = UonSerializer.DEFAULT;
+       static final HtmlSerializer HTML = HtmlSerializer.create().sq().build();
+       static final MsgPackSerializer MSGPACK = MsgPackSerializer.DEFAULT;
+       static final CsvSerializer CSV = CsvSerializer.DEFAULT;
+
+       
//====================================================================================================
+       // Iterator serialization with JSON (lazy path)
+       
//====================================================================================================
+       @Test void a01_iteratorWithJson() throws Exception {
+               var i = List.of("foo", "bar", "baz").iterator();
+               assertEquals("['foo','bar','baz']", JSON.serialize(i));
+       }
+
+       
//====================================================================================================
+       // Iterable (non-Collection) serialization with JSON
+       
//====================================================================================================
+       @Test void a02_iterableWithJson() throws Exception {
+               Iterable<String> iterable = () -> List.of("foo", "bar", 
"baz").iterator();
+               assertEquals("['foo','bar','baz']", JSON.serialize(iterable));
+       }
+
+       
//====================================================================================================
+       // Stream serialization with JSON
+       
//====================================================================================================
+       @Test void a03_streamWithJson() throws Exception {
+               var stream = Stream.of("foo", "bar", "baz");
+               assertEquals("['foo','bar','baz']", JSON.serialize(stream));
+       }
+
+       
//====================================================================================================
+       // Iterator with XML serializer
+       
//====================================================================================================
+       @Test void a04_iteratorWithXml() throws Exception {
+               var i = List.of("foo", "bar", "baz").iterator();
+               var result = XML.serialize(i);
+               assertTrue(result.contains("foo"), "XML output should contain 
'foo': " + result);
+               assertTrue(result.contains("bar"), "XML output should contain 
'bar': " + result);
+               assertTrue(result.contains("baz"), "XML output should contain 
'baz': " + result);
+       }
+
+       
//====================================================================================================
+       // Iterable with XML serializer
+       
//====================================================================================================
+       @Test void a05_iterableWithXml() throws Exception {
+               Iterable<String> iterable = () -> List.of("foo", "bar", 
"baz").iterator();
+               var result = XML.serialize(iterable);
+               assertTrue(result.contains("foo"), "XML output should contain 
'foo': " + result);
+               assertTrue(result.contains("bar"), "XML output should contain 
'bar': " + result);
+       }
+
+       
//====================================================================================================
+       // Stream with XML serializer
+       
//====================================================================================================
+       @Test void a06_streamWithXml() throws Exception {
+               var stream = Stream.of("foo", "bar", "baz");
+               var result = XML.serialize(stream);
+               assertTrue(result.contains("foo"), "XML output should contain 
'foo': " + result);
+               assertTrue(result.contains("baz"), "XML output should contain 
'baz': " + result);
+       }
+
+       
//====================================================================================================
+       // Iterator with UON serializer
+       
//====================================================================================================
+       @Test void a07_iteratorWithUon() throws Exception {
+               var i = List.of("foo", "bar", "baz").iterator();
+               assertEquals("@(foo,bar,baz)", UON.serialize(i));
+       }
+
+       
//====================================================================================================
+       // Iterator with MsgPack serializer (materialized path)
+       
//====================================================================================================
+       @Test void a08_iteratorWithMsgPack() throws Exception {
+               var i = List.of("foo", "bar", "baz").iterator();
+               var result = MSGPACK.serialize(i);
+               assertNotNull(result);
+               assertTrue(result.length > 0, "MsgPack output should not be 
empty");
+       }
+
+       
//====================================================================================================
+       // Iterator with HTML serializer (materialized path)
+       
//====================================================================================================
+       @Test void a09_iteratorWithHtml() throws Exception {
+               var i = List.of("foo", "bar", "baz").iterator();
+               var result = HTML.serialize(i);
+               assertTrue(result.contains("foo"), "HTML output should contain 
'foo': " + result);
+               assertTrue(result.contains("bar"), "HTML output should contain 
'bar': " + result);
+               assertTrue(result.contains("baz"), "HTML output should contain 
'baz': " + result);
+       }
+
+       
//====================================================================================================
+       // Stream with HTML serializer
+       
//====================================================================================================
+       @Test void a10_streamWithHtml() throws Exception {
+               var stream = Stream.of("foo", "bar", "baz");
+               var result = HTML.serialize(stream);
+               assertTrue(result.contains("foo"), "HTML output should contain 
'foo': " + result);
+               assertTrue(result.contains("baz"), "HTML output should contain 
'baz': " + result);
+       }
+
+       
//====================================================================================================
+       // Iterator with CSV serializer
+       
//====================================================================================================
+       @Test void a11_iteratorWithCsv() throws Exception {
+               var i = List.of("foo", "bar", "baz").iterator();
+               var result = CSV.serialize(i);
+               assertTrue(result.contains("foo"), "CSV output should contain 
'foo': " + result);
+               assertTrue(result.contains("bar"), "CSV output should contain 
'bar': " + result);
+       }
+
+       
//====================================================================================================
+       // Empty Iterator edge case
+       
//====================================================================================================
+       @Test void a12_emptyIterator() throws Exception {
+               var i = Collections.emptyIterator();
+               assertEquals("[]", JSON.serialize(i));
+       }
+
+       
//====================================================================================================
+       // Empty Stream edge case
+       
//====================================================================================================
+       @Test void a13_emptyStream() throws Exception {
+               var stream = Stream.empty();
+               assertEquals("[]", JSON.serialize(stream));
+       }
+
+       
//====================================================================================================
+       // Numeric Iterator
+       
//====================================================================================================
+       @Test void a14_numericIterator() throws Exception {
+               var i = List.of(1, 2, 3).iterator();
+               assertEquals("[1,2,3]", JSON.serialize(i));
+       }
+
+       
//====================================================================================================
+       // Iterable with UON serializer
+       
//====================================================================================================
+       @Test void a15_iterableWithUon() throws Exception {
+               Iterable<String> iterable = () -> List.of("foo", "bar", 
"baz").iterator();
+               assertEquals("@(foo,bar,baz)", UON.serialize(iterable));
+       }
+
+       
//====================================================================================================
+       // Stream with UON serializer
+       
//====================================================================================================
+       @Test void a16_streamWithUon() throws Exception {
+               var stream = Stream.of("foo", "bar", "baz");
+               assertEquals("@(foo,bar,baz)", UON.serialize(stream));
+       }
+
+       
//====================================================================================================
+       // Enumeration serialization (backward compat via native support)
+       
//====================================================================================================
+       @Test void a17_enumerationWithJson() throws Exception {
+               var v = new Vector<>(List.of("foo", "bar", "baz"));
+               var e = v.elements();
+               var result = JSON.serialize(e);
+               assertEquals("['foo','bar','baz']", result);
+       }
+
+       
//====================================================================================================
+       // Stream with MsgPack serializer (materialized path)
+       
//====================================================================================================
+       @Test void a19_streamWithMsgPack() throws Exception {
+               var stream = Stream.of("foo", "bar", "baz");
+               var result = MSGPACK.serialize(stream);
+               assertNotNull(result);
+               assertTrue(result.length > 0, "MsgPack output should not be 
empty");
+       }
+
+       
//====================================================================================================
+       // Iterable with MsgPack serializer (materialized path)
+       
//====================================================================================================
+       @Test void a20_iterableWithMsgPack() throws Exception {
+               Iterable<String> iterable = () -> List.of("foo", "bar", 
"baz").iterator();
+               var result = MSGPACK.serialize(iterable);
+               assertNotNull(result);
+               assertTrue(result.length > 0, "MsgPack output should not be 
empty");
+       }
+
+       
//====================================================================================================
+       // Mixed-type Iterator
+       
//====================================================================================================
+       @Test void a21_mixedTypeIterator() throws Exception {
+               var i = List.<Object>of("foo", 123, true).iterator();
+               assertEquals("['foo',123,true]", JSON.serialize(i));
+       }
+
+       
//====================================================================================================
+       // Iterable with CSV serializer
+       
//====================================================================================================
+       @Test void a22_iterableWithCsv() throws Exception {
+               Iterable<String> iterable = () -> List.of("foo", "bar", 
"baz").iterator();
+               var result = CSV.serialize(iterable);
+               assertTrue(result.contains("foo"), "CSV output should contain 
'foo': " + result);
+       }
+
+       
//====================================================================================================
+       // Stream with CSV serializer
+       
//====================================================================================================
+       @Test void a23_streamWithCsv() throws Exception {
+               var stream = Stream.of("foo", "bar", "baz");
+               var result = CSV.serialize(stream);
+               assertTrue(result.contains("foo"), "CSV output should contain 
'foo': " + result);
+       }
+}

Reply via email to