This is an automated email from the ASF dual-hosted git repository.

jamesbognar pushed a commit to branch docs
in repository https://gitbox.apache.org/repos/asf/juneau.git


The following commit(s) were added to refs/heads/docs by this push:
     new aaadee212b TODO-248: Document stream-only marshaller serialize/parse 
I/O (drop File/StringBuilder)
aaadee212b is described below

commit aaadee212be1908a0a9118b3a97e59bb9e0e8a21
Author: James Bognar <[email protected]>
AuthorDate: Thu Jul 16 10:14:32 2026 -0400

    TODO-248: Document stream-only marshaller serialize/parse I/O (drop 
File/StringBuilder)
    
    10.0.0 breaking-change release note + migration guide entry: 
serialize/parse no
    longer accept File/StringBuilder; show Files.newBufferedReader/Writer and
    StringWriter wrap-it-yourself migration. Update Marshallers + TokenStreaming
    topics for the narrowed stream-only contract.
    
    Co-authored-by: Cursor <[email protected]>
---
 pages/release-notes/10.0.0.md           | 27 +++++++++++++++++++++++++++
 pages/topics/03.01.Marshallers.md       |  2 +-
 pages/topics/03.47.02.TokenStreaming.md | 11 +++++++----
 pages/topics/27.V10MigrationGuide.md    | 26 +++++++++++++++++++++++++-
 4 files changed, 60 insertions(+), 6 deletions(-)

diff --git a/pages/release-notes/10.0.0.md b/pages/release-notes/10.0.0.md
index 3f0c862c24..7fadb3145a 100644
--- a/pages/release-notes/10.0.0.md
+++ b/pages/release-notes/10.0.0.md
@@ -628,6 +628,33 @@ _TBD — to be filled in as development continues._
   - **i18n unaffected:** `Messages.getString(key, args)` (resource-bundle 
i18n) and `LogRecord.getMessage()` (logging) continue to render 
MessageFormat-style `.properties`/log patterns — they now route through `mf()` 
internally, so `{0}`-style entries in your resource bundles keep working 
exactly as before. Juneau's `Logger` MessageFormat-style logging is likewise 
unchanged.
   - The dual-syntax `StringFormat` engine still exists and remains directly 
usable (`StringFormat.of(...)`) for callers that want both grammars in one 
pattern; only the `f()`/`fs()`/`StringUtils.format` entry points were narrowed 
to printf.
 
