Jakarta JSON-B + JAXB Integration

The fun-jakarta-jaxb module provides Jakarta JSON Binding (JSON-B) and Jakarta XML Binding (JAXB) adapters for all dmx-fun types. Both APIs are optional dependencies — the core fun library has no runtime dependency on either specification. fun-jakarta-jaxb declares both APIs as compileOnly, following the same peer-dependency pattern as fun-jackson.

Adding the dependency

You must supply a Jakarta EE or MicroProfile runtime that includes JSON-B and JAXB. For tests and standalone applications, add the reference implementations (Yasson + Parsson for JSON-B, JAXB RI for JAXB).

Gradle:

// dmx-fun adapter
implementation 'codes.domix:fun-jakarta-jaxb:VERSION'
// JSON-B API + reference implementation (tests / standalone)
implementation 'jakarta.json.bind:jakarta.json.bind-api:3.0.1'
implementation 'org.eclipse:yasson:3.0.4'
runtimeOnly 'org.eclipse.parsson:parsson:1.1.7'
// JAXB API + reference implementation (tests / standalone)
implementation 'jakarta.xml.bind:jakarta.xml.bind-api:4.0.2'
runtimeOnly 'com.sun.xml.bind:jaxb-impl:4.0.8'

Maven:

<dependency>
<groupId>codes.domix</groupId>
<artifactId>fun-jakarta-jaxb</artifactId>
<version>VERSION</version>
</dependency>
<!-- JSON-B RI (tests / standalone) -->
<dependency>
<groupId>jakarta.json.bind</groupId>
<artifactId>jakarta.json.bind-api</artifactId>
<version>3.0.1</version>
</dependency>
<dependency>
<groupId>org.eclipse</groupId>
<artifactId>yasson</artifactId>
<version>3.0.4</version>
</dependency>
<dependency>
<groupId>org.eclipse.parsson</groupId>
<artifactId>parsson</artifactId>
<version>1.1.7</version>
<scope>runtime</scope>
</dependency>

JSON-B adapters

Register all adapters at once via DmxFunJsonbAdapters.all():

Jsonb jsonb = JsonbBuilder.create(new JsonbConfig()
.withAdapters(DmxFunJsonbAdapters.all()));

JSON shapes

TypePresent / successAbsent / failure
Option<T>{"value": v}{}
Result<V,E>{"ok": v}{"err": e}
Try<V>{"value": v}{"error": "message"}
Either<L,R>{"right": r}{"left": l}
Validated<E,A>{"valid": a}{"invalid": e}
Tuple2<A,B>{"_1": a, "_2": b}
Tuple3<A,B,C>{"_1": a, "_2": b, "_3": c}
Tuple4<A,B,C,D>{"_1": a, "_2": b, "_3": c, "_4": d}
NonEmptyList<T>[head, …tail]

Example

Jsonb jsonb = JsonbBuilder.create(new JsonbConfig()
.withAdapters(DmxFunJsonbAdapters.all()));
// Serialise
String json = jsonb.toJson(Option.some("alice"));
// {"value":"alice"}
String none = jsonb.toJson(Option.none());
// {}
String ok = jsonb.toJson(Result.ok(42));
// {"ok":42}

JAXB adapters

Apply adapters field-by-field using @XmlJavaTypeAdapter:

@XmlRootElement
public class UserRecord {
@XmlJavaTypeAdapter(OptionXmlAdapter.class)
public Option<String> nickname;
@XmlJavaTypeAdapter(ResultXmlAdapter.class)
public Result<Integer, String> score;
@XmlJavaTypeAdapter(EitherXmlAdapter.class)
public Either<String, String> decision;
}

XML shapes

TypePresent / successAbsent / failure
Option<T><f><value>v</value></f><f/>
Result<V,E><f><ok>v</ok></f><f><err>e</err></f>
Try<V><f><value>v</value></f><f><error>msg</error></f>
Either<L,R><f><right>r</right></f><f><left>l</left></f>

All string values are serialised as String.valueOf(v). Deserialisation returns the string representation as-is; for typed deserialization in a full Jakarta EE context, wrap the adapted field in a richer enclosing type with @XmlJavaTypeAdapter at the package or class level.

Version compatibility

The module is tested in CI against the following combinations on every pull request that touches the jakarta-jaxb/ module:

Jakarta JSON-BYassonJakarta JAXBStatus
2.0.02.0.43.0.1tested (EE 9)
3.0.03.0.34.0.0tested (EE 10)
3.0.13.0.44.0.2tested (latest)

To test locally against a specific combination:

Terminal window
./gradlew :jakarta-jaxb:test \
-PjakartaJsonbVersion=2.0.0 -PyassonVersion=2.0.4 \
-PjakartaJaxbVersion=3.0.1 -PjaxbImplVersion=3.0.2 \
-PjakartaJsonApiVersion=2.0.2 -PparssonVersion=1.1.7