Skip to main content
Version: dev

Getting Started

Requirements and installation

Fory JSON supports Java 8 and later on standard JDKs, GraalVM native images, and Android. Java records are supported on Java 17 and later.

Fory JSON is available from Maven Central.

Maven:

<dependency>
<groupId>org.apache.fory</groupId>
<artifactId>fory-json</artifactId>
<version>1.5.0</version>
</dependency>

Gradle:

implementation("org.apache.fory:fory-json:1.5.0")

Use the same version for every Fory module in one application.

JDK 25 and later

On JDK 25 and later, opening java.lang.invoke to Fory core is also recommended. It avoids the current-JDK Unsafe fallback and is required when Unsafe access is disabled or unavailable, including with --sun-misc-unsafe-memory-access=deny. For a classpath application:

--add-opens=java.base/java.lang.invoke=ALL-UNNAMED

For a module-path application:

--add-opens=java.base/java.lang.invoke=org.apache.fory.core

The JPMS module name of Fory JSON is org.apache.fory.json.

Quick start

Create one ForyJson instance and reuse it. The instance is thread-safe and has no close lifecycle.

import java.nio.charset.StandardCharsets;
import org.apache.fory.json.ForyJson;

public final class JsonExample {
private static final ForyJson JSON = ForyJson.builder().build();

public static final class User {
public long id;
public String name;

public User() {}

User(long id, String name) {
this.id = id;
this.name = name;
}
}

public static void main(String[] args) {
User input = new User(7, "Alice");

String text = JSON.toJson(input);
byte[] utf8 = JSON.toJsonBytes(input);

User fromText = JSON.fromJson(text, User.class);
User fromUtf8 = JSON.fromJson(utf8, User.class);

System.out.println(text);
System.out.println(new String(utf8, StandardCharsets.UTF_8));
System.out.println(fromText.name + " / " + fromUtf8.name);
}
}

Unknown input properties are skipped unless a read-enabled Any field or any-setter receives them. Null object properties are omitted by default. Default JSON property discovery order is not a compatibility contract; use JsonPropertyOrder or JsonProperty.index when emitted property order must be explicit.

Reading and writing APIs

Fory JSON supports String input/output and UTF-8 byte input/output. It does not currently provide an InputStream parsing API.

OperationRuntime typeDeclared ClassDeclared TypeRef
String outputtoJson(value)toJson(value, type)toJson(value, typeRef)
UTF-8 bytestoJsonBytes(value)toJsonBytes(value, type)toJsonBytes(value, typeRef)
UTF-8 OutputStreamwriteJsonTo(value, out)writeJsonTo(value, type, out)writeJsonTo(value, typeRef, out)
String input-fromJson(text, type)fromJson(text, typeRef)
UTF-8 input-fromJson(bytes, type)fromJson(bytes, typeRef)

Every fromJson call consumes exactly one JSON value and rejects trailing non-whitespace content. Returned Strings and byte arrays are detached from internal reusable buffers.

writeJsonTo buffers the complete UTF-8 document, performs one OutputStream.write, and neither flushes nor closes the caller-owned stream. It is an output convenience API, not incremental JSON streaming. I/O failures are wrapped in ForyJsonException.

Generic types

Use TypeRef whenever a root type contains generic arguments:

import java.util.List;
import org.apache.fory.json.ForyJson;
import org.apache.fory.reflect.TypeRef;

ForyJson json = ForyJson.builder().build();
TypeRef<List<User>> usersType = new TypeRef<List<User>>() {};

List<User> users = json.fromJson("[{\"id\":7,\"name\":\"Alice\"}]", usersType);
String encoded = json.toJson(users, usersType);

Declared writes require a fully bound type. Wildcards and type variables are rejected. A non-null value must be assignable to the declared raw type.

The declared schema controls serialization. For example, a property declared as a concrete parent class uses the parent's mapped properties rather than automatically adding subclass-only fields. A declared Object value uses runtime dispatch when writing and natural JSON mapping when reading.

Declared types and polymorphism

The no-type write overloads dispatch from the runtime class. Use a declared-type overload when a base type owns JsonSubTypes metadata:

Shape shape = new Circle(2);

json.toJson(shape); // Circle's concrete representation
json.toJson(shape, Shape.class); // Shape's configured subtype representation
json.toJsonBytes(shape, Shape.class);
json.writeJsonTo(shape, Shape.class, outputStream);

For containers of polymorphic values, carry the declared base type in TypeRef:

TypeRef<List<Shape>> shapesType = new TypeRef<List<Shape>>() {};
String encoded = json.toJson(shapes, shapesType);