Сериализация/десериализация Rust JSON с помощью serde/serde_json при использовании дженериков и времени жизни?

Этот вопрос отличается от serde_json с десериализацией и временем жизни для универсальной функции, потому что ни from_slice, ни from_str не работают, а сообщения об ошибках разные.

Этот вопрос отличается от serde/rust десериализации JSON в Hashmap, поскольку они не сталкиваются с проблемами с границами признаков.

Этот вопрос отличается от Пожизненная ошибка с Serde в универсальной функции, потому что я все еще сталкиваюсь с проблемой, когда меняю Deserialize на DeserializeOwned или реализую границы признака более высокого ранга.


Моя цель очень проста: создать оболочку структуры вокруг карты диапазона (crate:rangemap) (которая уже сериализуется с помощью функции serde1), которая позволит мне сохранять данные в файл.

Я также хочу, чтобы он вызывал функцию сохранения при удалении структуры (путем реализации Drop) В следующем коде для краткости отсутствуют некоторые очевидные проверки (допустимость расположения файла).

Определение структуры:

    use serde::{Deserialize, Serialize};
    use serde_json;
    use rangemap::RangeMap;
    use serde::de::DeserializeOwned;
    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct RangeDataStorage<K, V> 
        where
            K: Ord + Clone + Eq + Debug + Default + Serialize + Deserialize,
            V: Default + Serialize + Debug + Eq + Clone + Deserialize {
        range_map: RangeMap<K, V>,
    }

Я прошел несколько итераций реализации структуры:

Структура реализации:

    impl<K, V> RangeDataStorage<K, V>
        where
            K: Ord + Clone + Eq + Debug + Default + Serialize + Deserialize,
            V: Default + Serialize + Debug + Eq + Clone + Deserialize{
        pub fn new(location: Option<String>) -> Result<RangeDataStorage<K, V>, Box<dyn Error>> {
            if location.is_some() {
                // load from file
                let location = location.unwrap();
                let data = std::fs::read_to_string(location)?;
                let data: RangeDataStorage<K, V> = serde_json::from_str(&data)?;
                let data = data.clone(); // does not fix problem
                return Ok(data);
            }
            Ok(
                RangeDataStorage {
                    range_map: RangeMap::new(),
                }
            )
        }
    
        pub fn insert(&mut self, key_start: K, key_end: K, value: V) {
            let range = Range {
                start: key_start,
                end: key_end,
            };
            self.range_map.insert(range, value);
        }
    
        pub fn save(&mut self, location: String) {
            let file = std::fs::File::create(location).unwrap();
            let writer = std::io::BufWriter::new(file);
            let res = serde_json::to_writer(writer, self);
            match res {
                Ok(_) => {},
                Err(e) => { println!("Error while saving file : {:?}", e); }
            }
        }
    
        pub fn get(&self, key: K) -> Option<&V> {
            self.range_map.get(&key)
        }
    }

Груз жалуется:

error[E0106]: missing lifetime specifier
  --> src\main.rs:13:61
   |
13 |         K: Ord + Clone + Eq + Debug + Default + Serialize + Deserialize,
   |                                                             ^^^^^^^^^^^ expected named lifetime parameter
   |
   = note: for more information on higher-ranked polymorphism, visit https://doc.rust-lang.org/nomicon/hrtb.html
help: consider making the bound lifetime-generic with a new `'a` lifetime
   |
13 |         K: Ord + Clone + Eq + Debug + Default + Serialize + for<'a> Deserialize<'a>,
   |                                                             +++++++            ++++
help: consider making the bound lifetime-generic with a new `'a` lifetime
   |
13 |         for<'a> K: Ord + Clone + Eq + Debug + Default + Serialize + Deserialize<'a>,
   |         +++++++                                                                ++++
help: consider introducing a named lifetime parameter
   |
11 ~ pub struct RangeDataStorage<'a, K, V>
12 |     where
13 ~         K: Ord + Clone + Eq + Debug + Default + Serialize + Deserialize<'a>,

В этой итерации груз жалуется на отсутствие спецификаторов времени жизни. Я до сих пор не понимаю, почему это проблема. Я прочитал статью о жизни десериализатора serde:

https://serde.rs/lifetimes.html

и я не уверен, чего мне не хватает. Я полагаю, что время жизни необходимо из-за того, что serde ориентирован на десериализацию с нулевым копированием (десериализованный объект ссылается на заимствованные данные десериализатора, поэтому средство проверки заимствований должно гарантировать, что заимствованные данные не выходят за пределы области действия, поэтому время жизни).

Однако клонирование данных должно решить эту проблему, верно? Это не так.

Cargo рекомендует добавить границы признаков более высокого ранга для отсутствующих спецификаторов времени жизни; в вышеупомянутой статье serde упоминается, что границы признаков более высокого ранга эквивалентны использованию DeserializeOwned (я пробовал оба):

