如何使用for-comprehension提取JSON值

时间:2013-07-19 14:56:50

标签: scala lift-json

我想提取JSON值usgin for-comprehensions

我的代码是:

import net.liftweb.json._

val json = parse("""     
{
    "took": 212,
    "timed_out": false,
    "_shards": {
        "total": 5,
        "successful": 5,
        "failed": 0
    },
    "hits": {
        "total": 4,
        "max_score": 0.625,
        "hits": [
            {
                "_index": "siteindex",
                "_type": "posts",
                "_id": "1",
                "_score": 0.625,
                "_source": {
                    "title": "title 1",
                    "content": "content 1"
                },
                "highlight": {
                    "title": [
                        "<b>title</b> 1"
                    ]
                }
            },
            {
                "_index": "siteindex",
                "_type": "posts",
                "_id": "4",
                "_score": 0.19178301,
                "_source": {
                    "title": "title 4",
                    "content": "content 4"
                },
                "highlight": {
                    "title": [
                        "<b>title</b> 4"
                    ]
                }
            },
            {
                "_index": "siteindex",
                "_type": "posts",
                "_id": "2",
                "_score": 0.19178301,
                "_source": {
                    "title": "title 2",
                    "content": "content 2"
                },
                "highlight": {
                    "title": [
                        "<b>title</b> 2"
                    ]
                }
            },
            {
                "_index": "siteindex",
                "_type": "posts",
                "_id": "3",
                "_score": 0.19178301,
                "_source": {
                    "title": "title 3",
                    "content": "content 3"
                },
                "highlight": {
                    "title": [
                        "<b>title</b> 3"
                    ]
                }
            }
        ]
    }
}      
""")

我的“案例类”是这样的:

case class Document(title:String, content:String)

我的“for”是这样的:

val ret: List[Document] = for {
  JObject(child)                          <- json
  JField("title",       JString(title))   <- child
  JField("content",     JString(content)) <- child
} yield (Document( title, content  ))

和我的“清单”是这样的:

ret: List[Document] = List(Document(title 1,content 1), Document(title 4,content 4), Document(title 2,content 2), Document(title 3,content 3))
直到这里一切都很好!

但现在我需要这样的东西:

List(Document2(1,<b>title</b> 1,content 1), Document2(4,<b>title</b> 4,content 4), Document2(2,<b>title</b> 2,content 2), Document2(3,<b>title</b> 3,content 3))

我需要以下值:

 "highlight": {
                    "title": [
                        "<b>*</b> *"
                    ]
                }

和此:

"_id": "*",

在我的清单中。

我的“案例类”是这样的:

case class Document2(_id:String, title:String, content:String)

我试试这个,但它不起作用

val ret: List[Document2] = for {
  JObject(child)                          <- json
  JField("_id",         JString(_id))     <- child
  JField("title",       JString(title))   <- child
  JField("content",     JString(content)) <- child
} yield (Document2( _id, title, content  ))

我不知道,如果这个json有更好的数据提取方法

但结果如下:

<console>:23: warning: `withFilter' method does not yet exist on net.liftweb.json.JValue, using `filter' method instead
         JObject(child)                          <- json

ret: List[Document2] = List()

任何建议请
谢谢你的帮助

1 个答案:

答案 0 :(得分:0)

这是一个类似于@flav方法的答案,但我会给你一个映射到json的结构以及如何获得最终结果。首先,案例类:

case class Document2(_id:String, title:String, content:String)

case class Results(hits:HitsList)
case class HitsList(hits:List[Hit])
case class Hit(_id:String, _source:Source, highlight:Highlight)
case class Source(title:String, content:String)
case class Highlight(title:List[String])

然后,解析它并转换它的代码:

implicit val formats = DefaultFormats
val results = json.extract[Results]
val docs2 = results.hits.hits.map{ hit => 
  Document2(hit._id, hit.highlight.title.head, hit._source.content)
}