Как и большинство библиотек в Scala, json4s работает с неизменяемостью. Невозможно изменить значение внутри JValue, но вы можете создать новое с изменениями (например, копирование классов дел).
Если вы хотите изменить каждое поле «ref», вы можете использовать mapField с сопоставлением с шаблоном.
import org.json4s._
import org.json4s.native.JsonMethods._
val str = """{ "foo": [
{
"bar": {
"baz": {
"ref": "my_old_value"
}}}]}"""
val json = parse(str)
val updated = json.mapField {
case ("foo", JArray(head :: tail)) => ("foo", JArray(head.mapField {
case ("ref", JString("my_old_value")) => ("ref", JString("new value"))
case otherwise => otherwise
} :: tail))
case otherwise => otherwise
}
println(updated)
// JObject(List((foo,JArray(List(JObject(List((bar,JObject(List((baz,JObject(List((ref,JString(new value)))))))))))))))
EDIT
Я изменил метод замены, чтобы добавить поддержку массивов, теперь вы можете изменять все элементы в массиве через "foo []" или определенный элемент "foo [index]". Добавьте этот неявный класс в вашу область видимости.
implicit class JValueOps(underlying:JValue) {
object ArrayIndex {
val R = """^([^\[]+)\[(\d+)\]""".r
def unapply(str: String): Option[(String, Int)] = str match {
case R(name, index) => Option(name, index.toInt)
case _ => None
}
}
object ArrayAll {
val R = """^([^\[]+)\[\]""".r
def unapply(str: String): Option[String] = str match {
case R(name) => Option(name)
case _ => None
}
}
def replace2(l: List[String], replacement: JValue): JValue = {
def rep(l: List[String], in: JValue): JValue = {
(l, in) match {
// eg "foo[0]"
case (ArrayIndex(name, index) :: Nil, JObject(fields)) => JObject(
fields.map {
case JField(`name`, JArray(array)) if array.length > index => JField(name, JArray(array.updated(index, replacement)))
case field => field
}
)
// eg "foo[0]" "bar"
case (ArrayIndex(name, index) :: xs, JObject(fields)) => JObject(
fields.map {
case JField(`name`, JArray(array)) if array.length > index => JField(name, JArray(array.updated(index, rep(xs, array(index)))))
case field => field
}
)
// eg "foo[]"
case (ArrayAll(name) :: Nil, JObject(fields)) => JObject(
fields.map {
case JField(`name`, JArray(array)) => JField(name, JArray(array.map(_ => replacement)))
case field => field
}
)
// eg "foo[]" "bar"
case (ArrayAll(name) :: xs, JObject(fields)) => JObject(
fields.map {
case JField(`name`, JArray(array)) => JField(name, JArray(array.map( elem => rep(xs, elem))))
case field => field
}
)
// eg "foo"
case (x :: Nil, JObject(fields)) => JObject(
fields.map {
case JField(`x`, value) ⇒ JField(x, replacement)
case field ⇒ field
}
)
// eg "foo" "bar"
case (x :: xs, JObject(fields)) => JObject(
fields.map {
case JField(`x`, value) ⇒ JField(x, rep(xs, value))
case field ⇒ field
}
)
case _ => in
}
}
rep(l, underlying)
}
}
Тогда вы можете сделать
json.replace2("foo[0]" :: "bar" :: "baz" :: "ref" :: Nil, JString("new value"))