[Java] Public, stable token-level JSON reader/writer API (and a standalone reader/writer artifact)

Abierto
#4,164 0 comentarios 0 reacciones 0 asignados Ver en GitHub

Los mantenedores suelen responder en 1 día

@dstepanov ya está trabajando en esto.

Desde el 14/10/2026.

  • #4180 de @dstepanov — abierto

Evaluación

Dificultad
5/5
Tiempo estimado
Más de una semana
Aptitud para principiantes
35/100
Tipo de issue
Nueva funcionalidad
Claridad
Bastante claro
Estado de actividad
Activo
Stack tecnológico
java
Área
api, backend

Línea de trabajo

Start by reading the Utf8JsonReader and Utf8JsonWriter APIs, JsonConfig, and the related builder and resolver code mentioned in the issue. Define which token methods are public and stable, how callers construct readers and writers, and whether a standalone artifact is in scope; the issue proposes several alternatives and does not settle those design choices. Done means framework integrations can use a documented token API without a split-package workaround, with the artifact boundary and packed-token support clarified.

Escrito por el modelo de indexación a partir del texto del issue.

Descripción

Feature Request

Make the token-level Utf8JsonReader / Utf8JsonWriter a supported public API, usable without going through ForyJson's object mapping, and consider publishing them as a separate, lightweight artifact.

Is your feature request related to a problem? Please describe

I'm evaluating fory-json (1.7.6) as a JSON backend for Micronaut Serialization. Micronaut Serialization has its own compile-time generated (de)serializers and only needs a fast streaming tokenizer/generator underneath, the same way it uses jackson-core today. So it drives Utf8JsonReader / Utf8JsonWriter directly and does not use ForyJson's codecs.

This works well. The module passes our full serialization TCK on the JVM and in a GraalVM native image. Benchmarks on our standard user-bean model (JDK 25) show:

serialize (ops/µs) deserialize (µs/op)
Micronaut Serialization on jackson-core 0.523 3.053
Micronaut Serialization on fory-json reader/writer 1.254 2.347

Most of the gain comes from the reader/writer internals: word-at-a-time scanning, number parsing/formatting, and especially the packed field-name tokens. We precompute "name": / ,"name": / {"name": as long words per property and use writeRawValue(long, long, long, long, int, int, int), writeObjectStartWithRawValue(long, long, int) and tryReadNextFieldNameToken0 / tryReadNextFieldNameToken8, the same way Fory's generated codecs do.

However, the integration currently relies on things that don't look like public API:

  1. Constructing a reader/writer needs a JsonConfig, but there is no public way to obtain one. JsonConfig has no public constructor or builder, and ForyJson.config() is package-private. We currently need a class placed in the org.apache.fory.json package (split package) just to call ForyJson.builder().build().config(). That won't work on the module path, and it's fragile.
  2. JsonTypeResolver / JsonSharedRegistry are required constructor arguments, even though a token-level user never registers or resolves types.
  3. It's unclear which reader/writer methods are stable. Several neighbouring methods are marked @Internal (e.g. Utf8JsonWriter.getBuffer()/setBuffer(), Utf8JsonReader.tryConsumeNextComma(), methods on JsonTypeResolver), and the packed-token methods above look like they are primarily meant for generated code.
Describe the solution you'd like
  • A public way to create readers/writers, e.g. a public JsonConfig builder, or factory methods such as ForyJson.newUtf8Reader() / newUtf8Writer() (or standalone Utf8JsonReader.create(options)). They shouldn't need a type resolver when used at token level.
  • A documented, stable token-level API on Utf8JsonReader / Utf8JsonWriter, including:
    • the structural/scalar methods (peekToken, expect, consume, consumeCommaOrEndObject/Array, read*, skipValue, finish, write*, writeComma, writeFieldName);
    • the packed field-name token methods (writeRawValue(long...), writeObjectStartWithRawValue, tryReadNextFieldNameToken0/8), ideally with a public helper that builds the packed token values for a given name, so callers don't have to re-implement the packing and escaping rules.
  • A separate artifact containing only the reader/writer (e.g. fory-json-stream or fory-json-core), without the object-mapping layer, codegen/Janino, annotations or codec registry. For framework integrations that bring their own mapping layer, this would:
    • keep the dependency footprint small, comparable to jackson-core vs jackson-databind (today the full fory-json plus fory-core is pulled in, roughly 3.9 MB);
    • simplify GraalVM native-image setup, since there are no runtime code generation paths;
    • give a clear boundary for what is public and stable.
Describe alternatives you've considered
  • Using ForyJson directly: not an option for us, because the mapping is done by our own generated code, which has to honour our annotations, views, subtype handling and so on.
  • Keeping the split-package workaround: it works on the classpath, but it's brittle across releases and incompatible with JPMS.
Additional context
  • Related: #3961 (InputStream-based reading). An InputStream/chunked input mode on the reader would let us avoid buffering the whole request body.
  • Happy to share the integration code or help with a PR if this direction makes sense.
Lenguaje dominante
Java
Estrellas
4.6k
Forks
470
Merge medio
9 h 28 min
PR fusionados (30 d)
33

Preparar el entorno

Primeros pasos

  1. Lee el issue completo y luego la guía de contribución del proyecto.
  2. Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
  3. Haz un fork del repositorio y trabaja en una rama.
  4. Abre un pull request que haga referencia al número del issue.

Más de apache/fory

Todos los issues de apache/fory

Issues similares

Más issues de Java

Recibe los nuevos issues en tu correo

Un resumen breve de issues de GitHub para principiantes.