Skip to content

fix(deps): update fory to v1.7.0 - #83

Merged
rossdanderson merged 1 commit into
mainfrom
renovate/fory
Sep 1, 2026
Merged

fix(deps): update fory to v1.7.0#83
rossdanderson merged 1 commit into
mainfrom
renovate/fory

Conversation

@rossdanderson

Copy link
Copy Markdown
Collaborator

This PR contains the following updates:

Package Change Age Confidence
org.apache.fory:fory-kotlin (source) 1.6.11.7.0 age confidence
org.apache.fory:fory-core (source) 1.6.11.7.0 age confidence

Release Notes

apache/fory (org.apache.fory:fory-kotlin)

v1.7.0

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:

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:

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 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:

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:

import org.apache.fory.json.kotlin.ForyJsonKotlin
import org.apache.fory.json.kotlin.jsonTypeRef

data class User(
  val id: ULong,
  val name: String,
  val nickname: String? = null,
)

val json = ForyJsonKotlin.builder().build()
val userType = jsonTypeRef<User>()

val user = json.fromJson("""{"id":7,"name":"Alice"}""", userType)
val text = json.toJson(user, userType)

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, Android guide, and GraalVM Native Image guide for setup and supported configurations.

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():

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.

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 for buffer ownership, null values, and byte-limit details.

Features
Bug Fix
Other Improvements
New Contributors

Full Changelog: apache/fory@v1.6.1...v1.7.0


Configuration

📅 Schedule: (UTC)

  • Branch creation
    • At any time (no schedule defined)
  • Automerge
    • At any time (no schedule defined)

🚦 Automerge: Disabled by config. Please merge this manually once you are satisfied.

Rebasing: Whenever PR becomes conflicted, or you tick the rebase/retry checkbox.

🔕 Ignore: Close this PR and you won't be reminded about these updates again.


  • If you want to rebase/retry this PR, check this box

This PR has been generated by Mend Renovate CLI.

@rossdanderson
rossdanderson merged commit 0a82e05 into main Sep 1, 2026
6 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants