You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何用Circe解析无方括号的JSON对象数组为List[MyScalaType]

无分隔符多JSON对象转Scala List[MyScalaType]的解决方法

你遇到的这种每行一个独立JSON对象、没有数组包裹的格式叫JSON Lines(NDJSON),常规JSON解析器会报错是因为它不符合标准JSON数组的语法规范。下面给出几种主流Scala JSON库的解决方式:

方案1:使用Circe库

Circe对JSON Lines有较好的支持,步骤如下:

  1. 添加sbt依赖:
libraryDependencies ++= Seq(
  "io.circe" %% "circe-core" % "0.14.6",
  "io.circe" %% "circe-generic" % "0.14.6",
  "io.circe" %% "circe-parser" % "0.14.6"
)
  1. 解析代码:
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可以通过逐行解析的方式处理:

  1. 添加sbt依赖:
libraryDependencies += "com.typesafe.play" %% "play-json" % "2.9.2"
  1. 解析代码:
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支持开启多语句解析特性来直接处理这种格式:

  1. 添加sbt依赖:
libraryDependencies ++= Seq(
  "com.fasterxml.jackson.core" % "jackson-databind" % "2.15.2",
  "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.15.2"
)
  1. 解析代码:
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,提问作者Дима Шестаев

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 05:34:55