Skip to content

fix(deps): update fory to v1.5.0 - #43

Open
rossdanderson wants to merge 1 commit into
mainfrom
renovate/fory
Open

fix(deps): update fory to v1.5.0#43
rossdanderson wants to merge 1 commit into
mainfrom
renovate/fory

Conversation

@rossdanderson

@rossdanderson rossdanderson commented Jun 19, 2026

Copy link
Copy Markdown
Collaborator

This PR contains the following updates:

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

Release Notes

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

v1.5.0

The Apache Fory team is pleased to announce the 1.5.0 release. This release includes 25 PRs. See the Install page to get the libraries for your platform.

Highlights
  • Fory JSON is now up to 5× faster than Jackson and 10× faster than Gson.
  • External-type serialization now covers Rust, Dart, Swift, and C#, allowing generated serializers for third-party structural types.
  • C# and Dart now support class inheritance, with Dart also supporting intentional omission of inherited private fields.
Faster Fory JSON

Fory 1.5.0 delivers a major performance leap for Fory JSON, with deep optimizations across both serialization and deserialization. It is now up to 5× faster than Jackson and 10× faster than Gson.

Representation Operation fory-json ops/sec Jackson ops/sec Gson ops/sec vs. Jackson vs. Gson
String Serialize 7,387,465 2,049,368 1,084,042 3.60× 6.81×
String Deserialize 2,897,955 1,074,885 902,772 2.70× 3.21×
UTF-8 bytes Serialize 10,375,498 1,868,614 1,037,211 5.55× 10.00×
UTF-8 bytes Deserialize 3,077,158 1,268,397 933,079 2.43× 3.30×
External-Type Serialization For Rust/Swift/CSharp/Dart

Fory 1.5.0 adds external-type serialization to Rust, Dart, Swift, and C#. Applications can define a local serializer or schema declaration for a third-party structural type that cannot be modified to carry Fory annotations. Fory then reads and writes the target value directly—without requiring a wrapper or intermediate mirror object.

The generated declaration preserves the runtime's normal registration and wire model. In xlang mode, external structs, enums, and unions use the same applicable identities and encodings as directly supported types. Private, opaque, or invariant-bearing targets can still use a custom serializer when structural generation is not appropriate.

In Rust, the local derive names the target type and is selected explicitly for root values:

use fory::{Fory, ForyStruct};

#[derive(ForyStruct)]

#[fory(target = third_party::User)]
struct UserSerializer {
    name: String,
    age: u32,
}

let mut fory = Fory::builder().xlang(true).build();
fory.register::<UserSerializer>(100)?;
let bytes = fory.serialize_with::<UserSerializer>(&user)?;
let decoded =
    fory.deserialize_with::<UserSerializer>(&bytes)?;

Dart generates a serializer from a local target declaration, then registers the third-party target through the generated module:

@&#8203;ForyStruct(target: third_party.User)
abstract final class UserSerializer {
  @&#8203;ForyField(id: 1)
  late final String name;

  @&#8203;ForyField(id: 2, type: Int32Type())
  late final int age;
}

ExternalSerializersForyModule.register(
  fory,
  third_party.User,
  id: 100,
);

Swift registers and selects the external serializer while the application continues to pass ThirdParty.User values:

@&#8203;ForyStruct(target: ThirdParty.User.self)
struct UserSerializer {
    var name: String
    var age: UInt32
}

try fory.register(UserSerializer.self, id: 100)
let bytes = try fory.serialize(user, with: UserSerializer.self)
let decoded = try fory.deserialize(bytes, with: UserSerializer.self)

C# source generation uses a local abstract declaration and registers the target type through the normal API:

using Apache.Fory;
using S = Apache.Fory.Schema.Types;

[ForyStruct(Target = typeof(ThirdParty.User))]
internal abstract class UserSerializer
{
    [ForyField(1)]
    public abstract string Name { get; }

    [ForyField(2, Type = typeof(S.Int32))]
    public abstract int Age { get; }
}

fory.Register<ThirdParty.User>(100);
byte[] bytes = fory.Serialize(user);

