如何用Circe解析无方括号的JSON对象数组为List[MyScalaType]
无分隔符多JSON对象转Scala List[MyScalaType]的解决方法
你遇到的这种每行一个独立JSON对象、没有数组包裹的格式叫JSON Lines(NDJSON),常规JSON解析器会报错是因为它不符合标准JSON数组的语法规范。下面给出几种主流Scala JSON库的解决方式:
方案1:使用Circe库
Circe对JSON Lines有较好的支持,步骤如下:
- 添加sbt依赖:
libraryDependencies ++= Seq( "io.circe" %% "circe-core" % "0.14.6", "io.circe" %% "circe-generic" % "0.14.6", "io.circe" %% "circe-parser" % "0.14.6" )
- 解析代码:
import io.circe.generic.auto._ import io.circe.parser._ case class MyScalaType(jsonValue1: String, jsonValue2: List[Int]) // 你的多行JSON字符串 val jsonStr = """{ "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]} { "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]} { "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]}""" // 逐行解析并转换为List val parseResult: Either[io.circe.Error, List[MyScalaType]] = jsonStr.split("\n") .filter(_.trim.nonEmpty) // 过滤空行 .map(line => parse(line).flatMap(_.as[MyScalaType])) .toList .sequence // 处理解析结果 parseResult match { case Right(dataList) => println(dataList) case Left(error) => println(s"解析失败:${error.getMessage}") }
如果追求更高效率,可以使用Circe的jawn模块专门处理JSON Lines,只需额外添加依赖:
libraryDependencies += "io.circe" %% "circe-jawn" % "0.14.6"
然后替换解析逻辑:
import io.circe.generic.auto._ import io.circe.jawn._ val parseResult: Either[io.circe.Error, List[MyScalaType]] = parseJsonLines(jsonStr).map(_.map(_.as[MyScalaType]).sequence).flatten
方案2:使用Play JSON库
Play JSON可以通过逐行解析的方式处理:
- 添加sbt依赖:
libraryDependencies += "com.typesafe.play" %% "play-json" % "2.9.2"
- 解析代码:
import play.api.libs.json._ case class MyScalaType(jsonValue1: String, jsonValue2: List[Int]) // 自动生成JSON格式转换器 implicit val myTypeFormat: OFormat[MyScalaType] = Json.format[MyScalaType] val jsonStr = """{ "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]} { "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]} { "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]}""" // 逐行解析并收集有效结果 val validDataList: List[MyScalaType] = jsonStr.split("\n") .filter(_.trim.nonEmpty) .map(line => Json.parse(line).validate[MyScalaType]) .toList .collect { case JsSuccess(value, _) => value }
方案3:使用Jackson库
Jackson支持开启多语句解析特性来直接处理这种格式:
- 添加sbt依赖:
libraryDependencies ++= Seq( "com.fasterxml.jackson.core" % "jackson-databind" % "2.15.2", "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.15.2" )
- 解析代码:
import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.scala.DefaultScalaModule import com.fasterxml.jackson.core.JsonParser.Feature case class MyScalaType(jsonValue1: String, jsonValue2: List[Int]) // 配置Jackson支持多JSON语句 val mapper = new ObjectMapper() .registerModule(DefaultScalaModule) .enable(Feature.ALLOW_MULTI_STATEMENTS) val jsonStr = """{ "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]} { "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]} { "jsonValue1": "val1", "jsonValue2": [1, 1, 2, 2]}""" // 直接解析为List[MyScalaType] val dataList: List[MyScalaType] = mapper.readValue(jsonStr, classOf[List[MyScalaType]])
内容的提问来源于stack exchange,提问作者Дима Шестаев
相关产品推荐
相关产品推荐

