TOML
Juneau supports converting arbitrary POJOs to and from TOML (Tom's Obvious Minimal Language) using native serializers and parsers implemented without any external dependencies.
TOML is a configuration file format that maps unambiguously to hash tables, widely used in projects like Cargo (Rust) and Python's pyproject.toml.
The TomlSerializer converts POJOs directly to TOML format, and the TomlParser creates POJOs directly from TOML without intermediate DOM objects.
TOML support is included in juneau-marshall.
| Maven | |
|---|
Quick Start
// Serialize a map to TOML
Map<String, Object> config = new LinkedHashMap<>();
config.put("name", "myapp");
config.put("port", 8080);
Map<String, Object> db = new LinkedHashMap<>();
db.put("host", "localhost");
db.put("port", 5432);
config.put("database", db);
String toml = Toml.of(config);
Produces:
name = "myapp"
[database]
host = "localhost"
port = 5432
Parsing
// Parse TOML into a Map or JsonMap
JsonMap parsed = Toml.to(toml, JsonMap.class);
String name = parsed.getString("name");
JsonMap dbConfig = parsed.getMap("database");
String host = (String) dbConfig.get("host");
Long port = (Long) dbConfig.get("port");
// Parse into a bean
MyConfig config = Toml.to(toml, MyConfig.class);
Serialization
// Use the default serializer
String toml = TomlSerializer.DEFAULT.write(someObject);
// Use the marshaller for convenience
String toml = Toml.of(someObject);
Supported TOML Features
The implementation conforms to the TOML v1.0.0 specification:
- Key-value pairs - Strings, integers, floats, booleans, dates, and arrays
- Tables -
[section]and nested[parent.child]tables - Inline tables -
{key = "value"}for simple nested structures - Arrays - Homogeneous arrays of primitives, strings, and inline tables
- Strings - Basic (
"..."), literal ('...'), and multi-line variants - Dates and times - LocalDate, LocalTime, LocalDateTime, OffsetDateTime (ISO 8601)
Bean-to-TOML Mapping
- Simple properties become key-value pairs.
- Nested beans and string-keyed maps become
[table]sections (or inline tables, see below). - Collections of simple values become arrays (
tags = ["a", "b"]). - Collections of beans/maps become arrays of tables (
[[name]]). - Null properties are omitted (TOML has no null); see
nullValuebelow. - Maps with non-string keys have their keys converted with
toString(). - Root-level arrays use
[[item]]for beans/maps, or a_valuewrapper for primitives and simple arrays.
Pre-configured instances
| Instance | Description |
|---|---|
TomlSerializer.DEFAULT | Default settings. |
TomlSerializer.DEFAULT_READABLE | Same, with ws() (whitespace) enabled. |
TomlParser.DEFAULT | Default parser. |
Serializer settings
Configured through TomlSerializer.create()
(see TomlSerializer.Builder),
in addition to the settings inherited from WriterSerializer.
| Builder method | Default | Description |
|---|---|---|
useInlineTables(boolean) | true | Write small nested objects as inline tables (addr = {city = "Boston", state = "MA"}) instead of [table] sections. |
inlineTableThreshold(int) | 3 | Maximum number of properties for a nested object to be written inline. |
sortKeys(boolean) | false | Sort keys alphabetically in the output. |
nullValue(String) | "<NULL>" | String written for null values when keepNullProperties() is enabled. Chosen so it is not confused with the literal string "null". |
useWhitespace() / ws() | off | Inherited whitespace setting. |
TomlSerializer s = TomlSerializer.create()
.useInlineTables(false)
.sortKeys(true)
.build();
With useInlineTables(false), a bean having a nested address bean is written as:
age = 30
name = "Alice"
tags = ["a", "b"]
[address]
city = "Boston"
state = "MA"
Null handling:
// Write null properties as nick = "~" rather than omitting them.
TomlSerializer s = TomlSerializer.create().keepNullProperties().nullValue("~").build();
Parser settings
| Builder method | Default | Description |
|---|---|---|
nullValue(String) | "<NULL>" | A string value equal to this marker is parsed as Java null. Must match the serializer's nullValue. |
// Round-trip nulls using a custom marker.
TomlParser p = TomlParser.create().nullValue("~").build();
MyBean b = p.read(toml, MyBean.class);
Notes:
- TOML has no native duration type; quoted ISO 8601 duration strings (e.g.
"PT1H30M") parse toDuration. - A bare 4-digit integer parses as a
Longrather than aYear; use a quoted string forYear.
Media Types
- Produces:
application/toml - Accept:
application/toml,text/toml
REST Integration
// Use BasicTomlConfig for TOML-only REST resources
@Rest
public class MyResource extends RestServlet implements BasicTomlConfig { ... }
// TOML is also included in BasicUniversalConfig
@Rest
public class MyResource extends RestServlet implements BasicUniversalConfig { ... }
Annotations
@TomlConfig applies to both TomlSerializer and TomlParser
on a REST class or method (see Context Annotations). Its only attribute today is rank;
TOML has no @Toml data annotation or @TomlApply.
- TOML v1.0.0 Specification for the full grammar and semantics.