推广 热搜: csgo  vue  angelababy  2023  gps  新车  htc  落地  app  p2p 

rust中使用serde操作json数据

   2023-08-09 网络整理佚名1810
核心提示:(1)将json数据字符串转为Rust值使用::函数;将JSON数据字节数组转为Rust值使用函数;将从像文件或TCP流获取的JSON数据使用函数。Doe,如果不想包含双引号,需要使用()函数将json字符串转为rust字符串。下面学习将json数据映射为rust结构体。Value::()函数将serde::Value转为json文本字符串。b,将Rust结构体序列化为json字符串。

1.什么是JSON? 为什么要使用它? 如何在 Rust 中表示它?

JSON 是一种普遍存在的开放标准格式,它使用人类可读的文本来传输由键值对组成的数据对象。

例如以下 JSON 数据

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

在 Rust 中处理 JSON 数据有三种常见情况。

serde 库使用 ::Value 来表示有效的 json 数据。

enum Value {    Null,    Bool(bool),    Number(Number),    String(String),    Array(Vec),    Object(Map<String, Value>),}

这个结构体就是::Value,它可以表达任何有效的json数据。

2. 如何将JSON数据转换为Rust值? 如何将 Rust 值转换为 JSON 数据?

(1)使用::函数将json数据字符串转换为Rust值; 使用函数将 JSON 数据字节数组转换为 Rust 值; 使用函数转换从文件或 TCP 流获取的 JSON 数据。

use serde_json::{Result, Value};
fn untyped_example() -> Result<()> { // Some JSON input data as a &str. Maybe this comes from the user. let data = r#" { "name": "John Doe", "age": 43, "phones": [ "+44 1234567", "+44 2345678" ] }"#;
// Parse the string of data into serde_json::Value. let v: Value = serde_json::from_str(data)?;
// Access parts of the data by indexing with square brackets. println!("Please call {} at the number {}", v["name"], v["phones"][0]);
Ok(()) }

serde::Value 通过方括号括起来的键名的语法来获取值内容。 如果键名不存在或者数组越界,则返回Value::Null,返回值类型为&Value类型。

当打印 Value 值时,字符串将显示双引号。 例如,名称的值为“John Doe”。 如果不想包含双引号,则需要使用()函数将json字符串转换为rust字符串。

在上面的例子中,我们可以发现我们可以直接操作使用serde::Value,对于基本任务来说已经足够了,但是如果你将v["name"]写成v["naem"],编译器无法帮助你找出错误。 我们可以使用 Rust 结构体来解决这个问题。

让我们学习将 json 数据映射到 Rust 结构。

例如:

use serde::{Deserialize, Serialize};use serde_json::Result;
#[derive(Serialize, Deserialize)]struct Person { name: String, age: u8, phones: Vec<String>,}
fn typed_example() -> Result<()> { // Some JSON input data as a &str. Maybe this comes from the user. let data = r#" { "name": "John Doe", "age": 43, "phones": [ "+44 1234567", "+44 2345678" ] }"#;
// Parse the string of data into a Person object. This is exactly the // same function as the one that produced serde_json::Value above, but // now we are asking it for a Person as output. let p: Person = serde_json::from_str(data)?;
// Do things just like with any other Rust data structure. println!("Please call {} at the number {}", p.name, p.phones[0]);
Ok(())}

和上面的例子一样,也使用了::函数,只不过返回的结果会自动将JSON数据映射到一个结构体中。

任何结构体和枚举都可以使用 #[()] 宏来反序列化 json 字符串并自动将其转换为 Rust 结构体。

现在编译器会检查p.name是否有拼写错误,因为p是一个结构体,IDE也会智能提示p.name字段。

(2) 将Rust值构造为json数据

Value::() 函数将 serde::Value 转换为 json 文本字符串。

a、库提供了json! 直接构造 serde::Value 的宏

例如:

use serde_json::json;
fn main() { // The type of `john` is `serde_json::Value` let john = json!({ "name": "John Doe", "age": 43, "phones": [ "+44 1234567", "+44 2345678" ] });
println!("first phone number: {}", john["phones"][0]);
// Convert to a string of JSON and print it out println!("{}", john.to_string());}

b、将Rust结构序列化为json字符串。

例如:

use serde::{Deserialize, Serialize};use serde_json::Result;
#[derive(Serialize, Deserialize)]struct Address { street: String, city: String,}
fn print_an_address() -> Result<()> { // Some data structure. let address = Address { street: "10 Downing Street".to_owned(), city: "London".to_owned(), };
// Serialize it to a JSON string. let j = serde_json::to_string(&address)?;
// Print, write to a file, or send to an HTTP server. println!("{}", j);
Ok(())}

任何实现特征的东西都可以通过 :: 函数进行序列化。 包含 rust 标准库中的内置函数,例如 Vec 和 ,以及声明 #[()] 的结构体和枚举。

只要有内存分配器,它也可以在没有 Rust 标准库的情况下使用。

通过禁用默认 std 功能并启用 alloc 功能来使用 serde 库。

[dependencies]serde_json = { version = "1.0", default-features = false, features = ["alloc"] }

以上就完成了常见的JSON数据到Rust值的转换,以及Rust值到JSON数据的转换。 下面描述一些特殊场景。

场景一:

结构体的字段是Name,想将其转换为json键名?

使用serde。

#[derive(Serialize, Deserialize, Debug)]struct Person {        #[serde(rename = "nickName")]    name: String,    age: u16,}

场景2:

该结构体的字段是蛇形的,转换为json时使用驼峰式大小写吗?

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

场景3:

结构体的某个字段不想被序列化?

#[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>,}

场景四:

客户端传输的JSON数据中的某个字段是可选的。 如何在 Rust 结构中表示它?

这确实很强大,请看:

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,
// 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()}
/// 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#" [ { "resource": "/users" }, { "timeout": 5, "priority": "High" } ] "#;
let requests: Vec<Request> = serde_json::from_str(json).unwrap();
// The first request has resource="/users", timeout=30, priority=ExtraLow println!("{:?}", requests[0]);
// The second request has resource="/", timeout=5, priority=High println!("{:?}", requests[1]);}

场景5:

json中的日期按照指定格式转换?

use chrono::{DateTime, Utc};use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize, Debug)]pub struct StructWithCustomDate { // DateTime supports Serde out of the box, but uses RFC3339 format. Provide // some custom logic to make it use our desired format. #[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";

// The signature of a serialize_with function must follow the pattern: // // fn serialize(&T, S) -> Result // where // S: Serializer // // although it may also be generic over the input types T. 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) }

// The signature of a deserialize_with function must follow the pattern: // // fn deserialize<'de, D>(D) -> Result // where // D: Deserializer<'de> // // although it may also be generic over the output types 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) }}

 
反对 0举报 0 收藏 0 打赏 0评论 0
 
更多>同类资讯
推荐图文
推荐资讯
点击排行
Powered By DESTOON