标签: serde

如何反序列化具有重复键的 JSON 而不丢失任何值?

我正在尝试反序列化一些具有重复键的 JSON,并且它们可能有任意数量。JSON 看起来像这样:

...
"abilities": [
    {
        "ability_id": 5134,
        "ability_level": 3
    }, 
    {
        "ability_id": 5136,
        "ability_level": 3
    }
],
"abilities": [
    {
        "ability_id": 7710,
        "ability_level": 4
    }
]
...
Run Code Online (Sandbox Code Playgroud)

原始json

我的 Rust 代码是:

#[derive(Deserialize, Debug)]
pub struct Ancient {
    score: usize,
    tower_state: usize,
    barracks_state: usize,
    picks: Option<Vec<HeroId>>,
    bans: Option<Vec<HeroId>>,
    players: Vec<PlayerDetailed>,
    abilities: Option<Vec<Ability>> // has many keys
}
Run Code Online (Sandbox Code Playgroud)

原锈

该结构Ancient是 json 中另一个结构的一部分。

只有最后一个abilities有很多键,而且数量也是可变的,我已经读过这篇文章,但无法将其更改为我喜欢的(我希望最终用户仍然拥有一个结构)。我什至尝试过,#[serde(flatten)]但它只是让一切None。如果可能的话我也想改变它:

