Как вы создаете объект Json со значениями разных типов?

Как вы создаете объект Json со значениями разных типов?

Я использую спрей-json

Вот код

val images : List[JsObject] = fetchImageUrls(url).map((url: String) => {
  JsObject(List(
        "link_path" -> JsString(url),
        "display_name" -> JsString("image"),
        "size" -> JsString(""),
        "modified" -> JsString(""),
        "thumbnail" -> JsString(url),
        "filename" -> JsString("image"),
        "is_dir" -> JsBoolean(x = false),
        "thumb_exists" -> JsBoolean(x = true)) )
  })

val jsonAst: JsObject = JsObject(List(
  "client" -> JsString("urlimages"),
  "view" -> JsString("thumbnails"),
  "contents" -> JsArray(images)
))

Работает, но выглядит очень тяжело. Есть ли способ определить json с помощью такого кода?

val images : List[List[(String, Any)]] = fetchImageUrls(url).map((url: String) => {
  List(
    "link_path" -> url,
    "display_name" -> "image",
    "size" -> "",
    "modified" -> "",
    "thumbnail" -> url,
    "filename" -> "image",
    "is_dir" -> false,
    "thumb_exists" -> true)
})

val jsonAst = List(
  "client" -> "urlimages",
  "view" -> "thumbnails",
  "contents" -> images
).toJson

Это не работает, говоря, что

Cannot find JsonWriter or JsonFormat type class for List[(String, Object)]
    ).toJson
      ^

Что я получаю, тип каждого поля не определен во время компиляции. Но почему это не сработает, если сериализатор все равно выполняет сопоставление с образцом?

Спасибо!


person expert    schedule 01.05.2013    source источник
comment
Библиотека может это поддерживать. Но если нет, создайте функцию implicit, которая берет String и преобразует ее в JsString.   -  person Jatin    schedule 01.05.2013


Ответы (2)


Вы идете на неправильный подход здесь. В целях согласованности я настоятельно рекомендую вам использовать case class.

Скажи, что у тебя есть это

case class Image(
    url: String,
    size: Double,
    properties: Map[String][String]
    optionalProperty: Option[String]
    // etc.
);

И затем вы используете parse и decompose, чтобы справиться с этим.

val image = parse(jsonString).extract[Image]; // extracts an Image from JSON.
val jsonForImage: JValue = decompose(image);  // serializes an Image to JSON.

И если вы хотите сериализовать List[Image] в JSON:

def serialize(images: List[Image]) : JValue = {
    for (image <- images) 
       yield decompose(image);
};

Чтобы разобрать список изображений из JSON:

val images: List[Image] = parse(jsonString).extract[List[Image]];

Использование Option[SomeType] в Image case class автоматически обрабатывает отсутствующие/необязательные параметры.

person flavian    schedule 01.05.2013

Я согласен с @ alex23 в том, что подход, основанный на классе случаев, будет лучше. Используя спрей-json, вы должны сначала определить структуру класса вашего случая, а также расширение DefaultJsonProtocol для описания классов случаев, которые вы хотите сериализовать. Это будет выглядеть так:

case class Image(link_path:String, display_name:String, size:Option[String], 
  modified:Option[String], thumbnail:String, filename:String, is_dir:Boolean, thumb_exists:Boolean)
object Image  

case class UrlImages(client:String, view:String, contents:List[Image])
object UrlImages

object MyJsonProtocol extends DefaultJsonProtocol {
  implicit val imageFormat = jsonFormat8(Image.apply)
  implicit val urlImagesFormat = jsonFormat3(UrlImages.apply)
}  

Тогда модифицированная версия вашего примера будет выглядеть так:

import MyJsonProtocol._
val images : List[Image] = fetchImageUrls(url).map((url: String) => {
  Image(url, "image", None, None, url, "image", false, true)      
})

val jsonAst = UrlImages("urlimages", "thumbnails", images).toJson

Причина, по которой вы видите эту ошибку, заключается в том, что spray-json не знает, как сериализовать списки кортежей, которые вы создаете. Если вы действительно хотите использовать эту структуру, а не идти по маршруту класса case, вы можете рассмотреть возможность предоставления собственного сериализатора для List[(String,Any)]. Ознакомьтесь с разделом документации spray-json под названием «Предоставление JsonFormats для других типов». Если вы хотите пойти по этому пути и вам нужна дополнительная помощь, дайте мне знать.

person cmbaxter    schedule 01.05.2013