使用 Serde 反序列化时如何忽略额外的元组项? (“尾随字符”错误)

2024-01-03

Serde 在反序列化为常规结构时会忽略未知的命名字段。当反序列化为元组结构(例如来自异构 JSON 数组)时,如何同样忽略额外的项目?

例如,此代码忽略额外的"c"字段就好了:

#[derive(Serialize, Deserialize, Debug)]
pub struct MyStruct { a: String, b: i32 }

fn test_deserialize() -> MyStruct {
    ::serde_json::from_str::<MyStruct>(r#"
    {
        "a": "foo",
        "b": 123,
        "c": "ignore me"
    }
    "#).unwrap()
}
// => MyStruct { a: "foo", b: 123 }

相比之下,这在元组中的额外项目上失败了:

#[derive(Serialize, Deserialize, Debug)]
pub struct MyTuple(String, i32);

fn test_deserialize_tuple() -> MyTuple {
    ::serde_json::from_str::<MyTuple>(r#"
        [
            "foo",
            123,
            "ignore me"
        ]
    "#).unwrap()
}
// => Error("trailing characters", line: 5, column: 13)

我想允许额外的项目以实现我的数据格式的前向兼容性。让 Serde 在反序列化时忽略额外元组项的最简单方法是什么?


您可以实施自定义Visitor它忽略了序列的其余部分。请注意,必须消耗整个序列。这是一个重要的部分(尝试删除它,你会得到同样的错误):

// This is very important!
while let Some(IgnoredAny) = seq.next_element()? {
    // Ignore rest
}

这是一个工作示例:

use std::fmt;

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

#[derive(Serialize, Debug)]
pub struct MyTuple(String, i32);

impl<'de> Deserialize<'de> for MyTuple {
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        struct MyTupleVisitor;

        impl<'de> Visitor<'de> for MyTupleVisitor {
            type Value = MyTuple;

            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
                formatter.write_str("struct MyTuple")
            }

            fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
            where
                V: SeqAccess<'de>,
            {
                let s = seq
                    .next_element()?
                    .ok_or_else(|| de::Error::invalid_length(0, &self))?;
                let n = seq
                    .next_element()?
                    .ok_or_else(|| de::Error::invalid_length(1, &self))?;

                // This is very important!
                while let Some(IgnoredAny) = seq.next_element()? {
                    // Ignore rest
                }

                Ok(MyTuple(s, n))
            }
        }

        deserializer.deserialize_seq(MyTupleVisitor)
    }
}

