This is an automated email from the ASF dual-hosted git repository. chaokunyang pushed a commit to branch update_guide_structure in repository https://gitbox.apache.org/repos/asf/fory-site.git
commit ba6426c57238786bf00564a277e638dc37397c96 Author: chaokunyang <[email protected]> AuthorDate: Wed Dec 10 22:53:24 2025 +0800 refine docs --- docs/docs/guide/cpp/_category_.json | 4 + docs/docs/guide/java/_category_.json | 4 + docs/docs/guide/python/_category_.json | 4 + docs/docs/guide/rust/_category_.json | 4 + docs/docs/guide/scala/_category_.json | 4 + docs/docs/guide/scala_guide.md | 313 -------------- docs/docs/guide/xlang/_category_.json | 4 + docs/docs/guide/xlang_serialization_guide.md | 610 --------------------------- 8 files changed, 24 insertions(+), 923 deletions(-) diff --git a/docs/docs/guide/cpp/_category_.json b/docs/docs/guide/cpp/_category_.json new file mode 100644 index 000000000..1832d9760 --- /dev/null +++ b/docs/docs/guide/cpp/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "C++", + "collapsed": true +} \ No newline at end of file diff --git a/docs/docs/guide/java/_category_.json b/docs/docs/guide/java/_category_.json new file mode 100644 index 000000000..77437fd8b --- /dev/null +++ b/docs/docs/guide/java/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Java", + "collapsed": true +} diff --git a/docs/docs/guide/python/_category_.json b/docs/docs/guide/python/_category_.json new file mode 100644 index 000000000..d07a16f69 --- /dev/null +++ b/docs/docs/guide/python/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Python", + "collapsed": true +} diff --git a/docs/docs/guide/rust/_category_.json b/docs/docs/guide/rust/_category_.json new file mode 100644 index 000000000..ad9884ddf --- /dev/null +++ b/docs/docs/guide/rust/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Rust", + "collapsed": true +} diff --git a/docs/docs/guide/scala/_category_.json b/docs/docs/guide/scala/_category_.json new file mode 100644 index 000000000..7ff63f8a8 --- /dev/null +++ b/docs/docs/guide/scala/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Scala", + "collapsed": true +} \ No newline at end of file diff --git a/docs/docs/guide/scala_guide.md b/docs/docs/guide/scala_guide.md deleted file mode 100644 index f2d42e0dd..000000000 --- a/docs/docs/guide/scala_guide.md +++ /dev/null @@ -1,313 +0,0 @@ ---- -title: Scala Serialization Guide -sidebar_position: 3 -id: scala_serialization -license: | - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---- - -Apache Fory™ supports all scala object serialization: - -- `case` class serialization supported -- `pojo/bean` class serialization supported -- `object` singleton serialization supported -- `collection` serialization supported -- other types such as `tuple/either` and basic types are all supported too. - -Scala 2 and 3 are both supported. - -## Install - -To add a dependency on Apache Fory™ scala for with sbt, use the following: - -```sbt -libraryDependencies += "org.apache.fory" %% "fory-scala" % "0.13.2" -``` - -## Quick Start - -```scala -case class Person(name: String, id: Long, github: String) -case class Point(x : Int, y : Int, z : Int) - -object ScalaExample { - val fory: Fory = Fory.builder().withScalaOptimizationEnabled(true).build() - // Register optimized fory serializers for scala - ScalaSerializers.registerSerializers(fory) - fory.register(classOf[Person]) - fory.register(classOf[Point]) - - def main(args: Array[String]): Unit = { - val p = Person("Shawn Yang", 1, "https://github.com/chaokunyang") - println(fory.deserialize(fory.serialize(p))) - println(fory.deserialize(fory.serialize(Point(1, 2, 3)))) - } -} -``` - -## Fory creation - -When using fory for scala serialization, you should create fory at least with following options: - -```scala -import org.apache.fory.Fory -import org.apache.fory.serializer.scala.ScalaSerializers - -val fory = Fory.builder().withScalaOptimizationEnabled(true).build() - -// Register optimized fory serializers for scala -ScalaSerializers.registerSerializers(fory) -``` - -Depending on the object types you serialize, you may need to register some scala internal types: - -```scala -fory.register(Class.forName("scala.Enumeration.Val")) -``` - -If you want to avoid such registration, you can disable class registration by `ForyBuilder#requireClassRegistration(false)`. -Note that this option allow to deserialize objects unknown types, more flexible but may be insecure if the classes contains malicious code. - -And circular references are common in scala, `Reference tracking` should be enabled by `ForyBuilder#withRefTracking(true)`. If you don't enable reference tracking, [StackOverflowError](https://github.com/apache/fory/issues/1032) may happen for some scala versions when serializing scala Enumeration. - -Note that fory instance should be shared between multiple serialization, the creation of fory instance is not cheap. - -If you use shared fory instance across multiple threads, you should create `ThreadSafeFory` instead by `ForyBuilder#buildThreadSafeFory()` instead. - -## Serialize case class - -```scala -case class Person(github: String, age: Int, id: Long) -val p = Person("https://github.com/chaokunyang", 18, 1) -println(fory.deserialize(fory.serialize(p))) -println(fory.deserializeJavaObject(fory.serializeJavaObject(p))) -``` - -## Serialize pojo - -```scala -class Foo(f1: Int, f2: String) { - override def toString: String = s"Foo($f1, $f2)" -} -println(fory.deserialize(fory.serialize(Foo(1, "chaokunyang")))) -``` - -## Serialize object singleton - -```scala -object singleton { -} -val o1 = fory.deserialize(fory.serialize(singleton)) -val o2 = fory.deserialize(fory.serialize(singleton)) -println(o1 == o2) -``` - -## Serialize collection - -```scala -val seq = Seq(1,2) -val list = List("a", "b") -val map = Map("a" -> 1, "b" -> 2) -println(fory.deserialize(fory.serialize(seq))) -println(fory.deserialize(fory.serialize(list))) -println(fory.deserialize(fory.serialize(map))) -``` - -## Serialize Tuple - -```scala -val tuple = (100, 10000L) //Tuple2 -println(fory.deserialize(fory.serialize(tuple))) -val tuple = (100, 10000L, 10000L, "str") //Tuple4 -println(fory.deserialize(fory.serialize(tuple))) -``` - -## Serialize Enum - -### Scala3 Enum - -```scala -enum Color { case Red, Green, Blue } -println(fory.deserialize(fory.serialize(Color.Green))) -``` - -### Scala2 Enum - -```scala -object ColorEnum extends Enumeration { - type ColorEnum = Value - val Red, Green, Blue = Value -} -println(fory.deserialize(fory.serialize(ColorEnum.Green))) -``` - -## Serialize Option - -```scala -val opt: Option[Long] = Some(100) -println(fory.deserialize(fory.serialize(opt))) -val opt1: Option[Long] = None -println(fory.deserialize(fory.serialize(opt1))) -``` - -## Scala Class Default Values Support - -Fory supports Scala class default values during deserialization when using compatible mode. This feature enables forward/backward compatibility when case classes or regular Scala classes have default parameters. - -### Overview - -When a Scala class has default parameters, the Scala compiler generates methods in the companion object (for case classes) or in the class itself (for regular Scala classes) like `apply$default$1`, `apply$default$2`, etc. that return the default values. Fory can detect these methods and use them when deserializing objects where certain fields are missing from the serialized data. - -### Supported Class Types - -Fory supports default values for: - -- **Case classes** with default parameters -- **Regular Scala classes** with default parameters in their primary constructor -- **Nested case classes** with default parameters -- **Deeply nested case classes** with default parameters - -### How It Works - -1. **Detection**: Fory detects if a class is a Scala class by checking for the presence of default value methods (`apply$default$N` or `$default$N`). - -2. **Default Value Discovery**: - - For case classes: Fory scans the companion object for methods named `apply$default$1`, `apply$default$2`, etc. - - For regular Scala classes: Fory scans the class itself for methods named `$default$1`, `$default$2`, etc. - -3. **Field Mapping**: During deserialization, Fory identifies fields that exist in the target class but are missing from the serialized data. - -4. **Value Application**: After reading all available fields from the serialized data, Fory applies default values to any missing fields using direct field access for optimal performance. - -### Usage - -This feature is automatically enabled when: - -- Compatible mode is enabled (`withCompatibleMode(CompatibleMode.COMPATIBLE)`) -- The target class is detected as a Scala class with default values -- A field is missing from the serialized data but exists in the target class - -No additional configuration is required. - -### Examples - -#### Case Class with Default Values - -```scala -// Class WITHOUT default values (for serialization) -case class PersonNoDefaults(name: String) - -// Class WITH default values (for deserialization) -case class PersonWithDefaults(name: String, age: Int = 25, city: String = "Unknown") - -val fory = Fory.builder() - .withCompatibleMode(CompatibleMode.COMPATIBLE) - .withScalaOptimizationEnabled(true) - .build() - -// Serialize using class without default values -val original = PersonNoDefaults("John") -val serialized = fory.serialize(original) - -// Deserialize into class with default values - missing fields will use defaults -val deserialized = fory.deserialize(serialized, classOf[PersonWithDefaults]) -// deserialized.name will be "John" -// deserialized.age will be 25 (default) -// deserialized.city will be "Unknown" (default) -``` - -#### Regular Scala Class with Default Values - -```scala -// Class WITHOUT default values (for serialization) -class EmployeeNoDefaults(val name: String) - -// Class WITH default values (for deserialization) -class EmployeeWithDefaults(val name: String, val age: Int = 30, val department: String = "Engineering") - -val fory = Fory.builder() - .withCompatibleMode(CompatibleMode.COMPATIBLE) - .withScalaOptimizationEnabled(true) - .build() - -// Serialize using class without default values -val original = new EmployeeNoDefaults("Jane") -val serialized = fory.serialize(original) - -// Deserialize into class with default values - missing fields will use defaults -val deserialized = fory.deserialize(serialized, classOf[EmployeeWithDefaults]) -// deserialized.name will be "Jane" -// deserialized.age will be 30 (default) -// deserialized.department will be "Engineering" (default) -``` - -#### Complex Default Values - -```scala -// Class WITHOUT default values (for serialization) -case class ConfigurationNoDefaults(name: String) - -// Class WITH default values (for deserialization) -case class ConfigurationWithDefaults( - name: String, - settings: Map[String, String] = Map("default" -> "value"), - tags: List[String] = List("default"), - enabled: Boolean = true -) - -val fory = Fory.builder() - .withCompatibleMode(CompatibleMode.COMPATIBLE) - .withScalaOptimizationEnabled(true) - .build() - -// Serialize using class without default values -val original = ConfigurationNoDefaults("myConfig") -val serialized = fory.serialize(original) - -// Deserialize into class with default values - missing fields will use defaults -val deserialized = fory.deserialize(serialized, classOf[ConfigurationWithDefaults]) -// deserialized.name will be "myConfig" -// deserialized.settings will be Map("default" -> "value") -// deserialized.tags will be List("default") -// deserialized.enabled will be true -``` - -#### Nested Case Classes - -```scala -object NestedClasses { - // Class WITHOUT default values (for serialization) - case class SimplePerson(name: String) - - // Class WITH default values (for deserialization) - case class Address(street: String, city: String = "DefaultCity") - case class PersonWithDefaults(name: String, address: Address = Address("DefaultStreet")) -} - -val fory = Fory.builder() - .withCompatibleMode(CompatibleMode.COMPATIBLE) - .withScalaOptimizationEnabled(true) - .build() - -// Serialize using class without default values -val original = NestedClasses.SimplePerson("Alice") -val serialized = fory.serialize(original) - -// Deserialize into class with default values - missing address field will use default -val deserialized = fory.deserialize(serialized, classOf[NestedClasses.PersonWithDefaults]) -// deserialized.name will be "Alice" -// deserialized.address will be Address("DefaultStreet", "DefaultCity") -``` diff --git a/docs/docs/guide/xlang/_category_.json b/docs/docs/guide/xlang/_category_.json new file mode 100644 index 000000000..a7b9da285 --- /dev/null +++ b/docs/docs/guide/xlang/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Cross Language", + "collapsed": true +} \ No newline at end of file diff --git a/docs/docs/guide/xlang_serialization_guide.md b/docs/docs/guide/xlang_serialization_guide.md deleted file mode 100644 index a5715a60a..000000000 --- a/docs/docs/guide/xlang_serialization_guide.md +++ /dev/null @@ -1,610 +0,0 @@ ---- -title: Xlang Serialization Guide -sidebar_position: 4 -id: xlang_serialization -license: | - Licensed to the Apache Software Foundation (ASF) under one or more - contributor license agreements. See the NOTICE file distributed with - this work for additional information regarding copyright ownership. - The ASF licenses this file to You under the Apache License, Version 2.0 - (the "License"); you may not use this file except in compliance with - the License. You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. ---- - -## Serialize built-in types - -Common types can be serialized automatically: primitive numeric types, string, binary, array, list, map and so on. - -**Java** - -```java -import org.apache.fory.*; -import org.apache.fory.config.*; - -import java.util.*; - -public class Example1 { - public static void main(String[] args) { - Fory fory = Fory.builder().withLanguage(Language.XLANG).build(); - List<Object> list = ofArrayList(true, false, "str", -1.1, 1, new int[100], new double[20]); - byte[] bytes = fory.serialize(list); - // bytes can be data serialized by other languages. - fory.deserialize(bytes); - Map<Object, Object> map = new HashMap<>(); - map.put("k1", "v1"); - map.put("k2", list); - map.put("k3", -1); - bytes = fory.serialize(map); - // bytes can be data serialized by other languages. - fory.deserialize(bytes); - } -} -``` - -**Python** - -```python -import pyfory -import numpy as np - -fory = pyfory.Fory() -object_list = [True, False, "str", -1.1, 1, - np.full(100, 0, dtype=np.int32), np.full(20, 0.0, dtype=np.double)] -data = fory.serialize(object_list) -# bytes can be data serialized by other languages. -new_list = fory.deserialize(data) -object_map = {"k1": "v1", "k2": object_list, "k3": -1} -data = fory.serialize(object_map) -# bytes can be data serialized by other languages. -new_map = fory.deserialize(data) -print(new_map) -``` - -**Golang** - -```go -package main - -import forygo "github.com/apache/fory/fory/go/fory" -import "fmt" - -func main() { - list := []interface{}{true, false, "str", -1.1, 1, make([]int32, 10), make([]float64, 20)} - fory := forygo.NewFory() - bytes, err := fory.Marshal(list) - if err != nil { - panic(err) - } - var newValue interface{} - // bytes can be data serialized by other languages. - if err := fory.Unmarshal(bytes, &newValue); err != nil { - panic(err) - } - fmt.Println(newValue) - dict := map[string]interface{}{ - "k1": "v1", - "k2": list, - "k3": -1, - } - bytes, err = fory.Marshal(dict) - if err != nil { - panic(err) - } - // bytes can be data serialized by other languages. - if err := fory.Unmarshal(bytes, &newValue); err != nil { - panic(err) - } - fmt.Println(newValue) -} -``` - -**JavaScript** - -```javascript -import Fory from "@apache-fory/fory"; - -/** - * @apache-fory/hps use v8's fast-calls-api that can be called directly by jit, ensure that the version of Node is 20 or above. - * Experimental feature, installation success cannot be guaranteed at this moment - * If you are unable to install the module, replace it with `const hps = null;` - **/ -import hps from "@apache-fory/hps"; - -const fory = new Fory({ hps }); -const input = fory.serialize("hello fory"); -const result = fory.deserialize(input); -console.log(result); -``` - -**Rust** - -```rust -use chrono::{NaiveDate, NaiveDateTime}; -use fory::{from_buffer, to_buffer, Fory}; -use std::collections::HashMap; - -fn run() { - let bin: Vec<u8> = to_buffer(&"hello".to_string()); - let obj: String = from_buffer(&bin).expect("should success"); - assert_eq!("hello".to_string(), obj); -} -``` - -## Serialize custom types - -Serializing user-defined types needs registering the custom type using the register API to establish the mapping relationship between the type in different languages. - -**Java** - -```java -import org.apache.fory.*; -import org.apache.fory.config.*; -import java.util.*; - -public class Example2 { - public static class SomeClass1 { - Object f1; - Map<Byte, Integer> f2; - } - - public static class SomeClass2 { - Object f1; - String f2; - List<Object> f3; - Map<Byte, Integer> f4; - Byte f5; - Short f6; - Integer f7; - Long f8; - Float f9; - Double f10; - short[] f11; - List<Short> f12; - } - - public static Object createObject() { - SomeClass1 obj1 = new SomeClass1(); - obj1.f1 = true; - obj1.f2 = ofHashMap((byte) -1, 2); - SomeClass2 obj = new SomeClass2(); - obj.f1 = obj1; - obj.f2 = "abc"; - obj.f3 = ofArrayList("abc", "abc"); - obj.f4 = ofHashMap((byte) 1, 2); - obj.f5 = Byte.MAX_VALUE; - obj.f6 = Short.MAX_VALUE; - obj.f7 = Integer.MAX_VALUE; - obj.f8 = Long.MAX_VALUE; - obj.f9 = 1.0f / 2; - obj.f10 = 1 / 3.0; - obj.f11 = new short[]{(short) 1, (short) 2}; - obj.f12 = ofArrayList((short) -1, (short) 4); - return obj; - } - - // mvn exec:java -Dexec.mainClass="org.apache.fory.examples.Example2" - public static void main(String[] args) { - Fory fory = Fory.builder().withLanguage(Language.XLANG).build(); - fory.register(SomeClass1.class, "example.SomeClass1"); - fory.register(SomeClass2.class, "example.SomeClass2"); - byte[] bytes = fory.serialize(createObject()); - // bytes can be data serialized by other languages. - System.out.println(fory.deserialize(bytes)); - } -} -``` - -**Python** - -```python -from dataclasses import dataclass -from typing import List, Dict, Any -import pyfory, array - - -@dataclass -class SomeClass1: - f1: Any - f2: Dict[pyfory.Int8Type, pyfory.Int32Type] - - -@dataclass -class SomeClass2: - f1: Any = None - f2: str = None - f3: List[str] = None - f4: Dict[pyfory.Int8Type, pyfory.Int32Type] = None - f5: pyfory.Int8Type = None - f6: pyfory.Int16Type = None - f7: pyfory.Int32Type = None - # int type will be taken as `pyfory.Int64Type`. - # use `pyfory.Int32Type` for type hint if peer - # are more narrow type. - f8: int = None - f9: pyfory.Float32Type = None - # float type will be taken as `pyfory.Float64Type` - f10: float = None - f11: pyfory.Int16ArrayType = None - f12: List[pyfory.Int16Type] = None - - -if __name__ == "__main__": - f = pyfory.Fory() - f.register_type(SomeClass1, typename="example.SomeClass1") - f.register_type(SomeClass2, typename="example.SomeClass2") - obj1 = SomeClass1(f1=True, f2={-1: 2}) - obj = SomeClass2( - f1=obj1, - f2="abc", - f3=["abc", "abc"], - f4={1: 2}, - f5=2 ** 7 - 1, - f6=2 ** 15 - 1, - f7=2 ** 31 - 1, - f8=2 ** 63 - 1, - f9=1.0 / 2, - f10=1 / 3.0, - f11=array.array("h", [1, 2]), - f12=[-1, 4], - ) - data = f.serialize(obj) - # bytes can be data serialized by other languages. - print(f.deserialize(data)) -``` - -**Golang** - -```go -package main - -import forygo "github.com/apache/fory/fory/go/fory" -import "fmt" - -func main() { - type SomeClass1 struct { - F1 interface{} - F2 string - F3 []interface{} - F4 map[int8]int32 - F5 int8 - F6 int16 - F7 int32 - F8 int64 - F9 float32 - F10 float64 - F11 []int16 - F12 fory.Int16Slice - } - - type SomeClas2 struct { - F1 interface{} - F2 map[int8]int32 - } - fory := forygo.NewFory() - if err := fory.RegisterNamedType(SomeClass1{}, "example.SomeClass1"); err != nil { - panic(err) - } - if err := fory.RegisterNamedType(SomeClass2{}, "example.SomeClass2"); err != nil { - panic(err) - } - obj1 := &SomeClass1{} - obj1.F1 = true - obj1.F2 = map[int8]int32{-1: 2} - obj := &SomeClass1{} - obj.F1 = obj1 - obj.F2 = "abc" - obj.F3 = []interface{}{"abc", "abc"} - f4 := map[int8]int32{1: 2} - obj.F4 = f4 - obj.F5 = fory.MaxInt8 - obj.F6 = fory.MaxInt16 - obj.F7 = fory.MaxInt32 - obj.F8 = fory.MaxInt64 - obj.F9 = 1.0 / 2 - obj.F10 = 1 / 3.0 - obj.F11 = []int16{1, 2} - obj.F12 = []int16{-1, 4} - bytes, err := fory.Marshal(obj); - if err != nil { - panic(err) - } - var newValue interface{} - // bytes can be data serialized by other languages. - if err := fory.Unmarshal(bytes, &newValue); err != nil { - panic(err) - } - fmt.Println(newValue) -} -``` - -**JavaScript** - -```javascript -import Fory, { Type, InternalSerializerType } from "@apache-fory/fory"; - -/** - * @apache-fory/hps use v8's fast-calls-api that can be called directly by jit, ensure that the version of Node is 20 or above. - * Experimental feature, installation success cannot be guaranteed at this moment - * If you are unable to install the module, replace it with `const hps = null;` - **/ -import hps from "@apache-fory/hps"; - -// Now we describe data structures using JSON, but in the future, we will use more ways. -const description = Type.object("example.foo", { - foo: Type.string(), -}); -const fory = new Fory({ hps }); -const { serialize, deserialize } = fory.registerSerializer(description); -const input = serialize({ foo: "hello fory" }); -const result = deserialize(input); -console.log(result); -``` - -**Rust** - -```rust -use chrono::{NaiveDate, NaiveDateTime}; -use fory::{from_buffer, to_buffer, Fory}; -use std::collections::HashMap; - -#[test] -fn complex_struct() { - #[derive(Fory, Debug, PartialEq)] - #[tag("example.foo2")] - struct Animal { - category: String, - } - - #[derive(Fory, Debug, PartialEq)] - #[tag("example.foo")] - struct Person { - c1: Vec<u8>, // binary - c2: Vec<i16>, // primitive array - animal: Vec<Animal>, - c3: Vec<Vec<u8>>, - name: String, - c4: HashMap<String, String>, - age: u16, - op: Option<String>, - op2: Option<String>, - date: NaiveDate, - time: NaiveDateTime, - c5: f32, - c6: f64, - } - let person: Person = Person { - c1: vec![1, 2, 3], - c2: vec![5, 6, 7], - c3: vec![vec![1, 2], vec![1, 3]], - animal: vec![Animal { - category: "Dog".to_string(), - }], - c4: HashMap::from([ - ("hello1".to_string(), "hello2".to_string()), - ("hello2".to_string(), "hello3".to_string()), - ]), - age: 12, - name: "helo".to_string(), - op: Some("option".to_string()), - op2: None, - date: NaiveDate::from_ymd_opt(2025, 12, 12).unwrap(), - time: NaiveDateTime::from_timestamp_opt(1689912359, 0).unwrap(), - c5: 2.0, - c6: 4.0, - }; - - let bin: Vec<u8> = to_buffer(&person); - let obj: Person = from_buffer(&bin).expect("should success"); - assert_eq!(person, obj); -} -``` - -## Serialize Shared Reference and Circular Reference - -Shared reference and circular reference can be serialized automatically, no duplicate data or recursion error. - -**Java** - -```java -import org.apache.fory.*; -import org.apache.fory.config.*; -import java.util.*; - -public class ReferenceExample { - public static class SomeClass { - SomeClass f1; - Map<String, String> f2; - Map<String, String> f3; - } - - public static Object createObject() { - SomeClass obj = new SomeClass(); - obj.f1 = obj; - obj.f2 = ofHashMap("k1", "v1", "k2", "v2"); - obj.f3 = obj.f2; - return obj; - } - - // mvn exec:java -Dexec.mainClass="org.apache.fory.examples.ReferenceExample" - public static void main(String[] args) { - Fory fory = Fory.builder().withLanguage(Language.XLANG) - .withRefTracking(true).build(); - fory.register(SomeClass.class, "example.SomeClass"); - byte[] bytes = fory.serialize(createObject()); - // bytes can be data serialized by other languages. - System.out.println(fory.deserialize(bytes)); - } -} -``` - -**Python** - -```python -from typing import Dict -import pyfory - -class SomeClass: - f1: "SomeClass" - f2: Dict[str, str] - f3: Dict[str, str] - -fory = pyfory.Fory(ref_tracking=True) -fory.register_type(SomeClass, typename="example.SomeClass") -obj = SomeClass() -obj.f2 = {"k1": "v1", "k2": "v2"} -obj.f1, obj.f3 = obj, obj.f2 -data = fory.serialize(obj) -# bytes can be data serialized by other languages. -print(fory.deserialize(data)) -``` - -**Golang** - -```go -package main - -import forygo "github.com/apache/fory/fory/go/fory" -import "fmt" - -func main() { - type SomeClass struct { - F1 *SomeClass - F2 map[string]string - F3 map[string]string - } - fory := forygo.NewFory(true) - if err := fory.Register(SomeClass{}, 65); err != nil { - panic(err) - } - value := &SomeClass{F2: map[string]string{"k1": "v1", "k2": "v2"}} - value.F3 = value.F2 - value.F1 = value - bytes, err := fory.Marshal(value) - if err != nil { - } - var newValue interface{} - // bytes can be data serialized by other languages. - if err := fory.Unmarshal(bytes, &newValue); err != nil { - panic(err) - } - fmt.Println(newValue) -} -``` - -**JavaScript** - -```javascript -import Fory, { Type } from '@apache-fory/fory'; -/** - * @apache-fory/hps use v8's fast-calls-api that can be called directly by jit, ensure that the version of Node is 20 or above. - * Experimental feature, installation success cannot be guaranteed at this moment - * If you are unable to install the module, replace it with `const hps = null;` - **/ -import hps from '@apache-fory/hps'; - -const description = Type.object('example.foo', { - foo: Type.string(), - bar: Type.object('example.foo'), -}); - -const fory = new Fory({ hps }); -const { serialize, deserialize } = fory.registerSerializer(description); -const data: any = { - foo: 'hello fory', -}; -data.bar = data; -const input = serialize(data); -const result = deserialize(input); -console.log(result.bar.foo === result.foo); -``` - -**JavaScript** -Reference cannot be implemented because of rust ownership restrictions - -## Zero-Copy Serialization - -**Java** - -```java -import org.apache.fory.*; -import org.apache.fory.config.*; -import org.apache.fory.serializer.BufferObject; -import org.apache.fory.memory.MemoryBuffer; - -import java.util.*; -import java.util.stream.Collectors; - -public class ZeroCopyExample { - // mvn exec:java -Dexec.mainClass="io.ray.fory.examples.ZeroCopyExample" - public static void main(String[] args) { - Fory fory = Fory.builder().withLanguage(Language.XLANG).build(); - List<Object> list = ofArrayList("str", new byte[1000], new int[100], new double[100]); - Collection<BufferObject> bufferObjects = new ArrayList<>(); - byte[] bytes = fory.serialize(list, e -> !bufferObjects.add(e)); - // bytes can be data serialized by other languages. - List<MemoryBuffer> buffers = bufferObjects.stream() - .map(BufferObject::toBuffer).collect(Collectors.toList()); - System.out.println(fory.deserialize(bytes, buffers)); - } -} -``` - -**Python** - -```python -import array -import pyfory -import numpy as np - -fory = pyfory.Fory() -list_ = ["str", bytes(bytearray(1000)), - array.array("i", range(100)), np.full(100, 0.0, dtype=np.double)] -serialized_objects = [] -data = fory.serialize(list_, buffer_callback=serialized_objects.append) -buffers = [o.to_buffer() for o in serialized_objects] -# bytes can be data serialized by other languages. -print(fory.deserialize(data, buffers=buffers)) -``` - -**Golang** - -```go -package main - -import forygo "github.com/apache/fory/fory/go/fory" -import "fmt" - -func main() { - fory := forygo.NewFory() - list := []interface{}{"str", make([]byte, 1000)} - buf := fory.NewByteBuffer(nil) - var bufferObjects []fory.BufferObject - fory.Serialize(buf, list, func(o fory.BufferObject) bool { - bufferObjects = append(bufferObjects, o) - return false - }) - var newList []interface{} - var buffers []*fory.ByteBuffer - for _, o := range bufferObjects { - buffers = append(buffers, o.ToBuffer()) - } - if err := fory.Deserialize(buf, &newList, buffers); err != nil { - panic(err) - } - fmt.Println(newList) -} -``` - -**JavaScript** - -```javascript -// Coming soon -``` --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
