-
Notifications
You must be signed in to change notification settings - Fork 569
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Can serde deserialize an arbitrary json structure into a recursive enum/tree? #144
Comments
Absolutely. Are you looking to use that specific one from rustc-serialize or can you use this one instead which works out of the box? You can embed // Deserialize something like `{"id": "x", "body": /* any valid json */}`
#[derive(Serialize, Deserialize)]
struct MyStruct {
id: String,
body: serde_json::Value,
} Then you can either use the enum directly, or if you want you can continue deserializing it further using let my_struct: MyStruct = serde_json::from_str(j).unwrap();
if my_struct.id == "x" {
let x: MyOtherStruct = serde_json::from_value(my_struct.body).unwrap();
/* ... */
} EDIT: and to deserialize an entire JSON input to a let value: serde_json::Value = serde_json::from_str(j).unwrap(); |
Thank you! 10 hours of reading docs didn't let me find this. Do you know if it's possible to 'pause' deserialization, to (for example), read a version number and swap out the remainder of the parsing/struct? Or does any kind of logic require a full manual implementation? |
I filed serde-rs/serde-rs.github.io#18 to add an example that uses serde_json::Value. Any logic more advanced than what is supported by the built-in attributes is going to require implementing Deserialize yourself. In this case if you have something like If you can say a bit more about what the JSON looks like and what you need the Rust data structure to look like, I can flesh out some of the details and possibly use it as the website example because this could be a pretty common use case. |
Thaaaanks! {
"ast_type": "Module",
"body": [
{ "ast_type": "Assign",},
{ "ast_type": "FunctionDef",},
{ "ast_type": "Expr",},
]
} (I omitted the rest of the information pertinent to each In order to parse it, I programmed a struct for the json, knowing that the body was going to be an array of unknown object structure: #[derive(Serialize, Deserialize, Debug)]
struct PyBody {
ast_type: String,
col_offset: u8,
lineno: u8,
//targets: Vec<PyTarget>
}
#[derive(Serialize, Deserialize, Debug)]
struct PyFunction {
ast_type: String,
body: Vec<serde_json::Value>
} For each PyBody "ast_type" I programmed a different struct: fn read_code_from_file<P: AsRef<Path>>(path: P) -> Result<PyFunction, Box<Error>> {
// Open the file in read-only mode.
let file = File::open(path)?;
// Read the JSON contents of the file as an instance of `User`.
let first_pass = serde_json::from_reader(file)?;
// Return the `User`.
Ok(first_pass)
}
fn main() {
let nodes = read_code_from_file("../client/file1.json").unwrap();
println!("Parsed {:?} nodes:\n", nodes.body.len());
//println!("{:#?}", nodes.body[0]);
//parse each node
for i in 0..nodes.body.len()
{
//parse each node
let n: PyBody = serde_json::from_value(nodes.body[i].clone()).unwrap();
match n.ast_type.as_ref() {
"Assign" => {
//println!("parsing Assign node:");
let assign: PyAssign = serde_json::from_value(nodes.body[i].clone()).unwrap();
println!("{:?}", assign.ast_type);
},
"FunctionDef" => {
//println!("parsing FunctionDef node:");
let function_def: PyFunctionDef = serde_json::from_value(nodes.body[i].clone()).unwrap();
println!("{:?}, {:?}", function_def.ast_type, function_def.name);
},
"Expr" => {
//println!("parsing Expr node:");
let expr: PyExpr = serde_json::from_value(nodes.body[i].clone()).unwrap();
println!("{:?}", expr.ast_type);
},
_ => println!("matched unknown node, no action taken: {:?}", n.ast_type)
}
//println!("{:?}", n);
}
} |
For example,
https://github.com/rust-lang-nursery/rustc-serialize/blob/master/src/json.rs#L261-L270
I'd like to mix validated and free-form JSON in the same string.
The text was updated successfully, but these errors were encountered: