У меня есть два объекта JSON (с одинаковой структурой):
Первый
json1 = {a: {b: [{c: "x" , d: val1}, {c: "y" , d: val2}]} }
а второй
json2 = {a: {b: [{c: "x" , d: val3}, {c: "y" , d: val4}]} }
есть ли способ объединить эти два объекта, чтобы получить один объект (если значение c совпадает, тогда суммируйте значения d):
result = {a: { b: [{c: "x", d: (val1+val3) } , {c: "y", d: (val2+val4) }] } }
если
json2 = {a: {b: [{c: "y" , d: val3}, {c: "z" , d: val4}]} }
result = {a: { b: [{c: "x" , d: val1} , {c: "y", d: (val2+val4+val3)},{c: "z" , d: val4}] } }
Есть ли какой-нибудь встроенный метод, чтобы сделать этот трюк. Спасибо.
Почему вы обрабатываете JSON, если не знаете ключей? Что вы пытаетесь с этим делать? Я бы рекомендовал не трогать данные, если вы хотя бы не знаете, как они устроены.
Обновленный вопрос. Пожалуйста, предложите @JamesWhiteley
@Rumoku Извините, но это не дубликат отмеченного вопроса, так как схема для обоих объектов json одинакова, необходимо объединить значения. Пробовал с глубоким слиянием, но он возвращает второй json
Правда! Но на самом деле вы не объединяете значения (например, c имеет значение «x» на выходе, такое же, как и исходное). Я думаю, вы преобразовали его в классы scala и каким-то образом реализовали код для «слияния» или «суммирования» этих классов.





Если вы знаете свою структуру JSON, один из способов сделать это - превратить их в классы case и сравнить их. Вот способ, который я нашел (который ни в коем случае не оптимизирован):
//Going by your JSON structure of {"a": {"b": [{"c": String , "d": Int}]}}
import play.api.libs.json.{Json, OFormat}
case class A(a: B)
object A{implicit val format: OFormat[A] = Json.format[A]}
case class B(b: Seq[C])
object B{implicit val format: OFormat[B] = Json.format[B]}
case class C(c: Option[String], d: Option[Int])
object C{implicit val format: OFormat[C] = Json.format[C]}
val json1 = Json.parse("""{"a": {"b": [{"c": "x" , "d": 1}, {"c": "y" , "d": 2}]}}""").as[A]
val json2 = Json.parse("""{"a": {"b": [{"c": "x" , "d": 3}, {"c": "y" , "d": 4}]}}""").as[A]
val cSeq: Seq[C] = {
(json1.a.b zip json2.a.b) map {
// List((C(Some(x),Some(1)),C(Some(x),Some(3))), (C(Some(y),Some(2)),C(Some(y),Some(4))))
c =>
val (c1, c2) = c
// assign a value to each element of the pairs
val BLANK_C = C(None, None)
if (c1.c.get == c2.c.get) C(c1.c, Some(c1.d.get + c2.d.get)) else BLANK_C
// if the "c" keys match, add the "d" keys. If not, return an empty C model
// will need to handle if get fails (ie None instead of Some(whatever))
}
}
val json3 = Json.toJson(A(B(cSeq)))
println(json3)
// {"a":{"b":[{"c":"x","d":4},{"c":"y","d":6}]}}
В настоящее время, если части не совпадают, возвращается пустой объект. Вы не указали, что вы хотите, чтобы произошло, когда они не совпадают, поэтому я оставлю это на ваше усмотрение.
Большое спасибо за ваш ответ, это действительно помогает. Немного обновлен вопрос, т.е. элементы должны добавляться независимо от их порядка в последовательности. Есть ли способ это сделать. Новичок в scala, не очень о нем представляю.
Возможный дубликат Как объединить JsValue с JsObject на плоском уровне