Как «сгладить» вектор для создания нескольких элементов XML при использовании serde?

У меня есть следующие структуры:

struct Artist {
    name: String,
    image: String,
}

struct Album {
    title: String,
    artists: Vec<Artist>,
}

Мне нужно создать XML, который выглядит так:

<album>
  <title>Some title</title>
  <artist>
    <name>Bonnie</name>
    <image>http://example.com/bonnie.jpg</image>
  </artist>
  <artist>
    <name>Cher</name>
    <image>http://example.com/cher.jpg</image>
  </artist>
</album>

Как я могу использовать serde для сериализации / десериализации в указанный выше формат XML, особенно в отношении выравнивания вектора artists для создания нескольких элементов artist? Это сторонний формат, который я не могу изменить :-(


person jbrown    schedule 01.01.2017    source источник
comment
Почему бы просто не реструктурировать данные в соответствии с вашими требованиями?   -  person Shepmaster    schedule 02.01.2017
comment
Кроме того, похоже, что у serde_xml нет никаких структур - ›возможностей XML.   -  person Shepmaster    schedule 02.01.2017
comment
@Shepmaster Serde может это сделать, если я не ошибаюсь: stackoverflow .com / questions / 37970355 / read-xml-file-into-struct. Как я уже упоминал, это сторонний формат, который я не могу изменить.   -  person jbrown    schedule 02.01.2017
comment
@Shepmaster Ах, нет модуля ser для xml в github.com/serde-rs/ xml / tree / master / src. Я этого не заметил. Думаю, мне нужно найти что-то еще :-(   -  person jbrown    schedule 02.01.2017


Ответы (1)


Ящик serde-xml-rs заменяет устаревший serde_xml ящик и поддерживает сериализацию структур данных в XML. в желаемом вами представлении.

extern crate serde;
extern crate serde_xml_rs;

use serde::ser::{Serialize, Serializer, SerializeMap, SerializeStruct};

struct Artist {
    name: String,
    image: String,
}

impl Serialize for Artist {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        let mut map = serializer.serialize_map(Some(2))?;
        map.serialize_entry("name", &self.name)?;
        map.serialize_entry("image", &self.image)?;
        map.end()
    }
}

struct Album {
    title: String,
    artists: Vec<Artist>,
}

impl Serialize for Album {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
        where S: Serializer
    {
        let len = 1 + self.artists.len();
        let mut map = serializer.serialize_struct("album", len)?;
        map.serialize_field("title", &self.title)?;
        for artist in &self.artists {
            map.serialize_field("artist", artist)?;
        }
        map.end()
    }
}

fn main() {
    let album = Album {
        title: "Some title".to_owned(),
        artists: vec![
            Artist {
                name: "Bonnie".to_owned(),
                image: "http://example.com/bonnie.jpg".to_owned(),
            },
            Artist {
                name: "Cher".to_owned(),
                image: "http://example.com/cher.jpg".to_owned(),
            },
        ],
    };

    let mut buffer = Vec::new();
    serde_xml_rs::serialize(&album, &mut buffer).unwrap();
    let serialized = String::from_utf8(buffer).unwrap();
    println!("{}", serialized);
}

Результат:

<album>
  <title>Some title</title>
  <artist>
    <name>Bonnie</name>
    <image>http://example.com/bonnie.jpg</image>
  </artist>
  <artist>
    <name>Cher</name>
    <image>http://example.com/cher.jpg</image>
  </artist>
</album>
person dtolnay    schedule 25.02.2018
comment
Мне пришлось использовать serde_xml_rs::to_string(&album).unwrap() вместо serde_xml_rs::serialize(&album, &mut buffer).unwrap(); - person nbari; 10.08.2020
comment
Он также работает с to_writer. - person MarkO; 07.01.2021