使用可变键转换 Json

Convert Json with variable keys

我在

中获得了JSON
 {
    "segment": {
        "134": "34",
        "154": "342"
    }
}

我想做的就是将键映射为值,即将其转换为类似

的格式
    {
    "segment ": [{
        "segmentationStrategyId ": 134,
        "segmentID ": 34
    }, {
        "segmentationStrategyId ": 154,
        "segmentID ": 342
    }]
}

尝试使用 json4s 解析器,但由于键有差异,我无法将其映射到大小写 class。

我不熟悉 json4s 但很快就写出来了,可能会有帮助:

import org.json4s._
import org.json4s.native.JsonMethods._

case class Segment(segmentationStrategyId: Int, segmentId: Int)

object Test {
  implicit val formats: DefaultFormats.type = DefaultFormats
  val json: String =
    """
      | {
      |    "segment": {
      |        "134": "34",
      |        "154": "342"
      |    }
      |}
    """.stripMargin

  def main(args: Array[String]): Unit = {
    val originalSegments = for {
      JObject(o) <- parse(json)
      JField("segment", JObject(segment))  <- o
    } yield segment

    val originalSegment = originalSegments.head
    val newSegments = originalSegment.map(
      s => Segment(s._1.toInt, s._2.extract[String].toInt)
    )
    println(newSegments)
  }
}

打印出来

List(Segment(134,34), Segment(154,342))

所以您现在有一个案例列表 类,您应该能够将其转化为您的 JSON

您可以使用spary.json转换json。 如果您使用 SBT,您可以将 spray-json 包含在您的项目中

libraryDependencies += "io.spray" %%  "spray-json" % "1.3.3"

为您的输入和输出定义 case class

case class InputJson(segment: Map[String, String])
case class OutputSegment(segmentationStrategyId: Int, segmentId: Int)
case class OutputJson(segment: List[OutputSegment])

通过将 case class 转换为 json 并将 json 转换为 case class

来定义协议
import spray.json._
object MyProtocol extends DefaultJsonProtocol {
  implicit val inputJsonFormat = jsonFormat1(InputJson.apply)
  implicit val outputSegmentFormat = jsonFormat2(OutputSegment.apply)
  implicit val outputJsonFormat = jsonFormat1(OutputJson.apply)
}

输入json:

val jsonString: String =
    """{
      |    "segment": {
      |        "134": "34",
      |        "154": "342"
      |    }
      |}""".stripMargin

将jsonString解析为JsValue

val jsonVal: JsValue = jsonString.parseJson

JsValue 转换为 Case Class

val jsonInput: InputJson = jsonVal.convertTo[InputJson]

现在,您可以将 Map[String,String] 段映射为 OutputSegment 格式。

val outputSegments: List[OutputSegment] = jsonInput.segment.flatMap {
    case (key, value) => Try(OutputSegment(key.toInt, value.toInt)).toOption
  }.toList

创建 OutputJson 并获得等效的 Json 字符串。

val outputJson: String = OutputJson(outputSegments).toJson.prettyPrint

输出Json字符串:

{
  "segment": [{
    "segmentationStrategyId": 134,
    "segmentId": 34
  }, {
    "segmentationStrategyId": 154,
    "segmentId": 342
  }]
}

最终完整代码示例:

import spray.json._
import scala.util.Try

object Test
  extends App {

  // case class
  case class InputJson(segment: Map[String, String])
  case class OutputSegment(segmentationStrategyId: Int, segmentId: Int)
  case class OutputJson(segment: List[OutputSegment])

  // protocol for json conversion
  object MyProtocol extends DefaultJsonProtocol {
    implicit val inputJsonFormat = jsonFormat1(InputJson.apply)
    implicit val outputSegmentFormat = jsonFormat2(OutputSegment.apply)
    implicit val outputJsonFormat = jsonFormat1(OutputJson.apply)
  }

  // input json
  val jsonString: String =
    """{
      |    "segment": {
      |        "134": "34",
      |        "154": "342"
      |    }
      |}""".stripMargin

  import MyProtocol._

  val jsonVal: JsValue = jsonString.parseJson

  val jsonInput: InputJson = jsonVal.convertTo[InputJson]

  val outputSegments: List[OutputSegment] = jsonInput.segment.flatMap {
    case (key, value) => Try(OutputSegment(key.toInt, value.toInt)).toOption
  }.toList

  val outputJson: String = OutputJson(outputSegments).toJson.prettyPrint

  println(outputJson)
}

参考link:https://github.com/spray/spray-json

使用 jsoniter-scala 更容易和更快。

添加库依赖:

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
)

定义输入和输出的数据结构JSON:

case class Input(segment: mutable.LinkedHashMap[Int, Int])
case class OutputSegment(segmentationStrategyId: Int, segmentID: Int)
case class Output(segment: List[OutputSegment])

为您的根本案例生成编解码器 类:

import com.github.plokhotnyuk.jsoniter_scala.macros._
import com.github.plokhotnyuk.jsoniter_scala.core._
implicit val inCodec: JsonValueCodec[Input] = JsonCodecMaker.make[Input](CodecMakerConfig())
implicit val outCodec: JsonValueCodec[Output] = JsonCodecMaker.make[Output](CodecMakerConfig())

读取输入,转换为输出并序列化:

val fis = new FileInputStream("/tmp/input.json")
val input = try readFromStream(fis) finally fis.close()
val output = Output(input.segment.map(kv => OutputSegment(kv._1, kv._2)))
val fos = new FileOutputStream("/tmp/output.json")
try writeToStream(output, fos) finally fos.close()