Scala中基于case class的嵌套JSON转TSV优雅实现方法问询
在Scala中优雅转换嵌套Case Class JSON到TSV的方案
当然有优雅的解决办法!针对你这种包含嵌套case class和List类型的场景,我们可以通过JSON解析→结构扁平化→TSV生成这三步来实现,下面一步步来拆解:
1. 准备依赖:用Circe处理JSON解析
Circe是Scala生态里处理JSON非常顺手的库,它能自动为case class生成编解码器,省去手动写解析逻辑的麻烦。首先在你的build.sbt里添加依赖:
libraryDependencies ++= Seq( "io.circe" %% "circe-core" % "0.14.6", "io.circe" %% "circe-generic" % "0.14.6", "io.circe" %% "circe-parser" % "0.14.6" )
2. 解析JSON到Case Class实例
先定义好你的case class(注意修正示例里的小细节:pid在JSON里是数值类型,case class里要对应Int,不能是字符串):
case class Product(pname: Option[String], pid: Int, pDetail: Option[PDetail]) case class PDetail(pbatchNo: List[Int])
然后用Circe解析JSON字符串:
import io.circe.generic.auto._, io.circe.parser.decode // 你的示例JSON(修正了pid的类型,从字符串改成数值) val jsonStr = """{ "pname" : "pnameValue", "pid" : 123, "pDetail": { "pbatchNo" : [1,2] } }""" // 解码成Product实例,返回Either类型处理可能的解析错误 val productResult: Either[io.circe.Error, Product] = decode[Product](jsonStr)
3. 扁平化嵌套结构,生成TSV行
接下来需要把嵌套的PDetail和里面的List[Int]扁平化成TSV的列。我们写一个函数来处理扁平化逻辑,同时处理Option的空值情况:
def flattenProduct(product: Product): List[String] = { // 基础字段:处理Option,空值用空字符串填充 val baseColumns = List( product.pname.getOrElse(""), product.pid.toString ) // 提取嵌套的batchNo列表,空的话返回空列表 val batchColumns = product.pDetail.map(_.pbatchNo.map(_.toString)).getOrElse(Nil) // 合并基础字段和batch字段 baseColumns ++ batchColumns }
最后把扁平化后的列表用制表符拼接成TSV行:
productResult match { case Right(product) => val tsvLine = flattenProduct(product).mkString("\t") println(tsvLine) // 输出:pnameValue 123 1 2 case Left(error) => println(s"解析JSON出错:${error.getMessage}") }
边界情况处理说明
- 如果
pname是None,会填充空字符串到对应列 - 如果
pDetail是None,则不会有batchNo的列 - 如果
pbatchNo是空List,同样不会添加额外列
如果你的场景中pbatchNo的长度不固定(比如有时2个元素,有时3个),需要保证所有TSV行的列数一致的话,可以先收集所有行的扁平化结果,找到最大列数,然后对不足的行补空字符串。
内容的提问来源于stack exchange,提问作者Avenger
相关产品推荐
相关产品推荐

