В Rust как мне получить handlebars_helper! обрабатывать объект JSON - PullRequest
0 голосов
/ 25 октября 2019

Надеюсь, этого контекста достаточно для вопроса ...

Используя Handlebars с Rust, я пытаюсь реализовать обработчик для обработки этого ввода:

 {{toJSON JSON_OBJ_OR_NONE}}

где JSON_OBJ_OR_NONEлибо допустимый фрагмент JSON, например

{
   "abc": 123,
   "def": ["g", "h", "i"],
   "jkl": {
     "m": 1,
     "n": "op"
   }
}

, либо ничего (пустая строка).

То, что он должен вернуть, это либо печатная версия предоставленного JSON, либо "{}"если JSON_OBJ_OR_NONE пуст.

Предоставленный фрагмент JSON полностью произвольный;он может содержать любой допустимый JSON или пустую строку. Вывод должен быть хорошо напечатан.

Я пытался реализовать это множеством разных способов, и сейчас я нахожусь на

handlebars_helper!(toJSON: |json_obj_or_none: str|
if json_obj_or_none.is_empty() {
    "{}"
} else {
    let s = serde_json::to_string_pretty(&json_obj_or_none).is_ok().to_string();
    &s[..]
});

Это выглядит близко, но явидеть

error[E0597]: `s` does not live long enough
   --> src/main.rs:145:10
    |
145 |         &s[..]
    |         -^----
    |         ||
    |         |borrowed value does not live long enough
    |         borrow later used here
146 |     });
    |     - `s` dropped here while still borrowed

, когда я его компилирую

Хотя это, похоже, близко к рабочему решению, я подозреваю, что есть гораздо более элегантный способ его кодирования.

Ответы [ 2 ]

1 голос
/ 01 ноября 2019

Код вроде:

{
   let s = something;
   &s
}

- почти всегда ошибка в Rust. Ссылки всегда заимствуют из чего-то, и ссылки не могут существовать после того, как эта вещь уничтожена. Локальные переменные уничтожаются в конце своей области видимости.

Итак, что это значит:

  1. Make s
  2. Взять от s
  3. Уничтожить s и его содержимое
  4. Вернуть ссылку на ту вещь, которая только что была уничтожена

Так что вам нужно передать право владения:

{
   let s = something;
   s // not borrowed!
}

или убедитесь, что s не будет уничтожен в ближайшее время путем перемещения let на уровень области выше:

let s;
{
   s = something;
   &s
   // `s` isn't destroyed here, because `let s` was outside `{}`
}
// `s` and `&s` are destroyed now

Если вы смешаете его со строковыми литералами в if/else, Rust будет жаловатьсячто String и &str различны. Используйте String::from("") для литерала или посмотрите тип Cow, который содержит оба. Rust должен знать, какие строки освобождать (String), а какие никогда не должны освобождать (&str), поэтому существует два типа.

0 голосов
/ 02 ноября 2019

Просто, чтобы обернуть это, я в итоге получил это работать следующим образом:

handlebars_helper!(toJSON: |json_obj_or_none: object|
if json_obj_or_none.is_empty() {
    "{}".into()
} else {
    let s = serde_json::to_string_pretty(&json_obj_or_none).unwrap_or_else(|_| "{}".to_string());
    s
});
...