This is an automated email from the ASF dual-hosted git repository. chaokunyang pushed a commit to branch release_fory_1.7 in repository https://gitbox.apache.org/repos/asf/fory-site.git
commit c49f3cc62ea051b8bddb1c21d7fe36775f84075c Author: chaokunyang <[email protected]> AuthorDate: Mon Aug 31 11:41:23 2026 +0800 docs: announce Apache Fory 1.7.0 --- blog/2026-08-28-fory_1_7_0_released.md | 178 ++++++++++++++++++++++++++++++++ docs/benchmarks/index.md | 6 +- docs/benchmarks/json/kotlin/README.md | 12 +-- docs/json/kotlin.md | 5 +- src/components/home/HomepageLanding.tsx | 24 ++--- src/pages/download/index.md | 12 +-- 6 files changed, 202 insertions(+), 35 deletions(-) diff --git a/blog/2026-08-28-fory_1_7_0_released.md b/blog/2026-08-28-fory_1_7_0_released.md new file mode 100644 index 00000000000..5c8a52ae459 --- /dev/null +++ b/blog/2026-08-28-fory_1_7_0_released.md @@ -0,0 +1,178 @@ +--- +slug: fory_1_7_0_release +title: Fory v1.7.0 Released +description: "Fory 1.7.0 adds JSON support for Scala and Kotlin and incremental decoding for JSON arrays and NDJSON streams." +authors: [chaokunyang] +tags: [fory, java, scala, kotlin, swift] +--- + +The Apache Fory team is pleased to announce the 1.7.0 release. This release includes [26 PRs](https://github.com/apache/fory/compare/v1.6.1...v1.7.0). See the [Getting Started](https://fory.apache.org/docs/start/) page to get the libraries for your platform. + +## Highlights + +- Added Fory JSON support for Scala 2.13 and Scala 3. +- Added Fory JSON support for Kotlin on Android, the JVM, and GraalVM Native Image. +- Enhanced Fory JSON on GraalVM Native Image with build-time code generation enabled by default and fine-grained generated codec caching. +- Added incremental JSON stream decoding for top-level arrays and newline-delimited JSON (NDJSON), allowing values to be processed progressively from chunked UTF-8 input. +- Expanded Swift platform support to visionOS, watchOS, tvOS, and Linux, and added Swift gRPC code generation. + +## JSON Support for Scala + +Fory 1.7.0 introduces `fory-json-scala` for Scala 2.13 and Scala 3. Scala applications can read and write standard JSON using case classes, constructor defaults, `Option`, `Either`, tuples, collections, maps, and value classes. The module works on the JVM and GraalVM Native Image. + +Add the Scala JSON module to your sbt build: + +```sbt +libraryDependencies += "org.apache.fory" %% "fory-json-scala" % "1.7.0" +``` + +Create a reusable `ForyJson` instance with `ForyJsonScala.builder()`. Missing defaulted parameters use Scala's compiler-generated constructor defaults, so immutable case classes do not need a zero-argument constructor or mutable fields: + +```scala +import org.apache.fory.json.scala.ForyJsonScala + +case class Person(name: String, age: Int = 18, aliases: List[String] = Nil) + +val json = ForyJsonScala.builder().build() +val person = json.fromJson("""{"name":"Ada"}""", classOf[Person]) +assert(person == Person("Ada", 18, Nil)) + +val text = json.toJson(person) +``` + +Fory JSON annotations work on Scala constructor properties. Scala 2 `Enumeration` values can use `JsonEnumeration` to retain their owning enumeration, including values inside collections and maps. On Scala 3, `derives ScalaJsonCodec` supports enums with parameterized cases and, together with `JsonSubTypes`, sealed hierarchies whose allowed subtypes are declared by the application. + +Use a complete `TypeRef` for parameterized types, or `ScalaTypeRef` when Scala value-type arguments would otherwise be erased. See the [Scala JSON guide](/docs/json/scala) for supported types, annotations, and Native Image setup. + +## JSON Support for Kotlin + +The new `fory-json-kotlin` module maps Kotlin models to standard JSON while preserving constructor defaults, nullability, unsigned types, value classes, and generic arguments. It supports the JVM, Android API 26 and later, and GraalVM Native Image without requiring `kotlin-reflect`. + +Add the runtime dependency: + +```kotlin +dependencies { + implementation("org.apache.fory:fory-json-kotlin:1.7.0") +} +``` + +Use `jsonTypeRef<T>()` to retain Kotlin type information at the root and in nested values. Ordinary Java type tokens cannot represent every Kotlin distinction, such as nullable collection elements or a value class lowered to a primitive: + +```kotlin +import org.apache.fory.json.kotlin.ForyJsonKotlin +import org.apache.fory.json.kotlin.jsonTypeRef + +data class Account( + val id: ULong, + val name: String, + val nickname: String? = null, +) + +val json = ForyJsonKotlin.builder().build() +val accountType = jsonTypeRef<Account>() + +val account = json.fromJson("""{"id":7,"name":"Alice"}""", accountType) +val text = json.toJson(account, accountType) +``` + +A missing member invokes its constructor default when one exists. An explicit JSON `null` is checked against the Kotlin declaration and never requests a default. Fory calls the model's constructor, so initialization and validation still run. Sealed classes and interfaces can use `JsonSubTypes` to declare a closed set of logical subtype names. + +On Android, runtime JSON code generation is disabled. Use the `fory-json-kotlin-ksp` processor when R8 or ProGuard shrinks Kotlin models, together with `JsonType` on application models or an exact `JsonMixin` for third-party targets. For Native Image, install `ForyJsonKotlin` in a reachable `ForyJsonProvider` configuration and make the required models and exact generic bindings reachable at build time. See the [Kotlin JSON guide](/docs/json/kotlin), [Android guide](/docs/json/android), a [...] + +## Incremental JSON Stream Decoding + +Fory JSON can now decode a top-level array or NDJSON stream as UTF-8 chunks arrive. Applications can process each completed element or record without buffering the complete document or waiting for the end of the stream. Chunks are supplied as `ByteBuffer` instances and can end partway through a JSON value. + +Use `newArrayStreamDecoder` for one top-level JSON array. Each successful `decodeNext` call exposes one decoded element through `value()`: + +```java +import java.nio.ByteBuffer; +import java.nio.charset.StandardCharsets; +import org.apache.fory.json.ForyJson; +import org.apache.fory.json.JsonStreamDecoder; + +public final class User { + public long id; + public String name; +} + +ForyJson json = ForyJson.builder().build(); +JsonStreamDecoder<User> decoder = + json.newArrayStreamDecoder(User.class, 1024 * 1024); + +ByteBuffer[] chunks = { + ByteBuffer.wrap("[{\"id\":1,\"name\":\"Ada\"},".getBytes(StandardCharsets.UTF_8)), + ByteBuffer.wrap("{\"id\":2,\"name\":\"Al".getBytes(StandardCharsets.UTF_8)), + ByteBuffer.wrap("ice\"}]".getBytes(StandardCharsets.UTF_8)) +}; + +for (ByteBuffer chunk : chunks) { + while (decoder.decodeNext(chunk)) { + User user = decoder.value(); + System.out.println(user.id + ": " + user.name); + } +} +decoder.finish(); +``` + +Use `newNdjsonStreamDecoder` for records separated by LF or CRLF. Call `finish()` at the end of input and consume its value when it returns `true`: this handles a final record without a trailing newline. + +```java +JsonStreamDecoder<User> decoder = + json.newNdjsonStreamDecoder(User.class, 1024 * 1024); + +ByteBuffer chunk = ByteBuffer.wrap( + ("{\"id\":1,\"name\":\"Ada\"}\n" + + "{\"id\":2,\"name\":\"Alice\"}").getBytes(StandardCharsets.UTF_8)); +while (decoder.decodeNext(chunk)) { + User user = decoder.value(); + System.out.println(user.id + ": " + user.name); +} +if (decoder.finish()) { + User user = decoder.value(); + System.out.println(user.id + ": " + user.name); +} +``` + +Drain each chunk before supplying the next one. The required `maxValueBytes` argument limits each array element or NDJSON record, rather than the complete stream. A decoder belongs to one stream, is not thread-safe, and cannot be reused after completion or failure. See [Incremental JSON streams](/docs/json/getting-started#incremental-json-streams) for buffer ownership, null values, and byte-limit details. + +## Features + +- feat(scala): add json support for scala by @chaokunyang in https://github.com/apache/fory/pull/3934 +- feat(scala): add scala2 json enumeration annotation by @chaokunyang in https://github.com/apache/fory/pull/3935 +- perf(scala): streamline exact List JSON writes by @chaokunyang in https://github.com/apache/fory/pull/3936 +- feat(json): add Kotlin JSON support by @chaokunyang in https://github.com/apache/fory/pull/3937 +- ci: reduce Android Kotlin setup time by @chaokunyang in https://github.com/apache/fory/pull/3951 +- feat: harden deserialization paths by @chaokunyang in https://github.com/apache/fory/pull/3955 +- feat(java): add incremental JSON stream decoding by @chaokunyang in https://github.com/apache/fory/pull/3956 +- ci: isolate Scala snapshot dependencies by @chaokunyang in https://github.com/apache/fory/pull/3957 +- refactor(java): remove unbounded metadata decompression by @chaokunyang in https://github.com/apache/fory/pull/3958 +- feat(json): expose stream value limit errors by @chaokunyang in https://github.com/apache/fory/pull/3959 +- perf(java): optimize GraalVM JSON interpreted access by @chaokunyang in https://github.com/apache/fory/pull/3960 +- perf(json): add ordered field read fast path by @chaokunyang in https://github.com/apache/fory/pull/3962 +- feat(java): refactor java generated codec cache granularity by @chaokunyang in https://github.com/apache/fory/pull/3963 +- feat(java): parse quoted JSON scalar values by @chaokunyang in https://github.com/apache/fory/pull/3967 +- feat(java): add sealed interface json subtypes support by @chaokunyang in https://github.com/apache/fory/pull/3968 +- feat(compiler): Add grpc support for Swift by @yash-agarwa-l in https://github.com/apache/fory/pull/3776 +- feat(swift): support more platforms by @chaokunyang in https://github.com/apache/fory/pull/3973 + +## Bug Fix + +- fix(scala): target Java 8 bytecode for fory-scala by @KarasevRob in https://github.com/apache/fory/pull/3941 +- fix(scala): support Enumeration JSON on Scala 3 by @chaokunyang in https://github.com/apache/fory/pull/3952 +- ci: stabilize JVM snapshot publishing by @chaokunyang in https://github.com/apache/fory/pull/3953 +- fix: fix source release artifact by @chaokunyang in https://github.com/apache/fory/pull/3969 + +## Other Improvements + +- chore: Bump org.apache.logging.log4j:log4j-api from 2.25.4 to 2.25.5 in /java/fory-test-core by @dependabot[bot] in https://github.com/apache/fory/pull/3933 +- chore: update release version to 1.6.1 by @chaokunyang in https://github.com/apache/fory/pull/3938 +- ci: update sbt setup action by @chaokunyang in https://github.com/apache/fory/pull/3939 +- chore: upgrade scala dependencies by @pjfanning in https://github.com/apache/fory/pull/3943 +- docs: update jackson annotations license by @chaokunyang in https://github.com/apache/fory/pull/3944 + +## New Contributors + +- @KarasevRob made their first contribution in https://github.com/apache/fory/pull/3941 + +**Full Changelog**: https://github.com/apache/fory/compare/v1.6.1...v1.7.0 diff --git a/docs/benchmarks/index.md b/docs/benchmarks/index.md index fd940fac3e2..622bac1b725 100644 --- a/docs/benchmarks/index.md +++ b/docs/benchmarks/index.md @@ -52,10 +52,8 @@ For additional benchmark notes, raw data, and the complete Java benchmark README ## Kotlin JSON Benchmark The Kotlin JSON harness compares Fory JSON Kotlin, kotlinx.serialization, Moshi, and Jackson Kotlin -with one immutable model and 16 isolated String/UTF-8 operations. The -[Kotlin JSON report](json/kotlin/README.md) is intentionally marked pending until a complete -measured run is published; no placeholder performance result is inferred from another language or -project. +with one immutable model and 16 String/UTF-8 operations. See [Kotlin JSON benchmarks](json/kotlin/README.md) +for the workloads and benchmark setup. ## Python Benchmark diff --git a/docs/benchmarks/json/kotlin/README.md b/docs/benchmarks/json/kotlin/README.md index 02220e384f0..4d430099a78 100644 --- a/docs/benchmarks/json/kotlin/README.md +++ b/docs/benchmarks/json/kotlin/README.md @@ -1,10 +1,6 @@ -# Kotlin JSON Benchmark Report +# Kotlin JSON Benchmarks -Measured results are pending. This page will be replaced only by a complete run of the repository -Kotlin JSON benchmark harness; no performance number or chart is inferred from the Java, Scala, or -historical external benchmark projects. - -The source-aligned harness is in +The benchmark harness is in [`benchmarks/kotlin`](https://github.com/apache/fory/tree/main/benchmarks/kotlin). It compares Fory JSON Kotlin, kotlinx.serialization, Moshi, and Jackson Kotlin with: @@ -16,7 +12,3 @@ It compares Fory JSON Kotlin, kotlinx.serialization, Moshi, and Jackson Kotlin w - one standard JMH invocation for all 16 methods; - retained declared-type serializers, adapters, readers, and writers prepared outside timing; - fixture decode, own-output round-trip, and all-output JSON-tree equivalence checks before timing. - -The eventual measured report will record the source revision, date, hardware, operating system, -JDK, Kotlin, JMH, Moshi codegen KSP plugin, library versions, and the exact benchmark settings. -Standard JMH JSON and the process log remain available together. diff --git a/docs/json/kotlin.md b/docs/json/kotlin.md index 0a6825f3c77..0d004a3433f 100644 --- a/docs/json/kotlin.md +++ b/docs/json/kotlin.md @@ -363,6 +363,5 @@ See [Troubleshooting](troubleshooting.md) for Kotlin metadata, nullability, gene Android shrinking, Native Image, syntax, limits, custom codecs, subtypes, and root-operation failures. -The source-aligned four-library benchmark methodology and publication status are in the -[Kotlin JSON benchmark report](../benchmarks/json/kotlin/README.md). No Kotlin result is inferred -from the Java or Scala benchmark. +See [Kotlin JSON benchmarks](../benchmarks/json/kotlin/README.md) for the workloads and setup +used to compare Fory JSON Kotlin, kotlinx.serialization, Moshi, and Jackson Kotlin. diff --git a/src/components/home/HomepageLanding.tsx b/src/components/home/HomepageLanding.tsx index cd929c9d238..5bc29a614de 100644 --- a/src/components/home/HomepageLanding.tsx +++ b/src/components/home/HomepageLanding.tsx @@ -138,7 +138,7 @@ const runtimeExamples: RuntimeExample[] = [ install: `<dependency> <groupId>org.apache.fory</groupId> <artifactId>fory-core</artifactId> - <version>1.6.1</version> + <version>1.7.0</version> </dependency>`, codeLanguage: "java", guide: "/docs/object-serialization/java/", @@ -159,7 +159,7 @@ Person out = (Person) fory.deserialize(bytes);`, id: "python", label: "Python", installLanguage: "bash", - install: `pip install pyfory==1.6.1`, + install: `pip install pyfory==1.7.0`, codeLanguage: "python", guide: "/docs/object-serialization/python/", summary: "pyfory supports xlang, Python native mode, dataclasses, row format, and out-of-band buffers.", @@ -181,7 +181,7 @@ out = fory.deserialize(data)`, id: "rust", label: "Rust", installLanguage: "bash", - install: `cargo add [email protected]`, + install: `cargo add [email protected]`, codeLanguage: "rust", guide: "/docs/object-serialization/rust/", summary: "Rust uses derive macros for type-safe structs and supports both xlang and native payloads.", @@ -206,7 +206,7 @@ fn main() -> Result<(), Error> { id: "go", label: "Go", installLanguage: "bash", - install: `go get github.com/apache/fory/go/[email protected]`, + install: `go get github.com/apache/fory/go/[email protected]`, codeLanguage: "go", guide: "/docs/object-serialization/go/", summary: "Go supports xlang and native modes with exported structs, circular references, and schema-aware serializers.", @@ -230,7 +230,7 @@ _ = f.Deserialize(payload, &out)`, FetchContent_Declare( fory GIT_REPOSITORY https://github.com/apache/fory.git - GIT_TAG v1.6.1 + GIT_TAG v1.7.0 SOURCE_SUBDIR cpp ) FetchContent_MakeAvailable(fory)`, @@ -257,7 +257,7 @@ auto out = fory.deserialize<Person>(bytes).value();`, id: "javascript", label: "JavaScript", installLanguage: "bash", - install: `npm install @apache-fory/[email protected] @apache-fory/[email protected]`, + install: `npm install @apache-fory/[email protected] @apache-fory/[email protected]`, codeLanguage: "typescript", guide: "/docs/object-serialization/javascript/", summary: "JavaScript/TypeScript is xlang-only, schema-driven, and runs in Node.js or browsers.", @@ -278,7 +278,7 @@ const out = deserialize(payload);`, id: "csharp", label: "C#", installLanguage: "bash", - install: `dotnet add package Apache.Fory --version 1.6.1`, + install: `dotnet add package Apache.Fory --version 1.7.0`, codeLanguage: "csharp", guide: "/docs/object-serialization/csharp/", summary: ".NET support uses source-generated serializers for Fory structs, enums, and unions.", @@ -301,7 +301,7 @@ Person out = fory.Deserialize<Person>(payload);`, id: "swift", label: "Swift", installLanguage: "swift", - install: `.package(url: "https://github.com/apache/fory.git", exact: "1.6.1")`, + install: `.package(url: "https://github.com/apache/fory.git", exact: "1.7.0")`, codeLanguage: "swift", guide: "/docs/object-serialization/swift/", summary: "Swift uses @ForyStruct, @ForyEnum, and @ForyUnion macros for xlang-compatible models.", @@ -324,7 +324,7 @@ let out: Person = try fory.deserialize(payload)`, label: "Dart", installLanguage: "yaml", install: `dependencies: - fory: ^1.6.1 + fory: ^1.7.0 dev_dependencies: build_runner: ^2.4.13`, @@ -359,7 +359,7 @@ final out = fory.deserialize<Person>(payload);`, id: "scala", label: "Scala", installLanguage: "sbt", - install: `libraryDependencies += "org.apache.fory" %% "fory-scala" % "1.6.1"`, + install: `libraryDependencies += "org.apache.fory" %% "fory-scala" % "1.7.0"`, codeLanguage: "scala", guide: "/docs/object-serialization/scala/", summary: "Scala builds on Fory Java with optimized serializers for case classes, collections, tuples, and Option.", @@ -379,8 +379,8 @@ val out = fory.deserialize(payload).asInstanceOf[Person]`, id: "kotlin", label: "Kotlin", installLanguage: "kotlin", - install: `implementation("org.apache.fory:fory-kotlin:1.6.1") -ksp("org.apache.fory:fory-kotlin-ksp:1.6.1")`, + install: `implementation("org.apache.fory:fory-kotlin:1.7.0") +ksp("org.apache.fory:fory-kotlin-ksp:1.7.0")`, codeLanguage: "kotlin", guide: "/docs/object-serialization/kotlin/", summary: "Kotlin adds data-class support, Android guidance, and KSP static serializers for xlang/schema mode.", diff --git a/src/pages/download/index.md b/src/pages/download/index.md index 19fd5854ca7..d5e6ada6fa2 100644 --- a/src/pages/download/index.md +++ b/src/pages/download/index.md @@ -9,11 +9,11 @@ For binary install, please see the Apache Fory™ [getting started](/docs/start/ ## The latest release -The latest source release is 1.6.1: +The latest source release is 1.7.0: | Version | Date | Source | Release Notes | | ------- | ---------- | ----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------- | -| 1.6.1 | 2026-08-16 | [source](https://www.apache.org/dyn/closer.lua/fory/1.6.1/apache-fory-1.6.1-src.tar.gz?action=download) [asc](https://downloads.apache.org/fory/1.6.1/apache-fory-1.6.1-src.tar.gz.asc) [sha512](https://downloads.apache.org/fory/1.6.1/apache-fory-1.6.1-src.tar.gz.sha512) | [release notes](https://github.com/apache/fory/releases/tag/v1.6.1) | +| 1.7.0 | 2026-08-28 | [source](https://www.apache.org/dyn/closer.lua/fory/1.7.0/apache-fory-1.7.0-src.tar.gz?action=download) [asc](https://downloads.apache.org/fory/1.7.0/apache-fory-1.7.0-src.tar.gz.asc) [sha512](https://downloads.apache.org/fory/1.7.0/apache-fory-1.7.0-src.tar.gz.sha512) | [release notes](https://github.com/apache/fory/releases/tag/v1.7.0) | ## All archived releases @@ -31,13 +31,13 @@ These files are named after the files they relate to but have `.sha512/.asc` ext To verify the SHA digests, you need the `.tar.gz` file and its associated `.tar.gz.sha512` file. An example command: ```bash -sha512sum --check apache-fory-1.6.1-src.tar.gz.sha512 +sha512sum --check apache-fory-1.7.0-src.tar.gz.sha512 ``` It should output something like: ```bash -apache-fory-1.6.1-src.tar.gz: OK +apache-fory-1.7.0-src.tar.gz: OK ``` ### Verifying Signatures @@ -54,13 +54,13 @@ gpg --import KEYS Then you can verify signature: ```bash -gpg --verify apache-fory-1.6.1-src.tar.gz.asc apache-fory-1.6.1-src.tar.gz +gpg --verify apache-fory-1.7.0-src.tar.gz.asc apache-fory-1.7.0-src.tar.gz ``` If something like the following appears, it means the signature is correct: ```bash -gpg: Signature made Wed Aug 12 20:28:26 2026 CST +gpg: Signature made Tue Aug 25 18:38:25 2026 CST gpg: using RSA key 1E2CDAE4C08AD7D694D1CB139D7BE8E45E580BA4 gpg: Good signature from "chaokunyang (CODE SIGNING KEY) <[email protected]>" [unknown] ``` --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
