Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I accept multiple deserialization names for the same Serde field?

I am trying to use Serde to deserialize JSON (serde-json) and XML (serde-xml-rs) files based on the following struct:

use serde_derive::Deserialize;

#[derive(Debug, Clone, PartialEq, Deserialize)]
pub struct SchemaConfig {
    pub name: String,
    #[serde(rename = "Cube")]
    pub cubes: Vec<CubeConfig>,
}

The fields I am deserializing on have different names based on the file type. In this case, I would like for a JSON file to have a cubes key with a list of cubes, but the equivalent in XML would be multiple <Cube /> elements.

I can't figure out how to accept both cubes and Cube as keys for the deserialization. The closest thing I found was the #[serde(rename = "Cube")] option but when I use that the JSON deserialization stops working since it only accepts the Cube key. If I remove that option, the XML deserialization stops working as it then only accepts cubes as the key.

Is there a simple way to accomplish this in Serde?

like image 321
MarcioPorto Avatar asked Jan 11 '19 15:01

MarcioPorto


1 Answers

I encourage you to read the Serde documentation. The field attributes chapter introduces the alias attribute, emphasis mine:

#[serde(alias = "name")]

Deserialize this field from the given name or from its Rust name. May be repeated to specify multiple possible names for the same field.

use serde::Deserialize; // 1.0.88
use serde_json; // 1.0.38

#[derive(Debug, Deserialize)]
struct SchemaConfig {
    #[serde(alias = "fancy_square", alias = "KUBE")]
    cube: [i32; 3],
}

fn main() -> Result<(), Box<std::error::Error>> {
    let input1 = r#"{
        "fancy_square": [1, 2, 3]
    }"#;

    let input2 = r#"{
        "KUBE": [4, 5, 6]
    }"#;

    let one: SchemaConfig = serde_json::from_str(input1)?;
    let two: SchemaConfig = serde_json::from_str(input2)?;

    println!("{:?}", one);
    println!("{:?}", two);

    Ok(())
}

I would like for a JSON file to have a cubes key with a list of cubes, but the equivalent in XML would be multiple <Cube /> elements.

This certainly sounds like you want two different structures to your files. In that case, look at something like:

  • How to transform fields during deserialization using Serde?
  • How do I serialize an enum without including the name of the enum variant?
like image 150
Shepmaster Avatar answered Nov 10 '22 07:11

Shepmaster