我正在尝试为NonEmptyList[A]
编写自定义JSON格式化程序:
package net
import spray.json._
import Foo.NonEmptySeq
class NonEmptyCustomFormatter[A](implicit ev: A => JsValue)
extends JsonFormat[NonEmptySeq[A]] {
override def read(json: JsValue): NonEmptySeq[A] =
???
override def write(xs: NonEmptySeq[A]): JsValue = {
val values: Seq[JsValue] = Foo.toSeq[A](xs).map(ev(_))
JsArray( values: _* )
}
}
object Foo {
type NonEmptySeq[A] = (A, Seq[A])
def toSeq[A](neq: NonEmptySeq[A]): Seq[A] =
neq._1 +: neq._2
implicit def stringToJsValue(x: String): JsValue = JsString(x)
}
REPL示例:
scala> import spray.json._
import spray.json._
scala> import net._
import net._
scala> import net.Foo._
import net.Foo._
scala> implicit object NonEmptyStringList extends NonEmptyCustomFormatter[String]
defined object NonEmptyStringList
scala> val xs: NonEmptySeq[String] = ("foo", Nil)
xs: net.Foo.NonEmptySeq[String] = (foo,List())
scala> xs.toJson
res0: spray.json.JsValue = ["foo"]
接下来,我即将实施read
方法,目前定义为???
。
如果我有一个非通用的,即String-specific
格式化程序,那么我可以简单地在JsString
上进行模式匹配,如果它不是{{1},则返回deserializationError
}}
但是,由于JsString
可以包含0个或更多JsArray
元素,因此我必须求助于反射吗?基本上,我想定义另一个JsValue
而不用反射。
我该怎么做?
修改
我将(implicit ev2: JsValue => A)
类型签名从ev2
更改为JsValue => Option[A]
- 因为会抛出异常(按照我所理解的每个喷涂惯例)来指示反序列化失败。
答案 0 :(得分:2)
我不确定你是否需要使用反射。你需要的是一个JsonFormat for A的实例,并用它组合你的NonEmptySeq格式。然后,您可以使用toJson
和convertTo[A]
例如:
class NonEmptyCustomFormatter[A : JsonFormat] extends JsonFormat[NonEmptySeq[A]] {
override def read(json: JsValue): NonEmptySeq[A] = json match {
case JsArray(Vector(value, values @ _*)) =>
(value.converTo[A], values.map(_.convertTo[A]))
}
override def write(xs: NonEmptySeq[A]): JsValue =
JsArray(Foo.toSeq[A](xs).map(_.toJson): _*)
}