6

異なる型の値を持つ 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
      ^

私が得る、各フィールドのタイプはコンパイル時に定義されていません。しかし、とにかくシリアライザがパターン マッチングを行うと、なぜ機能しないのでしょうか?

ありがとう!

4

2 に答える 2

4

ケースクラスベースのアプローチの方が優れているという@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 が認識していないためです。本当にその構造を使用したいが、ケース クラスのルートには行かない場合は、List[(String,Any)] のカスタム シリアライザーを提供することを検討できます。スプレー json ドキュメントの「他のタイプの JsonFormats の提供」というタイトルのセクションを確認してください。この方法をご希望で、さらにサポートが必要な場合は、お知らせください。

于 2013-05-01T11:58:03.137 に答える
1

あなたはここで間違ったアプローチをしようとしています。一貫性を保つために、 を使用することを強くお勧めしますcase class

これを持っていると言う

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

そして、これに対処するためにparseandを使用します。decompose

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

List[Image]また、aを 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と、不足している/オプションのパラメーターが自動的に処理されます。

于 2013-05-01T11:17:13.717 に答える