Record Streaming
The RecordReader / RecordWriter surface yields one whole-value record per call. It works uniformly across every Juneau format that implements the RecordReadable / RecordWritable role.
See the per-format capability matrix for which formats support record reading/writing and whether the cursor streams O(1) or buffers.
Reading records
try (RecordReader r = JsonParser.DEFAULT.readRecords(input)) {
while (r.canRead()) {
Bean bean = r.read(Bean.class);
process(bean);
}
}
For single-rooted formats (json, xml, bson, yaml, ...), the cursor yields exactly one record (the root value), then exhausts. For naturally multi-rooted formats (jsonl, csv, sse), the cursor yields N records — one per line, row, or event on the wire.
Writing records
try (RecordWriter w = JsonSerializer.DEFAULT.writeRecords(output)) {
w.write(bean);
}
For single-rooted formats, exactly one write(...) call is allowed; subsequent calls throw.
For multi-rooted formats, N calls produce N records on the wire — wire-equivalent to
serializer.write(List.of(records)).
Iterator and Stream views
Convenient JDK-friendly views on top of read(Class):
try (RecordReader r = JsonlParser.DEFAULT.readRecords(input)) {
for (Bean b : (Iterable<Bean>) () -> r.iterator(Bean.class)) {
process(b);
}
}
try (RecordReader r = JsonlParser.DEFAULT.readRecords(input)) {
int totalAge = r.stream(Bean.class).mapToInt(b -> b.age).sum();
}
Equivalence with parse(...)
For single-rooted formats, parser.read(input, T) and
parser.readRecords(input).read(T) produce identical results. For multi-rooted formats,
readRecords(input).read(T) returns the FIRST record while parse(input, T) may return the first
or all of them depending on T:
// JSONL: 3 records on the wire.
String wire = "{\"n\":\"a\"}\n{\"n\":\"b\"}\n{\"n\":\"c\"}";
Bean first = JsonlParser.DEFAULT.read(wire, Bean.class); // returns Bean("a")
try (RecordReader r = JsonlParser.DEFAULT.readRecords(wire)) {
Bean a = r.read(Bean.class); // first
Bean b = r.read(Bean.class); // second
Bean c = r.read(Bean.class); // third
}
@SuppressWarnings("unchecked")
List<Bean> all = (List<Bean>) JsonlParser.DEFAULT.read(wire, List.class, Bean.class);
Capability check
if (parser instanceof RecordReadable p) {
try (RecordReader r = p.readRecords(input)) {
// ...
}
}
Format-specific notes
- CSV / JSONL / SSE — naturally row/line/event streamed;
readRecordsis the multi-record cursor. - JsonSchema / JCS / SOAP-XML — writer-only;
writeRecords(output).write(value)produces the schema / canonical / SOAP-wrapped output. NoreadRecords. - PlainText — only round-trips strings via
toString().readRecords(input).read(String.class)returns the body verbatim. - CBOR / MsgPack / BSON / Prototext / Parquet — binary; pass an
OutputStream/byte[]/InputStreaminstead of aWriter/Reader.
See also
- Token-Streaming Basics
- Token Streaming — fine-grained structural cursor.
- Array-Record Streaming.