#rust #serde
#Ржавчина #serde
Вопрос:
Я новичок в rust (но опытный программист), и я пытаюсь создать простую служебную функцию для чтения данных из файла json, и мне явно не хватает важного понимания rust, чтобы справиться с этим. Я огляделся, но не смог заставить его работать с другими вопросами rust. Я пытаюсь сделать что-то вроде этого:
pub fn read_data_from_json<'a, T: Deserialize<'a>, P: AsRef<Path>>(path: P) -> T {
let result = std::fs::read_to_string(path).unwrap();
return serde_json::from_str(amp;result).unwrap();
}
Проблема в том, что я хочу предоставить serde_json::from_str()
amp;str
требуемое, но получаю a String
от чтения файла. Итак, компилятор rust говорит:
40 | return serde_json::from_str(amp;result).unwrap();
| ---------------------^^^^^^^-
| | |
| | borrowed value does not live long enough
Причина, очевидно, в том, что result
переменная удаляется до from_str()
завершения работы со значением, но я не смог получить «только фрагмент» со значением. Я пробовал as_str()
, amp;*
, amp;'static str
и несколько других вариантов, чтобы попытаться заставить это работать, но я явно что-то упускаю, поскольку это похоже на базовый вариант использования. Я должен признать, что я все еще немного нечетко понимаю «время жизни» и связанные с ним дженерики, поэтому проблема может быть там.
Комментарии:
1. Эта страница документации представляет довольно точно вашу ситуацию: docs.serde.rs/serde/de/trait . DeserializeOwned.html
Ответ №1:
Я бы посоветовал вам прочитать «Понимание времени жизни десериализатора» из руководства serde. Там они предлагают T: DeserializeOwned
, явно упоминая ваш usecase:
Обычно это происходит потому, что данные, из которых десериализуются, будут удалены до возврата функции, поэтому
T
им нельзя разрешать заимствовать из нее.
Итак, решение таково:
use serde::de::DeserializeOwned;
pub fn read_data_from_json<T: DeserializeOwned, P: AsRef<Path>>(path: P) -> T {
let result = std::fs::read_to_string(path).unwrap();
return serde_json::from_str(amp;result).unwrap();
}
Комментарии:
1. Обратите внимание, что это может повлечь за собой изменение структуры для десериализации, поскольку она должна владеть своими данными.
2. Хорошо, интересно, но является ли это проблемой только для serde- способа сериализации с нулевой копией? Я подумал, что это общая вещь с заимствованием, которую мне нужно понять. Я чувствую, что должен иметь возможность указать Rust, чтобы он просто сохранял ссылку до завершения функции / области видимости, или что мне просто нужен фрагмент, а не объект string.
3. @leondepeon Rust сохранял ссылку до тех пор, пока функция / область не завершилась. Ваш
from_str()
вызов был бы хорош, если бы вы присвоили его результат локальной переменной и использовали его внутри функции, чтобы он не пережилresult
. Но вы попытались вернуть сконструированное значение, а это недопустимо, потому что ссылки с нулевой копией внутри него останутся висячими послеresult
удаления.