0
点赞
收藏
分享

微信扫一扫

Rust json 序列化与反序列化

Jonescy 2022-08-24 阅读 253


文章目录

  • ​​一、json-rust​​
  • ​​1.1 反序列化​​
  • ​​1.2 序列化 Serialize​​
  • ​​二、Serde JSON​​
  • ​​示例一​​
  • ​​示例:读取json文件反序列​​
  • ​​缺失字段设置默认值​​
  • ​​跳过(条件跳过)某些字段,选择字段​​
  • ​​在不缓冲到 Vec 的情况下处理一系列值​​
  • ​​将枚举序列化为数字​​
  • ​​序列化为驼峰命名方式​​
  • ​​json 反序列化-日期格式​​
  • ​​三、拓展:【使用 Rust 写 Parser 】​​


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


举报

相关推荐

0 条评论