递归转换游戏中的 json



我需要通过两种方式转换以下json

  1. val重命名为值
  2. 删除id字段。

我的代码

val tmp=new String ("[{"id":3,"date":"1969-07-20","val":4}, {"id":4,"date":"1944-07-20","val":5}]")

我想过使用prunecopyValue变换,但我知道它们不适用于递归JsPath

我感谢这方面的帮助。

如果你想将你的JSON解析为纯字符串,你可以用replace做一些简单的事情:

val tmp= """[{"id":3,"date":"1969-07-20","val":4}, {"id":4,"date":"1944-07-20","val":5}]"""
tmp.replaceAll(""val"", ""value"").replaceAll(""id"[^,]*,", "")
// [{"date":"1969-07-20","value":4}, {"date":"1944-07-20","value":5}]

这并不理想,并且只有在id后跟逗号时才有效,但您可以得到图片。您可以使用replaceAll进行正则表达式匹配,并将找到的内容替换为预期结果。


一个更好的首选方法(在我看来(是将 JSON 作为 JsObject 进行操作,并使用案例类来存储它。

假设您有以下 JSON:

val jamesAsJson: JsObject = Json.obj("name" -> "james", "age" -> 34)
// jamesAsJson: play.api.libs.json.JsObject = {"name":"james","age":34}

您可以将其映射到具有相应objectcase class其中包含一些 JSON-y 魔法,如下所示:

case class Person(name: String, age: Int)
object Person {
// This is magic. Don't worry about how it works
implicit val format: OFormat[Person] = Json.format[Person] 
}
// I know this JSON matches my case class but if you're unsure,
// you should use getOrElse otherwise it'll throw an Exception
val jamesAsPerson = jamesAsJson.validate[Person].get
// jamesAsPerson: Person = Person(james,34)

接下来,您可以使用所需的新字段创建另一个案例类,并将此旧数据弹出到新案例类中:

case class AltPerson(fullName: String, age: Int)
object AltPerson {
implicit val format: OFormat[AltPerson] = Json.format[AltPerson]
}
val jamesAsAltPerson = AltPerson(jamesAsPerson.name, jamesAsPerson.age)
val jamesAsAltJson = Json.toJson(jamesAsAltPerson)
// jamesAsAltJson: play.api.libs.json.JsObject = {"fullName":"james","age":34}

因此,这是更改字段名称的一种方法。在 Scala 中,有数百种方法可以做某事;这只是其中之一。另一种方法是将 JSON 读取为字符串,对要更改的key执行replaceAll,然后将其解析为 JSON 对象以供下一阶段使用......

一旦你对你的JSON键感到满意,操作JsObject字段就非常容易了。使用我们之前的示例,它就像这样简单:

jamesAsAltJson - "age"
// res0: play.api.libs.json.JsObject = {"fullName":"james"}

只要您愿意,这可以进行:

jamesAsAltJson - "age" + ("height" -> JsString("234")) + ("eye colour" -> JsString("blue"))
// res1: play.api.libs.json.JsObject = {"fullName":"james","height":"234","eye colour":"blue"}

最后,您的示例包含一个数组,它使事情变得更加复杂,但以下是如何使用Scala Play的JSON解析器进行操作:

import play.api.libs.json._
// import play.api.libs.json._
val tmp = """[{"id":3,"date":"1969-07-20","val":4}, {"id":4,"date":"1944-07-20","val":5}]"""
// tmp: String = [{"id":3,"date":"1969-07-20","val":4}, {"id":4,"date":"1944-07-20","val":5}]
case class Tmp(id: Int, date: String, `val`: Int)
// defined class Tmp
object Tmp {
implicit val format: OFormat[Tmp] = Json.format[Tmp]
}
// defined module Tmp
val tmpAsClass = Json.parse(tmp).as[Seq[Tmp]]
// tmpAsClass: Seq[Tmp] = List(Tmp(3,1969-07-20,4), Tmp(4,1944-07-20,5))
case class NewTmp(id: Int, date: String, value: Int)
// defined class NewTmp
object NewTmp {
implicit val format: OFormat[NewTmp] = Json.format[NewTmp]
}
// defined module NewTmp
val newTmp = tmpAsClass.map(x => NewTmp(x.id, x.date, x.`val`))
// newTmp: Seq[NewTmp] = List(NewTmp(3,1969-07-20,4), NewTmp(4,1944-07-20,5))
// JsArray is annoying to work with so I've used List[JsObject] instead
val jsonList: List[JsObject] = Json.toJson(newTmp).as[List[JsObject]].map(_ - "id")
// jsonList: List[play.api.libs.json.JsObject] = List({"date":"1969-07-20","value":4}, {"date":"1944-07-20","value":5})
Json.toJson(jsonList)
// res0: play.api.libs.json.JsValue = [{"date":"1969-07-20","value":4},{"date":"1944-07-20","value":5}]

您必须记住,您正在使用一个 Json 解析器,该解析器生成 Json 文档的抽象语法树,并转换为表示 Json 文档的 JsValue。出于同样的原因,你不能改变类的变量的名称(除非你重写它(,你也不能将val更改为值。

但是,我看到您正在尝试在此处将您的代码表示为字符串,而不是这样做:

val json:JsValue = Json.parse("""
{
"arrayObjects" : [{"id":3,"date":"1969-07-20","val":4}, {"id":4,"date":"1944-07-20","val":5}]
} 
""") 

如果这不是你的意图,那么你不需要play-json。您可以通过简单地操作字符串来找到解决问题的简单方法。

好的,如果tmp是字符串类型(提醒:使用"""进行编译(,您可以对其使用.replace

scala> val tmp=new String ("""[{"id":3,"date":"1969-07-20","val":4}, {"id":4,"date":"1944-07-20","val":5}]""")
tmp: String = [{"id":3,"date":"1969-07-20","val":4}, {"id":4,"date":"1944-07-20","val":5}]
scala> tmp.replace("val","whatever") 
res0: String = [{"id":3,"date":"1969-07-20","whatever":4}, {"id":4,"date":"1944-07-20","whatever":5}]

使用案例类的另一种方法

我通常喜欢尽可能避免字符串操作。这种方法怎么样:

  1. 有两个不同的事例类。一个镜像您提供的 Json。其次是要转换为的案例类。

  2. 使用 Json 读取并将其转换为第一个案例类。你最终会得到这个类的列表。

  3. 你映射它并删除id(因为第二个事例类没有它(;并将val的值移动到第二个事例类中value的值中。

最新更新