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. |