Jackson 3 series companion code
37 runnable examples covering the eight feature posts on ankurm.com, verified against Jackson 3.2.1 on Temurin 21.0.5. Every output committed under docs/ was produced by run-all.sh. Also documents 11 places where the published snippets do not compile or do not behave as printed against a real Jackson 3 build - most notably that writeValueAsString(List<Base>) silently drops the polymorphic type discriminator, so the post's serialised output cannot be read back.
This commit is contained in:
80
docs/part6-streaming.md
Normal file
80
docs/part6-streaming.md
Normal file
@@ -0,0 +1,80 @@
|
||||
# Part 6 — Streaming API and the tree model
|
||||
|
||||
Post: <https://ankurm.com/jackson-streaming-api-jsonnode/>
|
||||
|
||||
Renames that break the post's code verbatim:
|
||||
|
||||
| Jackson 2 | Jackson 3 |
|
||||
|---|---|
|
||||
| `com.fasterxml.jackson.core.JsonFactory` | `tools.jackson.core.json.JsonFactory` (note the extra `.json`) |
|
||||
| `parser.getCurrentName()` | `parser.currentName()` |
|
||||
| `parser.getText()` | `parser.getString()` |
|
||||
| `JsonToken.FIELD_NAME` | `JsonToken.PROPERTY_NAME` |
|
||||
| `gen.writeNumberField` / `writeStringField` | `gen.writeNumberProperty` / `writeStringProperty` |
|
||||
| `node.asText()` | `node.asString()` |
|
||||
| `factory.createParser(file)` | `factory.createParser(ObjectReadContext.empty(), file)` |
|
||||
|
||||
The comparison post's performance section gives the import as
|
||||
`tools.jackson.core.JsonFactory`, which does not resolve — the class is in the
|
||||
`.json` subpackage.
|
||||
|
||||
## G01 — filtering a large array
|
||||
|
||||
[`G01StreamingParserFilter.java`](../src/main/java/com/ankurm/jackson3/part6streaming/G01StreamingParserFilter.java)
|
||||
|
||||
```
|
||||
ERROR: Database connection failed
|
||||
Total errors found: 1
|
||||
```
|
||||
|
||||
## G02 — writing a million records
|
||||
|
||||
[`G02StreamingGenerator.java`](../src/main/java/com/ankurm/jackson3/part6streaming/G02StreamingGenerator.java)
|
||||
|
||||
The post's loop, kept at its full 1,000,000 iterations, with the heap delta measured so
|
||||
"constant memory usage" is a number.
|
||||
|
||||
```
|
||||
records written : 1000000
|
||||
file size : 30 MB
|
||||
elapsed : 129 ms
|
||||
heap delta : 0 MB <- the document is never held in memory
|
||||
```
|
||||
|
||||
## G03 — the tree model
|
||||
|
||||
[`G03TreeModelNavigation.java`](../src/main/java/com/ankurm/jackson3/part6streaming/G03TreeModelNavigation.java)
|
||||
|
||||
```
|
||||
Customer: Alice
|
||||
KB-01 x2
|
||||
MS-42 x1
|
||||
Has discount: false
|
||||
path(missing) : (class MissingNode)
|
||||
get(missing) : null
|
||||
deep path : '<default>'
|
||||
treeToValue : CustomerRecord[name=Alice, tier=gold]
|
||||
```
|
||||
|
||||
The `path(missing)` / `get(missing)` pair is the whole argument for `path()`: it returns
|
||||
a `MissingNode` that chains safely, where `get()` returns `null` and the next call NPEs.
|
||||
|
||||
## G04 — the decision table, measured
|
||||
|
||||
[`G04ThreeApproachesMeasured.java`](../src/main/java/com/ankurm/jackson3/part6streaming/G04ThreeApproachesMeasured.java)
|
||||
|
||||
The post closes with a table asserting relative memory and verbosity. This runs the same
|
||||
filter three ways over a generated 20 MB file.
|
||||
|
||||
```
|
||||
input file : 20 MB, 200000 entries
|
||||
|
||||
data binding (readValue) errors=4000 524 ms heap delta 47 MB
|
||||
tree model (readTree) errors=4000 341 ms heap delta 102 MB
|
||||
streaming (JsonParser) errors=4000 78 ms heap delta 1 MB
|
||||
```
|
||||
|
||||
Single-shot measurements on a 2-core container, not JMH — treat the ordering as the
|
||||
result, not the absolute figures. Two things do stand out and are stable across runs:
|
||||
the tree model costs roughly twice the heap of data binding for the same document, and
|
||||
streaming is the only approach whose heap does not scale with input size.
|
||||
Reference in New Issue
Block a user