0

I am trying to implement an insert function using the ujson library:

Here is my attempt:

import ujson.{Obj, Value}
import upickle.default._

object Example extends App {
  def r = transform(
    List(Map(
      "a" -> Map("b" -> Obj("c" -> List(1,2,3), "d" -> List(2,4,6))), 
      "e" -> Map("f" -> Obj("g" -> List(1,2,3)))))
  ).to(Value)

  def insert(j: ujson.Value, k: String, v: ujson.Value): Unit = j match {
    case a: ujson.Arr => a.arr.foreach(e => insert(e, k, v))
    case o: ujson.Obj =>
    if (o.obj.keySet contains k)  o.obj(k) = v
    else o.obj.values.foreach(e => insert(e, k, v))
    case _ => Nil
  }

  println(r)
  insert(r, "b", transform(None).to(Value))
  println(r)
}

However, this gives me output that is unchanged:

[{"a":{"b":{"c":[1,2,3],"d":[2,4,6]}},"e":{"f":{"g":[1,2,3]}}}]
[{"a":{"b":{"c":[1,2,3],"d":[2,4,6]}},"e":{"f":{"g":[1,2,3]}}}]

Given that the Value type is mutable, why does this not mutate and update the key, k, with value v for json value object r?

finite_diffidence
  • 893
  • 2
  • 11
  • 20

1 Answers1

1

You are creating Value anew every time you call r so, every changes you would make to it, are dismissed.

You create one copy when you call println(r).

Then you create a separate copy with insert(r, "b", transform(None).to(Value)), mutate it and dismiss.

Then you are creating third copy with another println(r).

If you want to refer to the same object use val instead of def.

Mateusz Kubuszok
  • 24,995
  • 4
  • 42
  • 64
  • Thanks @Mateusz, I think I made a typo - Value is mutable according this link: https://www.lihaoyi.com/post/HowtoworkwithJSONinScala.html#traversing-json I will try to fix the insert function as it seems that is where I am messing up. I think based on what you said I will have to return a leaf node in the base case here. – finite_diffidence Jun 18 '20 at 08:59