Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
按Scala circe中的字段值将json列表解析为两种列表类型_Json_Scala_List_Parsing_Circe - Fatal编程技术网

按Scala circe中的字段值将json列表解析为两种列表类型

按Scala circe中的字段值将json列表解析为两种列表类型,json,scala,list,parsing,circe,Json,Scala,List,Parsing,Circe,我得到了(示例)json: 元素列表中始终包含两种可能的对象: 输入“nodeX”和属性:id、a和b 键入“nodeY”和属性:id和c 我想得到给定类的两个列表: case class NodeX(val id:Long, val a:Long, val b:Long) case class NodeY(val id:Long, val c:List[String]) 我尝试了circe(Scala库)将此json解析为类: case class Element(val 'type':

我得到了(示例)json:

元素列表中始终包含两种可能的对象:

  • 输入“nodeX”和属性:id、a和b
  • 键入“nodeY”和属性:id和c
我想得到给定类的两个列表:

case class NodeX(val id:Long, val a:Long, val b:Long)
case class NodeY(val id:Long, val c:List[String])
我尝试了circe(Scala库)将此json解析为类:

case class Element(val 'type':String, val id:Long, val a:Option[Long],val b:Option[Long], val c:Option[List[String]])
case class MyJson(val version:Double, val author:String, val elements:List[Element])
但不幸的是,我得到了带有可选字段的objects元素列表。
目前,我正在使用此解决方案:

val elements = // MyJson.elements
for (elem <- elements)
    elem match {
      case Element("nodeX", _,_,_,_) => //here convert to NodeX and add to list List[NodeX]
      case Element("nodeY", _,_,_,_) => //here convert to NodeY and add to list List[NodeY]
    }
val elements=//MyJson.elements
for(elem//此处转换为NodeX并添加到列表[NodeX]
case元素(“nodeY”,“nodeY”,“nodeY”,“nodeY”,“nodeY)=>//此处转换为nodeY并添加到列表[nodeY]
}
我正在寻找更好、更快的解决方案,因为这个json中的列表包含的元素从不少于70k


提前感谢:)

如果允许您将
NodeX
NodeY
类定义为具有密封特征的ADT,则可以轻松解析

将库添加到依赖项列表中

libraryDependencies ++= Seq(
  "com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-core" % "0.29.2" % Compile, 
  "com.github.plokhotnyuk.jsoniter-scala" %% "jsoniter-scala-macros" % "0.29.2" % Provided // required only in compile-time
)
定义您的案例类别:

sealed trait Node
final case class NodeX(val id:Long, val a:Long, val b:Long) extends Node
final case class NodeY(val id:Long, val c:List[String]) extends Node

case class MyJson(val version:Double, val author:String, val elements:List[Node])
为根案例类生成编解码器并使用它

import java.io._
import com.github.plokhotnyuk.jsoniter_scala.macros._
import com.github.plokhotnyuk.jsoniter_scala.core._

val myJsonCodec = JsonCodecMaker.make[MyJson](CodecMakerConfig())

val myJson = {
  val fin = new FileInputStream("/tmp/my.json")
  try readFromStream(codec, fin)
  finally fin.close()
}

另一种方法是dynamicScala in
Circe
+
Monocle
,它为动态语言提供了不安全的灵活性:

libraryDependencies += "io.circe" %% "circe-optics" % circeVersion
import io.circe.optics.JsonPath._
import io.circe.parser

val json = parser.parse(jsonString).right.get

case class NodeX(val id:Long, val a:Long, val b:Long)
case class NodeY(val id:Long, val c:List[String]) 

val nodexs = root.elements.each
    .filter(root.`type`.string.getOption(_).contains("nodeX"))
    .as[NodeX].getAll(json)
//res: List[NodeX] = List(NodeX(1L, 1L, 2L), NodeX(2L, 1L, 2L))
val nodeys = root.elements.each
    .filter(root.`type`.string.getOption(_).contains("nodeY"))
    .as[NodeY].getAll(json)
//res: List[NodeY] = List(NodeY(3L, List("qaz", "wsx")))

我相信,circe generic可以做到安德烈·普洛霍特纽克回答中所描述的同样的事情。

你是如何解码的?半自动派生解码器?@michaJlS我用
decode[MyJson](json)
解码,我对circe没有经验。我读过关于半自动派生解码器的文章,但我不知道它的用法。你必须展示你的解析代码,并告诉你从这个json中得到了什么。
libraryDependencies += "io.circe" %% "circe-optics" % circeVersion
import io.circe.optics.JsonPath._
import io.circe.parser

val json = parser.parse(jsonString).right.get

case class NodeX(val id:Long, val a:Long, val b:Long)
case class NodeY(val id:Long, val c:List[String]) 

val nodexs = root.elements.each
    .filter(root.`type`.string.getOption(_).contains("nodeX"))
    .as[NodeX].getAll(json)
//res: List[NodeX] = List(NodeX(1L, 1L, 2L), NodeX(2L, 1L, 2L))
val nodeys = root.elements.each
    .filter(root.`type`.string.getOption(_).contains("nodeY"))
    .as[NodeY].getAll(json)
//res: List[NodeY] = List(NodeY(3L, List("qaz", "wsx")))