使用变量键

时间:2018-02-25 19:15:57

标签: scala json4s

我在

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

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

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

尝试使用json4s解析器,但作为键是diff我无法将其映射到case类。

3 个答案:

答案 0 :(得分:3)

您可以使用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类转换为json和json到case类

来定义协议
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

将json String解析为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 String。

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

输出Json String:

{
  "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)
}

参考链接:https://github.com/spray/spray-json

答案 1 :(得分:2)

我对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

答案 2 :(得分:0)

使用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()