Home > Blockchain >  How to convert scala.some to scala.mutable.Map?
How to convert scala.some to scala.mutable.Map?

Time:05-13

i am trying to write code to mask nested json fields..

 def maskRecursively(map :mutable.Map[String,Object]):mutable.Map[String,Object] ={
val maskColumns = PII_Data.getPIIData()
for((k,v) <- map){
  if(v.isInstanceOf[Map[String,Object]]){
    maskRecursively(map.get(k).asInstanceOf[mutable.Map[String,Object]])
  }else if(v.isInstanceOf[List[Object]]) {

  } else {
    if(maskColumns.contains(k)){map =(k->"*****")}
  }

}


map }

calling this method from ..

val mapper = new ObjectMapper()
    mapper.registerModule(DefaultScalaModule)
    val result = mapper.readValue(jsonStr, classOf[ java.util.Map[String,Object] ])
    import scala.collection.JavaConverters._
    val myScalaMap = result.asScala
    maskRecursively(result.asScala)

i am getting error while trying to iterate a nested json object ..

Cannot cast value of type 'scala.Some' to type 'scala.collection.mutable.Map'

how do i recurse a complex nested json object this way ?

CodePudding user response:

Your mistake was

if(v.isInstanceOf[Map[String,Object]]){
    maskRecursively(map.get(k).asInstanceOf[mutable.Map[String,Object]])

There are a few issues:

  1. You check if v is an instance of Map, but then attempt to cast it to mutable.Map. They are technically different types (mutable vs immutable).
  2. You check the type of v, but then apply the cast to map.get(k), which is going to be a different value and type from v. A map's get method returns an Option, hence the error message.
  3. Thanks to type erasure on the JVM, the runtime won't be able to tell the difference between e.g. a Map[String, Object] and a Map[SomethingElse, Whatever] - both will just look like Map at runtime. The compiler should have given you a warning about the isInstanceOf call for this reason.

If you do an isInstanceOf / asInstanceOf combo, make sure the operand is the same each time. You already have v, so you don't need to look it up a second time from the map. And make sure you use the same type on both instanceOf calls.

Fix this by changing it to

if(v.isInstanceOf[mutable.Map[_, _]]){
    maskRecursively(v.asInstanceOf[mutable.Map[String,Object]])

CodePudding user response:

After some digging , i was able to solve this..

    def maskJson(jsonStr: String): String = {
    implicit val formats = org.json4s.DefaultFormats
    val mapper = new ObjectMapper()
    mapper.registerModule(DefaultScalaModule)
    val result = mapper.readValue(jsonStr, classOf[Map[String, Object]])
    val maskedJson = maskRecursively(result)
    mapper.writeValueAsString(maskedJson)

  }


  def maskRecursively(map: Map[String, Object]): collection.mutable.Map[String, Object] = {
    val mutable = collection.mutable.Map[String, Object]()
    val maskColumns = PII_Data.getJsonPIIFields()
    for ((k, v) <- map) {
      if (v.isInstanceOf[Map[String, Object]]) {
        mutable  = k -> maskRecursively(v.asInstanceOf[Map[String, Object]])
      } else if (v.isInstanceOf[List[Object]]) {
        val list = v.asInstanceOf[List[Map[String, Object]]].map(i => maskRecursively(i)).toList
        mutable  = k -> list
      } else {
        if (maskColumns.contains(k)) {
          mutable  = (k -> "*****")
        }
        else {
          mutable  = k -> v
        }
      }
    }
    mutable
  }
  • Related