喷雾 JSON:灵活性 Array/Object

Spray JSON: Flexibility Array/Object

使用 Spray JSON,我希望能够解析一个字符串数组,但如果出现单个字符串,我仍然能够正确反序列化。 也就是说,有了这个字段:

arrayval: List[String]

和这个 JSON:

arrayval: ["a", "b"]

它会创建一个列表("a","b"),然后 JSON:

arrayval: "a"

它将创建一个列表("a")。 使用默认的 listFormat 它会在第二种情况下抱怨。 有没有办法配置这种灵活性?

如果它对任何人有帮助,我已经通过覆盖 CollectionFormats(在 DefaultJsonProtocol 中使用)中的 listFormat 来解决它。

trait FlexibleCollectionFormats extends CollectionFormats {

  implicit override def listFormat[T: JsonFormat] = new RootJsonFormat[List[T]] {
    import spray.json._

    def write(list: List[T]) = JsArray(list.map(_.toJson).toVector)
    def read(value: JsValue): List[T] = value match {
      case JsArray(elements) => elements.map(_.convertTo[T])(collection.breakOut)
      case JsString(element) => List[T](new JsString(element).convertTo[T]) 
      case x                 => deserializationError("Expected List as JsArray, but got " + x)
    }
  }
}

然后我创建了自己的协议而不是 DefaultJsonProtocol,它基本上使用与 Default 相同的协议但覆盖了 CollectionFormats:

trait FlexibleDefaultJsonProtocol
        extends BasicFormats
        with StandardFormats
        // with CollectionFormats
        with FlexibleCollectionFormats
        with ProductFormats
        with AdditionalFormats

object FlexibleDefaultJsonProtocol extends FlexibleDefaultJsonProtocol

之后你使用 extends FlexibleDefaultJsonProtocol 而不是 DefaultJsonProtocol。您可以随时在 类 中切换和使用其中一个,所以我喜欢它提供的灵活性。