yesod — получение тела запроса для ПУБЛИКАЦИИ «Тип содержимого: приложение / json»

#haskell #yesod

#haskell #yesod

Вопрос:

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

 curl -v -H "Accept: application/json" -H "Content-Type: application/json" -X POST -d '{"name":"oscar"}'    http://localhost:3000/user/xyz
  

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

 (pp, files) <- runRequestBody
  

Но это не удается из-за типа содержимого. Есть ли другая функция для этого?

Ответ №1:

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

 postFooR :: Handler Value
postFooR = do
 foo <- requireJsonBody :: Handler Foo -- get the json body as Foo (assumes FromJSON instance)
 returnJson foo -- return json (assumes ToJSON instance)
  

Комментарии:

1. Обратите внимание, что вы также можете сделать requireJsonBody :: Handler Value , а затем просто извлечь нужные вам поля с помощью Lens, если вас не беспокоит написание нового типа данных для Foo .

Ответ №2:

Вот как это сделать сейчас. Для будущих выпусков я надеюсь добавить несколько удобных оболочек; вклад в это приветствуется.

Объяснение: Каждая функция-обработчик находится в GGHandler sub master (Iteratee ByteString IO) монаде. Это довольно сложно, но это означает, что это монадный преобразователь обработчика вокруг итерации, который получает поток байтовых строк. Этот поток байтовых строк является необработанным телом запроса.

Итак, нам нужно использовать функцию enumerator consume, чтобы взять весь этот поток байтовых строк и сохранить их в виде списка. И нам нужно использовать функцию lift, чтобы перенести это во внутреннюю монаду (Iteratee). Затем L.fromChunks преобразует список строгих байтовых строк в отложенную байтовую строку, которую вы можете проанализировать с помощью любой произвольной библиотеки JSON (Yesod стандартизирует aeson).

Я предполагаю, что наиболее удобной функцией, которую я мог бы предоставить, была бы parseRequestJson :: GGHandler s m (Iteratee ByteString IO) (Maybe Data.Aeson.Value) . Я могу добавить это в точечном выпуске yesod-json.

Комментарии:

1. Спасибо, это имеет смысл. Одновременно изучаю Haskell и Yesod, поэтому этот ответ был полезен.

2. Этот помощник уже доступен? Если нет, то как это будет выглядеть (особенно часть синтаксического анализа JSON)? Мне удается получить ленивую байтовую строку, но мне трудно разобрать ее в некоторый JSON.

3. @DaxFohl hackage.haskell.org/packages/archive/yesod-json/1.0.0.1/doc / … делает это действительно простым и работает с любым экземпляром FromJSON.

Ответ №3:

В Yesod 1.0 (и, возможно, ранее, не уверен), похоже, работает следующее:

 postRootR = do
    wr <- waiRequest
    bss <- lift $ lazyConsume $ requestBody wr
    let requestBody = L.fromChunks bss