Rust json 序列化与反序列化


json在大多数的语言中都具有举足轻重的地位,特别在网络传中的常用数据交换格式。 【百度百科】
关于 Rust 结构数组、序列化与反序列化

一、json-rust

下面会举例一些常用的json序列化与反序列化的用法,在Rust中json对象详情【请查看】

1.1 反序列化

反序列化 json::parse

json-rust:https://github.com/maciejhirsz/json-rust 【文档查看更多方法】

如下:使用了对象宏,数组,其中数组可以保存混合类型。
cargo.toml

[dependencies]
json = "*"
#[macro_use]
extern crate json;

fn main() {
    let parsed = json::parse(r#"
    {
        "code": 200,
        "success": true,
        "payload": {
            "features": [
                "awesome",
                "easyAPI",
                "lowLearningCurve"
            ]
        }
    }
    "#).unwrap();

    let instantiated = object!{
        "code" => 200,
        "success" => true,
        "payload" => object!{
            "features" => array![
                "awesome",
                "easyAPI",
                "lowLearningCurve"
            ]
        }
    };

    assert_eq!(parsed, instantiated);
    println!("解析输出字段:code={}",instantiated["code"]);
    println!("解析输出字段:success={}",instantiated["success"]);
    println!("解析输出对象:payload={:?}",instantiated["payload"]);
    println!("解析输出数组:features={:?}",instantiated["payload"]["features"]);
    println!("解析输出数组元素:0={}",instantiated["payload"]["features"][0]);
    println!("解析输出数组元素:1={}",instantiated["payload"]["features"][1]);
    println!("解析输出数组元素:2={}",instantiated["payload"]["features"][2]);
}


// 解析输出字段:code=200
// 解析输出字段:success=true
// 解析输出对象:payload=Object(Object { store: [("features", Array([Short("awesome"), Short("easyAPI"), Short("lowLearningCur
// ve")]), 0, 0)] })
// 解析输出数组:features=Array([Short("awesome"), Short("easyAPI"), Short("lowLearningCurve")])
// 解析输出数组元素:0=awesome
// 解析输出数组元素:1=easyAPI
// 解析输出数组元素:2=lowLearningCurve
1.2 序列化 Serialize

Serialize with json::stringify(value)

如下涉及到:

  • 显式空类型json::null
  • 可选类型 Optional
  • 向量vector
  • 可选类型向量
  • 数组 与 数组宏 array!
  • 对象与 对象宏 object!
assert_eq!(json::stringify(json::Null), "null");         //显式空类型

let data = vec![Some(1), None, Some(2), None, Some(3)];  //可选类型向量 
assert_eq!(json::stringify(data), "[1,null,2,null,3]");

对于对象格式使用:object.dump()

#[macro_use]
extern crate json;

fn main() {
    let features_0 : Option<String> = Some("美貌".to_string());
    let features_1 : Option<String> = None;
    let score = vec![67,78,87];
    let score_other = vec![Some(87),Some(89),None];
    let hobby = json::Null;

    let mut sub_items = json::JsonValue::new_object();
    sub_items["跳高"] = 2.into();
    sub_items["跳远"] = 3.into();

    let mut subject = json::JsonValue::new_array();
    subject.push(100);
    subject.push(99);
    subject.push(sub_items);



    let data = array!["123",true,json::Null,300];
    let students = object!{
        "name" => "zhangsan",
        "sex" => 15,
        "height" => 156,
        "weight" => 45,
        "hobby1" => "吹牛逼".to_string(),
        "hobby2" => hobby,
        "ke_mu" => subject,
        "features" => array![features_0,features_1],
        "score_main" => score,
        "score_branch" => score_other,
        "others"=> data
    };
    let response = students.dump();
    println!("[返回数据]:{}",response)
}

// {
// 	"name": "zhangsan",
// 	"sex": 15,
// 	"height": 156,
// 	"weight": 45,
// 	"hobby1": "吹牛逼",
// 	"hobby2": null,
// 	"ke_mu": [100, 99, {
// 		"跳高": 2,
// 		"跳远": 3
// 	}],
// 	"features": ["美貌", null],
// 	"score_main": [67, 78, 87],
// 	"score_branch": [87, 89, null],
// 	"others": ["123", true, null, 300]
// }

二、Serde JSON

serde文档:https://serde.rs/

示例一

Serde JSON:https://github.com/serde-rs/json , 【文档查看更多方法】
Cargo.toml 文件

[dependencies]
serde = "*"
serde_derive = "*"
serde_json = "*"

测试数据文件sample.json内容如下:

{
    "name": "John Doe",
    "age": 43,
    "address": {
        "street": "10 Downing Street",
        "city": "London"
    },
    "phones": [
        "+44 1234567",
        "+44 2345678"
    ]
}

解析为脏类型

extern crate serde_json;
use std::fs::File;


fn main() {
    let f = File::open("./sample.json").unwrap();
    let values:serde_json::Value = serde_json::from_reader(f).unwrap();
    println!("整个字符串:{:?}",values);

    println!("name:{}",values["name"]);
    println!("age:{}",values["age"]);
    println!("address-city:{}",values["address"]["city"]);
    println!("address-street:{}",values["address"]["street"]);
    println!("phones-0:{}",values["phones"][0]);
    println!("phones-1:{}",values["phones"][1]);

    // 解析为脏类型
    println!("{:?}", values["name"].as_str().unwrap());
    println!("{:?}", values["age"].as_i64().unwrap());
}

//=================================================
// 整个字符串:
// Object(
//     {
//         "address": Object({
//             "city": String("London"),
//             "street": String("10 Downing Street")
//         }),
//         "age": Number(43),
//         "name": String("John Doe"),
//         "phones": Array([String("+44 1234567"), String("+44 2345678")])
//     }
// )

// name:"John Doe"
// age:43
// address-city:"London"
// address-street:"10 Downing Street"
// phones-0:"+44 1234567"
// phones-1:"+44 2345678"

// "John Doe"
// 43

解析为强类型(From struct to JSON)(From JSON to struct)

extern crate serde;
extern crate serde_json;

#[macro_use]                // 此处必须添加否则会报错,serde_derive是一个宏
extern crate serde_derive;
use std::fs::File;

#[derive(Debug, Serialize, Deserialize)]
struct Address{
    street: String,
    city: String,
}

#[derive(Debug, Serialize, Deserialize)]
struct Person{
    name: String,
    age:u8,
    address:Address,
    phones:Vec<String>,
}


impl Person {
    fn default() -> Self {
        Person{
            name: "zhangsan".to_string(),
            age: 18u8,
            address:Address{
                street: "East nanjing road".to_string(),
                city: "shanghai".to_string(),
            },
            phones:vec!["13562958755".to_string(),"15963695569".to_string()],
        }
    }
}

fn main() {
    let f = File::open("./sample.json").unwrap();
    let values:Person = serde_json::from_reader(f).unwrap();
    println!("强类型解析输出:{:?}",values);

    let name = &values.name;
    let age = &values.age;
    let city = &values.address.city;
    let phones = &values.phones;
    println!("== name =={}",name);
    println!("== age =={}",age);
    println!("== city =={}",city);
    println!("== phones =={:?}",phones);
    println!("==address-street=={}",&values.address.street);


    let person = Person::default();
    let person_json = serde_json::to_string(&person).expect("Couldn't serialize config");
    let person_json_pretty = serde_json::to_string_pretty(&person).expect("Couldn't serialize config");
    println!("person_json 直接转成json:\n {}", person_json);
    println!("person_json_pretty 转成格式化json:\n {}", person_json_pretty);
}


// 强类型解析输出:
// Person {
// 	name: "John Doe",
// 	age: 43,
// 	address: Address {
// 		street: "10 Downing Street",
// 		city: "London"
// 	},
// 	phones: ["+44 1234567", "+44 2345678"]
// }


// == name ==John Doe
// == age ==43
// == city ==London
// == phones ==["+44 1234567", "+44 2345678"]
// ==address-street==10 Downing Street

=================================================================
// person_json:
//  {"name":"zhangsan","age":18,"address":{"street":"East nanjing road","city":"shanghai"},"phones":["13562958755","15963695569"]}

// person_json_pretty:
//  {
//   "name": "zhangsan",
//   "age": 18,
//   "address": {
//     "street": "East nanjing road",
//     "city": "shanghai"
//   },
//   "phones": [
//     "13562958755",
//     "15963695569"
//   ]
// }
示例:读取json文件反序列

toml文件,同上面的写法差不多

[dependencies]
serde = { version = "1.0.124", features = ["derive"] }
serde_json = "1.0.64"
use serde::Deserialize;
use serde_json;

#[derive(Deserialize,Debug)]
struct Recognize{
    recognize: Vec<LocalInfo>
}

#[derive(Deserialize,Debug)]
struct LocalInfo {
    position: Position,
    score:f64,
    #[serde(rename = "type")]
    type_: String,
    words: String
}

#[derive(Deserialize,Debug)]
struct Position{
    width:i32,
    top:i32,
    left:i32,
    height:i32
}


fn main() {
    let filename = std::env::args().nth(1).unwrap();
    let file = std::fs::File::open(filename).expect("read file error!");
    let temp:Recognize = serde_json::from_reader(file).unwrap();
    println!("result: {:#?}",temp.recognize[0].position.height);
    println!("result: {:#?}",temp.recognize[0].type_);
    println!("result: {:#?}",temp.recognize[0].words);
}

缺失字段设置默认值
use serde::Deserialize;


#[derive(Deserialize, Debug)]
struct Request {
    // Use the result of a function as the default if "resource" is not included in the input.
    #[serde(default = "default_resource")]
    resource: String,

    #[serde(default = "default_resource_num")]
    resource_num: i32,

    // Use the type's implementation of std::default::Default if "timeout" is not included in the input.
    #[serde(default)]
    timeout: Timeout,
    

    // Use a method from the type as the default if "priority" is not
    // included in the input. This may also be a trait method.
    #[serde(default = "Priority::lowest")]
    priority: Priority,
}

fn default_resource() -> String {
    "/".to_string()
}


fn default_resource_num() -> i32 {
    404
}


/// Timeout in seconds.
#[derive(Deserialize, Debug)]
struct Timeout(u32);
impl Default for Timeout {
    fn default() -> Self {
        Timeout(30)
    }
}

#[derive(Deserialize, Debug)]
enum Priority { ExtraHigh, High, Normal, Low, ExtraLow }
impl Priority {
    fn lowest() -> Self { Priority::ExtraLow }
}

fn main() {
    let json = r#"
        [
        {
            "timeout":3
        },
          {
            "timeout": 5,
            "priority": "High"
          }
        ]
    "#;

    let requests: Vec<Request> = serde_json::from_str(json).unwrap();
    println!("{:#?}", requests);
}

/*
[
    Request {
        resource: "/",
        resource_num: 404,
        timeout: Timeout(
            3,
        ),
        priority: ExtraLow,
    },
    Request {
        resource: "/",
        resource_num: 404,
        timeout: Timeout(
            5,
        ),
        priority: High,
    },
]
*/
跳过(条件跳过)某些字段,选择字段
use serde::Serialize;

use std::collections::BTreeMap as Map;


#[derive(Debug, Serialize)]
#[serde(untagged)]
enum Speech {
    Str(String),
    StrArray(Vec<String>),
    text_all(TextInfo),
}

#[derive(Debug,Serialize)]
pub struct TextInfo {
    item_words: String,
    chinese_key: String,
    item_score: f64,
}


#[derive(Serialize)]
struct Resource {
    // Always serialized.
    name: String,

    // Never serialized.
    #[serde(skip_serializing)]
    hash: String,

    // Use a method to decide whether the field should be skipped.
    #[serde(skip_serializing_if = "Map::is_empty")]
    metadata: Map<String, String>,
    
    #[serde(skip_serializing_if = "Option::is_none")]
    image_result: Option<Speech>,
}

fn main() {
    let resources = vec![
        Resource {
            name: "Stack Overflow".to_string(),
            hash: "b6469c3f31653d281bbbfa6f94d60fea130abe38".to_string(),
            image_result: Some(Speech::Str("zhangsan".to_string())),
            metadata: Map::new(),
        },
        Resource {
            name: "tensorflow".to_string(),
            hash: "b2469c3f31653d281bbbfa6f94d60fea130abe38".to_string(),
            image_result: None,
            metadata: Map::new(),
        },
        Resource {
            name: "torch".to_string(),
            hash: "b1239c3f31653d281bbbfa6f94d60fea130abe38".to_string(),
            image_result: Some(Speech::text_all(TextInfo{
                item_words: "第一个单词".to_string(),
                chinese_key: "简体中文".to_string(),
                item_score: 0.985142,}
                )),
            metadata: Map::new(),
        },
        Resource {
            name: "GitHub".to_string(),
            hash: "5cb7a0c47e53854cd00e1a968de5abce1c124601".to_string(),
            image_result:Some(Speech::StrArray(vec!["recognize_01".to_string(), "recognize_02 all".to_string()])),
            metadata: {
                let mut metadata = Map::new();
                metadata.insert("headquarters".to_string(),
                                "San Francisco".to_string());
                metadata
            },
        },
    ];

    let json = serde_json::to_string_pretty(&resources).unwrap();
    println!("{}", json);
}

/*
[
  {
    "name": "Stack Overflow",
    "image_result": "zhangsan"
  },
  {
    "name": "tensorflow"
  },
  {
    "name": "torch",
    "image_result": {
      "item_words": "第一个单词",
      "chinese_key": "简体中文",
      "item_score": 0.985142
    }
  },
  {
    "name": "GitHub",
    "metadata": {
      "headquarters": "San Francisco"
    },
    "image_result": [
      "recognize_01",
      "recognize_02 all"
    ]
  }
]
*/
在不缓冲到 Vec 的情况下处理一系列值

假设我们有一个整数阵列,我们希望找出最大值,而无需同时将整个阵列保留在内存中。这种方法可以适应处理各种其他情况,其中数据需要处理,同时被除名,而不是之后。

use serde::{Deserialize, Deserializer};
use serde::de::{self, Visitor, SeqAccess};

use std::{cmp, fmt};
use std::marker::PhantomData;

#[derive(Deserialize)]
struct Outer {
    id: String,

    // 通过计算序列(JSON数组)的最大值来反序列化此字段
    #[serde(deserialize_with = "deserialize_max")]
   
    // JSON 字段为 `values`.
    #[serde(rename(deserialize = "values"))]
    max_value: u64,
}

/// 反序列化值序列的最大值。整个序列不会:先反序列化为Vec<T>然后计算最大值,无需缓冲到内存中。
/// T可以是实现Ord的泛型, it is used with T=u64.
fn deserialize_max<'de, T, D>(deserializer: D) -> Result<T, D::Error>
where
    T: Deserialize<'de> + Ord,
    D: Deserializer<'de>,
{
    struct MaxVisitor<T>(PhantomData<fn() -> T>);

    impl<'de, T> Visitor<'de> for MaxVisitor<T>
    where
        T: Deserialize<'de> + Ord,
    {
        /// 访问者的返回类型。这个访问者计算T类型的值序列的最大值,因此最大值的类型是T。
        type Value = T;

        fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
            formatter.write_str("a nonempty sequence of numbers")
        }

        fn visit_seq<S>(self, mut seq: S) -> Result<T, S::Error>
        where
            S: SeqAccess<'de>,
        {
            // 从最大值等于序列中的第一个值开始。
            let mut max = seq.next_element()?.ok_or_else(||
                // 空序列处理。
                de::Error::custom("no values in seq when looking for maximum")
            )?;

            // 更新最大值
            while let Some(value) = seq.next_element()? {
                max = cmp::max(max, value);
            }

            Ok(max)
        }
    }

    // 创建访问者并要求反序列化程序驱动它。如果输入数据中存在seq,反序列化程序将调用visitor.visit_seq().
    let visitor = MaxVisitor(PhantomData);
    deserializer.deserialize_seq(visitor)
}