For construction requirements, nested containers, dynamic values, and advanced mappings, see the dedicated guides for Rust, Dart, Swift, and C#.

Class Inheritance for C# and Dart

Fory 1.5.0 adds class inheritance support to C# and Dart. In both runtimes, inherited and child storage is represented as one flattened schema rather than a nested base object, so ordinary field ordering, schema evolution, reference tracking, and graph-memory checks continue to apply to the concrete type.

In C#, annotate every participating class directly because [ForyStruct] is not inherited. Abstract annotated bases provide schema fields for their concrete descendants, while only the concrete derived type is registered:

[ForyStruct]
public abstract class Entity
{
    [ForyField(1)]
    private long _id;

    public long Id => _id;
}

[ForyStruct]
public sealed class User : Entity
{
    [ForyField(2)]
    public string Name { get; set; } = string.Empty;
}

fory.Register<User>(102);

Dart generation discovers superclass and applied-mixin storage. Public inherited fields need no annotation on the parent, and a concrete child can intentionally omit inherited private fields:

class MessageBase {
  int sequence = 0;
  String _cache = '';
}

@&#8203;ForyStruct(ignoreInheritedPrivateFields: true)
class TextMessage extends MessageBase {
  TextMessage();

  String text = '';
}

The generated TextMessage schema contains sequence and text, but not the inherited private _cache. The option does not omit inherited public fields or private fields declared by the child itself.

See C# class inheritance and Dart inheritance for constructor rules, private-field access across packages, mixins, generics, references, and schema compatibility.

Features
Bug Fix
Other Improvements

Full Changelog: apache/fory@v1.4.0...v1.5.0

v1.4.0

Highlights
  • Introduced Fory JSON for Java, featuring high-performance code generation, rich annotations and mix-ins, dynamic properties, and support for Android and GraalVM native images.
  • Improved performance, safety, and compatibility with a configurable container memory budget, more efficient stream deserialization, Python 3.14 support, and numerous cross-runtime fixes.
Fory JSON for Java

Fory 1.4.0 introduces Fory JSON, a high-performance, thread-safe JSON serialization framework for Java applications. It provides direct mapping between standard JSON and idiomatic Java domain objects, making it suitable for HTTP APIs, browser traffic, logs, configuration, and other interoperable text payloads.

Its main capabilities include:

  • High-performance serialization: optimized readers and writers work with interpreted and runtime-generated serializers to accelerate both JSON encoding and decoding.
  • Rich Java object mapping: ordinary classes, Java records, immutable creator-based classes, common JDK types, and generic containers are supported.
  • Flexible customization: annotations, mix-ins, and custom codecs adapt application types to JSON, covering property names, order, inclusion, creators, polymorphism, unwrapped values, dynamic properties, and specialized representations.
  • Broad platform support: supports JDK 8 and later, Android, and GraalVM native images.

Add the fory-json artifact to your application:

<dependency>
  <groupId>org.apache.fory</groupId>
  <artifactId>fory-json</artifactId>
  <version>1.4.0</version>
</dependency>

ForyJson is immutable and thread-safe after construction, so one instance can be reused across threads:

import org.apache.fory.json.ForyJson;

public final class JsonExample {
  private static final ForyJson JSON = ForyJson.builder().build();

  public static final class User {
    public long id;
    public String name;

    public User() {}
  }

  public static void main(String[] args) {
    User user = new User();
    user.id = 7;
    user.name = "Alice";

    // Serialize to JSON text and deserialize from text.
    String text = JSON.toJson(user);
    User fromText = JSON.fromJson(text, User.class);

    // Serialize directly to UTF-8 bytes and deserialize without an intermediate String.
    byte[] utf8 = JSON.toJsonBytes(user);
    User fromUtf8 = JSON.fromJson(utf8, User.class);
  }
}

See the Fory JSON documentation for the complete type model, annotations and mix-ins, dynamic properties, custom serializers, security controls, and Android or GraalVM setup.

Features
Bug Fix
Other Improvements
New Contributors

Full Changelog: apache/fory@v1.3.0...v1.4.0

v1.3.0

Highlights
  • Python gRPC code generation now defaults to the grpc.aio AsyncIO API, while synchronous grpcio output remains available through --grpc-python-mode=sync.
  • Dart joins the generated gRPC service surface: foryc --dart_out=... --grpc now emits package:grpc clients, service bases, method descriptors, and Fory-backed payload serialization.
  • Compiler gRPC documentation was refined across languages, including clearer guidance for generated service dependencies and transport behavior.
  • Runtime hardening continued with remote schema metadata limits and Java aligned-varint/type-checker fixes.
Python Async gRPC Mode

Python gRPC generation now targets AsyncIO by default. Generated companions use
grpc.aio: servicer bases expose async def methods, stubs are used with
grpc.aio.Channel instances, and streaming RPCs use async iterables. This keeps
the generated code aligned with modern Python async services while preserving
the same Fory-backed request and response encoding used by the existing gRPC
support.

Generate the default async companion with:

foryc service.fdl --python_out=./generated/python --grpc

For a simple unary service, the generated async server shape is:

import asyncio

import grpc.aio

import demo_greeter
import demo_greeter_grpc

class Greeter(demo_greeter_grpc.GreeterServicer):
    async def say_hello(self, request, context):
        return demo_greeter.HelloReply(reply=f"Hello, {request.name}")

async def serve():
    server = grpc.aio.server()
    demo_greeter_grpc.add_servicer(Greeter(), server)
    server.add_insecure_port("[::]:50051")
    await server.start()
    await server.wait_for_termination()

asyncio.run(serve())

Clients use a grpc.aio channel and await generated stub methods:

import grpc
import grpc.aio

import demo_greeter
import demo_greeter_grpc

credentials = grpc.ssl_channel_credentials()
async with grpc.aio.secure_channel("api.example.com:443", credentials) as channel:
    stub = demo_greeter_grpc.GreeterStub(channel)
    reply = await stub.say_hello(demo_greeter.HelloRequest(name="Fory"))

Existing synchronous applications can still request sync companions explicitly:

foryc service.fdl --python_out=./generated/python --grpc --grpc-python-mode=sync

In sync mode the generated public names and <module>_grpc.py filename stay the
same, but applications use grpc.server(...), standard grpc.Channel
instances, and regular def servicer methods.

Dart gRPC Code Generation

Fory 1.3.0 adds Dart gRPC service generation for schemas with service
definitions. Service definitions can come from Fory IDL, protobuf IDL, or
FlatBuffers rpc_service definitions. The generated code uses normal
grpc-dart APIs for clients, service bases, method descriptors, call options,
deadlines, cancellations, metadata, and status codes, while each request and
response object is serialized with Fory instead of protobuf message bytes.

Add grpc and build_runner alongside the Fory package in the Dart
application:

dependencies:
  fory: ^1.3.0
  grpc: ^4.0.0

dev_dependencies:
  build_runner: ^2.4.0

Generate Dart models and the gRPC companion with:

foryc service.fdl --dart_out=./lib/generated --grpc
dart run build_runner build --delete-conflicting-outputs

For a demo.greeter package, the generator emits the model file, the
build_runner serializer part, and a <stem>_grpc.dart companion with
GreeterServiceBase and GreeterClient. The generated client and service base
install the schema's Fory module automatically on first use, so service
implementations do not need a separate manual registration step for the
generated message types.

A unary Dart server uses grpc-dart's Server and the generated service base:

import 'dart:io';

import 'package:grpc/grpc.dart';
import 'demo/greeter/greeter.dart';
import 'demo/greeter/greeter_grpc.dart';

class GreeterService extends GreeterServiceBase {
  @&#8203;override
  Future<HelloReply> sayHello(ServiceCall call, HelloRequest request) async {
    return HelloReply()..reply = 'Hello, ${request.name}';
  }
}

Future<void> main() async {
  final server = Server.create(services: [GreeterService()]);
  await server.serve(address: InternetAddress.loopbackIPv4, port: 50051);
}

