Вы можете представить себе это:
scala> import spray.json._
import spray.json._
scala> case class Foo(bar: String) {
def toJson:JsValue = JsObject( "bar" -> JsString(bar) )
}
defined class Foo
scala> Foo("bar").toJson
res2: spray.json.JsValue = {"bar":"bar"}
Пока все хорошо, но это не вписывается в механизм классов типов Spray. Например, DSL маршрутизации Spray выдал бы вам ошибку типа, если бы вы затем попытались преобразовать Foo в / из JsValue (например, используя маршрут entity( as[Foo] ) { ... }
). И имплициты, которые они уже подготовили для вас, для таких типов, как List и Set, не могут работать с Foo:
scala> import DefaultJsonProtocol._
import DefaultJsonProtocol._
scala> List(Foo("bar")).toJson
<console>:31: error: Cannot find JsonWriter or JsonFormat type class for List[Foo]
List(Foo("bar")).toJson
потому что у них нет класса JsonFormat, который можно было бы использовать для преобразования Foo, как тот, который создал бы JsonFormat1(Foo)
.
Затем вы можете подумать о том, чтобы поместить формат внутри сопутствующего объекта Foo, поскольку сопутствующий объект класса в области видимости находится на неявном пути поиска, например:
object Foo extends DefaultJsonProtocol {
implicit val fooFormat = jsonFormat1(Foo)
}
case class Foo(bar: String)
Но поскольку мы еще не закончили определение Foo на этом этапе, компилятор выдает нам ошибку типа:
[error] found : Foo.type
[error] required: ? => ?
[error] Note: implicit value fooFormat is not applicable here because it comes after the application point and it lacks an explicit result type
Добавление явного типа результата RootJsonFormat[Foo]
не решает проблему:
[error] found : Foo.type
[error] required: ? => Foo
[error] implicit val fooFormat:RootJsonFormat[Foo] = jsonFormat1(Foo)
Уловка (спасибо, knutwalker!) Состоит в том, чтобы явно передать Foo.apply
:
object Foo extends DefaultJsonProtocol {
implicit val fooFormat = jsonFormat1(Foo.apply)
}
case class Foo(bar: String)
person
AmigoNico
schedule
09.04.2014