Добавление границ признаков более высокого ранга:

    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct RangeDataStorage<K, V>
        where
            K: Ord + Clone + Eq + Debug + Default + Serialize + for<'a>Deserialize<'a>,
            V: Default + Serialize + Debug + Eq + Clone + for<'a>Deserialize<'a> {
        range_map: RangeMap<K, V>,
    }
    
    impl<K, V> RangeDataStorage<K, V>
        where
            K: Ord + Clone + Eq + Debug + Default + Serialize + for<'a>Deserialize<'a>,
            V: Default + Serialize + Debug + Eq + Clone + for<'a>Deserialize<'a>{

Новая проблема, нужны аннотации типов? Где? Как?

    error[E0283]: type annotations needed: cannot satisfy `K: Deserialize<'_>`
      --> src\main.rs:11:12
       |
    11 | pub struct RangeDataStorage<K, V>
       |            ^^^^^^^^^^^^^^^^^^^^^^
       |
    note: multiple `impl`s or `where` clauses satisfying `K: Deserialize<'_>` found
      --> src\main.rs:10:35
       |
    10 | #[derive(Debug, Clone, Serialize, Deserialize)]
       |                                   ^^^^^^^^^^^
    ...
    13 |         K: Ord + Clone + Eq + Debug + Default + Serialize + for<'a>Deserialize<'a>,
       |                                                             ^^^^^^^^^^^^^^^^^^^^^^
    note: required for `RangeDataStorage<K, V>` to implement `Deserialize<'de>`
      --> src\main.rs:10:35
       |
    10 | #[derive(Debug, Clone, Serialize, Deserialize)]
       |                                   ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
    11 | pub struct RangeDataStorage<K, V>
       |            ^^^^^^^^^^^^^^^^^^^^^^
       = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)

Та же ошибка возникает при замене границ признака более высокого ранга на DeserializeOwned:

    #[derive(Debug, Clone, Serialize, Deserialize)]
    pub struct RangeDataStorage<K, V>
        where
            K: Ord + Clone + Eq + Debug + Default + Serialize + DeserializeOwned,
            V: Default + Serialize + Debug + Eq + Clone + DeserializeOwned {
        range_map: RangeMap<K, V>,
    }
    
    impl<K, V> RangeDataStorage<K, V>
        where
            K: Ord + Clone + Eq + Debug + Default + Serialize + DeserializeOwned,
            V: Default + Serialize + Debug + Eq + Clone + DeserializeOwned{
    error[E0283]: type annotations needed: cannot satisfy `K: Deserialize<'_>`
      --> src\main.rs:11:12
       |
    11 | pub struct RangeDataStorage<K, V>
       |            ^^^^^^^^^^^^^^^^^^^^^^
       |
    note: multiple `impl`s or `where` clauses satisfying `K: Deserialize<'_>` found
      --> src\main.rs:10:35
       |
    10 | #[derive(Debug, Clone, Serialize, Deserialize)]
       |                                   ^^^^^^^^^^^
    ...
    13 |         K: Ord + Clone + Eq + Debug + Default + Serialize + DeserializeOwned,
       |                                                             ^^^^^^^^^^^^^^^^
    note: required for `RangeDataStorage<K, V>` to implement `Deserialize<'de>`
      --> src\main.rs:10:35
       |
    10 | #[derive(Debug, Clone, Serialize, Deserialize)]
       |                                   ^^^^^^^^^^^ unsatisfied trait bound introduced in this `derive` macro
    11 | pub struct RangeDataStorage<K, V>
       |            ^^^^^^^^^^^^^^^^^^^^^^
       = note: this error originates in the derive macro `Deserialize` (in Nightly builds, run with -Z macro-backtrace for more info)

Краткий поиск в Google по этой проблеме дает следующий результат: https://github.com/serde-rs/serde/issues/2418

Это мне не помогает, поскольку удаление предложенияwhere в моей структуре также вызывает у меня проблемы, поскольку груз теперь жалуется, что типы K и V должны быть ограничены Ord, Clone, Eq (требуется десериализацией).

На данный момент я заблудился и не могу найти больше информации для задачи, которая должна быть относительно простой, и я даже не дошел до реализации функции Drop.

Спасибо за любую помощь, которую вы можете оказать.

Почему Python в конце концов умрет
Почему Python в конце концов умрет
Последние 20 лет были действительно хорошими для Python. Он прошел путь от "просто языка сценариев" до основного языка, используемого для написания...
2
0
130
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Макрос вывода Deserialize не может определить, каковы фактические границы, необходимые для реализации Deserialize вашей структуры. Результатом являются довольно непрозрачные сообщения об ошибках, которые вы получаете от компилятора.

Чтобы это исправить, вы можете написать границы реализации Deserialize самостоятельно вместо того, чтобы serde пытался их выяснить. Это также означает, что вы можете полностью удалить привязку where из своей структуры; на самом деле вам не нужны никакие из этих границ для определения структуры, и обычно вам не следует связывать общие параметры типа, если только это абсолютно не требуется для определения типа.

Результат выглядит примерно так:

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct RangeDataStorage<K, V> {
    #[serde(bound(deserialize = r"
        K: Ord + Clone + Deserialize<'de>,
        V: Eq + Clone + Deserialize<'de>,
    "))]
    range_map: RangeMap<K, V>,
}

Вы можете получить эти границы, начав с пустых границ и добавляя то, что предлагает компилятор, до компиляции, или скопировав границы из реализации Deserialize RangeMap.

Спасибо! Я бы точно не догадался, что проблема в самом макросе; Я думаю, множественные следы были подсказкой. Это было очень полезно; Меня заблокировали по этому поводу примерно на три дня.

EatonWu 18.06.2024 06:40

Другие вопросы по теме