3

I am trying to deserialize a set of unknown key-value style labels from JSON into my struct.

This is my current implementation of parsing the JSON:

use std::collections::HashMap;
use serde::{Serialize, Deserialize};
use anyhow::Result;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Node {
    metadata: Metadata,
    pub spec: Spec,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Metadata {
    name: String,
    labels: HashMap<String, String>,
    expires: String,
    id: i64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Spec {
    pub hostname: String,
}

fn main() -> Result<()> {
    let json = r#"
[
  {
    "metadata": {
      "name": "161bee39-cf07-4e31-90ba-6593c9f505cb",
      "labels": {
        "application": "api",
        "owner": "team_x"
      },
      "expires": "2021-12-06T20:49:04.136656523Z",
      "id": 1638823144137190452
    },
    "spec": {
      "hostname": "host1.example.com"
    }
  },
  {
    "metadata": {
      "name": "c1b3ee09-8e4a-49d4-93b8-95cbcb676f20",
      "labels": {
        "application": "database",
        "owner": "team_y"
      },
      "expires": "2021-12-06T20:49:55.23841272Z",
      "id": 1638823195247684748
    },
    "spec": {
      "hostname": "host2.example.com"
    }
  }
]
    "#;
    let nodes: Vec<Node> = serde_json::from_str(json)?;
    println!("{:?}", nodes);
    Ok(())
}

The example works as it should, but now I would like to add a Label struct like this:

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Metadata {
    name: String,
    labels: Vec<Label>,
    expires: String,
    id: i64,
}

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Label {
    key: String,
    value: String,
}

This does obviously not work, but I am unsure how to go on from here. From my research prior to this question, I know that you can implement a custom Deserializer, but I could not find out how to properly do that. Maybe this is also not the best approach and I am not seeing the obvious solution.

Thanks in advance for any example or help.

4
  • I don't understand, why do you want do that ? Commented Dec 6, 2021 at 22:42
  • To be honest I could just go on with the HashMap approach, as the Label struct is probably not a good way to do it anyway, but now I researched a lot on how to do it and at this point I kind of just want to know how that would be done. Commented Dec 6, 2021 at 22:48
  • 1
    docs.rs/serde_with/1.11.0/serde_with/rust/tuple_list_as_map/… Commented Dec 6, 2021 at 22:52
  • Thank you very much this was very helpful! Commented Dec 6, 2021 at 23:00

1 Answer 1

2

As of Stargateurs comment, the serde_with crate offers a solution to this:

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Metadata {
    name: String,
    #[serde(with = "serde_with::rust::tuple_list_as_map")]
    labels: Vec<Label>,
    expires: String,
    id: i64,
}

type Label = (String, String);
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.