Как я могу десериализовать Vec в Vec на Rust? [дубликат]

Вопрос или проблема

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

pub struct Data {
   num: i32,
   text: String,
}

У меня есть Vec<String> (назовем его myVecOfStrings), в котором каждый элемент – это String, который выглядит следующим образом:

"{ num: 1, text: \"a\"}"

Как я могу создать привязку (переменную) myVecOfStrings:Vec<String> типа Vec<Data>:

myVecOfData:Vec<Data> = ?

возможно, используя serde_json или любую другую библиотеку?

Обратите внимание, что этот вопрос не совсем похож на Парсинг JSON-строки с помощью serde_json, так как тот вопрос не касается проблемы, что строка находится внутри Vec.

Да, вы можете сделать это с помощью serde_json, просто применив отображение к serde_json::from_str. Вот универсальная функция, которая может принимать Vec<String> и возвращает Result, содержащий Vec любого десериализуемого типа:

use serde::de::DeserializeOwned;

pub fn parse_json_strings<T: DeserializeOwned, S: AsRef<str>>(
    items: impl IntoIterator<Item = S>,
) -> Result<Vec<T>, serde_json::Error> {
    items
        .into_iter()
        .map(|i| serde_json::from_str(i.as_ref()))
        .collect()
}

Ответ или решение

Чтобы десериализовать Vec<String> в Vec<Data> в Rust, вы можете воспользоваться библиотекой serde_json, которая предоставляет мощные инструменты для работы с сериализацией и десериализацией данных в формате JSON.

Шаги по реализации

  1. Определите структуру данных: Вашей основной структурой является Data, которая содержит два поля: num и text.

    use serde::Deserialize;
    
    #[derive(Debug, Deserialize)]
    pub struct Data {
       num: i32,
       text: String,
    }
  2. Используйте serde_json для десериализации: Для преобразования каждого элемента Vec<String> в Data, вы можете использовать функцию serde_json::from_str. Однако, чтобы сделать код более универсальным, создадим обобщённую функцию, которая принимает итератор и возвращает Result<Vec<T>, serde_json::Error>.

  3. Реализация функции:

    use serde::de::DeserializeOwned;
    use serde_json;
    
    pub fn parse_json_strings<T: DeserializeOwned, S: AsRef<str>>(
       items: impl IntoIterator<Item = S>,
    ) -> Result<Vec<T>, serde_json::Error> {
       items
           .into_iter()
           .map(|i| serde_json::from_str(i.as_ref()))
           .collect()
    }
  4. Используйте функцию для десериализации:

    Теперь, чтобы создать Vec<Data> из вашего Vec<String>, вы можете сделать следующее:

    fn main() -> Result<(), serde_json::Error> {
       let my_vec_of_strings = vec![
           r#"{"num": 1, "text": "a"}"#.to_string(),
           r#"{"num": 2, "text": "b"}"#.to_string(),
           r#"{"num": 3, "text": "c"}"#.to_string(),
       ];
    
       let my_vec_of_data: Vec<Data> = parse_json_strings(my_vec_of_strings)?;
    
       println!("{:?}", my_vec_of_data);
       Ok(())
    }

Общие замечания

  • Формат JSON: Обратите внимание, что строки в Vec<String> должны быть в корректном формате JSON. В вашем примере вы использовали синтаксис "{ num: 1, text: \"a\"}", который не является валидным JSON. Правильный формат будет следующим: r#"{"num": 1, "text": "a"}"#.

  • Ошибки десериализации: При использовании serde_json, важно обрабатывать возможные ошибки десериализации. Поэтому функция возвращает Result, и вы должны обрабатывать этот результат в коде, где вызываете parse_json_strings.

Заключение

Данный подход позволяет вам эффективно и просто десериализовать Vec<String> в Vec<Data> с помощью serde_json. Эта методология позволяет вашему коду быть более гибким и легко адаптируемым для работы со структурами данных различного формата. Используйте данное решение как основу для более сложных задач взаимодействия со структурированными данными в Rust.

Оцените материал
Добавить комментарий

Капча загружается...