[Java] Public, stable token-level JSON reader/writer API (and a standalone reader/writer artifact)
Los mantenedores suelen responder en 1 día
Evaluación
- Dificultad
- 5/5
- Tiempo estimado
- Más de una semana
- Aptitud para principiantes
- 35/100
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:
- Constructing a reader/writer needs a
JsonConfig, but there is no public way to obtain one.JsonConfighas no public constructor or builder, andForyJson.config()is package-private. We currently need a class placed in theorg.apache.fory.jsonpackage (split package) just to callForyJson.builder().build().config(). That won't work on the module path, and it's fragile. JsonTypeResolver/JsonSharedRegistryare required constructor arguments, even though a token-level user never registers or resolves types.- It's unclear which reader/writer methods are stable. Several neighbouring methods are marked
@Internal(e.g.Utf8JsonWriter.getBuffer()/setBuffer(),Utf8JsonReader.tryConsumeNextComma(), methods onJsonTypeResolver), 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
JsonConfigbuilder, or factory methods such asForyJson.newUtf8Reader()/newUtf8Writer()(or standaloneUtf8JsonReader.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.
- the structural/scalar methods (
- A separate artifact containing only the reader/writer (e.g.
fory-json-streamorfory-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-corevsjackson-databind(today the fullfory-jsonplusfory-coreis 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.
- keep the dependency footprint small, comparable to
Describe alternatives you've considered
- Using
ForyJsondirectly: 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). AnInputStream/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
- Sin Dockerfile ni archivo de Docker Compose
- Tiene una plantilla de pull request
- Leer la guía de contribución
Primeros pasos
- Lee el issue completo y luego la guía de contribución del proyecto.
- Comenta en el issue que vas a ocuparte — evita que dos personas hagan lo mismo.
- Haz un fork del repositorio y trabaja en una rama.
- Abre un pull request que haga referencia al número del issue.
Más de apache/fory
-
[Python] Compatible xlang read silently drops fields when the peer writes camelCase/PascalCase namesAbierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 85/100
Los mantenedores suelen responder en 1 día
-
[Build] Add ASF license headers to config files that allow commentsQuizá libre de nuevo @Swatantra-66 la tomó hace 28 días y no hay ningún pull request abierto. Abiertoenhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
apache/fory#4124 · 3 comentarios ·
Los mantenedores suelen responder en 1 día
-
xlang: the snake_case conversion of field names is not specified, and the runtimes do not agreeQuizá libre de nuevo @dhruv-dagar la tomó hace 15 días y no hay ningún pull request abierto. Abiertobug
Dificultad 5/5 Más de una semana Aptitud para principiantes 25/100
apache/fory#4187 · 2 comentarios ·
Los mantenedores suelen responder en 1 día
-
[Rust] Add an option to use Rust native enumPosiblemente ocupada @BaldDemian la tomó hace 19 días. Abierto
Dificultad 4/5 3-5 días Aptitud para principiantes 35/100
apache/fory#4177 · 1 comentario · 1 asignado ·
Los mantenedores suelen responder en 1 día
-
Untyped read collapses a number literal that does not fit a doublePosiblemente ocupada @mohitjoshi-hey la tomó hace 21 días. Abiertobug
Dificultad 3/5 1-2 días Aptitud para principiantes 68/100
apache/fory#4170 · 3 comentarios · 1 asignado ·
Los mantenedores suelen responder en 1 día
Todos los issues de apache/fory
Issues similares
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 72/100
wildfly/wildfly-channel#446 ·
-
Dificultad 2/5 1-3 horas Aptitud para principiantes 62/100
Los mantenedores suelen responder en 1 día
-
5.0.x backport enhancement
Dificultad 2/5 1-3 horas Aptitud para principiantes 63/100
spring-cloud/spring-cloud-function#1507 ·
Los mantenedores suelen responder en 1 día
-
Empty blood pressure handled as “null” string in exam editPosiblemente ocupada Un pull request vinculado a esta issue está abierto o ya se fusionó. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 65/100
open-learning-exchange/myplanet#18484 ·
Los mantenedores suelen responder en 1 día
-
ELProcessor.defineFunction() fails for valid method signaturesPosiblemente ocupada @RaphaelFakhri la tomó hoy. Abierto
Dificultad 2/5 1-3 horas Aptitud para principiantes 68/100
jakartaee/expression-language#492 ·