NonEmptyList的自定义喷雾格式化程序[A]

时间:2015-09-18 15:30:34

标签: json scala spray

我正在尝试为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] - 因为会抛出异常(按照我所理解的每个喷涂惯例)来指示反序列化失败。

1 个答案:

答案 0 :(得分:2)

我不确定你是否需要使用反射。你需要的是一个JsonFormat for A的实例,并用它组合你的NonEmptySeq格式。然后,您可以使用toJsonconvertTo[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): _*)
}