文章目录
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"
}
*/