将复杂的Scala模型/对象转换为Map[String,Any]

c0vxltue  于 5个月前  发布在  Scala
关注(0)|答案(1)|浏览(80)

我试图将一个复杂的Scala模型/对象转换为Map[String,Any] Map的“值”可以是Map[String,Any]或String,Boolean,Int等。我在实际的模型中有多个层次的嵌套。我找不到一个干净的方法将任何给定的具有复杂嵌套的模型转换为Map[String,Any]
我尝试了下面的方法将模型转换为Map,但下面的方法不能正确地将内部模型转换为Map。
例如

def toMapWithOption[TCaseClass <: Product](tCaseClass: TCaseClass): Map[String, Any] = {
    tCaseClass.getClass.getDeclaredFields
      .map(_.getName)
      .zip(tCaseClass.productIterator.toIndexedSeq)
      .toSeq
      .toMap
      .filter { attribute =>
        attribute._2 match {
          case option: Option[Any] => option.isDefined
          case _                   => true
        }
      }
      .map { attribute =>
        attribute._2 match {
          case option: Option[Any] => attribute._1 -> option.get
          case _                   => attribute
        }
      }
  }

val contact_details = new ContactDetails(Some("00236485766"), "919347439483", "[email protected]")
val address = new Address("12B", "sample street", "Some_State", Some(contact_details))
val person = new Person(1, "John", address)
print(toMapWithOption(person));

case class Person(id: Int, name: String, address: Address)
case class ContactDetails(house_phone: Option[String], mobile_phone: String, email: String)
case class Address(house_number: String, street: String, state: String, contact_details: Option[ContactDetails])

字符串
实际响应:Map(id -> 1, name -> John, address -> Address(12B,sample street,Some_State,Some(ContactDetails(Some(00236485766),919347439483, [[email protected]](https://stackoverflow.com/cdn-cgi/l/email-protection) ))))
预期响应:Map(id -> 1, name -> John, address -> Map(house_number -> 12B, street -> sample street, state -> Some_State, contact_details -> Map(house_phone -> 00236485766, mobile_phone -> 919347439483, email -> [[email protected]](https://stackoverflow.com/cdn-cgi/l/email-protection) )))
仅供参考:没有任何嵌套的模型可以很好地使用上述方法进行转换

mcdcgff0

mcdcgff01#

如果值也是一个Product,您希望递归地将嵌套对象转换为Map。
所以你需要在你的map块中再次调用toMapWithOption。

.map { attribute =>
          attribute._2 match {
            case Some(value) if(value.isInstanceOf[TCaseClass]) => attribute._1 -> toMapWithOption(value.asInstanceOf[TCaseClass])
            case Some(value) => attribute._1 -> value
            case t: TCaseClass => attribute._1 -> toMapWithOption(t)
            case t => attribute._1 -> t
          }
        }

字符串

相关问题