Configuration

Note: This document describes the current v1 configuration options for 0.1.0.

All configuration is done through the JsonBuilder fluent API:

import io.github.arthurhoch.kissjson.Json;
import io.github.arthurhoch.kissjson.FieldNaming;
import io.github.arthurhoch.kissjson.DateFormat;
import io.github.arthurhoch.kissjson.EnumMode;

Json json = Json.builder()
    .fieldNaming(FieldNaming.SNAKE_CASE)
    .includeNulls(false)
    .failOnUnknownProperties(true)
    .maxDepth(64)
    .prettyPrint(true)
    .build();

Configuration is immutable after build(). The resulting Json instance is thread-safe for reads.


Options Reference

fieldNaming

Property Value
Type FieldNaming
Default FieldNaming.IDENTITY

Description:

Naming strategy for converting Java field names to JSON keys and matching JSON keys to Java fields during deserialization.

Effect on serialization:

Java field names are transformed according to the strategy before writing as JSON keys. @JsonName annotations take precedence over this strategy.

Strategy userName becomes
IDENTITY userName
LOWER_CASE username
UPPER_CASE USERNAME
CAMEL_CASE userName
SNAKE_CASE user_name
KEBAB_CASE user-name

Effect on deserialization:

JSON keys are matched against Java fields using the same strategy. Matching also considers @JsonName and @JsonAliases.

Json json = Json.builder().fieldNaming(FieldNaming.SNAKE_CASE).build();

// Java field "firstName" matches JSON key "first_name"

includeNulls

Property Value
Type boolean
Default true

Description:

Whether to include fields with null values in the serialized JSON output.

Effect on serialization:

Can be overridden per-field with @JsonIncludeNull and @JsonExcludeNull.

Effect on deserialization:

None. This option only affects serialization output.

Json json = Json.builder().includeNulls(false).build();

User user = new User();
user.name = "Alice";
// email is null

String text = json.stringify(user);
// {"name":"Alice"}

failOnUnknownProperties

Property Value
Type boolean
Default false

Description:

Whether to throw a JsonMappingException when a JSON object key has no matching Java field.

Effect on serialization:

None. This option only affects deserialization.

Effect on deserialization:

Json json = Json.builder().failOnUnknownProperties(true).build();

String input = """
    {"name":"Alice","phone":"555-1234"}
    """;

// Throws JsonMappingException: Unknown property 'phone' at $ [target=User]
User user = json.parse(input, User.class);

failOnMissingRequiredFields

Property Value
Type boolean
Default false

Description:

Whether to throw a JsonMappingException when a field annotated with @JsonRequired is missing from the JSON input.

Effect on serialization:

None. This option only affects deserialization.

Effect on deserialization:

This option only enforces fields that are annotated with @JsonRequired; it does not make every field required.

public class User {
    @JsonRequired String email;
    String name;
}

Json json = Json.builder().failOnMissingRequiredFields(true).build();

// Throws JsonMappingException: Required field 'email' is missing
json.parse("{\"name\":\"Alice\"}", User.class);

failOnNullForPrimitives

Property Value
Type boolean
Default false

Description:

Whether to throw a JsonMappingException when a null JSON value would be assigned to a primitive Java field (int, long, boolean, etc.).

Effect on serialization:

None. This option only affects deserialization.

Effect on deserialization:

public class Score {
    int value;
}

Json json = Json.builder().failOnNullForPrimitives(true).build();

// Throws JsonMappingException: Cannot assign null to primitive int at $.value
json.parse("{\"value\":null}", Score.class);

With the default (false):

Json json = Json.create();
Score score = json.parse("{\"value\":null}", Score.class);
// score.value == 0 (default int value)

failOnDuplicateKeys

Property Value
Type boolean
Default false

Description:

Whether to throw a JsonParseException when a JSON object contains duplicate keys.

Effect on serialization:

None. This option only affects deserialization/parsing.

Effect on deserialization:

Json json = Json.builder().failOnDuplicateKeys(true).build();

String input = """
    {"name":"Alice","name":"Bob"}
    """;

// Throws JsonParseException: Duplicate key 'name' at line 1, column 22
json.parse(input, User.class);

failOnCycles

Property Value
Type boolean
Default true

Description:

Whether to detect circular references (object cycles) during serialization and throw a JsonException.

Effect on serialization:

Cycle detection uses identity comparison (==), not equals(), so distinct objects with equal content are not flagged.

Effect on deserialization:

None. This option only affects serialization.

public class Node {
    String value;
    Node next;
}

Node a = new Node();
a.value = "A";
Node b = new Node();
b.value = "B";
a.next = b;
b.next = a; // cycle

Json json = Json.create();
json.stringify(a);
// Throws JsonException: Cycle detected at $.next.next

maxDepth

Property Value
Type int
Default 128

Description:

Maximum nesting depth for both serialization and deserialization. Prevents deeply nested structures from causing StackOverflowError.