fn main() {
    let j = r#"
        {
          "id": "demo-deserialize-max",
          "values": [
            256,
            100,
            384,
            314,
            271
          ]
        }
    "#;

    let out: Outer = serde_json::from_str(j).unwrap();

    // Prints "max value: 384"
    println!("max value: {}", out.max_value);
将枚举序列化为数字

serde_repr板条箱提供了替代的源宏,这些宏源具有相同的序列化和非系列化特征,但委托给 C 样列举的基本表示。例如,这允许将类似 C 的列举格式化为整数,而不是 JSON 中的字符串。

[dependencies]
serde = "1.0"
serde_json = "1.0"
serde_repr = "0.1"

use serde_repr::*;

#[derive(Serialize_repr, Deserialize_repr, PartialEq, Debug)]
#[repr(u8)]
enum SmallPrime {
    Two = 2,
    Three = 3,
    Five = 5,
    Seven = 7,
}

fn main() {
    use SmallPrime::*;
    let nums = vec![Two, Three, Five, Seven];

    // Prints [2,3,5,7]
    println!("{}", serde_json::to_string(&nums).unwrap());
    assert_eq!(Two, serde_json::from_str("2").unwrap());
}
序列化为驼峰命名方式
use serde::Serialize;

#[derive(Serialize)]
#[serde(rename_all = "camelCase")]
struct Person {
    first_name: String,
    last_name: String,
}

fn main() {
    let person = Person {
        first_name: "Graydon".to_string(),
        last_name: "Hoare".to_string(),
    };

    let json = serde_json::to_string_pretty(&person).unwrap();
    println!("{}", json);
}

/*
{
  "firstName": "Graydon",
  "lastName": "Hoare"
}
*/
json 反序列化-日期格式
use chrono::{DateTime, Utc};
use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]
pub struct StructWithCustomDate {
    // DateTime支持Serde开箱即用,但使用rfc339格式。提供一些自定义逻辑
    #[serde(with = "my_date_format")]
    pub timestamp: DateTime<Utc>,

