Skip to main content

CBOR

Juneau supports converting arbitrary POJOs to and from CBOR (Concise Binary Object Representation) per RFC 8949 using native serializers and parsers. CBOR is a compact binary format designed for extremely small code size, very small message size, and extensibility. It is widely used in IoT, constrained environments, COSE (CBOR Object Signing and Encryption), and WebAuthn.

The CborSerializer converts POJOs directly to CBOR format, and the CborParser creates POJOs directly from CBOR.

CBOR shares the same data model as JSON: maps, arrays, strings, numbers, booleans, and null. Compared to MsgPack, CBOR follows a different specification (RFC 8949) with different encoding rules and a larger ecosystem (IETF standards, COSE, WebAuthn).

CBOR support is included in juneau-marshall.

Maven
<dependency>
<groupId>org.apache.juneau</groupId>
<artifactId>juneau-marshall</artifactId>
<version>${juneau.version}</version>
</dependency>

Quick Start​

// A simple bean
public class Person {
public String name;
public int age;
public Person() {}
public Person(String name, int age) { this.name = name; this.age = age; }
}

// Serialize a bean to CBOR
Person alice = new Person("Alice", 30);
byte[] cbor = Cbor.of(alice);

// Parse CBOR into a bean
Person parsed = Cbor.to(cbor, Person.class);

Parsing​

// Parse CBOR into a bean
Person p = Cbor.to(cbor, Person.class);

// Parse into a map
JsonMap map = Cbor.to(cbor, JsonMap.class);

// Parse from InputStream
try (InputStream is = new FileInputStream("data.cbor")) {
Person p = Cbor.to(is, Person.class);
}

Serialization​

// Use the default serializer
byte[] cbor = CborSerializer.DEFAULT.write(someObject);

// Use the marshaller for convenience
byte[] cbor = Cbor.of(someObject);

// Serialize to OutputStream
try (OutputStream os = new FileOutputStream("data.cbor")) {
Cbor.of(someObject, os);
}

Java-to-CBOR Type Mapping​

Java TypeCBOR EncodingNotes
Bean, MapMap (major type 5)Nested structures
Collection, arrayArray (major type 4)Definite-length
String, EnumText string (major type 3)UTF-8
int, long (positive)Unsigned integer (major type 0)Compact encoding
int, long (negative)Negative integer (major type 1)-1-n encoding
floatFloat32 (0xFA)IEEE 754 single
doubleFloat64 (0xFB)IEEE 754 double
booleanSimple value 20/21 (0xF4/0xF5)
nullSimple value 22 (0xF6)
byte[]Byte string (major type 2)Native binary
Date, Instant, etc.Text stringISO 8601
DurationText stringISO 8601 duration

SpacedHex and Base64 Variants​

For debugging and text-based transport, CBOR provides SpacedHex and Base64 variants:

// Spaced-hex output: "A2 61 78 01 61 79 02"
String hex = CborSerializer.SpacedHex.DEFAULT.write(bean);
JsonMap parsed = CborParser.SpacedHex.DEFAULT.read(hex, JsonMap.class);

// Base64 output
String b64 = CborSerializer.Base64.DEFAULT.write(bean);
JsonMap parsed = CborParser.Base64.DEFAULT.read(b64, JsonMap.class);

Media Types​

  • Produces: application/cbor
  • Accepts: application/cbor

REST Integration​

// CBOR support is included via BasicUniversalConfig (there is no dedicated CBOR-only config interface).
@Rest
public class MyResource extends RestServlet implements BasicUniversalConfig { ... }

Limitations​

  • BigInteger/BigDecimal: Cast to long/double; precision loss for values exceeding range. Use ObjectSwap for string serialization if needed.
  • Indefinite-length: Parser does not support indefinite-length arrays/maps from external producers.
  • Half-precision float: Serializer always uses float32/float64; parser accepts float16 from external producers.
  • Semantic tags: Parser ignores tag numbers; tagged value is parsed normally. Tag output deferred to future release.

Token Streaming​

CBOR is a FULL-capability streaming format. The CborParser implements TokenReadable and ArrayRecordReadable; the CborSerializer implements TokenWritable and ArrayRecordWritable. This means you can read and write CBOR using fine-grained structural token cursors in O(1) memory, without materializing the entire document.

// Read CBOR tokens one at a time
try (TokenReader r = CborParser.DEFAULT.readTokens(cborBytes)) {
while (r.next() != TokenType.END_OF_STREAM) {
// inspect r.getCurrentToken(), r.getString(), etc.
}
}

// Write CBOR tokens directly
ByteArrayOutputStream baos = new ByteArrayOutputStream();
try (TokenWriter w = CborSerializer.DEFAULT.writeTokens(baos)) {
w.startObject();
w.fieldName("name");
w.string("Alice");
w.endObject();
}

See Token-Streaming Basics for the full capability matrix and API overview, Token Streaming for the TokenReader/TokenWriter API, and Array-Record Streaming for element-by-element streaming over top-level arrays (CBOR uses indefinite-length arrays on write, so the array-record writer needs no element count).

Annotations​

@CborConfig sets serializer/parser properties on a REST class or method (see Context Annotations). Attributes are strings:

AttributeDescription
addBeanTypesAdd _type properties to beans whose type can't be inferred through reflection (default false).
useTagsUse CBOR semantic tags for dates and other typed values (default false).
maxLengthMaximum wire-declared length for byte/text strings and array/map element counts when parsing.
rankOrdering relative to other config annotations.
@Rest
@CborConfig(useTags="true", maxLength="1048576")
public class MyResource extends BasicRestServlet { ... }

@Cbor is a class/method/field marker (its only attribute is description), and @CborApply applies it to other classes/members via on()/onClass() (see Dynamically Applied Annotations).

See Also​