+- **Serializer/Parser I/O narrowed to streams — `File` and `StringBuilder` no 
longer accepted (TODO-248).** The core serialize/parse I/O surface now accepts 
only `Reader` / `Writer` / `InputStream` / `OutputStream` (plus the existing 
scalar `String` / `byte[]` / `CharSequence` shortcut forms). The `File` and 
`StringBuilder` `instanceof` branches were removed from the internal 
`SerializerPipe` / `ParserPipe` I/O plumbing, so passing a `File` or 
`StringBuilder` to `Serializer.serialize(Obj [...]
+  - The same narrowing applies to the **token/record streaming** surface 
(TODO-248 "Option B"): `serializeTokens(...)` / `parseTokens(...)` / 
`serializeRecords(...)` / `serializeArrayRecords(...)` (and the `Marshaller` 
`ofTokens`/`ofRecords`/`ofArrayRecords` shortcuts) no longer accept 
`File`/`StringBuilder` either — the `*TokenWriter.forOutput(...)` factories 
(JSON / JSONL / CBOR / MsgPack) are stream-only.
+  - **Migration — `File`:** wrap it yourself.
+
+    ```java
+    // Serialize to a file:
+    try (Writer w = Files.newBufferedWriter(path)) {          // char-based 
formats
+        JsonSerializer.DEFAULT.serialize(bean, w);
+    }
+    try (OutputStream os = Files.newOutputStream(path)) {     // byte-based 
formats
+        MsgPackSerializer.DEFAULT.serialize(bean, os);
+    }
+
+    // Parse from a file:
+    try (Reader r = Files.newBufferedReader(path)) {          // char-based 
formats
+        var bean = JsonParser.DEFAULT.parse(r, MyBean.class);
+    }
+    ```
+  - **Migration — `StringBuilder`:** serialize to a `StringWriter` and read 
`.toString()` afterward (or just call the `String`-returning shortcut 
`Json.of(bean)` / `serializer.serialize(bean)`).
+
+    ```java
+    var sw = new StringWriter();
+    JsonSerializer.DEFAULT.serialize(bean, sw);
+    String json = sw.toString();
+    ```
+  - The `SerializerPipe` / `ParserPipe` classes are **retained** (they still 
own the stream close/flush lifecycle, charset decoding, debug capture, and 
position tracking for the surviving stream types) — only their 
`File`/`StringBuilder` handling and the now-dead `fileCharset` pipe-constructor 
argument were removed. The `fileCharset(...)` builder setting still exists but 
is now a no-op for the narrowed I/O surface.
+
 _Other entries TBD — to be filled in before release. See also the major 
version bump note above._
 
 ### Deprecations
diff --git a/pages/topics/03.01.Marshallers.md 
b/pages/topics/03.01.Marshallers.md
index 6d8c2d766a..ad5703cfd8 100644
--- a/pages/topics/03.01.Marshallers.md
+++ b/pages/topics/03.01.Marshallers.md
@@ -146,7 +146,7 @@ Every format method provides the following overloads:
 | Signature | Purpose |
 |---|---|
 | `format(Object)` | Serialize to `String` or `byte[]` |
-| `format(Object, Object)` | Serialize to a `Writer`, `OutputStream`, `File`, 
or `StringBuilder` |
+| `format(Object, Object)` | Serialize to a `Writer` or `OutputStream` |
 | `format(Object, Class<T>)` | Parse from any input — throws checked 
`IOException` |
 | `format(Object, Type, Type...)` | Parse from any input with a parameterized 
type — throws checked `IOException` |
 | `format(String, Class<T>)` | Parse from `String` — exceptions wrapped as 
unchecked |
diff --git a/pages/topics/03.47.02.TokenStreaming.md 
b/pages/topics/03.47.02.TokenStreaming.md
index 309fd03ffa..e79515bc2f 100644
--- a/pages/topics/03.47.02.TokenStreaming.md
+++ b/pages/topics/03.47.02.TokenStreaming.md
@@ -47,8 +47,8 @@ For numeric values both the original lexeme and the parsed 
`Number` are availabl
 ## Push side: TokenWriter
 
 ```java