    // Any other fields in the struct.
    pub bidder: String,
}

mod my_date_format {
    use chrono::{DateTime, Utc, TimeZone};
    use serde::{self, Deserialize, Serializer, Deserializer};
    const FORMAT: &'static str = "%Y-%m-%d %H:%M:%S";
    
    
    pub fn serialize<S>(
        date: &DateTime<Utc>,
        serializer: S,
    ) -> Result<S::Ok, S::Error>
    where
        S: Serializer,
    {
        let s = format!("{}", date.format(FORMAT));
        serializer.serialize_str(&s)
    }

    // 反序列化函数的签名必须遵循以下模式:
    // 尽管它也可能是输出类型T上的泛型。
    pub fn deserialize<'de, D>(
        deserializer: D,
    ) -> Result<DateTime<Utc>, D::Error>
    where
        D: Deserializer<'de>,
    {
        let s = String::deserialize(deserializer)?;
        Utc.datetime_from_str(&s, FORMAT).map_err(serde::de::Error::custom)
    }
}

fn main() {
    let json_str = r#"
      {
        "timestamp": "2017-02-16 21:54:30",
        "bidder": "Skrillex"
      }
    "#;

    let data: StructWithCustomDate = serde_json::from_str(json_str).unwrap();
    println!("{:#?}", data);

    let serialized = serde_json::to_string_pretty(&data).unwrap();
    println!("{}", serialized);
}

