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 ce2ef13627 docs: document sorted-properties default change, removed
sortProperties API, and MarshallUtils overloads
ce2ef13627 is described below
commit ce2ef136272b1ce54eb4d3370fcc43161f28db43
Author: James Bognar <[email protected]>
AuthorDate: Mon May 4 08:41:08 2026 -0400
docs: document sorted-properties default change, removed sortProperties
API, and MarshallUtils overloads
Co-authored-by: Cursor <[email protected]>
---
pages/release-notes/9.2.1.md | 81 ++++++++++++++++++++++++++--
pages/topics/02.02.Marshallers.md | 94 ++++++++++++++++++++++++++++++++-
pages/topics/02.04.03.BeanAnnotation.md | 27 ++++++++--
3 files changed, 192 insertions(+), 10 deletions(-)
diff --git a/pages/release-notes/9.2.1.md b/pages/release-notes/9.2.1.md
index 761cc51524..5ce80357e8 100644
--- a/pages/release-notes/9.2.1.md
+++ b/pages/release-notes/9.2.1.md
@@ -6,7 +6,7 @@ title: "Release 9.2.1"
**Date:** TBD
-Juneau 9.2.1 is a minor release with native TOML and YAML support, BSON
(Binary JSON) support for MongoDB-interoperable binary serialization, CBOR
(Concise Binary Object Representation) per RFC 8949 for IoT and constrained
environments, full CSV serializer/parser support, JCS (JSON Canonicalization
Scheme) per RFC 8785 for deterministic hashing and signing, RDF/THRIFT and
RDF/PROTO binary format support, native serialization support for
lazy-evaluated sequence types, large-dataset stream [...]
+Juneau 9.2.1 is a minor release with native TOML and YAML support, BSON
(Binary JSON) support for MongoDB-interoperable binary serialization, CBOR
(Concise Binary Object Representation) per RFC 8949 for IoT and constrained
environments, full CSV serializer/parser support, JCS (JSON Canonicalization
Scheme) per RFC 8785 for deterministic hashing and signing, RDF/THRIFT and
RDF/PROTO binary format support, native serialization support for
lazy-evaluated sequence types, large-dataset stream [...]
### juneau-marshall
@@ -244,6 +244,52 @@ For JSON5 syntax (single quotes, comments, trailing
commas, unquoted keys), use
See [JSON Basics](/docs/topics/JsonBasics), [JSON
Parsers](/docs/topics/JsonParsers), and [JSON 5](/docs/topics/Json5) for full
documentation.
+#### Sorted Bean Properties by Default; `@Bean(unsorted)` Opt-Out
+
+Bean properties are now serialized in **alphabetical order by default** across
all serializers. Previously, the default was natural JVM order and opting in
to sorted output required explicit configuration.
+
+**New API:**
+
+- **`@Bean(unsorted=true)`** — Opts a specific bean class out of the default
sorted order, using natural JVM property order instead.
+- **`BeanContext.Builder.unsortedProperties()`** — Disables sorted properties
globally for all beans.
+- **`BeanContext.Builder.unsortedProperties(Class<?>...on)`** — Disables
sorted properties for specific bean classes only.
+- **`BeanFilter.Builder.unsortedProperties()`** — Per-bean-filter opt-out of
sorted properties.
+- **`BeanFilter.isUnsortedProperties()`** — Returns `true` if this bean filter
opts out of sorting.
+- **`BeanSession.isUnsortedProperties()`** — Session-level accessor for the
unsorted flag.
+
+**Migration:**
+
+```java
+// Before: opt in to sorted output
+@Bean(sort=true)
+public class MyBean { ... }
+
+// After: sorted is the default, opt out with unsorted=true
+@Bean(unsorted=true)
+public class MyBean { ... } // opts out of default sorted behavior
+
+// Before: global sorted flag required explicit opt-in
+JsonSerializer s = JsonSerializer.create().sortProperties().build();
+
+// After: sorted by default; use unsortedProperties() to opt out
+JsonSerializer s = JsonSerializer.create().unsortedProperties().build();
+```
+
+**Removed API:**
+
+- `@Bean(sort)` — Removed. Use `@Bean(unsorted=true)` with inverted semantics.
+- `BeanContext.Builder.sortProperties()` / `sortProperties(boolean)` —
Removed. Use `unsortedProperties()`.
+- `BeanContext.Builder.sortProperties(Class<?>...on)` — Removed. Use
`unsortedProperties(Class<?>...on)`.
+- `BeanContextable.Builder.sortProperties()` / `sortProperties(Class<?>...on)`
— Removed. Use `unsortedProperties()` / `unsortedProperties(Class<?>...on)`.
+- `BeanFilter.Builder.sortProperties()` / `sortProperties(boolean)` — Removed.
Use `unsortedProperties()`.
+- `BeanFilter.isSortProperties()` / `BeanSession.isSortProperties()` —
Removed. Use `isUnsortedProperties()`.
+- `BeanMeta.isSortProperties()` — Removed. Use `isUnsortedProperties()`.
+- All serializer/parser builder `sortProperties()` /
`sortProperties(Class<?>...on)` overrides — Removed.
+
+**Internal rename:**
+
+- `BeanMeta.sortProperties` field — Renamed to `unsortedProperties` with
inverted semantics. The field now stores `true` when the bean opts out of
default sorted order, rather than `true` when sorted is explicitly enabled.
+
#### `@BeanIgnore(ignoreAccessors=true)` on fields
`@BeanIgnore` gains **`ignoreAccessors`** (default **`false`**) for use on
**fields**. When **`ignoreAccessors = true`**, `BeanMeta` also excludes the
matching **JavaBean accessor pair** (`getX`/`setX`, or `isX` for booleans) from
bean property discovery, so the property is omitted from serialization,
parsing, and `BeanMap` metadata while accessors can remain for other frameworks.
@@ -849,9 +895,36 @@ List<MyBean> beans = parquet(bytes, MyBean.class);
| `bson(o)` | BSON | `byte[]` |
| `parquet(o)` | Apache Parquet | `byte[]` |
-Every text format also has a corresponding parse overload (same method name,
`String` + `Class<T>` arguments).
-Binary formats have a `byte[]` + `Class<T>` parse overload. Parse methods
wrap checked exceptions in unchecked
-runtime exceptions so they can be used in lambdas and streams without
`try/catch`.
+##### Full Overload Set
+
+Every format method is overloaded across the following signatures:
+
+| Signature | Purpose |
+|---|---|
+| `format(Object)` | Serialize to `String` (text) or `byte[]` (binary) |
+| `format(Object, Object)` | Serialize to a `Writer`, `OutputStream`, `File`,
or `StringBuilder` |
+| `format(Object, Class<T>)` | Parse from any input (`String`, `byte[]`,
`File`, `Reader`, etc.) — throws `IOException` |
+| `format(Object, Type, Type...)` | Parse from any input with a parameterized
type |
+| `format(String, Class<T>)` | Parse from `String` — wraps exceptions in
unchecked runtime exceptions |
+| `format(String, Type, Type...)` | Parse from `String` with a parameterized
type — unchecked |
+| `format(byte[], Class<T>)` | Parse from `byte[]` (binary formats) —
unchecked |
+| `format(byte[], Type, Type...)` | Parse from `byte[]` with a parameterized
type (binary formats) — unchecked |
+
+The checked overloads (`Object`-based input) propagate `ParseException` and
`IOException`. The `String`- and
+`byte[]`-based overloads wrap checked exceptions in unchecked runtime
exceptions so they can be used directly
+in lambdas and streams without `try/catch`.
+
+All methods are designed for `static import`; no explicit marshaller reference
is needed at call sites.
+
+##### Also updated: `Jcs` and `Parquet` marshallers
+
+Both marshaller classes were updated to expose the full static API:
+
+- **`Jcs`** — Added `of(Object, Object)`, `to(Object, Class)`, `to(Object,
Type, Type...)`,
+ `to(String, Type, Type...)` to match the standard char-marshaller contract.
+- **`Parquet`** — Added `of(Object, Object)`, `to(Object, Class)`, `to(Object,
Type)`,
+ `to(byte[], Type, Type...)` (Parquet parse methods return `List<T>` since
the format is
+ always collection-oriented).
#### `JsonMap` and `JsonList`: New `toX()` Serialization Methods
diff --git a/pages/topics/02.02.Marshallers.md
b/pages/topics/02.02.Marshallers.md
index 69bb687cde..4230eaf3e4 100644
--- a/pages/topics/02.02.Marshallers.md
+++ b/pages/topics/02.02.Marshallers.md
@@ -65,4 +65,96 @@ marshalling on POJOs:
MyPojo myPojo = Json.to(jsonString, MyPojo.class);
String json = Json.of(myPojo);
```
-:::
\ No newline at end of file
+:::
+
+## MarshallUtils
+
+`MarshallUtils` provides a single set of **statically-imported convenience
methods** that cover every
+serialization format. Instead of referencing a specific marshaller class, you
import `MarshallUtils.*`
+and call format-named methods directly.
+
+```java
+import static org.apache.juneau.marshaller.MarshallUtils.*;
+
+// Serialize to any text format
+String a = json(myBean);
+String b = json5(myBean);
+String c = xml(myBean);
+String d = yaml(myBean);
+String e = toml(myBean);
+String f = csv(myBean);
+
+// Serialize to binary formats
+byte[] m = msgPack(myBean);
+byte[] n = cbor(myBean);
+byte[] o = bson(myBean);
+
+// Parse — same method name, overloaded by input
+MyBean b1 = json(jsonString, MyBean.class);
+MyBean b2 = xml(xmlString, MyBean.class);
+MyBean b3 = msgPack(bytes, MyBean.class);
+```
+
+### Supported Formats
+
+| Method | Format | Serialize output |
+|---|---|---|
+| `json(o)` | Standard JSON (RFC 8259) | `String` |
+| `json5(o)` | JSON5 | `String` |
+| `jsonl(o)` | JSON Lines (NDJSON) | `String` |
+| `jcs(o)` | Canonical JSON (RFC 8785) | `String` |
+| `hjson(o)` | HJSON | `String` |
+| `xml(o)` | XML | `String` |
+| `html(o)` | HTML | `String` |
+| `uon(o)` | URL-Encoded Object Notation | `String` |
+| `urlEncoding(o)` | URL Encoding | `String` |
+| `yaml(o)` | YAML | `String` |
+| `csv(o)` | CSV | `String` |
+| `openApi(o)` | OpenAPI | `String` |
+| `plainText(o)` | Plain text | `String` |
+| `markdown(o)` | Markdown (fragment) | `String` |
+| `markdownDoc(o)` | Markdown (document) | `String` |
+| `ini(o)` | INI / properties | `String` |
+| `toml(o)` | TOML | `String` |
+| `hocon(o)` | HOCON | `String` |
+| `proto(o)` | Protobuf Text Format | `String` |
+| `msgPack(o)` | MessagePack | `byte[]` |
+| `cbor(o)` | CBOR (RFC 8949) | `byte[]` |
+| `bson(o)` | BSON | `byte[]` |
+| `parquet(o)` | Apache Parquet | `byte[]` |
+
+### Overload Set
+
+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, 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 |
+| `format(String, Type, Type...)` | Parse from `String` with a parameterized
type — unchecked |
+| `format(byte[], Class<T>)` | Parse from `byte[]` (binary formats) —
unchecked |
+| `format(byte[], Type, Type...)` | Parse from `byte[]` with a parameterized
type — unchecked |
+
+The `String`- and `byte[]`-input overloads wrap `ParseException` /
`IOException` in unchecked
+runtime exceptions so they can be used directly in lambdas and streams.
+
+```java
+// Checked overload — use when the caller can handle IOException
+MyBean bean = json(reader, MyBean.class);
+
+// Unchecked overload — convenient in lambdas/streams
+List<MyBean> beans = inputStrings.stream()
+ .map(s -> json(s, MyBean.class))
+ .toList();
+
+// Parameterized type
+List<MyBean> list = json(jsonString, List.class, MyBean.class);
+Map<String, MyBean> map = json(jsonString, Map.class, String.class,
MyBean.class);
+
+// Write to an existing Writer or OutputStream
+json(myBean, responseWriter);
+msgPack(myBean, outputStream);
+```
\ No newline at end of file
diff --git a/pages/topics/02.04.03.BeanAnnotation.md
b/pages/topics/02.04.03.BeanAnnotation.md
index 7f93f3d24d..623ff35f03 100644
--- a/pages/topics/02.04.03.BeanAnnotation.md
+++ b/pages/topics/02.04.03.BeanAnnotation.md
@@ -24,15 +24,32 @@ Bean properties can be excluded using the <a
href="/site/apidocs/org/apache/june
public class Address { ... }
```
-Bean properties can be sorted alphabetically using <a
href="/site/apidocs/org/apache/juneau/annotation/Bean.html#sort()"
target="_blank">@Bean(sort)</a>
+Bean properties are sorted alphabetically by default. To opt a specific bean
out of this default sorting, use <a
href="/site/apidocs/org/apache/juneau/annotation/Bean.html#unsorted()"
target="_blank">@Bean(unsorted)</a>:
```java
-// Address class with only street/city/state properties (in that order).
-// All other properties are ignored.
-@Bean(sort=true)
+// Opt this bean out of the default alphabetical property ordering.
+@Bean(unsorted=true)
public class MyBean { ... }
```
+Sorting can also be disabled globally for all beans via
`BeanContext.Builder.unsortedProperties()`:
+
+```java
+WriterSerializer serializer = JsonSerializer
+ .create()
+ .unsortedProperties() // disable sorting for all beans
+ .build();
+```
+
+Or for individual classes without modifying the bean class itself:
+
+```java
+WriterSerializer serializer = JsonSerializer
+ .create()
+ .unsortedProperties(MyBean.class) // disable sorting for MyBean only
+ .build();
+```
+
The <a
href="/site/apidocs/org/apache/juneau/annotation/Bean.html#propertyNamer()"
target="_blank">@Bean(propertyNamer)</a> annotation is used to
provide customized naming of properties.
@@ -125,7 +142,7 @@ public class Address {
The <a href="/site/apidocs/org/apache/juneau/annotation/Bean.html#on()"
target="_blank">@Bean(on)</a> and <a
href="/site/apidocs/org/apache/juneau/annotation/Bean.html#onClass()"
target="_blank">@Bean(onClass)</a> annotations can be used to programmatically
attach @Bean annotations to classes.
```java
-@Bean(onClass=Address.class, sort=true, excludeProperties="city,state")
+@Bean(onClass=Address.class, unsorted=true, excludeProperties="city,state")
public class MyAnnotatedClass {...}
// Create a serializer configured using annotations.