rust - 使用 into_serde 反序列化字符串会使应用程序恐慌
问题描述
我的一个朋友正在尝试使用serde_json
crate 反序列化 WebSocket 发送的一些消息。
我们遇到了一个特定的错误,我们设法使用以下代码片段重新创建它:
use serde::{Deserialize, Serialize};
#[derive(Deserialize, Debug)]
struct EffetSer {
test: String
}
fn main() {
let test_value = JsValue::from_str("{\"test\": \"value\"}");
let test_value: EffetSer = test_value.into_serde().unwrap();
log::error!("WOW : {:?}", test_value);
}
我们的 TOML 有以下依赖:
wasm-bindgen = { version = '0.2.63', features = ['serde-serialize'] }
serde = { version = '1.0', features = ["derive"] }
serde_json = '1.0.55'
js-sys = '0.3.40'
错误如下:
app.js:310 panicked at 'called `Result::unwrap()` on an `Err` value: Error("invalid type: string \"{\\\"test\\\": \\\"value\\\"}\", expected struct EffetSer", line: 1, column: 23)'
任何帮助将不胜感激,因为我们仍在努力理解我们做错了什么以及为什么我们不能反序列化我们的String
.
解决方案
into_serde
这个问题很可能是对's 语义的误解。
根据文档,它的工作原理如下:
对此值调用 JSON.stringify,然后将生成的 JSON 解析为任意 Rust 值。
换句话说,它的语义如下:
- 将 的每个组件转换
JsValue
为相应的serde
内部元素; - 从给定的组件树中反序列化所需的类型。
现在,这在我们的案例中意味着什么?好吧,您创建JsValue
using JsValue::from_str
,再次根据文档,
创建一个新的 JS 值,它是一个字符串。
因此,JsValue
正如您可能假设的那样,here 不是一个对象;它是一个原语 - 一个字符串,恰好具有对象 JSON 表示的形状。然后,当您调用 时from_serde
,Serde 将字符串视为 - 不是作为输入,而是作为内部表示,不能转换为对象。
现在,该怎么办?有几种方法可以修复此代码:
- 首先也是最明显的:根本不要使用
JsValue
,&str
直接使用serde_json::from_str
. - 使用js_sys::JSON::parse从字符串中获取类对象
JsValue
,然后将其转换为EffetSer
withinto_serde
。这可能效率较低,因为它需要往返JSON::parse
并将JSON::serialize
字符串转换为对象,然后再转换回字符串。 - 编写您自己的方法以直接转换
JsValue
为EffetSer
。但是,我不确定这是否可能,因为我无法找到从 JS 对象中提取单个字段的方法。
推荐阅读
- react-native - react native 中的日历事件
- java - 执行简单 SPRING MVC 示例时出现异常严重:子容器在启动 java.util.concurrent 期间失败
- typescript - 在 Promise 库上创建一个通用接口
- javascript - javascript中的类追加和删除
- node.js - 在流星中完成页面加载后如何调用函数?
- unity3d - 如何使用 UnityWebRequest 在 Unity 中编写 HTTP 发布请求?
- java - 我无法将 Tomcat webapp 配置为能够在 Eclipse 上进行调试
- ssh - GitLab.com 配置文件上的备用 SSH 连接
- javascript - 在节点模块中导入 Typescript 和 Js 文件的问题
- java - SQLite 驱动程序不适合