Hi! I'm try to use serde to handle deserializing the incoming message. However, the message has multiple form with no key indication since it a json root message in array form.
Here is all the form the message can be in.
- Form#1 : [ id, code, action, payload ] i.e. ( [ 132, "0ae", "Hello", {"status" : "great", "timestamp" : "xxx"}] )
- Form#2 : [ id, code, payload ] i.e. ( [ 132, "0ae", {"status" : "great", "timestamp" : "xxx"}] )
- Form#3 : [ id, code, error_code, error_payload ] i.e. ( [124, "a45", "ec#01", "some sample err"] )
My Objective
- write a single serde from_str that can convert all message form.
What I have tried
- I have try with using enum and 'serde(untagged)' but it seem only working with json with key not json root array.
- Try it with if clause at the beginning to check if the string contain some keyword. But, there is no pattern at all.
- Try using Option on the struct.
The code below is the minimal code that should reproduce what I try to explain
use serde::{Deserialize, Serialize};
use serde_json::Value;
#[derive(Serialize, Deserialize)]
pub enum Action {
Hello,
Bye,
Touch,
Kick,
}
#[derive(Serialize, Deserialize)]
struct abctest {
msg_id: u8,
msg_code: String,
msg_action: Option<Action>,
msg_payload: Value,
}
#[derive(Serialize, Deserialize)]
#[serde(untagged)]
enum ReceiveMsg {
Type1 {
msg_id: u8,
msg_code: String,
msg_action: Action,
msg_payload: Value,
},
Type2 {
msg_id: u8,
msg_code: String,
msg_payload: Value,
},
Type3 {
msg_id: u8,
msg_code: String,
error_code: String,
error_msg: String,
},
}
fn main() {
let input_msg = r#"[159,"01a",{"status":"Accepted","currentTime":"2023-07-14T07:33:58.528Z","interval":14400}]"#;
let input_msg2 = r#"[129,"02a", "Touch", {"status":"Accepted","currentTime":"2023-07-14T07:33:58.528Z","interval":14400}]"#;
let input_msg3 = r#"[94, "02a", "error-code1", "Error because blabla"]"#; // If possible
match serde_json::from_str::<abctest>(&input_msg) {
Ok(_) => println!("Success"),
Err(e) => {
println!("Failed with {}", e);
}
}
match serde_json::from_str::<ReceiveMsg>(&input_msg2) {
Ok(_) => println!("Success"),
Err(e) => {
println!("Failed with {}", e);
}
}
match serde_json::from_str::<ReceiveMsg>(&input_msg3) {
Ok(_) => println!("Success"),
Err(e) => {
println!("Failed with {}", e);
}
}
}
Here is the result from the run.
Finished dev [unoptimized + debuginfo] target(s) in 0.40s
Running `target/debug/playground`
Failed with unknown variant `status`, expected one of `Hello`, `Bye`, `Touch`, `Kick` at line 1 column 20
Failed with data did not match any variant of untagged enum ReceiveMsg
Failed with data did not match any variant of untagged enum ReceiveMsg
Are there anyway to archive my objective? Thanks. And really sorry for any confusion, English is my second language.