作为Circe-Json的一部分,如何使用Hcursor或Optics返回匹配对象的列表?

时间:2018-12-18 15:04:41

标签: json scala circe

我的代码大致如下:

val json: Json = parse("""
[
{
"id": 1,
"type": "Contacts",
"admin": false,
"cookies": 3
},
{
"id": 2,
"type": "Apples",
"admin": false,
"cookies": 6
},
{
"id": 3,
"type": "Contacts",
"admin": true,
"cookies": 19
}
]
""").getOrElse(Json.Null)

我正在使用Circe,Cats,Scala,Circe-json等,并且Parse调用成功。

我想返回一个列表,其中完整显示了类型为“ Contacts”的每个顶级对象。

类似: List [String] = [“ {” id“:1,” type“:” Contacts“,” admin“:false,” cookies“:3}”,“ {” id“:3,” type“:” Contacts “,” admin“:true,” cookies“:19}”]

背景是我的磁盘上有大的JSON文件。我需要过滤出与某个type=值匹配的对象子集(在本例中为type=Contacts),然后将其与json文件的其余部分分开。我不是要修改文件,而是要grep匹配对象并进行相应处理。

谢谢。

1 个答案:

答案 0 :(得分:0)

完成这种操作的最直接方法是将文档解码为List[Json]List[JsonObject]值。例如,给定您对json的定义:

import io.circe.JsonObject

val Right(docs) = json.as[List[JsonObject]]

然后您可以根据type进行查询:

scala> val contacts = docs.filter(_("type").contains(Json.fromString("Contacts")))
contacts: List[io.circe.JsonObject] = List(object[id -> 1,type -> "Contacts",admin -> false,cookies -> 3], object[id -> 3,type -> "Contacts",admin -> true,cookies -> 19])

scala> contacts.map(Json.fromJsonObject).map(_.noSpaces).foreach(println)
{"id":1,"type":"Contacts","admin":false,"cookies":3}
{"id":3,"type":"Contacts","admin":true,"cookies":19}

考虑到您的用例,广角光学似乎不太适合(关于{Monocle的Traversal为什么用任意谓词进行过滤为什么有些尴尬的讨论,请参见my answer here)。

但是,如果您有兴趣解析和过滤大型JSON文件而不将文件的全部内容加载到内存中,则可能值得研究circe-fs2或circe-iteratee。在这两种情况下,原理都与上面的List[JsonObject]代码相同–您将大型JSON数组解码为JsonObject值流,您可以根据需要查询。