Как преобразовать scala.some в scala.mutable.Map?

я пытаюсь написать код для маскировки вложенных полей json..

 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 }

вызов этого метода из ..

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)

я получаю сообщение об ошибке при попытке выполнить итерацию вложенного объекта json..

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

как мне рекурсивно использовать сложный вложенный объект json таким образом?


43
2

Ответы:

Ваша ошибка была

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

Есть несколько вопросов:

  1. Вы проверяете, является ли v экземпляром Map, но затем пытаетесь привести его к mutable.Map. Технически это разные типы (изменяемые и неизменяемые).
  2. Вы проверяете тип v, но затем применяете приведение к map.get(k), значение и тип которого будут отличаться от v. Метод get карты возвращает Option, отсюда и сообщение об ошибке.
  3. Благодаря стиранию типов в JVM среда выполнения не сможет определить разницу между, например, Map[String, Object] и Map[SomethingElse, Whatever] - оба будут выглядеть как Map во время выполнения. По этой причине компилятор должен был предупредить вас о вызове isInstanceOf.

Если вы выполняете комбинацию isInstanceOf / asInstanceOf, убедитесь, что операнд каждый раз один и тот же. У вас уже есть v, поэтому вам не нужно искать его во второй раз на карте. И убедитесь, что вы используете один и тот же тип для обоих вызовов instanceOf.

Исправьте это, изменив его на

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

Решено

После некоторого копания я смог решить эту проблему.

    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
  }