Спрей JSON: массив гибкости / объект - PullRequest
0 голосов
/ 21 мая 2018

Используя Spray JSON, я хотел бы иметь возможность анализировать массив String, но при этом иметь возможность правильно десериализоваться, если приходит одна строка.То есть с этим полем:

arrayval: List[String]

и этим JSON:

arrayval: ["a", "b"]

будет создан список ("a", "b"), а с этим JSON:

arrayval: "a"

это создаст список («а»).Используя defaultFormat list, он будет жаловаться во втором случае.Есть ли способ настроить этот тип гибкости?

1 Ответ

0 голосов
/ 21 мая 2018

В случае, если это кому-нибудь поможет, я решил это, переопределив listFormat в CollectionFormats (который используется в 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)
    }
  }
}

Затем я создал собственный протокол вместо DefaultJsonProtocol, который в основном использует те же, что и Default, но переопределяет CollectionFormats:

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

object FlexibleDefaultJsonProtocol extends FlexibleDefaultJsonProtocol

и позже вы используете extends FlexibleDefaultJsonProtocol вместоDefaultJsonProtocol.Вы всегда можете переключаться и использовать один или другой в своих классах, поэтому мне нравится гибкий подход, который он предоставляет.

...