Generated Dart clients use standard ClientChannel values and return the
grpc-dart call types:

import 'package:grpc/grpc.dart';
import 'demo/greeter/greeter.dart';
import 'demo/greeter/greeter_grpc.dart';

final channel = ClientChannel(
  'localhost',
  port: 50051,
  options: const ChannelOptions(credentials: ChannelCredentials.insecure()),
);
final client = GreeterClient(channel);

final reply = await client.sayHello(HelloRequest()..name = 'Fory');
await channel.shutdown();

Dart generation covers unary, server-streaming, client-streaming, and
bidirectional streaming RPC shapes following grpc-dart conventions.

Features
Bug Fix
Other Improvements
New Contributors

Full Changelog: apache/fory@v1.2.0...v1.3.0

v1.2.0

Highlights
  • Expanded generated gRPC support across Go, Rust, Kotlin, Scala, C#, and JavaScript, including Node.js and browser gRPC-Web support for JavaScript.
  • Improved cross-language compatibility with refined register-by-name APIs, compatible scalar read conversions, and default compatible mode for native serialization.
  • Strengthened Java platform support by adding Java 9/16 module-info generation and removing sun.misc.Unsafe usage for JDK 25.
  • Improved runtime safety and robustness with additional read checks, deflater leak fixes, and safer serializer/type-info error handling.
  • Optimized compatible-mode and row-format performance through faster compatible reads, compact row layout caching, and inlined custom-codec dispatch.
  • Enhanced compiler output quality across Rust, C++, and service generation with better identifier escaping, name-collision handling, nested container reference handling, and map code generation.
Java 25+ Without sun.misc.Unsafe

JDK 25 continues the platform shift away from sun.misc.Unsafe. Fory 1.2.0
adds a Java 25 multi-release runtime path so applications can run on JDK 25+
without resolving sun.misc.Unsafe from Fory's active class graph.

Older JDKs keep the existing fast paths. On JDK 25+, Fory uses replacement
classes backed by supported JVM mechanisms such as VarHandle, MethodHandle,
arrays, and ByteBuffer. Classes that previously depended on constructor
bypassing should provide an accessible no-arg constructor, use records, or
register a custom serializer.

Compatible Scalar Field Reads

Compatible mode already allows readers and writers to add, remove, and reorder
fields. Fory 1.2.0 extends that model to selected scalar type changes: when a
matched top-level field changes between boolean, string, numeric, and decimal
types, the reader can deserialize the value if the conversion is lossless.

Examples include reading "123" as an integer field, reading 1 or 0 as a
boolean field, reading booleans as 1/0, reading numbers or decimals as
canonical strings, and widening or narrowing numeric values only when no range
or precision is lost. Invalid strings, out-of-range values, lossy float/integer
conversions, and reference-tracked scalar type changes fail during
deserialization. The conversion applies to matched compatible fields, not to
root values or collection elements.

The examples below show Rust and Java using an int64 writer field and a
String reader field. The same compatible scalar field conversion is supported
across Fory's compatible-mode runtimes: Java, Python, Rust, C++, Go, C#, Swift,
Dart, JavaScript/TypeScript, Kotlin, and Scala. Compatible mode is enabled by
default in the Java and Python runtimes for both xlang and native serialization.

Rust example:

use fory::{Fory, ForyStruct};

#[derive(ForyStruct)]
struct MetricV1 {
    value: i64,
}

#[derive(ForyStruct)]
struct MetricV2 {
    value: String,
}

let mut writer = Fory::builder().xlang(true).compatible(true).build();
writer.register_by_name::<MetricV1>("example.Metric")?;

let mut reader = Fory::builder().xlang(true).compatible(true).build();
reader.register_by_name::<MetricV2>("example.Metric")?;

let bytes = writer.serialize(&MetricV1 { value: 42 })?;
let value: MetricV2 = reader.deserialize(&bytes)?;
assert_eq!(value.value, "42");

Java example:

public class MetricV1 {
  public long value;
}

