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 7ceed948d1 Add tree-model and RFC 6901 JSON-Pointer docs; note
ObjectRest removal.
7ceed948d1 is described below
commit 7ceed948d1f4fc8f7039e5b0a2e4ccf83979e2ee
Author: James Bognar <[email protected]>
AuthorDate: Tue Jun 16 10:29:37 2026 -0400
Add tree-model and RFC 6901 JSON-Pointer docs; note ObjectRest removal.
- Add MarshalledNode/JsonPointer topic page (+ sidebar entry).
- Update ObjectTools page and 10.0.0 release notes for the public
ObjectRest removal and the ObjectRestException -> PathTraversalException rename.
- Fix stale collections javadoc links on the JsonMap/JsonList page
(marshall.collections).
Co-authored-by: Cursor <[email protected]>
---
pages/release-notes/10.0.0.md | 22 ++
.../02.08.01.MarshalledNodeAndJsonPointer.md | 231 +++++++++++++++++++++
pages/topics/02.08.JsonMap.md | 26 +--
pages/topics/02.24.ObjectTools.md | 126 ++++-------
sidebars.ts | 5 +
5 files changed, 306 insertions(+), 104 deletions(-)
diff --git a/pages/release-notes/10.0.0.md b/pages/release-notes/10.0.0.md
index c42b7e3633..87452d8a85 100644
--- a/pages/release-notes/10.0.0.md
+++ b/pages/release-notes/10.0.0.md
@@ -180,6 +180,23 @@ A full topic-page family lives under "2.50. Token / Record
Streaming" in the Mar
The streaming surface is **purely structural** — object swaps and `@Schema`
annotations apply only on the POJO databind path, never at the token layer.
Both surfaces are additive; the existing POJO ↔ document API remains the
primary, recommended path.
+#### `MarshalledNode` typed tree façade + RFC 6901 JSON-Pointer addressing
+
+Juneau 10.0 adds a typed tree façade and an RFC 6901 JSON-Pointer surface over
the existing `MarshalledMap`/`MarshalledList` collections model (in
`org.apache.juneau.marshall.collections`):
+
+- **`MarshalledNode`** — a public, **live** typed-tree façade (not a parallel
Jackson-style node hierarchy) wrapping a backing `Map`/`List`/scalar/`null`.
Provides node-type introspection (`isObject`/`isArray`/`isValue`/`isNull`),
typed accessors
(`asString`/`asInt`/`asLong`/`asDouble`/`asBoolean`/`as(Class)`/`value`),
navigation (`get(String)`/`get(int)`/`size`), fluent in-place builders
(`put`/`add`), a deep-copy `copy()` snapshot, and the RFC 6901 pointer methods
`at`/`find`/`set`/`re [...]
+- **`JsonPointer`** — a public RFC 6901 JSON-Pointer helper:
`JsonPointer.of(String)`, `eval(root)` (read, null-miss), `set(root, value)`
(auto-vivifying write; `-` appends), `remove(root)`, and static
`encodeToken`/`decodeToken` (`~0`→`~`, `~1`→`/`). The empty string `""`
addresses the whole document; a non-empty pointer must begin with `/`.
+- **Convenience** — `MarshalledMap.at(String)` and `MarshalledList.at(String)`
resolve a pointer and return a `MarshalledNode`.
+
+```java
+JsonMap doc = Json.to("{foo:{bar:['x','y']}}", JsonMap.class);
+
+String y = doc.at("/foo/bar/1").asString(); // "y"
+MarshalledNode.of(doc).set("/foo/bar/-", "z"); // appends ->
['x','y','z']
+```
+
+Both `MarshalledNode` and `JsonPointer` are marked **Beta — API subject to
change**. See the new [Tree Model & RFC 6901
JSON-Pointer](/docs/topics/MarshalledNode) topic page.
+
### Bug Fixes
_TBD — to be filled in as development continues._
@@ -188,6 +205,11 @@ _TBD — to be filled in as development continues._
- **`juneau-my-jetty-microservice` removed.** The template-project module has
been retired in favor of the new `JettyMicroservice` facade + bundled defaults
in `juneau-microservice-jetty`. See the New Features section above for
migration guidance.
- **`juneau-examples-rest{,-jetty,-springboot,-jetty-ftest}` removed.** The
four-module legacy example family has been retired in favor of the new
`juneau-petstore-{core,jetty,springboot}` showcase family. The legacy modules
carried an unpatched Hibernate ORM 5.6.x SQL-injection vulnerability
(CVE-2026-0603) that had no upstream fix because Hibernate 5.6.x is
end-of-life; deletion closes that exposure surface. The accompanying
`scripts/start-examples-rest-jetty.py` and `scripts/start-exa [...]
+- **Public `ObjectRest` class removed.** The
`org.apache.juneau.objecttools.ObjectRest` class is gone; its URL-addressed
GET/PUT/POST/DELETE traversal engine survives only as an internal
`PathTraversal` helper (not a supported public API). Per-consumer migration:
+ - **`ResponseContent.asObjectRest()` / `asObjectRest(Class)`**
(`juneau-rest-client`) — removed. Replace with
`response.getContent().as(JsonMap.class).getAt(path, type)`, or the RFC 6901
form `response.getContent().as(JsonMap.class).at(pointer)`.
+ - **Reflective helpers** — `ObjectRest.invokeMethod(...)` /
`getPublicMethods(...)` were dropped; use `ObjectIntrospector` directly if you
need that capability.
+ - **Unaffected** — `MarshalledMap`/`MarshalledList` (and
`JsonMap`/`JsonList`) `getAt`/`putAt`/`postAt`/`deleteAt` are unchanged (now
backed by `PathTraversal`); the companion exception is now
`PathTraversalException` (public, renamed to match `PathTraversal`); the
`Traversable` REST response converter and Swagger/OpenAPI `$ref` (`#/`)
resolution behavior are unchanged.
+ - **New replacement APIs** — the new `MarshalledNode` typed tree façade and
`JsonPointer` (see New Features above) provide typed navigation and RFC 6901
JSON-Pointer addressing over the same collections model.
_Other entries TBD — to be filled in before release. See also the major
version bump note above._
diff --git a/pages/topics/02.08.01.MarshalledNodeAndJsonPointer.md
b/pages/topics/02.08.01.MarshalledNodeAndJsonPointer.md
new file mode 100644
index 0000000000..60de65fd4b
--- /dev/null
+++ b/pages/topics/02.08.01.MarshalledNodeAndJsonPointer.md
@@ -0,0 +1,231 @@
+---
+title: "Tree Model and RFC 6901 JSON-Pointer"
+slug: MarshalledNode
+---
+
+The <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html"
target="_blank">MarshalledNode</a> class is a typed tree
+**façade** layered over the generic-collections model — <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledMap.html"
target="_blank">MarshalledMap</a> /
+<a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledList.html"
target="_blank">MarshalledList</a> and their
+<a href="/site/apidocs/org/apache/juneau/marshall/collections/JsonMap.html"
target="_blank">JsonMap</a> /
+<a href="/site/apidocs/org/apache/juneau/marshall/collections/JsonList.html"
target="_blank">JsonList</a> subclasses.
+
+It gives developers coming from Jackson the ergonomics they expect — node-type
introspection, typed value accessors, fluent
+tree building, and <a href="https://datatracker.ietf.org/doc/html/rfc6901"
target="_blank">RFC 6901</a> JSON-Pointer addressing — **without**
+introducing a parallel Jackson-style node hierarchy.
+
+:::important
+`MarshalledNode` is a **live view**, not a copy and not a new node type. A
node wraps a single backing value that is one of:
+
+- a `Map` (an *object* node),
+- a `List` (an *array* node),
+- a scalar (`String`, `Number`, `Boolean`, …) (a *value* node), or
+- `null` (a *null* node).
+
+The underlying representation is still plain `MarshalledMap`/`MarshalledList`
(or any `Map`/`List`). There is no `ObjectNode` /
+`ArrayNode` / `TextNode` class tree to learn — `MarshalledNode` is the single
façade type for every node kind.
+:::
+
+#### Creating nodes
+
+Use the static factories to wrap an existing value or to start a fresh tree:
+
+```java
+// Wrap an existing value (stored as-is, no copy).
+MarshalledNode node = MarshalledNode.of(myJsonMap);
+
+// Start fresh containers (backed by a new empty JsonMap / JsonList).
+MarshalledNode obj = MarshalledNode.objectNode();
+MarshalledNode arr = MarshalledNode.arrayNode();
+```
+
+You can also obtain a node directly from the collections classes via the
convenience <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledMap.html#at(java.lang.String)"
target="_blank">MarshalledMap.at(String)</a>
+and <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledList.html#at(java.lang.String)"
target="_blank">MarshalledList.at(String)</a> methods, which
+resolve an RFC 6901 pointer and return a `MarshalledNode`:
+
+```java
+JsonMap doc = Json.to("{foo:{bar:['x','y']}}", JsonMap.class);
+
+// Returns a MarshalledNode wrapping "y".
+MarshalledNode n = doc.at("/foo/bar/1");
+```
+
+#### Node-type introspection
+
+Four predicates report the kind of value a node wraps:
+
+<tree>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#isObject()"
target="_blank">isObject()</a></java-class> — wraps a
<code>Map</code>.</node-0>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#isArray()"
target="_blank">isArray()</a></java-class> — wraps a
<code>List</code>.</node-0>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#isValue()"
target="_blank">isValue()</a></java-class> — wraps a non-<code>null</code>
scalar.</node-0>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#isNull()"
target="_blank">isNull()</a></java-class> — wraps <code>null</code>.</node-0>
+</tree>
+
+#### Typed accessors
+
+Value nodes can be read in a target type. The scalar accessors return `null`
when the node is not a value node or the value
+cannot be converted (rather than throwing):
+
+```java
+String s = node.get("name").asString();
+Integer i = node.get("age").asInt();
+Long l = node.get("id").asLong();
+Double d = node.get("score").asDouble();
+Boolean b = node.get("active").asBoolean();
+```
+
+For richer conversions — including converting an *object* node straight to a
bean — use <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#as(java.lang.Class)"
target="_blank">as(Class)</a>,
+which routes through the same conversion machinery as
`MarshalledMap.get(String,Class)`. Use <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#value()"
target="_blank">value()</a>
+to get the raw backing object:
+
+```java
+// Convert an object node to a bean.
+Address addr = node.get("address").as(Address.class);
+
+// Get the raw backing value.
+Object raw = node.value();
+```
+
+#### Navigation
+
+Navigate into children by key (object nodes) or index (array nodes). Both
`get(...)` forms return `null` on a miss (absent
+key, out-of-range index, or wrong node kind), and <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#size()"
target="_blank">size()</a>
+returns the entry/element count (`0` for value and null nodes):
+
+```java
+MarshalledNode child = node.get("address"); // by key
+MarshalledNode first = node.get("phones").get(0); // by index
+int count = node.get("phones").size();
+```
+
+#### Fluent tree building
+
+The <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#put(java.lang.String,java.lang.Object)"
target="_blank">put(String,Object)</a>
+(object nodes) and <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#add(java.lang.Object)"
target="_blank">add(Object)</a>
+(array nodes) builders return `this` for chaining. They **mutate the backing
container in place**, so callers still holding the
+underlying map/list see the change.
+
+:::tip Example
+```java
+// Build a tree fluently (mutates a backing JsonMap/JsonList in place).
+MarshalledNode node = MarshalledNode.objectNode()
+ .put("a", 1)
+ .put("b", MarshalledNode.arrayNode().add("x").add("y").value());
+
+String json = Json.of(node.value()); // {"a":1,"b":["x","y"]}
+
+// Navigate and read typed values.
+Integer a = node.get("a").asInt(); // 1
+String x = node.get("b").get(0).asString(); // "x"
+```
+:::
+
+`put(...)` on a non-object node and `add(...)` on a non-array node both throw
`IllegalStateException`.
+
+#### Live view vs. `copy()` snapshot
+
+Because a node is a live view, building or mutating through it changes the
shared backing container:
+
+```java
+JsonMap backing = new JsonMap();
+MarshalledNode node = MarshalledNode.of(backing);
+node.put("x", 1);
+// backing now contains {"x":1} — the caller's map saw the mutation.
+```
+
+When you need an independent snapshot, use <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#copy()"
target="_blank">copy()</a>,
+which returns a new node backed by a recursive **deep copy** (maps into new
`JsonMap`s, lists into new `JsonList`s; scalars and
+`null` are returned as-is). Mutating the copy never affects the original and
vice versa:
+
+```java
+MarshalledNode snapshot = node.copy();
+snapshot.put("x", 999); // does not affect the original 'node'.
+```
+
+#### RFC 6901 JSON-Pointer addressing
+
+`MarshalledNode` exposes the full <a
href="https://datatracker.ietf.org/doc/html/rfc6901" target="_blank">RFC
6901</a> pointer surface relative to its
+backing value:
+
+<tree>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#at(java.lang.String)"
target="_blank">at(String)</a></java-class> — read; returns the addressed node
or <code>null</code> on a read-miss.</node-0>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#find(java.lang.String)"
target="_blank">find(String)</a></java-class> — read returning an
<code>Optional<MarshalledNode></code> (distinguishes a present
<code>null</code> value from an absent one).</node-0>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#set(java.lang.String,java.lang.Object)"
target="_blank">set(String,Object)</a></java-class> — auto-vivifying write;
the <code>-</code> token appends to a list. The root pointer is
rejected.</node-0>
+<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html#remove(java.lang.String)"
target="_blank">remove(String)</a></java-class> — removes the addressed
member/element and returns it (<code>null</code> if absent).</node-0>
+</tree>
+
+```java
+JsonMap doc = Json.to("{foo:{bar:['x','y']}}", JsonMap.class);
+MarshalledNode root = MarshalledNode.of(doc);
+
+// Read.
+String y = root.at("/foo/bar/1").asString(); // "y"
+
+// Optional read — present even when the value is JSON null.
+Optional<MarshalledNode> maybe = root.find("/foo/baz"); // Optional.empty()
+
+// Auto-vivifying write — intermediate containers are created as needed.
+root.set("/foo/qux/0", "new"); // creates {foo:{qux:["new"]}} alongside bar
+
+// Append to a list with the '-' token.
+root.set("/foo/bar/-", "z"); // bar is now ['x','y','z']
+
+// Remove.
+Object removed = root.remove("/foo/bar/0"); // returns "x"
+```
+
+A read-miss (missing key, out-of-range index, or type mismatch) resolves to
`null` from `at(...)`. The empty pointer `""`
+addresses the whole backing document; on a node, `set("", …)` is rejected with
`IllegalArgumentException` because the backing
+value cannot be replaced in place — set against a non-empty pointer instead.
+
+#### The `JsonPointer` helper
+
+For pointer operations against an arbitrary `Map`/`List` root (not just
through a node), use the standalone
+<a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonPointer.html"
target="_blank">JsonPointer</a> class directly. A pointer is a string of
+zero or more `/`-prefixed reference tokens; the empty string `""` references
the whole document (the root), and a non-empty
+pointer **must** begin with `/`.
+
+```java
+JsonMap doc = JsonMap.of("foo", JsonList.of("bar", "baz"));
+
+// Read (read-miss resolves to null).
+Object v = JsonPointer.of("/foo/0").eval(doc); // "bar"
+
+// Auto-vivifying write; '-' appends. Returns the (possibly new) effective
root.
+JsonPointer.of("/foo/-").set(doc, "qux"); // appends "qux"
+
+// Remove returns the removed value (null if absent).
+Object removed = JsonPointer.of("/foo/0").remove(doc); // "bar"
+```
+
+##### Token escaping (`~0` / `~1`) and the `-` append token
+
+Within a reference token, `/` is escaped as `~1` and `~` is escaped as `~0`
(decode order matters: `~1`→`/` first, then
+`~0`→`~`). Use <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonPointer.html#encodeToken(java.lang.String)"
target="_blank">encodeToken(String)</a>
+and <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonPointer.html#decodeToken(java.lang.String)"
target="_blank">decodeToken(String)</a>
+to convert between raw member names and escaped tokens:
+
+```java
+// A member name literally named "a/b~c".
+JsonPointer.encodeToken("a/b~c"); // "a~1b~0c"
+JsonPointer.decodeToken("a~1b~0c"); // "a/b~c"
+
+// Addressing that member:
+JsonMap doc = Json.to("{'a/b~c':42}", JsonMap.class);
+Object v = JsonPointer.of("/a~1b~0c").eval(doc); // 42
+```
+
+On a write, the special `-` token references "the element after the last
element" of an array — i.e. it **appends**:
+
+```java
+JsonMap doc = Json.to("{items:[1,2]}", JsonMap.class);
+JsonPointer.of("/items/-").set(doc, 3); // items is now [1,2,3]
+```
+
+`toString()` round-trips a parsed pointer back to its canonical escaped string
form. Array index tokens are strict base-10
+non-negative integers with no leading zeros (`0` itself is allowed); anything
else is treated as an object member name.
+
+:::note
+`MarshalledNode` and `JsonPointer` are part of the next-generation typed tree
model layered over the `Marshalled*` collections
+and are marked **Beta — API subject to change**. The underlying
`MarshalledMap`/`MarshalledList` path-navigation methods
+(`getAt`/`putAt`/`postAt`/`deleteAt`) remain the stable, long-standing way to
address nodes by slash-delimited path.
+:::
diff --git a/pages/topics/02.08.JsonMap.md b/pages/topics/02.08.JsonMap.md
index 3984ffd165..15f3be75e5 100644
--- a/pages/topics/02.08.JsonMap.md
+++ b/pages/topics/02.08.JsonMap.md
@@ -3,7 +3,7 @@ title: "JsonMap and JsonList"
slug: JsonMap
---
-The <a href="/site/apidocs/org/apache/juneau/collections/JsonMap.html"
target="_blank">JsonMap</a> and <a
href="/site/apidocs/org/apache/juneau/collections/JsonList.html"
target="_blank">JsonList</a> classes are generic Java representations of JSON
objects and arrays.
+The <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonMap.html"
target="_blank">JsonMap</a> and <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonList.html"
target="_blank">JsonList</a> classes are generic Java representations of JSON
objects and arrays.
These classes can be used to create "unstructured" models for serialization
(as opposed to "structured" models
consisting of beans).
@@ -11,31 +11,31 @@ If you want to quickly generate JSON/XML/HTML from generic
maps/collections, or
maps/collections, these classes work well.
:::tip
-In v9.5, `JsonMap` / `JsonList` were re-parented onto a new neutral base — <a
href="/site/apidocs/org/apache/juneau/collections/MarshalledMap.html"
target="_blank">MarshalledMap</a> / <a
href="/site/apidocs/org/apache/juneau/collections/MarshalledList.html"
target="_blank">MarshalledList</a> — which carries all the marshaller-agnostic
surface (typed accessors, fluent setters, `getAt`/`putAt` path navigation, bean
integration, etc.) with no language coupling. `JsonMap` / `JsonList` are no
[...]
+In v9.5, `JsonMap` / `JsonList` were re-parented onto a new neutral base — <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledMap.html"
target="_blank">MarshalledMap</a> / <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledList.html"
target="_blank">MarshalledList</a> — which carries all the marshaller-agnostic
surface (typed accessors, fluent setters, `getAt`/`putAt` path navigation, bean
integration, etc.) with no language coupling. `JsonMap` / [...]
:::
These classes extend the following JCF / Juneau classes:
<tree>
<node-0><java-class><a
href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/LinkedHashMap.html"
target="_blank">java.util.LinkedHashMap</a></java-class></node-0>
-<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/collections/MarshalledMap.html"
target="_blank">org.apache.juneau.collections.MarshalledMap</a></java-class></node-1>
-<node-2><java-class><a
href="/site/apidocs/org/apache/juneau/collections/JsonMap.html"
target="_blank">org.apache.juneau.collections.JsonMap</a></java-class></node-2>
+<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledMap.html"
target="_blank">org.apache.juneau.marshall.collections.MarshalledMap</a></java-class></node-1>
+<node-2><java-class><a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonMap.html"
target="_blank">org.apache.juneau.marshall.collections.JsonMap</a></java-class></node-2>
<node-0><java-class><a
href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/LinkedList.html"
target="_blank">java.util.LinkedList</a></java-class></node-0>
-<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/collections/MarshalledList.html"
target="_blank">org.apache.juneau.collections.MarshalledList</a></java-class></node-1>
-<node-2><java-class><a
href="/site/apidocs/org/apache/juneau/collections/JsonList.html"
target="_blank">org.apache.juneau.collections.JsonList</a></java-class></node-2>
+<node-1><java-class><a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledList.html"
target="_blank">org.apache.juneau.marshall.collections.MarshalledList</a></java-class></node-1>
+<node-2><java-class><a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonList.html"
target="_blank">org.apache.juneau.marshall.collections.JsonList</a></java-class></node-2>
</tree>
-The <a href="/site/apidocs/org/apache/juneau/collections/JsonMap.html"
target="_blank">JsonMap</a> and <a
href="/site/apidocs/org/apache/juneau/collections/JsonList.html"
target="_blank">JsonList</a> classes are very similar to the `JSONObject` and
`JSONArray` classes found in other libraries.
+The <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonMap.html"
target="_blank">JsonMap</a> and <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonList.html"
target="_blank">JsonList</a> classes are very similar to the `JSONObject` and
`JSONArray` classes found in other libraries.
However, the names were chosen because the concepts of `Maps` and `Lists` are
already familiar to Java programmers, and
these classes can be used with any of the serializers or parsers.
These object can be serialized in one of three ways:
-- Using the provided <a
href="/site/apidocs/org/apache/juneau/collections/JsonMap.html#writeTo(java.io.Writer)"
target="_blank">JsonMap.writeTo(java.io.Writer)</a> or <a
href="/site/apidocs/org/apache/juneau/collections/JsonList.html#writeTo(java.io.Writer)"
target="_blank">JsonList.writeTo(java.io.Writer)</a> methods.
+- Using the provided <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonMap.html#writeTo(java.io.Writer)"
target="_blank">JsonMap.writeTo(java.io.Writer)</a> or <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonList.html#writeTo(java.io.Writer)"
target="_blank">JsonList.writeTo(java.io.Writer)</a> methods.
- Passing them to one of the <a
href="/site/apidocs/org/apache/juneau/marshall/serializer/Serializer.html"
target="_blank">Serializer</a> serialize methods.
-- Simply calling the <a
href="/site/apidocs/org/apache/juneau/collections/JsonMap.html#toString()"
target="_blank">JsonMap.toString()</a> or <a
href="/site/apidocs/org/apache/juneau/collections/JsonList.html#toString()"
target="_blank">JsonList.toString()</a> methods which will serialize it as
strict RFC 8259 JSON. (Use <a
href="/site/apidocs/org/apache/juneau/marshall/json5/Json5Map.html"
target="_blank">Json5Map</a> / <a
href="/site/apidocs/org/apache/juneau/marshall/json5/Json5List.ht [...]
+- Simply calling the <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonMap.html#toString()"
target="_blank">JsonMap.toString()</a> or <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonList.html#toString()"
target="_blank">JsonList.toString()</a> methods which will serialize it as
strict RFC 8259 JSON. (Use <a
href="/site/apidocs/org/apache/juneau/marshall/json5/Json5Map.html"
target="_blank">Json5Map</a> / <a
href="/site/apidocs/org/apache/juneau/marshall/ [...]
-Any valid JSON can be parsed into an unstructured model consisting of generic
<a href="/site/apidocs/org/apache/juneau/collections/JsonMap.html"
target="_blank">JsonMap</a> and <a
href="/site/apidocs/org/apache/juneau/collections/JsonList.html"
target="_blank">JsonList</a> objects.
+Any valid JSON can be parsed into an unstructured model consisting of generic
<a href="/site/apidocs/org/apache/juneau/marshall/collections/JsonMap.html"
target="_blank">JsonMap</a> and <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonList.html"
target="_blank">JsonList</a> objects.
(Any valid XML can also be parsed into an unstructured model)
```java
@@ -61,7 +61,7 @@ String strict2 = map.toJson(); // synonym for toString().
String json5 = map.toJson5(); // {a:{name:'John Smith',age:21}, ...}
```
-The <a href="/site/apidocs/org/apache/juneau/collections/JsonMap.html"
target="_blank">JsonMap</a> and <a
href="/site/apidocs/org/apache/juneau/collections/JsonList.html"
target="_blank">JsonList</a> classes have many convenience features:
+The <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonMap.html"
target="_blank">JsonMap</a> and <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonList.html"
target="_blank">JsonList</a> classes have many convenience features:
```java
// Convert the map to a bean.
@@ -93,9 +93,9 @@ map.inner(anotherMap);
:::note
As a general rule, if you do not specify a target type during parsing, or if
the target type cannot be determined through reflection, the parser generates a
flavored map/list whose runtime type matches the parser:
-- <a href="/site/apidocs/org/apache/juneau/marshall/json/JsonParser.html"
target="_blank">JsonParser</a> produces <a
href="/site/apidocs/org/apache/juneau/collections/JsonMap.html"
target="_blank">JsonMap</a> / <a
href="/site/apidocs/org/apache/juneau/collections/JsonList.html"
target="_blank">JsonList</a>.
+- <a href="/site/apidocs/org/apache/juneau/marshall/json/JsonParser.html"
target="_blank">JsonParser</a> produces <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonMap.html"
target="_blank">JsonMap</a> / <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonList.html"
target="_blank">JsonList</a>.
- <a href="/site/apidocs/org/apache/juneau/marshall/json5/Json5Parser.html"
target="_blank">Json5Parser</a> produces <a
href="/site/apidocs/org/apache/juneau/marshall/json5/Json5Map.html"
target="_blank">Json5Map</a> / <a
href="/site/apidocs/org/apache/juneau/marshall/json5/Json5List.html"
target="_blank">Json5List</a>.
-- All other parsers (`XmlParser`, `YamlParser`, `UonParser`, `HoconParser`,
`MsgPackParser`, `CborParser`, `BsonParser`, `HtmlParser`, `JsonlParser`,
`HjsonParser`, `MarkdownParser`, `CsvParser`, RDF parsers, etc.) currently
produce the neutral <a
href="/site/apidocs/org/apache/juneau/collections/MarshalledMap.html"
target="_blank">MarshalledMap</a> / <a
href="/site/apidocs/org/apache/juneau/collections/MarshalledList.html"
target="_blank">MarshalledList</a>.
+- All other parsers (`XmlParser`, `YamlParser`, `UonParser`, `HoconParser`,
`MsgPackParser`, `CborParser`, `BsonParser`, `HtmlParser`, `JsonlParser`,
`HjsonParser`, `MarkdownParser`, `CsvParser`, RDF parsers, etc.) currently
produce the neutral <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledMap.html"
target="_blank">MarshalledMap</a> / <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledList.html"
target="_blank">MarshalledList</a>.
Callers that need a specific runtime type — for example to keep an explicit
`(JsonMap)` cast working — should pass an explicit target class to the parser,
e.g. `parser.parse(text, JsonMap.class)`. The flavor hook is only consulted for
unbound `Object` / `Map<String,Object>` / `Collection<Object>` targets;
explicit target classes always win.
:::
diff --git a/pages/topics/02.24.ObjectTools.md
b/pages/topics/02.24.ObjectTools.md
index 72192e1406..e964ab79de 100644
--- a/pages/topics/02.24.ObjectTools.md
+++ b/pages/topics/02.24.ObjectTools.md
@@ -9,7 +9,6 @@ classes for accessing and manipulating POJOs.
It consists of the following classes:
<tree>
-<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/objecttools/ObjectRest.html"
target="_blank">ObjectRest</a></java-class></node-0>
<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/objecttools/ObjectSearcher.html"
target="_blank">ObjectSearcher</a></java-class></node-0>
<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/objecttools/ObjectSorter.html"
target="_blank">ObjectSorter</a></java-class></node-0>
<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/objecttools/ObjectViewer.html"
target="_blank">ObjectViewer</a></java-class></node-0>
@@ -18,106 +17,51 @@ It consists of the following classes:
<node-0><java-class><a
href="/site/apidocs/org/apache/juneau/objecttools/ObjectMerger.html"
target="_blank">ObjectMerger</a></java-class></node-0>
</tree>
-#### ObjectRest
+#### ObjectRest (Removed in 10.0)
-The <a href="/site/apidocs/org/apache/juneau/objecttools/ObjectRest.html"
target="_blank">ObjectRest</a> class provides the ability to perform
-standard REST operations (GET, PUT, POST, DELETE) against nodes in a POJO
model.
-Nodes in the POJO model are addressed using URLs.
-
-A POJO model is defined as a tree model where nodes consist of consisting of
the following:
-
-<tree>
-<node-0><java-class><a
href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Map.html"
target="_blank">Maps</a> and Java beans representing JSON
objects.</java-class></node-0>
-<node-0><java-class><a
href="https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Collection.html"
target="_blank">Collections</a> and arrays representing JSON
arrays.</java-class></node-0>
-<node-0>Java beans.</node-0>
-</tree>
+:::warning Removed
+The public `ObjectRest` class was **removed** in Juneau 10.0. Its
URL-addressed GET/PUT/POST/DELETE traversal engine survives
+as an internal `PathTraversal` helper and is **not** a supported public API.
+:::
-Leaves of the tree can be any type of object.
+The path-addressed node operations that `ObjectRest` provided are now
available directly on the collections classes, and a new
+typed tree façade plus RFC 6901 JSON-Pointer surface covers the same ground:
-- Use <a
href="/site/apidocs/org/apache/juneau/objecttools/ObjectRest.html#get(java.lang.String)"
target="_blank">get()</a> to retrieve an element from a JSON tree.
-- Use <a
href="/site/apidocs/org/apache/juneau/objecttools/ObjectRest.html#put(java.lang.String,java.lang.Object)"
target="_blank">put()</a> to create (or overwrite) an element in a JSON tree.
-- Use <a
href="/site/apidocs/org/apache/juneau/objecttools/ObjectRest.html#post(java.lang.String,java.lang.Object)"
target="_blank">post()</a> to add an element to a list in a JSON tree.
-- Use <a
href="/site/apidocs/org/apache/juneau/objecttools/ObjectRest.html#delete(java.lang.String)"
target="_blank">delete()</a> to remove an element from a JSON tree.
+- **Slash-delimited path navigation** — use the unchanged <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledMap.html"
target="_blank">MarshalledMap</a> /
+ <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledList.html"
target="_blank">MarshalledList</a> methods `getAt` / `putAt` / `postAt` /
+ `deleteAt` (also available on `JsonMap` / `JsonList`). These behave exactly
as before — they are now backed by the internal
+ `PathTraversal` helper.
+- **RFC 6901 JSON-Pointer addressing** — use `MarshalledMap.at(String)` /
`MarshalledList.at(String)`, the new
+ <a
href="/site/apidocs/org/apache/juneau/marshall/collections/MarshalledNode.html"
target="_blank">MarshalledNode</a> typed tree façade
+ (`at` / `find` / `set` / `remove`), or the standalone <a
href="/site/apidocs/org/apache/juneau/marshall/collections/JsonPointer.html"
target="_blank">JsonPointer</a>
+ helper. See the [Tree Model & RFC 6901
JSON-Pointer](/docs/topics/MarshalledNode) page.
-:::tip Example
+:::tip Migration
```java
-// Construct an unstructured POJO model
-JsonMap map = JsonMap.ofString(""
- + "{"
- + " name:'John Smith', "
- + " address:{ "
- + " streetAddress:'21 2nd Street', "
- + " city:'New York', "
- + " state:'NY', "
- + " postalCode:10021 "
- + " }, "
- + " phoneNumbers:[ "
- + " '212 555-1111', "
- + " '212 555-2222' "
- + " ], "
- + " additionalInfo:null, "
- + " remote:false, "
- + " height:62.4, "
- + " 'fico score':' > 640' "
- + "} "
-
-);
-
-// Wrap Map inside an ObjectRest object
-ObjectRest johnSmith = ObjectRest.create(map);
-
-// Get a simple value at the top level
-// "John Smith"
-String name = johnSmith.getString("name");
-
-// Change a simple value at the top level
-johnSmith.put("name", "The late John Smith");
-
-// Get a simple value at a deep level
-// "21 2nd Street"
-String streetAddress = johnSmith.getString("address/streetAddress");
-
-// Set a simple value at a deep level
-johnSmith.put("address/streetAddress", "101 Cemetery Way");
-
-// Get entries in a list
-// "212 555-1111"
-String firstPhoneNumber = johnSmith.getString("phoneNumbers/0");
-
-// Add entries to a list
-johnSmith.post("phoneNumbers", "212 555-3333");
-
-// Delete entries from a model
-johnSmith.delete("fico score");
-
-// Add entirely new structures to the tree
-JsonMap medicalInfo = JsonMap.ofString(""
- + "{"
- + " currentStatus: 'deceased',"
- + " health: 'non-existent',"
- + " creditWorthiness: 'not good'"
- + "}"
-
-);
-johnSmith.put("additionalInfo/medicalInfo", medicalInfo);
-```
-:::
+JsonMap map = Json.to("{name:'John Smith',address:{streetAddress:'21 2nd
Street'},phoneNumbers:['212 555-1111']}", JsonMap.class);
-In the special case of `Collections`/arrays of `Maps`/beans, a special
XPath-like selector notation can be used in lieu of
-index numbers on GET requests to return a map/bean with a specified attribute
value.
-The syntax is `@attr=val`, where attr is the attribute name on the child map,
and val is the matching value.
+// OLD: ObjectRest johnSmith = ObjectRest.create(map);
+// String name = johnSmith.getString("name");
+// String street = johnSmith.getString("address/streetAddress");
-:::tip Example
-```java
-// Get map/bean with name attribute value of 'foo' from a list of items
-Map map = objectRest.getMap("/items/@name=foo");
+// NEW (unchanged slash-path navigation):
+String name = map.getAt("name", String.class);
+String street = map.getAt("address/streetAddress", String.class);
+map.putAt("address/streetAddress", "101 Cemetery Way");
+map.postAt("phoneNumbers", "212 555-3333");
+map.deleteAt("name");
+
+// NEW (RFC 6901 JSON-Pointer):
+String street2 = map.at("/address/streetAddress").asString();
```
:::
-:::note
-This class is used in the <a
href="/site/apidocs/org/apache/juneau/rest/server/converter/Traversable.html"
target="_blank">Traversable</a> REST response
-converter.
-:::
+The reflective `ObjectRest.invokeMethod(...)` / `getPublicMethods(...)`
helpers were dropped — use
+<a href="/site/apidocs/org/apache/juneau/objecttools/ObjectIntrospector.html"
target="_blank">ObjectIntrospector</a> directly if you need that
+capability. The companion exception was renamed to
+<a
href="/site/apidocs/org/apache/juneau/objecttools/PathTraversalException.html"
target="_blank">PathTraversalException</a>, and the
+<a
href="/site/apidocs/org/apache/juneau/rest/server/converter/Traversable.html"
target="_blank">Traversable</a> REST response
+converter is unaffected.
#### ObjectSearcher
diff --git a/sidebars.ts b/sidebars.ts
index 08288346c8..568cab0e4b 100644
--- a/sidebars.ts
+++ b/sidebars.ts
@@ -198,6 +198,11 @@ const sidebars: SidebarsConfig = {
id:
'topics/02.08.JsonMap',
label: '2.8. JsonMap
and JsonList',
},
+ {
+ type: 'doc',
+ id:
'topics/02.08.01.MarshalledNodeAndJsonPointer',
+ label: '2.8.1. Tree
Model & RFC 6901 JSON-Pointer',
+ },
{
type: 'doc',
id:
'topics/02.09.ComplexDataTypes',