【问题标题】:Scala Reads: How to handle Option[Map[String, Any]]Scala 阅读:如何处理 Option[Map[String, Any]]
【发布时间】:2014-09-09 09:30:38
【问题描述】:

我无法理解为什么它会在以下行引发错误:

val anyReads = Reads[Any](m => metaValueToJsValue(m))

错误信息:type mismatch; found : play.api.libs.json.JsValue required: play.api.libs.json.JsResult[Any] Note: implicit value readsMap is not applicable here because it comes after the application point and it lacks an explicit result type

我在下面粘贴了我的代码。 任何帮助表示赞赏!谢谢!

import play.api.libs.json._
import play.api.libs.json.util._
import play.api.libs.functional.syntax._

case class TempClass(
  metaValue: Option[Map[String, Any]])

object TempClass {

  val anyReads = Reads[Any](m => metaValueToJsValue(m))

  def metaValueToJsValue(m: Any): JsValue = {
    m match {
      case s: String => JsString(s)
      case n: Int => JsNumber(n): JsValue
      case n: Long => JsNumber(n): JsValue
      case n: Double => JsNumber(n): JsValue
      case n: BigDecimal => JsNumber(n): JsValue
      case b: Boolean => JsBoolean(b)
      case l: Seq[Any] => JsArray(l.map(metaValueToJsValue)): JsValue
    }
  }

  implicit val readsMap = Reads[Map[String, Any]](m => Reads.mapReads[Any](anyReads).reads(m))
  implicit val reads = Json.reads[TempClass]
}

【问题讨论】:

  • 您需要将类型归因于您的隐式 val。参考stackoverflow.com/questions/2731185/…
  • 隐式 val readsMap: Reads[Map[String, Any]] = Reads[Map[String, Any]](m => Reads.mapReads[Any](anyReads).reads(m))隐式 val 读取:Reads[TempClass] = Json.reads[TempClass] 虽然上面没有效果:/我做错了吗?

标签: json scala


【解决方案1】:

看起来你在这里做错了什么。

val anyReads = Reads[Any](m => metaValueToJsValue(m))

Reads 将接受JsValue 并返回JsResult[A] 的函数作为参数,但您传递的是一个接受Any 并返回JsValue 的函数。

所以def metaValueToJsValue(m: Any): JsValue = {的签名应该是这样的

def metaValueToJsValue(m: JsValue): JsResult[Any] = {

注意:通常框架不为多态映射 (Map[String, Any]) 提供默认序列化程序,因为 Any 可以再次成为映射/列表并且可以进入任何级别。所以应用程序应该知道传入的 JSON 结构。在下面的代码中,我做了一个级别的假设,即 Json 属性值本身不能是 Json 对象/数组

请参考以下代码:

object TempClass {

    implicit val readsMap = Reads[Map[String, Any]](m => Reads.mapReads[Any](anyReads).reads(m))
    implicit val reads = Json.reads[TempClass]
    val anyReads = Reads[Any](m => metaValueToJsValue(m))

    def metaValueToJsValue(m: JsValue): JsResult[Any] = {
      m match {
        case JsObject(m) => {
          val m1 = m.map(f => (f._1, convert(f._2))).toMap
          JsSuccess(m1)
        }
        case JsString(s) => JsSuccess(s)
        case JsNumber(n) => JsSuccess(n)
        case JsBoolean(b) => JsSuccess(b)
        case JsArray(arr) => {
          val list = arr.map(convert)
          JsSuccess(list)
        }
      }
    }

    def convert(m: JsValue): Any = {
      m match {
        case JsString(s) => s
        case JsNumber(n) => n
        case JsBoolean(b) => b
      }
    }

    def main(args: Array[String]) {
      val json = """{"metaValue" : {"name":"John", "age":30}}"""
      val tmpClass = Json.parse(json).as[TempClass]
      println(tmpClass)
    }

  }

【讨论】:

  • 抱歉,您能向我解释一下以下内容吗?对象中的主要方法的目的是什么,为什么我不再能够解析这个类? val tempClass = Json.parse(response.body).as[TempClass]
  • 我添加了 main 方法只是为了展示如何从 json 字符串中解析 TempClass。您可以删除该方法。此外,您还需要通过在方法中匹配更多案例(如 JsNull、JsUndefined 等)来增强此代码。
【解决方案2】:

我发现最好将 JsObject 放在最后,否则所有东西都可以作为 JsObject 进行匹配。也不需要转换。一个更好的解决方案(虽然不完整)如下:

object ContractDetails {
  implicit val readsMap = Reads[Map[String, Any]](m => Reads.mapReads[Any](anyReads).reads(m))
  implicit val reads = Json.reads[ContractDetails]
  val anyReads = Reads[Any](m => metaValueToJsValue(m))

  def metaValueToJsValue(m: JsValue): JsResult[Any] = {
    m match {
      case JsBoolean(b) => JsSuccess(b)
      case JsNumber(n) => JsSuccess(n)
      case JsString(s) => JsSuccess(s)
      case JsArray(arr) => {
        val list = arr.map(metaValueToJsValue)
        JsSuccess(list)
      }
      case JsNull => JsSuccess(null)
      //case x => JsFailure(x.toString())
      case JsObject(m) => {
        val m1 = m.map(f => (f._1, metaValueToJsValue(f._2))).toMap
        JsSuccess(m1)
      }
    }
  }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-05-18
    • 1970-01-01
    • 2019-02-13
    • 2021-04-04
    • 2015-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多