public class MetricV2 {
  public String value;
}

Fory writer = Fory.builder().withXlang(true).withCompatible(true).build();
writer.register(MetricV1.class, "example", "Metric");

Fory reader = Fory.builder().withXlang(true).withCompatible(true).build();
reader.register(MetricV2.class, "example", "Metric");

MetricV1 source = new MetricV1();
source.value = 42L;
byte[] bytes = writer.serialize(source);
MetricV2 value = reader.deserialize(bytes, MetricV2.class);
assert value.value.equals("42");

The same rule works in the other direction, for example reading a String
field value such as "42" as int64, when the string uses Fory's strict
finite decimal grammar and the target range can represent the value exactly.

Generated gRPC Support

Fory 1.2.0 expands compiler-generated gRPC service companions. The generated
services use standard gRPC transports, channels, deadlines, metadata,
interceptors, status codes, and streaming shapes, while request and response
objects are encoded with Fory instead of protobuf message bytes. Use this mode
when both sides of the RPC are generated from the same Fory IDL, protobuf IDL,
or FlatBuffers IDL and you want gRPC operational semantics with Fory payload
encoding.

Generated gRPC support now covers Java, Python, Go, Rust, C#, Scala, Kotlin,
and JavaScript/TypeScript. JavaScript includes Node.js gRPC support and browser
gRPC-Web client generation. Only Rust and Java snippets are shown below; the
other supported languages provide the same Fory-backed service companion model
without duplicating code here.

The examples below use this shared schema:

package demo.greeter;

message HelloRequest {
  string name = 1;
}

message HelloReply {
  string reply = 1;
}

service Greeter {
  rpc SayHello (HelloRequest) returns (HelloReply);
}

Rust generation emits tonic-based service API and binding modules:

use demo_greeter::{HelloReply, HelloRequest};
use demo_greeter_service::Greeter;
use demo_greeter_service_grpc::greeter_client::GreeterClient;
use demo_greeter_service_grpc::greeter_server::GreeterServer;

tonic::transport::Server::builder()
    .add_service(GreeterServer::new(MyGreeter::default()))
    .serve(addr)
    .await?;

let mut client = GreeterClient::connect("http://[::1]:50051").await?;
let reply = client.say_hello(HelloRequest { name: "Fory".into() }).await?;

Java generation emits grpc-java service bases, stubs, and Fory codecs:

final class GreeterService extends GreeterGrpc.GreeterImplBase {
  @&#8203;Override
  public void sayHello(
      HelloRequest request, StreamObserver<HelloReply> responseObserver) {
    HelloReply reply = new HelloReply();
    reply.setReply("Hello, " + request.getName());
    responseObserver.onNext(reply);
    responseObserver.onCompleted();
  }
}

Server server = ServerBuilder.forPort(50051)
    .addService(new GreeterService())
    .build()
    .start();

GreeterGrpc.GreeterBlockingStub stub = GreeterGrpc.newBlockingStub(channel);
HelloRequest request = new HelloRequest();
request.setName("Fory");
HelloReply reply = stub.sayHello(request);

The generated gRPC companions intentionally do not make gRPC a hard dependency
of the core Fory language packages. Applications add the transport libraries
they use: grpc-java for Java and Scala, grpcio for Python, grpc-go for Go,
tonic/bytes for Rust, .NET gRPC packages for C#, @grpc/grpc-js or
grpc-web for JavaScript, and grpc-java/grpc-kotlin for Kotlin.

Features
Bug Fix
Other Improvements
New Contributors

Full Changelog: apache/fory@v1.1.0...v1.2.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.

@rossdanderson rossdanderson changed the title fix(deps): update fory to v1.2.0 fix(deps): update fory to v1.3.0 Jun 29, 2026
@rossdanderson rossdanderson changed the title fix(deps): update fory to v1.3.0 fix(deps): update fory to v1.4.0 Jul 20, 2026
@rossdanderson rossdanderson changed the title fix(deps): update fory to v1.4.0 fix(deps): update fory to v1.5.0 Aug 3, 2026
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