/*
StructWithCustomDate {
    timestamp: 2017-02-16T21:54:30Z,
    bidder: "Skrillex",
}
{
  "timestamp": "2017-02-16 21:54:30",
  "bidder": "Skrillex"
}
*/

三、拓展:【使用 Rust 写 Parser 】

nom 文档:https://docs.rs/nom/5.1.2/nom/

  1. 初识 nom
  2. 解析Redis协议
  3. 解析JSON
  4. 解析 binlog

拓展:https://stackoverflow.com/questions/62031397/how-to-deserialize-in-rust-using-serde-optional-json-parameter-that-can-be-eit?r=SearchResults

Rust中,序列化反序列化是将对象转化为便于传输的格式和将序列化的数据恢复为对象的过程。常见的序列化格式包括二进制格式、字节数组、JSON字符串和XML字符串。为了使数据类型支持序列化反序列化,该类型需要实现Serialize和Deserialize trait。在Rust中,可以使用Serde库来提供基础类型和标准库类型的Serialize和Deserialize实现。\[2\]\[3\] 例如,使用Serde库进行JSON序列化反序列化的示例代码如下: ```rust use serde::{Serialize, Deserialize}; use serde_json::{Result, Value}; #\[derive(Serialize, Deserialize)\] struct Person { name: String, age: u32, } fn main() -> Result<()> { // 序列化JSON字符串 let person = Person { name: "Alice".to_string(), age: 25, }; let json = serde_json::to_string(&person)?; println!("Serialized JSON: {}", json); // 反序列化JSON字符串为对象 let deserialized_person: Person = serde_json::from_str(&json)?; println!("Deserialized Person: {:?}", deserialized_person); Ok(()) } ``` 在上面的示例中,我们定义了一个名为Person的结构体,并为其实现了Serialize和Deserialize trait。然后,我们可以使用serde_json库的to_string函数将Person对象序列化JSON字符串,并使用from_str函数将JSON字符串反序列化为Person对象。\[1\] 总结起来,Rust中的序列化反序列化是通过实现Serialize和Deserialize trait来将对象转化为传输格式和恢复为对象的过程,可以使用Serde库来简化序列化反序列化的操作。 #### 引用[.reference_title] - *1* [Rust json 序列化反序列化](https://blog.csdn.net/wsp_1138886114/article/details/109357476)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *2* [Rust 结构数组、序列化反序列化](https://blog.csdn.net/wsp_1138886114/article/details/108835634)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Rust 中的序列化反序列化](https://blog.csdn.net/u012666784/article/details/112787047)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^koosearch_v1,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

SongpingWang

你的鼓励是我创作的最大动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值