How to Create a JsonParser in Jackson 3 Using Only jackson-core
The Paradigm Shift in Jackson 3
In Jackson 2, the streaming API (jackson-core) was somewhat tightly coupled to the object-mapping API (jackson-databind) via the ObjectCodec class. To resolve this, Jackson 3 introduces a cleaner separation of concerns by routing parser and generator creation through ObjectReadContext and ObjectWriteContext.
If you are migrating to Jackson 3 and want to stick strictly to jackson-core without pulling in jackson-databind, you might find yourself confused by the new JsonFactory method signatures, which now require an ObjectReadContext.
The Solution: Use ObjectReadContext.empty()
To create a JsonParser without jackson-databind, you do not need to implement your own context. Jackson 3 provides a built-in, lightweight, empty context specifically for core-only streaming operations: ObjectReadContext.empty().
Here is a complete, runnable example demonstrating how to parse JSON using only Jackson 3 Core:
import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;
import com.fasterxml.jackson.core.ObjectReadContext;
import java.io.IOException;
public class Jackson3CoreExample {
public static void main(String[] args) throws IOException {
String json = "{\"name\": \"Jackson 3\", \"version\": 3}";
// 1. Create the JsonFactory
JsonFactory factory = new JsonFactory();
// 2. Get the empty read context for core-only usage
ObjectReadContext readContext = ObjectReadContext.empty();
// 3. Create the JsonParser by passing the context and the source
try (JsonParser parser = factory.createParser(readContext, json)) {
while (parser.nextToken() != null) {
JsonToken token = parser.currentToken();
System.out.println("Token: " + token
+ " | Name: " + parser.currentName()
+ " | Value: " + parser.getValueAsString());
}
}
}
}Why This Change Was Made
In Jackson 2.x, the JsonParser held a direct reference to an ObjectCodec (usually the ObjectMapper). This forced a dependency cycle and meant the low-level parser had to know about high-level data-binding concepts.
In Jackson 3.x, this dependency is inverted. The parser only knows about the ObjectReadContext interface. When you use the full jackson-databind library, the DeserializationContext implements this interface. When you use only jackson-core, ObjectReadContext.empty() provides a no-op implementation, keeping your classpath lightweight and free of databind overhead.