-StringBuilder sb = new StringBuilder();
-try (TokenWriter w = JsonSerializer.DEFAULT.serializeTokens(sb)) {
+StringWriter sw = new StringWriter();
+try (TokenWriter w = JsonSerializer.DEFAULT.serializeTokens(sw)) {
     w.startObject();
     w.fieldName("a");
     w.number(1);
@@ -59,9 +59,12 @@ try (TokenWriter w = 
JsonSerializer.DEFAULT.serializeTokens(sb)) {
     w.endArray();
     w.endObject();
 }
-// sb is now: {"a":1,"b":[true,null]}
+// sw is now: {"a":1,"b":[true,null]}
 ```
 
+The output target must be a `Writer` or `OutputStream` (for byte-based 
formats).  To capture output as
+a string, use a `StringWriter` and read `sw.toString()` afterward.
+
 Method families:
 
 - `startObject()` / `endObject()` / `startArray()` / `endArray()` — structural 
framing.
@@ -92,7 +95,7 @@ Cursor-level settings are derived from the 
parser/serializer's builder. The foll
 are honored on token cursors:
 
 - **Reader** (from `Parser.Builder`): `autoCloseStreams`, `unbuffered`, 
`trimStrings`,
-  `streamCharset`, `fileCharset`.
+  `streamCharset`.
 - **Writer** (from `JsonSerializer.Builder`): `useWhitespace`, `maxIndent`,
   `quoteChar` / `quoteCharOverride`, `escapeSolidus`, `trimStrings`.
 
diff --git a/pages/topics/27.V10MigrationGuide.md 
b/pages/topics/27.V10MigrationGuide.md
index a131890d5c..6921886d56 100644
--- a/pages/topics/27.V10MigrationGuide.md
+++ b/pages/topics/27.V10MigrationGuide.md
@@ -168,6 +168,30 @@ CRTP `SELF` self-type on `SerializerBuilder<SELF>` / 
`ParserBuilder<SELF>` handl
 Remove any override boilerplate that existed solely to narrow the return type; 
the base setters already return the
 correct concrete builder type.
 
+## Serializer / Parser I/O Narrowed to Streams (`File` / `StringBuilder` 
Dropped)
+
+The core serialize/parse I/O surface now accepts only `Reader` / `Writer` / 
`InputStream` / `OutputStream` (plus the
+scalar `String` / `byte[]` / `CharSequence` shortcut forms).  The `File` and 
`StringBuilder` `instanceof` branches were
+removed from the internal `SerializerPipe` / `ParserPipe` plumbing, so passing 
a `File` or `StringBuilder` to
+`Serializer.serialize(Object, Object)`, `Parser.parse(Object, ...)`, the 
token/record streaming methods
+(`serializeTokens` / `parseTokens` / `serializeRecords` / 
`serializeArrayRecords`), or any session `createPipe(...)` now
+throws at runtime.  Because these methods are typed `Object`, callers passing 
the dropped forms still **compile** — the
+change surfaces at runtime as `"Cannot convert object of type ... to a 
Writer/OutputStream/InputStream"`.
+
+Wrap it yourself:
+
+| Was | Now |
+|---|---|
+| `serializer.serialize(bean, file)` (char) | `try (Writer w = 
Files.newBufferedWriter(file.toPath())) { serializer.serialize(bean, w); }` |
+| `serializer.serialize(bean, file)` (binary) | `try (OutputStream os = 
Files.newOutputStream(file.toPath())) { serializer.serialize(bean, os); }` |
+| `parser.parse(file, MyBean.class)` (char) | `try (Reader r = 
Files.newBufferedReader(file.toPath())) { parser.parse(r, MyBean.class); }` |
+| `serializer.serialize(bean, sb)` (`StringBuilder`) | `var sw = new 
StringWriter(); serializer.serialize(bean, sw); String out = sw.toString();` — 
or just use the `String`-returning shortcut (`Json.of(bean)`). |
+
+`SerializerPipe` / `ParserPipe` are retained (they still own the stream 
close/flush lifecycle, charset decoding, debug
+capture, and position tracking) — only their `File` / `StringBuilder` handling 
and the now-dead `fileCharset`
+pipe-constructor argument were removed.  The `fileCharset(...)` builder 
setting still exists but is now a no-op for the
+narrowed I/O surface.
+
 ## Bean→Marshalled Renames
 
 ### Annotation Renames
@@ -828,7 +852,7 @@ unaffected — they route through `mf()` internally. See the
 |-----|-----|-------|
 | `Tuple2Function` / `Tuple3Function` / `Tuple4Function` / `Tuple5Function` | 
`Function2` / `Function3` / `Function4` / `Function5` | Hard rename — API is 
equivalent (same arity, same `apply(...)` signature). |
 | `Console.format(String, Object...)` | `Shorts.f(String format, Object... 
args)` (or `StringUtils.format(...)`) | Hard removal — duplicated 
functionality. `Console.err(...)` / `Console.out(...)` are unchanged. |
-| `BasicRuntimeException` (concrete subclass used to wrap arbitrary checked 
exceptions) | `ThrowableUtils.runtimeException(...)` (with optional `Throwable 
cause` overload) | Retired in favor of the `ThrowableUtils` factory. Use 
`runtimeException(msg, args)` or `runtimeException(cause, msg, args)`. New 
helpers in `ThrowableUtils`: `unsupportedOp(String, Object...)`, 
`ioException(String, Object...)`, plus cause-accepting overloads of 
`illegalArg(...)` / `runtimeException(...)`. |
+| `BasicRuntimeException` (concrete subclass used to wrap arbitrary checked 
exceptions) | `Shorts.rex(...)` (with optional `Throwable cause` overload) | 
Retired in favor of the terse `Shorts` exception factories (`import static 
org.apache.juneau.commons.utils.Shorts.*;`). Use `rex(msg, args)` or 
`rex(cause, msg, args)`. Sibling helpers: `iaex(...)` 
(`IllegalArgumentException`), `isex(...)` (`IllegalStateException`), 
`uoex(...)` (`UnsupportedOperationException`), `ioex(...)` (`IOException [...]
 | `ArrayUtils` static methods | `CollectionUtils` static methods (same 
signatures: `last()`, `append()`, `combine()`, `indexOf()`, `toList()`, 
`contains()`, etc.) | `ArrayUtils` is now `@Deprecated` and delegates to 
`CollectionUtils`. Migrate at your convenience; both will continue to work 
during the deprecation period. |
 | `ResettableSupplier` | `OptionalSupplier` | Class rename. |
 

Reply via email to