我需要通过两种方式转换以下json
:
- 将
val
重命名为值 - 删除
id
字段。
我的代码
val tmp=new String ("[{"id":3,"date":"1969-07-20","val":4}, {"id":4,"date":"1944-07-20","val":5}]")
我想过使用prune
和copyValue
变换,但我知道它们不适用于递归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}
您可以将其映射到具有相应object
的case 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}]
使用案例类的另一种方法
我通常喜欢尽可能避免字符串操作。这种方法怎么样:
有两个不同的事例类。一个镜像您提供的 Json。其次是要转换为的案例类。
使用 Json 读取并将其转换为第一个案例类。你最终会得到这个类的列表。
你映射它并删除
id
(因为第二个事例类没有它(;并将val
的值移动到第二个事例类中value
的值中。