代码之家  ›  专栏  ›  技术社区  ›  xmar

喷涂JSON:柔性阵列/对象

  •  0
  • xmar  · 技术社区  · 7 年前

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

    arrayval: List[String]
    

    这个JSON:

    arrayval: ["a", "b"]
    

    它将创建一个列表(“A”、“B”),并使用此JSON:

    arrayval: "a"
    

    它将创建一个列表(“A”)。 在第二种情况下,使用默认的listformat会有问题。 有没有办法配置这种灵活性?

    1 回复  |  直到 7 年前
        1
  •  1
  •   xmar    7 年前

    如果它对任何人都有帮助,我通过重写CollectionFormats中的listform(在DefaultJSonProtocol中使用)来解决它。

    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)
        }
      }
    }
    

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

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

    以后你用 extends FlexibleDefaultJsonProtocol 而不是默认的jsonProtocol。在您的类中,您总是可以切换和使用其中的一个或另一个,所以我喜欢它提供的灵活性。