Java和Rust實現(xiàn)JSON序列化互轉(zhuǎn)的解決方案詳解
1.背景
最近在使用Rust實現(xiàn)Rocketmq的項目 rocketmq-rust,在實現(xiàn)的過程中就會遇到請求頭以及相關的數(shù)據(jù)JSON序列化在兩個不同語言中的序列化和反序列的情況。在這種情況下遇到下面的問題:Java中存在繼承,例如
public class Test { public static void main(String[] args) { Student object = new Student(); object.setName("mxsm"); object.setAge("18"); object.setSchool("杭州電子科技大學"); System.out.println(JSON.toJSONString(object)); } public static class Person { private String name; private String age; //ignore get set method } public static class Student extends Person { private String school; //ignore get set method } }
那么在Java中序列化就會打印成這樣:
{"age":"18","name":"mxsm","school":"杭州電子科技大學"}
問題就來了。在Rust中沒有這樣的繼承關系該如何處理這樣的代碼情況。隨著跨語言開發(fā)的流行,將數(shù)據(jù)在不同編程語言之間進行序列化和反序列化變得越來越重要。本文將探討如何在Java和Rust之間實現(xiàn)JSON數(shù)據(jù)的序列化互轉(zhuǎn),并解決在Rust中處理Java繼承序列化的挑戰(zhàn)。
2. Java和Rust之間的JSON序列化互轉(zhuǎn)
Java中有許多庫可以用于JSON序列化,其中最流行的是Jackson和Gson以及Fastjson。我們將以Fastjson為例進行介紹(Rocketmq中使用的就是Fastjson進行序列)。Rust中使用serde作為例子,在 Rocketmq-rust 項目中JSON序列化使用的是 serde 。
2.1 無繼承的簡單數(shù)據(jù)結構
Java示例代碼:
public static class Person { private String name; private String age; private String homeAddress //ignore get set method }
轉(zhuǎn)換成對應的Rust代碼
#[derive(Clone,Debug,Serialize,Deserialize)] #[serde(rename_all="camelCase")] pub struct Person{ name: String, age: String, home_address: String }
這里有個需要說明,在Java規(guī)范中字段的命名遵循的是駝峰,而rust使用的snake case,兩者是有區(qū)別的。 這里就需要注意如果是以Java為主的項目那么Rust的序列化和反序列化都應該使用駝峰的方式來進行。也就是上面代碼的增加的 #[serde(rename_all="camelCase")] 而如果是Rust項目為主,很大可能序列后的JSON字符串使用的就是snake case 那么Java項目就需要進行相對應的處理。
2.2 Java代碼有繼承的結構
代碼示例:
public static class Person { private String name; private String age; //ignore get set method } public static class Student extends Person { private String school; //ignore get set method }
在Java代碼中繼承是很常見的一種操作,但是在Rust中struct的繼承并不存在。那么這種情況下應該如何解決。
2.2.1 將所有的代碼扁平化
代碼扁平化這個是最簡單的方式。以上面代碼為例。如果扁平化后我們后我們處理后的Rust代碼:
#[derive(Clone,Debug,Serialize,Deserialize)] #[serde(rename_all="camelCase")] pub struct Person{ name: String, age: String, } #[derive(Clone,Debug,Serialize,Deserialize)] #[serde(rename_all="camelCase")] pub struct Person{ name: String, age: String, school: String }
所謂扁平化就是直接將繼承代碼的屬性移到最底層的繼承代碼中。這樣做就是簡單,能夠?qū)崿F(xiàn)和Java相同的序列化的效果。
優(yōu)點:
簡單,快速解決問題
缺點:
需要實現(xiàn)的重復代碼量大
2.2.2 抽象出來trait
將公共的方法操作方法抽象出來trait然后,使用trait繼承的方式來實現(xiàn)。同樣已上面的代碼為例:
pub trait PersonTrait{ fn get_name(&self)->String; fn get_age(&self)->String; }
然后所有的struct進行實現(xiàn)。這個優(yōu)缺點也很明顯。
優(yōu)點:
- 簡單,相比第一種方式多了一個抽象trait的步驟,其他的和第一種差不多
- 可以使用Trait作為方法的參數(shù)或者struct的屬性。提供了類似Java的多態(tài)(這個對于無需要進行序列化的比較好)
缺點:
需要實現(xiàn)的重復代碼量大
2.2.3 使用struct聚合配合serde的扁平化(重點)
使用struct聚合配合serde的扁平化來解決Java項目和Rust項目的JSON數(shù)據(jù)的序列化和反序列交互比較優(yōu)的解。通用用上面的代碼為例子。如果使用這種方式來處理,轉(zhuǎn)換成Rust代碼后的代碼:
#[derive(Clone,Debug,Serialize,Deserialize)] #[serde(rename_all="camelCase")] pub struct Person{ name: String, age: String, } #[derive(Clone,Debug,Serialize,Deserialize)] #[serde(rename_all="camelCase")] pub struct Person{ #[serde(flatten)] // 這個是扁平化關鍵 person: Persion school: String }
同樣定義跟Java相同的代碼,然后通過聚合的方式來模擬Rust中的繼承關系。 將需要扁平化的代碼進行扁平化使用 #[serde(flatten)] 來實現(xiàn)。
優(yōu)點:
- 能夠和其他語言相同的JSON序列化方式(需要serde的扁平化支持)
- 整體的序列化相對較靈活
缺點:
需要Rust JSON序列化工具的支持。如果工具不支持沒辦法實現(xiàn)。只能手動序列化
說明:使用struct聚合配合serde的扁平化來解決JSON序列化的方式也是 Rocketmq-rust 項目中的解決方式。因為rocketmq-rust需要支持和Java版本進行互通。
3.總結
對于Java JSON序列化和Rust JSON序列化主要差異由以下兩種原因引起:
- 屬性的命名規(guī)范,Java使用的是駝峰 而Rust使用的是snake case。這就導致在序列化的情況下兩者之間的序列化會存在屬性的命名差異。
- Java有繼承關系,繼承的最底層的類進行序列化會將父類的屬性進行扁平化序列化。而Rust中不存在所以導致Rust中的序列化的差異性,為了解決這種差異性就有了上面的三種方式。
就單純解決JSON序列化使用 使用struct聚合配合serde的扁平化 是一種比較憂的解決方式。但是不是唯一的方式。
到此這篇關于Java和Rust實現(xiàn)JSON序列化互轉(zhuǎn)的解決方案詳解的文章就介紹到這了,更多相關Java Rust實現(xiàn)JSON序列化互轉(zhuǎn)內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
詳解Java中的reactive stream協(xié)議
Stream大家應該都很熟悉了,java8中為所有的集合類都引入了Stream的概念。優(yōu)雅的鏈式操作,流式處理邏輯,相信用過的人都會愛不釋手。本文將詳細介紹Java中的reactive stream協(xié)議。2021-06-06Mybatis或Mybatis-Plus框架的xml文件中特殊符號的使用詳解
這篇文章主要介紹了Mybatis或Mybatis-Plus框架的xml文件中特殊符號的使用詳解,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-11-11SSM框架+Plupload實現(xiàn)分塊上傳大文件示例
這篇文章主要介紹了SSM框架+Plupload實現(xiàn)分塊上傳示例(Spring+SpringMVC+MyBatis+Plupload),將用戶選中的文件(可多個)分隔成一個個小塊,依次向服務器上傳,有興趣的可以了解一下。2017-03-03