создание Writeable[Argonaut.Json] для http-ответа игровой платформы

Я пытаюсь изменить реализацию этой функции, используя библиотеку play json, например

def apply[T](action: => ApiResponse[T])(implicit tjs: Writes[T], ec: ExecutionContext): Future[Result] = {
    action.fold(
      err =>
        Status(err.statusCode) {
          JsObject(Seq(
            "status" -> JsString("error"),
            "statusCode" -> JsNumber(err.statusCode),
            "errors" -> Json.toJson(err.errors)
          ))
        },
      t =>
        Ok {
          JsObject(Seq(
            "status" -> JsString("ok"),
            "response" -> Json.toJson(t)
          ))
        }
    )
  }

использовать argonaut вот так

def apply[T](action: => ApiResponse[T])(implicit encodeJson: EncodeJson[T], ec: ExecutionContext): Future[Result] = {
    action.fold(
      err =>
        Status(err.statusCode) {
          Json(
          "status" -> jString("error"),
          "statusCode" -> jNumber(err.statusCode),
          "errors" -> err.errors.asJson
          )
        },
      t =>
        Ok {
          Json(
          "status" -> jString("ok"),
          "response" -> t.asJson
          )
        }
    )
  }

но я получаю

Не удается записать экземпляр argonaut.Json в ответ HTTP. Попробуйте определить Writeable[argonaut.Json]

как для блока Status{}, так и для блока Ok{}, и я получил полезный ответ на эту проблему здесь https://groups.google.com/forum/#!topic/play-framework/vBMf72a10Zc

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

implicit def writeableOfArgonautJson(implicit codec: Codec): Writeable[Json] = {
      Writeable(jsval => codec.encode(jsval.toString))
    }

который, я думаю, преобразует объект json в строку и предоставляет его codec.encode, который должен преобразовать его в Array[Bytes], но я получаю

Не удается угадать тип содержимого для argonaut.Json. Попробуйте определить ContentTypeOf[argonaut.Json]

jsval.nospaces.getBytes также возвращает Array[Bytes], поэтому я не знаю, можно ли это вообще использовать для помощи

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

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


person Mark    schedule 01.02.2015    source источник
comment
Когда .nospaces возвращает JSON в виде строки, вы можете передать его Ok(js.nospaces).as("application/json")   -  person cchantep    schedule 02.02.2015


Ответы (1)


Вы, кажется, ответили на свой вопрос, но, чтобы подтвердить, Writable[A] это:

  1. как преобразовать тип A в Array[Bytes] и
  2. какой тип контента использовать в ответе, что также требует
  3. текущая кодировка символов

О кодировке символов заботится неявный экземпляр Codec, поэтому вам нужен неявный ContentTypeOf[A], где A равно argonaunt.Json:

implicit def contentTypeOf_ArgonautJson(implicit codec: Codec): ContentTypeOf[argonaut.Json] = {
  ContentTypeOf[argonaut.Json](Some(ContentTypes.JSON))
}

а затем Writable[A], у которого есть введите ограничение на A, чтобы было ContentTypeOf[A] в области видимости (которое вы только что определили):

implicit def writeableOf_ArgonautJson(implicit codec: Codec): Writeable[argonaut.Json] = {
  Writeable(jsval => codec.encode(jsval.toString))
}

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

Возможно, вы могли бы поместить эти имплициты в трейт ExtraJsonHelpers и смешать его с вашими контроллерами для большего сокращения шаблонов.

person Mikesname    schedule 01.02.2015
comment
Спасибо, все оказалось не так плохо, как я думал. Я думаю, это наказание за выход за рамки и использование argonaut. - person Mark; 01.02.2015
comment
Не могли бы вы порекомендовать мне хорошее место для размещения этих двух имплицитов, чтобы они были доступны везде, где я мог бы попытаться вернуть ответ http - person Mark; 01.02.2015
comment
Очень полезный ответ. Было интересно, не могли бы вы также дать нам подразумеваемое «пожалуйста» для чтения, чтобы завершить картину? - person Armin; 22.06.2015
comment
@Armin, вы можете спутать это с Writes (как преобразовать что-то в JSON), которое отличается от используемого здесь Writeable (как преобразовать что-то в результат) - person Jacob Wang; 05.01.2016