#[derive(Deserialize, Debug)]
pub struct Ancient {
    score: …
Run Code Online (Sandbox Code Playgroud)

json rust deserialization serde

3
推荐指数
1
解决办法
1645
查看次数

如何使用 serde 序列化包含 ndarray 字段的结构?

我对 Rust 相当陌生,但希望将它用于一些数字工作,并开始探索ndarray箱。serde::Serialize然而,这样做时,我在尝试导出包含数组的结构时遇到了一些困难serde::Deserialize

特别是,我尝试编译以下代码片段,但这样做时出现错误:

extern crate serde;
use ndarray::{ Array1 };
use serde::{ Serialize, Deserialize };

#[derive(Serialize, Deserialize)]
pub struct Canary {
    pub xs: Array1<f64>
}
Run Code Online (Sandbox Code Playgroud)
error[E0277]: the trait bound `ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>: serde::Serialize` is not satisfied
  --> src/lib.rs:40:5
   |
40 |     pub xs: Array1<f64>
   |     ^^^ the trait `serde::Serialize` is not implemented for `ndarray::ArrayBase<ndarray::OwnedRepr<f64>, ndarray::Dim<[usize; 1]>>`
   |
   = note: required by `serde::ser::SerializeStruct::serialize_field`
Run Code Online (Sandbox Code Playgroud)
# Cargo.toml
[dependencies]
ndarray = { version = "0.12.1", features = …
Run Code Online (Sandbox Code Playgroud)

rust serde

3
推荐指数
1
解决办法
1407
查看次数

使用 Box 对结构实施反序列化

包含 Box 作为成员变量的结构:

type Item = dyn Fn() -> Result<(), Box<dyn std::error::Error + Send + Sync>>;
struct Inner {
    pub data: Box<Item>,
}

// a function, like the type: Item
fn parse() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
    println!("parse called");
    Ok(())
}
Run Code Online (Sandbox Code Playgroud)

Inner现在出现了自定义实现结构体反序列化的问题:

let s = r#"{"data": "parse"}"#;
Run Code Online (Sandbox Code Playgroud)

进入结构体内部:

{
    data: Box::new(parse)
}
Run Code Online (Sandbox Code Playgroud)

我知道serde不要实现 deserialize for ,并且必须手动实现 Deserialize ,这是我的代码,遵循docmentaionBox<T>给出的示例:

let s = r#"{"data": "parse"}"#;
Run Code Online (Sandbox Code Playgroud)

但是,当我运行这些代码时,出现错误:

{
    data: Box::new(parse)
}
Run Code Online (Sandbox Code Playgroud)

粗略地说,我猜问题出在(***) …

rust deserialization serde serde-json

3
推荐指数
1
解决办法
2176
查看次数

如何使用 serde 将 JSON 数组反序列化为结构体?

我正在尝试将以下 JSON 片段反序列化为Vecof struct Shape

use serde::{Deserialize, Serialize};
use serde_json::{Result, Value};

#[derive(Debug, Serialize, Deserialize)]
struct Shape {  // this struct is not working, for display purpose only
    shape_type: String,
    d0: f64,
    d1: f64,
    d2: f64, //optional, like the case of "dot"
    d3: f64, //optional, like the case of "circle"
}

let json = r#"
  {[
    ["line", 1.0, 1.0, 2.0, 2.0],
    ["circle", 3.0, 3.0, 1.0],
    ["dot", 4.0, 4.0]
  ]}"#;

let data: Vec<Shape> = match serde_json::from_str(json)?;
Run Code Online (Sandbox Code Playgroud)

显然,每种类型都Shape需要 …

json struct rust deserialization serde

3
推荐指数
1
解决办法
1万
查看次数

使用 serde 通过数值作为类型标识符对 json 进行反序列化

我对 Rust 很陌生,并且有 OOP 背景。所以,也许我误解了一些 Rust 基础知识。

我想用 serde 解析固定的 json 结构。该结构代表不同的消息类型之一。每条消息都有一个数字type属性来区分它。各个消息类型的确切结构大多不同,但它们也可以是相同的。

{"type": 1, "sender_id": 4, "name": "sender", ...}
{"type": 2, "sender_id": 5, "measurement": 3.1415, ...}
{"type": 3, "sender_id": 6, "measurement": 13.37, ...}
...
Run Code Online (Sandbox Code Playgroud)

首先,我定义了 aenum来区分消息类型,也struct为每种类型的消息定义了 a ,而没有存储类型的字段。

#[derive(Debug, Serialize, Deserialize)]
#[serde(tag = "type")]
enum Message {
    T1(Type1),
    T2(Type2),
    T3(Type3),
    // ...
}

#[derive(Debug, Serialize, Deserialize)]
struct Type1 {
    sender_id: u32,
    name: String,
    // ...
}
#[derive(Debug, Serialize, Deserialize)]
struct Type2 {
    sender_id: u32, …
Run Code Online (Sandbox Code Playgroud)

enums rust json-deserialization serde

3
推荐指数
1
解决办法
3397
查看次数

如何将 serde_json 与 enum 等联合类型一起使用?

我有两个结构体,我想将它们序列化/反序列化,并将标签作为"type"JSON 中的字段,如下所示。

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
struct ThingA {
    value: usize,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
struct ThingB {
    value: usize,
}
Run Code Online (Sandbox Code Playgroud)

这些按预期序列化。例如,

let a = ThingA { value: 0 };
println!("{}", serde_json::to_string(&a)?);
// This yields the expected result:
// {"type":"ThingA","value":0}
Run Code Online (Sandbox Code Playgroud)

但是,当我尝试添加枚举来代替结构的联合类型时,我遇到了麻烦。

#[derive(Debug, Clone, Serialize, Deserialize)]
#[serde(tag = "type")]
enum Thing {
    ThingA(ThingA),
    ThingB(ThingB),
}
Run Code Online (Sandbox Code Playgroud)

上面的定义对于反序列化 JSON 来说效果很好,但在序列化过程中添加了一个额外的字段。

let json = r#"{"type": "ThingB", "value": 0}"#;
let thing: Thing = serde_json::from_str(json)?;
// Correctly …
Run Code Online (Sandbox Code Playgroud)

rust serde serde-json

3
推荐指数
1
解决办法
6710
查看次数

如何在包含 &amp;'static str 的结构上实现 serde::Deserialize?

serde::Deserialize我正在尝试在一个结构体上实现SourceConfig,该结构体包装了一个包含 的结构体&'static str以及它自己的一些数据(游乐场)

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
pub struct Config {
    pub name: &'static str,
}

#[derive(Serialize, Deserialize)]
struct SourceConfig {
    config: Config,
    id: u32,
}
Run Code Online (Sandbox Code Playgroud)

但这给了我一个终生错误:

   Compiling playground v0.0.1 (/playground)
error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'de` due to conflicting requirements
  --> src/lib.rs:10:5
   |
10 |     config: Config,
   |     ^^^^^^
   |
note: first, the lifetime cannot outlive the lifetime `'de` as defined on the impl at 8:21...
  --> …
Run Code Online (Sandbox Code Playgroud)

string rust deserialization borrow-checker serde

3
推荐指数
1
解决办法
4026
查看次数

我可以相信两个相同结构的序列化是相同的吗?

考虑以下代码:

use serde::{Serialize, Deserialize};

#[derive(Serialize, Deserialize)]
struct MyStruct {
   a: u32,
   b: u32
}

#[derive(Serialize, Deserialize)]
#[serde(rename = "MyStruct")]
struct AlsoMyStruct {
   a: u32,
   b: u32
}
Run Code Online (Sandbox Code Playgroud)

我想知道我是否可以安全地做类似的事情:

let ser = any_encoding::serialize(&MyStruct{a: 33, b: 44}).unwrap();
let deser: AlsoMyStruct = any_encoding::deserialize(&ser).unwrap();
Run Code Online (Sandbox Code Playgroud)

其中any_encoding是,例如bincodejson或任何其他 Serde 支持的编码。在我看来,这应该很好地工作:两个结构具有相同的名称(我明确重命名AlsoMyStruct"MyStruct")和完全相同的字段:相同的字段名称、相同的字段类型、相同的字段顺序。

但是,我想知道:这真的能保证有效吗?MyStruct或者 Serde 序列化器/反序列化器是否可能在/的表示中包含一些其他的、极端情况的、可能与平台相关的、不可预见的信息,AlsoMyStruct这些信息可能会导致两种表示不兼容?

rust serde

3
推荐指数
1
解决办法
201
查看次数

如何获取 serde SeqAccess 内部序列的 SeqAccess 类型?

我正在编写一个库来解析 json 数据,如下所示:

{"x": [[1, "a"], [2, "b"]]}
Run Code Online (Sandbox Code Playgroud)

即我有一个带有列表列表的键,其中内部列表可以包含不同的数据类型,但每个内部列表具有相同的类型序列。内部列表的类型序列可以针对不同的 json 模式而改变,但会提前知道。

所需的输出将类似于:( vec![vec![1,2], vec!["a", "b"]] 数据包装在不同数据类型的适当枚举中)。

我开始实现DeserializeSeedfor Vec<DataTypes>,下面是一些类似的伪代码。

enum DataTypes {
    I32,
    I64,
    String,
    F32,
    F64
}


fn visit_seq<S>(self, mut seq: S) -> Result<Self::Value, S::Error>
    where
        S: SeqAccess<'de>,
    {
        let types: Vec<DataTypes> = self.0.data;
        let out: Vec<Vec<...>>;
        while let Some(inner_seq: S) = seq.next_element::<S>()? { // <-- this is the line
           for (i, type) in types.enumerate() {
               match type {
                   DataTypes::I32 => out[i].push(inner_seq.next_element::<i32>()?),
                   DataTypes::I64 => out[i].push(inner_seq.next_element::<i64>()?),
                   ...
               } …
Run Code Online (Sandbox Code Playgroud)

rust serde serde-json

3
推荐指数
1
解决办法
713
查看次数

在 Rust 中使用可选的 JSON 字段,避免在 JSON 中使用 None / null,而是使用 undefined

除了这个之外,还有更好(更精简)的方式来表达我自己:

#[derive(Serialize, Deserialize, Debug, Default]
pub struct PagingObject {
  #[serde(skip_serializing_if = "Option::is_none")]
  offsetId: Option<String>,     // offset expressed as element id (uuid)
  #[serde(skip_serializing_if = "Option::is_none")]
  offset: Option<i32>,          // offset expressed as index (numeric)
  #[serde(skip_serializing_if = "Option::is_none")]
  total: Option<i32>,           // total number of elements
  #[serde(skip_serializing_if = "Option::is_none")]
  totalPages: Option<i32>,      // total number of pages based on limit
  #[serde(skip_serializing_if = "Option::is_none")]
  previous: Option<String>,     // link to previous page
  #[serde(skip_serializing_if = "Option::is_none")]
  next: Option<String>,         // link to next page
  #[serde(skip_serializing_if = "Option::is_none")]
  limit: Option<i32> …
Run Code Online (Sandbox Code Playgroud)

json rust serde

3
推荐指数
1
解决办法
3471
查看次数