Effect on serialization:

If the object graph exceeds maxDepth nesting levels, a JsonException is thrown.

Effect on deserialization:

If the JSON input exceeds maxDepth nesting levels, a JsonException is thrown.

Json json = Json.builder().maxDepth(64).build();

// If JSON has more than 64 levels of nesting, parsing fails

prettyPrint

Property Value
Type boolean
Default false

Description:

Whether to format JSON output with indentation (2 spaces per level).

Effect on serialization:

{
  "name": "Alice",
  "age": 30
}

Effect on deserialization:

None. The parser handles both compact and pretty-printed JSON regardless of this setting.

Json json = Json.builder().prettyPrint(true).build();

dateFormat

Property Value
Type DateFormat
Default DateFormat.ISO

Description:

Global strategy for serializing and deserializing date/time types.

Effect on serialization:

Strategy Output
ISO ISO-8601 string: "2025-01-15T10:30:00"
EPOCH_MILLIS Long epoch milliseconds for instant-like temporal types
EPOCH_SECONDS Long epoch seconds for instant-like temporal types

Effect on deserialization:

Strategy Accepts
ISO ISO-8601 string
EPOCH_MILLIS Number for instant-like temporal types
EPOCH_SECONDS Number for instant-like temporal types

Can be overridden per-field with @JsonDateFormat("pattern").

Epoch formats apply to Instant, OffsetDateTime, ZonedDateTime, Date, and Calendar. LocalDate, LocalTime, LocalDateTime, Duration, and Period remain ISO because converting them to an epoch loses local semantic information.

Json json = Json.builder().dateFormat(DateFormat.EPOCH_MILLIS).build();

Event event = new Event();
event.timestamp = Instant.parse("2025-01-15T10:30:00Z");

String text = json.stringify(event);
// {"timestamp":1736934600000}

zoneId

Property Value
Type java.time.ZoneId
Default ZoneId.of("UTC")

Description:

Timezone used for converting java.util.Date and java.util.Calendar to/from java.time types internally.

Effect on serialization:

Date and Calendar values are converted to the specified timezone for ISO-8601 output.

Effect on deserialization:

Date and Calendar values are constructed using the specified timezone.

This option does not affect java.time types (they have their own timezone/offset information).

import java.time.ZoneId;

Json json = Json.builder()
    .zoneId(ZoneId.of("America/New_York"))
    .build();

enumMode

Property Value
Type EnumMode
Default EnumMode.NAME

Description:

Strategy for serializing and deserializing enum values.

Effect on serialization:

Mode Output
NAME Enum.name() — the declared enum constant name: "ACTIVE"
TO_STRING Enum.toString() — the custom string representation

Effect on deserialization:

Mode Matching
NAME Match by Enum.name() (case-sensitive)
TO_STRING Match by Enum.toString() (case-sensitive)

If no enum constant matches, a JsonMappingException is thrown with the invalid value and the enum type.

Json json = Json.builder().enumMode(EnumMode.NAME).build();

// Serialization: Status.ACTIVE -> "ACTIVE"
// Deserialization: "ACTIVE" -> Status.ACTIVE

Configuration Summary

Option Type Default Serialization Deserialization
fieldNaming FieldNaming IDENTITY Transforms field names Matches JSON keys
includeNulls boolean true Include/exclude null fields
failOnUnknownProperties boolean false Throw on unknown keys
failOnMissingRequiredFields boolean false Throw on missing required
failOnNullForPrimitives boolean false Throw on null → primitive
failOnDuplicateKeys boolean false Throw on duplicate keys
failOnCycles boolean true Detect cycles
maxDepth int 128 Limit nesting depth Limit nesting depth
prettyPrint boolean false Format with indentation
dateFormat DateFormat ISO Date format strategy Date format strategy
zoneId ZoneId UTC Timezone for Date/Calendar Timezone for Date/Calendar
enumMode EnumMode NAME Enum representation Enum matching

Thread Safety and Immutability

// Safe: build once, share across threads
Json json = Json.builder()
    .fieldNaming(FieldNaming.SNAKE_CASE)
    .includeNulls(false)
    .build();

// Multiple threads can use json concurrently
ExecutorService executor = Executors.newFixedThreadPool(10);
executor.submit(() -> json.stringify(user));   // thread-safe
executor.submit(() -> json.parse(text, User.class)); // thread-safe

Annotation Overrides

Annotations override global configuration at the field level:

Annotation Overrides
@JsonName fieldNaming — always uses the specified name
@JsonAliases Adds extra key matches during deserialization
@JsonIgnore Always excludes regardless of other settings
@JsonRequired Marks a field for required-field enforcement when failOnMissingRequiredFields is true
@JsonIncludeNull includeNulls = false — includes this field even when null
@JsonExcludeNull includeNulls = true — excludes this field when null
@JsonDateFormat dateFormat — uses the specified pattern for this field

All configuration options described above are the current v1 contract for 0.1.0.