[Java] Public, stable token-level JSON reader/writer API (and a standalone reader/writer artifact)
Maintainer thường phản hồi trong vòng 1 ngày
Đánh giá
- Độ khó
- 5/5
- Thời gian dự kiến
- Hơn một tuần
- Mức phù hợp với người mới
- 35/100
Hướng nghiên cứu
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.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Mô tả
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.
- Ngôn ngữ chính
- Java
- Star
- 4.6k
- Fork
- 470
- Merge trung bình
- 9 giờ 28 phút
- Pull request đã merge (30 ngày)
- 33
Chuẩn bị môi trường
- Không có Dockerfile hay tệp Docker Compose
- Có mẫu pull request
- Đọc hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Issue khác của apache/fory
-
[Python] Compatible xlang read silently drops fields when the peer writes camelCase/PascalCase namesĐang mở
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 85/100
Maintainer thường phản hồi trong vòng 1 ngày
-
[Build] Add ASF license headers to config files that allow commentsCó thể làm lại được @Swatantra-66 đã nhận 28 ngày trước và không có pull request nào đang mở. Đang mởenhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
apache/fory#4124 · 3 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
xlang: the snake_case conversion of field names is not specified, and the runtimes do not agreeCó thể làm lại được @dhruv-dagar đã nhận 15 ngày trước và không có pull request nào đang mở. Đang mởbug
Độ khó 5/5 Hơn một tuần Mức phù hợp với người mới 25/100
apache/fory#4187 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
[Rust] Add an option to use Rust native enumCó thể đã có người làm @BaldDemian đã nhận 19 ngày trước. Đang mở
Độ khó 4/5 3-5 ngày Mức phù hợp với người mới 35/100
apache/fory#4177 · 1 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Untyped read collapses a number literal that does not fit a doubleCó thể đã có người làm @mohitjoshi-hey đã nhận 21 ngày trước. Đang mởbug
Độ khó 3/5 1-2 ngày Mức phù hợp với người mới 68/100
apache/fory#4170 · 3 bình luận · 1 người được giao ·
Maintainer thường phản hồi trong vòng 1 ngày
Issue tương tự
-
5.0.x backport enhancement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 63/100
spring-cloud/spring-cloud-function#1507 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 65/100
open-learning-exchange/myplanet#18484 ·
Maintainer thường phản hồi trong vòng 1 ngày
-
ai-driven-fuzzing bug claude Minor
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 66/100
linagora/twake-calendar-side-service#1417 · 2 bình luận ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 74/100
line/armeria#7109 · 3 reaction ·
Maintainer thường phản hồi trong vòng 1 ngày
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 72/100
open-feature/java-sdk-contrib#1966 ·
Maintainer thường phản hồi trong vòng 1 ngày