使用into_serde反序列化字符串会使应用程序惊慌失措

问题描述

与我的一个朋友一起,我们试图使用RUST中的serde_json板条箱反序列化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)'

任何帮助将不胜感激,因为我们仍在努力了解我们在做什么错以及为什么我们不能对字符串反序列化。

解决方法

问题可能是对into_serde语义的误解。

根据documentation,它的工作方式如下:

对此值调用JSON.stringify,然后将生成的JSON解析为任意Rust值。

换句话说,其语义如下:

  • JsValue的每个组成部分转换为相应的serde内部元素;
  • 从给定的组件树中反序列化所需的类型。

现在,在我们的案例中这意味着什么?好吧,您使用JsValue::from_str创建了JsValue,再次根据文档,

创建一个新的JS值,它是一个字符串。

因此,JsValue并不是一个对象,就像您可能会假设的那样;它是一个原语-一个字符串,它恰好具有对象的JSON表示形式。然后,当您调用from_serde时,Serde看到的字符串-不是作为输入,而是作为内部表示,不能转换为对象。


现在,该怎么办?有几种方法可以修复此代码:

  1. 首先也是最明显的一点:根本不使用JsValue,直接与&strserde_json::from_str反序列化。
  2. 使用js_sys::JSON::parse从字符串中获取类似对象的JsValue,然后使用EffetSer将其转换为into_serde。这可能效率不高,因为它需要往返JSON::parseJSON::serialize才能将字符串转换为对象,然后再转换回字符串。
  3. 编写您自己的方法,将JsValue直接转换为EffetSer。但是我不确定是否可行,因为我无法找到一种从JS对象提取单个字段的方法。

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...