2

I would like to deserialize my incoming data from Rocket with Serde with my own deserializer for one field. The tags field is originally a string and should be deserialized into a Vec<String>. The format of the string is more-or-less comma-separated values with a special treatment of some characters.

The documentation of Serde is completely unclear for me how to treat that case. The basic structure of tags_deserialize I just copied from the documentation.

Currently my code is as follows:

#[derive(Deserialize)]
#[serde(deny_unknown_fields)]
pub struct TaskDataJson {
    pub name: String,
    pub description: String,
    #[serde(deserialize_with = "tags_deserialize")]
    pub tags: Vec<String>
}

fn tags_deserialize<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
    where
        D: Deserializer<'de>,
{
    ??? - How do I access the string coming from the response and how do I set it??
}

A sample of incoming data is:

{
    "name":"name_sample",
    "description":"description_sample",
    "tags":"tag1,tag2,tag5"
}

where this should lead to:

name = "name_sample";
description = "description_sample"
tags = ["tag1", "tag2", "tag5"]
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
Fabian
  • 403
  • 5
  • 13
  • I don't understand, this is just json, why not use serde_json ? And then just parse `tags` field *after* with whatever you like. serde is not mean to be a parser. – Stargateur Jan 02 '19 at 12:27
  • @Stargateur Yes, this is also my backup plan if this does not work directly with serde. However, I would like to have a more _elegant_ solution especially because I already basically did the same vice-versa for my output data and there I got it working. – Fabian Jan 02 '19 at 12:58

1 Answers1

3

A workaround is to deserialize the string sequence "tag1,tag2,tag3" as a String value and then convert it to a Vec of strings, for example:

fn tags_deserialize<'de, D>(deserializer: D) -> Result<Vec<String>, D::Error>
where
    D: Deserializer<'de>,
{
    let str_sequence = String::deserialize(deserializer)?;
    Ok(str_sequence
        .split(',')
        .map(|item| item.to_owned())
        .collect())
}
Shepmaster
  • 388,571
  • 95
  • 1,107
  • 1,366
attdona
  • 17,196
  • 7
  • 49
  • 60
  • Thank you @attdona . Your solution works great :D The only thing left was that I was at first not sure which error to return when deserializing does not work but I found out that `return Err(serde::de::Error::custom("Custom error string"));` is sufficient for me. – Fabian Jan 02 '19 at 15:58