14

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?

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
MarcioPorto
  • 555
  • 7
  • 22

1 Answers1

17

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:

Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
  • 2
    Thank you for the code sample. I did read the documentation, but it wasn't clear to me from the documentation how to specify multiple `alias` values. Your code sample here makes it perfectly clear. – Gary Sheppard Jan 29 '20 at 14:33
  • This looks the only workaround. but it's buggy. think about `fancy_square` and `KUBE` can be in the same file or different file. – ibigbug Nov 07 '21 at 17:12