使用可变键转换 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)
}
使用 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()
我在
中获得了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)
}
使用 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()