我需要以下两种方法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
。
感谢您的帮助。
答案 0 :(得分:1)
如果您想将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}
您可以将其映射到case class
,其中有一个相应的object
,其中包含一些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读取为字符串,在要更改的replaceAll
上执行key
,然后将其解析为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}]
答案 1 :(得分:0)
您必须请记住,您正在使用Json解析器,该解析器生成Json文档的抽象语法树,并将其转换为代表Json文档的JsValue。出于同样的原因,您不能更改类变量的名称(除非您重写了它),也无法将val更改为value。
但是,我看到您试图在此处将代码表示为字符串,而不是这样做:
val json:JsValue = Json.parse("""
{
"arrayObjects" : [{"id":3,"date":"1969-07-20","val":4}, {"id":4,"date":"1944-07-20","val":5}]
}
""")
如果这不是您的意图,那么您就不需要play-json。您只需操作字符串即可找到解决问题的简单方法。
答案 2 :(得分:0)
好吧,如果tmp
是String类型的(提醒:使用"""
是可编译的),则可以在其上使用.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}]
使用案例类的另一种方法
我通常希望尽可能避免String操作。那么这种方法呢:
具有两个不同的案例类。反映您提供的Json的一个。然后,第二个要转换为的案例类。
您可以使用Json read并将其转换为第一个case类。您最终获得了该课程的列表。
您可以通过它映射并删除id
(因为第二种情况下没有它);并移动val
的值;放入第二个案例类中的value
的值中。