SJF4J — Simple JSON Facade for Java
SJF4J is a lightweight facade over multiple JSON libraries, including Jackson, 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, offering consistent APIs for modeling (OBNT), parsing (JSON/YAML), navigating (JSON Path), patching (JSON Patch), validating (JSON Schema), and mapping (Transformation) across data formats and native object graphs.
Install
SJF4J requires JDK 8+ and has no external dependencies (except for the chosen data parser).
Gradle:
implementation("org.sjf4j:sjf4j:{version}")Maven:
<dependency>
<groupId>org.sjf4j</groupId>
<artifactId>sjf4j</artifactId>
<version>{version}</version>
</dependency>Optional Runtime Dependencies
Data parsers are enabled automatically when their corresponding libraries are present, and can also be configured explicitly if needed.
JSON
- Include one of:
Jackson 3.x,Jackson 2.x,Gson,Fastjson2, orJSON-P(withParssonor others). - By default, SJF4J automatically detects and uses the first available implementation in that order.
- If none are detected, it falls back to a built-in simple JSON parser (functional but slower).
- Or use
Sjf4j.builder().jsonFacade(...).build()to explicitly specify the backend.
- Include one of:
YAML
- Include
SnakeYAML(The only YAML 1.1 backend).
- Include
Java Properties
- Built-in support.
- Conversion is inherently limited by its flat key-value structure.
In-Memory
- Built-in support.
- Provides the same JSON-semantic APIs on in-memory object graphs via OBNT.
- Useful even without external data sources (e.g., DB result mapping, complex nested data processing).
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 demonstrates a complete lifecycle for processing structured data:
Modeling → Parsing → Navigating → Patching → Validating → MappingModeling
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
Use Sjf4j to encode and decode structured data across multiple formats.
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 = new 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.getInt("age"); // 18Learn more → Parsing (JSON/YAML)
Navigating
Every OBNT node supports declarative structural navigating, expressive querying, and precise mutation via JSON Path (RFC 9535) or JSON Pointer (RFC 6901).
student.getIntByPath("$.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 → Navigating (JSON Path)
Patching
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.getIntByPath("$.scores.physics"); // 91Learn more → Patching (JSON Patch)
Validating
Declare JSON Schema (Draft 2020-12) constraints with @ValidJsonSchema (like Jakarta Validation style).
@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 → Validating (JSON Schema)
Mapping
While JsonPatch focuses on in-place partial modification, NodeMapper produces a new structure from the source object graph.
NodeMapper<Student, StudentDto> mapper = NodeMapper
.builder(Student.class, StudentDto.class)
.copy("studentName", "name")
.ensureValue("$.info.school", "PKU")
.compute("/avgScore", root ->
root.getScores().values().stream().mapToInt(i -> i).average().orElse(0))
.build();
StudentDto studentDto = mapper.map(student);Learn more → Mapping (Transformation)
Benchmarks
SJF4J delivers high performance with minimal overhead while providing a unified JSON-semantic processing model.
Reflection Access Benchmark
Lambda-based accessor generation minimizes reflection overhead, delivering performance close to direct field or method invocation.
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.
JSON Path Navigating Benchmark
SJF4J shows strong performance in compile and query workloads, while also providing mutation operations.
Within SJF4J, Map/List achieves the highest speed, with JOJO generally closer to Map/List than plain POJO.
JSON Schema Validating 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
JSON is not only well-defined and widely adopted, but also backed by a comprehensive set of RFCs and related standards.
Perhaps it’s time for Java to start treating JSON as a first-class data model.
Contributions are welcome in many forms, including code, documentation, bug reports, examples, benchmarks, and thoughtful feedback.
A good place to start is by opening an issue.
So, what might JSON-oriented development look like in Java?