fn main() {
    let two_elements = r#"["foo", 123]"#;
    let three_elements = r#"["foo", 123, "bar"]"#;

    let tuple: MyTuple = serde_json::from_str(two_elements).unwrap();
    assert_eq!(tuple.0, "foo");
    assert_eq!(tuple.1, 123);

    let tuple: MyTuple = serde_json::from_str(three_elements).unwrap();
    assert_eq!(tuple.0, "foo");
    assert_eq!(tuple.1, 123);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Serde 反序列化时如何忽略额外的元组项? (“尾随字符”错误) 的相关文章

随机推荐

  • 将 Jpeg 更改为渐进式 Jpeg 图像 [关闭]

    Closed 这个问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 我想从基线 Jpeg 图像转换为渐进式 Jpeg 图像 我的磁盘中存储了 10 000 张图像 我尝试
  • 如何混合两个图像?

    我的视图中有两个图像 我需要混合这两个图像 但问题是无法得到完美的融合 图像混合代码 CGSize newSize CGSizeMake backGroundImage frame size width backGroundImage fr
  • NHibernate Future 对象图许多查询

    给定一个使用 Future 调用的多级对象图 var Dads db Session Query
  • jQuery 验证无法正常工作

    我需要在单击 div 按钮时触发此验证 如果验证成功 我希望它提醒 很好 不幸的是 尽管会触发验证并检查所有规则 但如果必填字段为空 则不会出错 不过 任何其他检查都会出错 最后 如果我正确填写字段并单击按钮 则不会发生任何情况 JS do
  • 当 Elasticsearch 索引的运行状况为黄色时,这意味着什么?

    我正在开发一个创建 N 个索引和 N 个别名的应用程序 并且这些索引和别名之间存在一一对应的关系 但偶尔 我会得到 N 个索引和 N 1 个别名 其中一个索引的名称本应由别名使用 由于某种原因 当发生这种情况时 虚假索引 应该是别名 的状态
  • 创建新站点时,如何告诉 IIS 6 将 .NET 版本设置为 2.0(而不是 1.1)?

    我们使用 IIS 管理器在 IIS 6 Windows Server 2003 中创建新站点 当这些站点在 IIS 6 中创建时 ASP NET 版本默认为 ASP NET 1 1 我们希望它默认为 ASP NET 2 0 这对我们来说是一
  • 如何将身份验证标头传递给 OData 服务

    我正在遵循以下描述的身份验证方法http blogs msdn com b astoriateam archive 2010 07 21 odata and authentication part 6 custom basic authen
  • getClass() 在基类的构造函数中报告哪个类

    在 Java 中 可以安全地假设getClass 在用作基类的类的构造函数中调用将提供有关派生类的信息 而不是基类的类的信息 它似乎有效 但我想这并不一定意味着它是安全的 例如 如果我有以下两个类 public class Parent p
  • Autofac:使用输入和输出类型参数解析变体类型

    这个问题是我之前问题的后续 Autofac 将多个逆变实现隐藏在一个组合后面 https stackoverflow com questions 7139054 autofac hiding multiple contravariant i
  • Windows 窗体 - 以透明度为背景的 PNG

    我正在开发一个小型个人项目 我需要创建一个具有阴影的非矩形窗口 更准确地说是一个圆形 尽管这可能会改变 如果表单将 png 设置为背景 我可以通过更改 Region 属性来获得圆形窗口 问题是窗口已对齐 PNG 的透明度不起作用 所以问题是
  • Picture.writeToStream() 未写出所有位图

    我在用着webview capturePicture 创建一个包含网页所有绘图对象的 Picture 对象 我可以使用以下方法成功将此 Picture 对象渲染为位图canvas drawPicture picture dst 没有问题 但
  • 在Java中将Key和Value添加到优先级队列并按Key排序

    我正在尝试获取字符串列表并将它们添加到带有键和值的优先级队列中 键是单词 值是单词的字符串值 然后我需要首先对具有最高字符串值的队列进行排序 优先级队列不允许我添加 2 个值 public static List
  • JavaScript,声明变量时语法混乱

    我最近在一本正在研究的 JavaScript 书中发现了以下代码行 var col top bottom 这是我第一次遇到一个变量似乎被赋予了三个变量 有人可以解释一下这行代码中发生了什么吗 它只是一个较短的版本 var col var t
  • Java 的 RAM 使用情况与任务管理器显示的不符

    我一直在玩Java的JVM 制作一个1024 3 基本上 1Gb 长度字节数组 我使用任务管理器 查看进程 和这个小片段测量了数组创建之前 之后以及数组被垃圾收集器销毁之后的 RAM 使用情况 public static void show
  • 使用wkhtmltopdf时如何处理ContentNotFoundError?

    有人可以告诉我如何解决以下问题吗 与以前的版本不同 wkhtmltopdf 没有传递代理信息 p 或 proxy 的选项 并且它也不使用系统 http proxy 和 https proxy env 变量 即使我为 libssl so 和
  • 应避免使用 flatDirs,因为它不支持任何元数据格式

    在 Android Studio 中构建时 我看到以下警告 应避免使用 flatDirs 因为它不支持任何元数据格式 我正在与本地打包的 aar 集成libs目录 是否有另一种集成方法 无需将以下有问题的块添加到我的build gradle
  • if comment.name == user 无法正常工作

    我希望用户能够删除他们写的评论 不幸的是 我无法让 if 语句发挥作用 if comment name user a href delete this comment a endif 所以我可以看到 user 和 comment name
  • Cocoa 脚本:接受并返回 NSData

    为了支持我的可编写脚本的 Mac 应用程序中的二进制数据交换 我希望能够使用 AS ObjC 桥接器以 NSData 形式接收和传递数据 如果可能的话 例如 我喜欢在 AppleScript 中实现以下代码 use framework Fo
  • 直接链接到 SWF 有哪些缺点?

    通常 Flash 和 Flex 应用程序使用以下组合嵌入到 HTML 中 object and embed标签 或更常见的是使用 JavaScript 但是 如果您直接链接到 SWF 文件 它将在浏览器窗口中打开 并且无需查看地址栏 您就无
  • 使用 Serde 反序列化时如何忽略额外的元组项? (“尾随字符”错误)

    Serde 在反序列化为常规结构时会忽略未知的命名字段 当反序列化为元组结构 例如来自异构 JSON 数组 时 如何同样忽略额外的项目 例如 此代码忽略额外的 c 字段就好了 derive Serialize Deserialize Deb