我有一个json数组中的传入数据,我将其反序列化为一个结构,但我似乎想不出如何将它序列化回一个数组而不是一个对象。
是否必须在这里实现自定义序列化程序,还是可以添加其他serde属性?
我已经查阅了关于serde.rs的文档,但是我似乎找不到任何可以解决这个问题的方法。
#[cfg(test)]
mod tests {
use serde_json;
#[test]
fn test_new() {
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase", untagged)]
enum Kind {
Authorization(AuthorizationKind),
Notification(NotificationKind),
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase", untagged)]
enum AuthorizationKind {
Request(AuthorizationRequest),
Response(AuthorizationResponse),
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct AuthorizationRequest {
request: String,
code: usize,
secret: String,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct AuthorizationResponse {
response: String,
code: usize,
authorized: bool,
token: Token,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct Token {
token: String,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
enum NotificationKind {
Request(NotificationRequest),
Response(NotificationResponse),
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct NotificationRequest {
request: String,
code: usize,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct NotificationResponse {
response: String,
}
let json = r#"["authorize request incoming",2,"TH15 15 MY! 53CR3T"]"#;
let request: Result<Kind, _> = serde_json::from_str(&json);
assert_eq!(request.is_ok(), true);
let request = request.unwrap();
let back_to_json = serde_json::to_string(&request).unwrap();
println!("{back_to_json}");
assert_eq!(json, back_to_json);
}
}
编辑1:我最终实现了一个自定义序列化程序,但不确定这是最好的方法。
#[cfg(test)]
mod tests {
#[test]
fn test_new() {
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase", untagged)]
enum Kind {
Authorization(AuthorizationKind),
Notification(NotificationKind),
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase", untagged)]
enum AuthorizationKind {
Request(AuthorizationRequest),
Response(AuthorizationResponse),
}
#[derive(serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct AuthorizationRequest {
request: String,
code: usize,
secret: String,
}
impl TryFrom<Kind> for AuthorizationRequest {
type Error = &'static str;
fn try_from(value: Kind) -> Result<Self, Self::Error> {
match value {
Kind::Authorization(auth) => match auth {
AuthorizationKind::Request(req) => Ok(AuthorizationRequest {
request: req.request,
code: req.code,
secret: req.secret,
}),
_ => Err("Failed to create type"),
},
_ => Err("Failed to create type"),
}
}
}
impl serde::Serialize for AuthorizationRequest {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer,
{
(&self.request, self.code, &self.secret).serialize(serializer)
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct AuthorizationResponse {
response: String,
code: usize,
authorized: bool,
token: Token,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct Token {
token: String,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
enum NotificationKind {
Request(NotificationRequest),
Response(NotificationResponse),
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct NotificationRequest {
request: String,
code: usize,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct NotificationResponse {
response: String,
}
let json = r#"["authorize request incoming",2,"TH15 15 MY! 53CR3T"]"#;
let request: Result<Kind, _> = serde_json::from_str(&json);
assert_eq!(request.is_ok(), true);
let request = request.unwrap();
let authorization_request: AuthorizationRequest = request.try_into().unwrap();
let back_json = serde_json::to_string(&authorization_request).unwrap();
assert_eq!(json, back_json);
}
}
编辑3
更好的方法是将AuthorizationKind
和NotificationKind
类型更改为元组。这将使序列化成json数组变得很容易。
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase", untagged)]
enum AuthorizationKind {
Request(String, usize, String),
Response(String, usize, bool, Token),
}
...
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
enum NotificationKind {
Request(String, usize),
Response(String),
}
发布于 2022-04-17 09:25:03
问题在于,在排序中,您必须跟踪键(我正在添加一个示例,但您可以选择其他的),然后您可以将json::Value
(对象)转换为迭代键的数组:
#[cfg(test)]
mod tests {
use serde_json;
#[test]
fn test_new() {
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase", untagged)]
enum Kind {
Authorization(AuthorizationKind),
Notification(NotificationKind),
}
impl Kind {
fn keys(&self) -> Vec<&str> {
match self {
Self::Authorization(a) => a.keys(),
Self::Notification(n) => n.keys(),
}
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase", untagged)]
enum AuthorizationKind {
Request(AuthorizationRequest),
Response(AuthorizationResponse),
}
impl AuthorizationKind {
fn keys(&self) -> Vec<&str> {
match self {
Self::Request(r) => r.keys(),
Self::Response(r) => r.keys(),
}
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct AuthorizationRequest {
request: String,
code: usize,
secret: String,
}
impl AuthorizationRequest {
fn keys(&self) -> Vec<&str> {
vec!["request", "code", "secret"]
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct AuthorizationResponse {
response: String,
code: usize,
authorized: bool,
token: Token,
}
impl AuthorizationResponse {
fn keys(&self) -> Vec<&str> {
vec!["response", "code", "authorized", "token"]
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct Token {
token: String,
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
enum NotificationKind {
Request(NotificationRequest),
Response(NotificationResponse),
}
impl NotificationKind {
fn keys(&self) -> Vec<&str> {
todo!()
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct NotificationRequest {
request: String,
code: usize,
}
impl NotificationRequest {
fn keys(&self) -> Vec<&str> {
todo!()
}
}
#[derive(serde::Serialize, serde::Deserialize, Debug, Clone, PartialEq)]
#[serde(rename_all = "camelCase")]
struct NotificationResponse {
response: String,
}
impl NotificationResponse {
fn keys(&self) -> Vec<&str> {
todo!()
}
}
let json = r#"["authorize request incoming",2,"TH15 15 MY! 53CR3T"]"#;
let request: Result<Kind, _> = serde_json::from_str(&json);
assert_eq!(request.is_ok(), true);
let request = request.unwrap();
let back_to_json = serde_json::to_value(&request).unwrap();
let as_array = serde_json::to_string(
&request
.keys()
.iter()
.map(|k| back_to_json.get(k).unwrap())
.collect::<Vec<_>>(),
)
.unwrap();
println!("{as_array}");
assert_eq!(json, as_array);
}
}
这不是最好的解决方案(但可行的),很多事情都可能在不匹配和再因素上出错。如果可能的话,将您的结构序列化为对象而不是数组。
https://stackoverflow.com/questions/71901405
复制