Воспроизвести Scala Нет десанциализатора Json для типа (String, String). Попробуйте реализовать неявные чтения или формат для этого типа

Эти сериализаторы Json в Play с помощью Scala приводят меня в бешенство.

Я прочитал десятки сообщений и учебников и документации. Пробовал четыре разных способа реализации переопределений Reads/Writes/Format и все безрезультатно.

Итак, я отступил от пользовательского типа и решил пойти uber simple:

  def suggest = Action(parse.json) {
    request =>
      request.body.validate[(String, String)].map {
        case (suggestion, categories) => Ok("You suggested " + suggestion + " for categories " + categories)
      }.recoverTotal {
        e => BadRequest(JsError.toFlatJson(e))
      }
  }

И ошибка возвращается, как отмечено в теме.

Нужно ли мне предоставлять пользовательскую реализацию Reads/Writes/Format для такого основного тела?

Тело ввода образца может быть:

{"suggestion":"add generics", "categories":"request;language;updates"}

Какая простая вещь мне не хватает?

Ответ 1

Играть! дает вам множество способов работы с Json. Из внешнего вида вашего кода вы идете по дороге Tuple. Что по существу позволяет конвертировать Json в Tuple. Вы также используете "чтения", который имеет недостаток, что вы не получаете точных отчетов об ошибках (т.е. Если недопустимый json был передан, вы знали бы его недопустимый... но вы не обязательно знаете, почему он был недействителен). Если вам нужна дополнительная обработка ошибок, вам нужно начать использовать метод проверки (подробности здесь: http://www.playframework.com/documentation/2.1.1/ScalaJsonCombinators).

Еще один способ, которым вы могли бы пойти, - сопоставить классы Json с case, которые делают что-то вроде:

import play.api.libs.json._

case class MyClass(
  suggestion: String,
  categories: String
)

object MyClass {
  implicit val readsMyClass: Reads[MyClass] = new Reads[MyClass] {
    def reads(json: JsValue): JsResult[MyClass] = {
      for {
        suggestion <- (json \ "suggestion").validate[String]
        categories <- (json \ "categories").validate[String]
      } yield MyClass(json,categories)
    }
  }
}

Это похоже на много кода, поэтому Play 2.1 представил Json 'Inception', который мне еще предстоит попробовать (http://www.playframework.com/documentation/2.1.1/ScalaJsonInception).

Наконец, если вам нужна проверка Json, но нет необходимости в сортировке/распаковке классов case, вы можете попробовать метод "береговое побережье". Это сохранит все ваши json как типы JsObject, но все равно даст вам подтверждение. Пример кода здесь: https://github.com/mandubian/play2-json-demo/blob/master/json-coast-to-coast/app/controllers/Application.scala

Надеюсь, что это поможет.

Ответ 2

Итак, я добавил это:

  implicit val rds = (
    (__ \ 'suggestion).read[String] and
    (__ \ 'categories).read[String]
  ) tupled

И это похоже на работу.

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