SJF4J — Simple JSON Facade for Java
SJF4J is a lightweight facade over multiple JSON libraries, including Jackson 2.x, Gson, Fastjson2, JSON-P.
Beyond JSON, it also supports YAML (via SnakeYAML) and Java Properties (built-in).
SJF4J provides a unified JSON-semantic structural processing layer, delivering consistent and expressive APIs for parsing, navigation, transformation, and validation across data formats and native object graphs.
Install
SJF4J requires JDK 8+ and has no external dependencies.
Gradle
implementation("org.sjf4j:sjf4j:{version}")Maven
<dependency>
<groupId>org.sjf4j</groupId>
<artifactId>sjf4j</artifactId>
<version>{version}</version>
</dependency>Optional Runtime Backends
SJF4J itself has no external runtime dependencies.
Format support is activated automatically when the corresponding libraries are present.
JSON — Include one of:
Jackson 2.x,Gson,Fastjson2, orJSON-P(withParssonor other).
SJF4J automatically detects and uses the first available implementation in that order. If none are detected, it falls back to a built-in minimal JSON parser (functional but slower).YAML — Include
SnakeYAML.Java Properties — A built-in parser is provided.
Conversions from Java Properties are inherently constrained by its flat key-value structure.In-Memory Usage (No External Data) — Built-in.
SJF4J can operate directly on in-memory object graphs through OBNT, providing the same JSON-semantic APIs for navigation, transformation, and validation.
Quickstart
SJF4J is built around a single structural model: the Object-Based Node Tree (OBNT).
- All structured data in SJF4J are mapped into OBNT.
- All nodes in OBNT are represented as native Java objects -- no dedicated AST.
- All APIs operate directly on native Java objects.
- All APIs follow -- or extend -- standard JSON semantics.
The following example, while slightly more elaborate, demonstrates the full lifecycle:
Modeling → Parsing → Navigation → Transformation → Validation
Modeling in OBNT
JOJO (JSON Object Java Object) extends JsonObject and unifies typed Java fields with dynamic JSON properties in a single object model.
Define a JOJO Student:
public class Student extends JsonObject {
private String name;
private Map<String, Integer> scores;
private List<Student> friends;
// Getters and setters
}Learn more → Modeling (OBNT)
Parsing from JSON
Use Sjf4j to encode and decode structured data across multiple formats through a unified facade.
String json = """
{
"name": "Alice",
"scores": {"math": 59, "art": 95},
"friends": [
{"name": "Bill", "active": true, "scores": {"math": 83}},
{"name": "Cindy", "friends": [{"name": "David", "scores": {"math": 95}}]}
],
"age": 18
}
""";
Student student = Sjf4j.fromJson(json, Student.class);Now student exposes two complementary access models:
- Strongly-typed Java getters/setters
- JSON-semantic dynamic APIs
student.getName(); // Alice
student.getInteger("age"); // 18Learn more → Parsing (Codec)
Navigating with JSON Path
Every OBNT node supports declarative structural navigation, expressive querying, and precise mutation via JSON Path (RFC 9535) or JSON Pointer (RFC 6901).
student.getIntegerByPath("$.scores.math");
// 59
student.findByPath("$..friends[?@.scores.math >= 90].name", String.class);
// ["David"]
student.ensurePutByPath("/friends/0/scores/music", 100);
// Bill's scores becomes: {"math": 83, "music": 100}Learn more → Navigation (JSON Path)
Transforming with JSON Patch
Every OBNT node supports standard-compliant structural updates via JSON Patch (RFC 6902).
JsonPatch patch = JsonPatch.fromJson("""
[
{ "op": "replace", "path": "/name", "value": "Alice Zhang" },
{ "op": "add", "path": "/scores/physics", "value": 91 }
]
""");
patch.apply(student);The changes are applied in-place:
student.getName(); // "Alice Zhang"
student.getIntegerByPath("$.scores.physics"); // 91Learn more → Transformation (JSON Patch)
Validating with JSON Schema
Declare JSON Schema (Draft 2020-12) constraints with @ValidJsonSchema (like Jakarta Bean Validation).
@ValidJsonSchema("""
{
"$ref": "#/$defs/Student",
"$defs": {
"Student": {
"type": "object",
"properties": {
"name": {
"type": "string",
"minLength": 1
},
"scores": {
"type": "object",
"additionalProperties": {"type": "integer", "minimum": 0}
},
"friends": {
"type": "array",
"items": {"$ref": "#/$defs/Student"}
}
},
"required": ["name"]
}
}
}
""")
public class Student extends JsonObject {
private String name;
private Map<String, Integer> scores;
private List<Student> friends;
}Validate at runtime:
SchemaValidator validator = new SchemaValidator();
validator.validate(student).isValid(); // trueLearn more → Validation (JSON Schema)
This example demonstrates how SJF4J unifies the entire lifecycle of structured data processing under a single JSON-semantic model.
Structured data — whether from JSON, YAML, Java Properties, or native object graphs — can be processed consistently using the same JSON-semantic APIs.
Benchmarks
SJF4J delivers high performance with minimal overhead while providing a unified JSON-semantic processing model.
JSON Parsing Benchmark
SJF4J operates on top of underlying JSON parsers while adding structural capabilities and flexible binding annotations.
In most cases, the additional overhead remains modest compared to native JSON libraries.
Reflection Access Benchmark
Lambda-based accessor generation minimizes reflection overhead, delivering performance close to direct field or method invocation.
JSON Schema Validation Benchmark
SJF4J fully supports JSON Schema Draft 2020-12 and consistently ranks among the top-performing Java implementations in Bowtie benchmarks.
Learn more → Benchmarks
Contributing
Given that JSON has evolved into a well-defined and widely adopted specification, SJF4J began as an exploration of what JSON-Oriented Development might look like in Java.
If you find the project interesting, contributions of all kinds — code, docs, bug reports, discussions, examples, or benchmarks — are welcome~!