【问题标题】:Deserializing case classes with Map[String,Any] properties with lift-json使用 Lift-json 反序列化具有 Map[String,Any] 属性的案例类
【发布时间】:2011-06-30 09:26:27
【问题描述】:

几天来,我一直在努力解决通过 lift-json 应该很简单的事情:将地图序列化为 JSON。

我知道,我知道——“根对象还不能是 List 或 Map”——但我现在愿意封装一个案例类,但我仍然无法让它工作。感谢一些堆栈溢出帮助,我已经进行了序列化,但我无法从字符串中反序列化它。我收到诸如“_ 没有可用值”和“没有关于类型的信息”之类的错误。

网络上还有其他较早的帖子表明类型提示是答案,但这只会导致不同的错误,例如“不知道如何反序列化 __。”

对于 Scala 2.8.0 和 Lift 2.2:

import net.liftweb.json._
import net.liftweb.json.Serialization.{read, write}

case class MapWrap(data: Map[String, Any])

object Scaffold {
    def main(args: Array[String]) {

        implicit val formats = Serialization.formats(NoTypeHints)
        //implicit val formats = Serialization.formats(ShortTypeHints(List(classOf[MapWrap])))
        //implicit val formats = Serialization.formats(FullTypeHints(List(classOf[MapWrap])))

        val ser = write(new MapWrap(Map[String,Any]("key" -> "value")))
        println("JSON: " + ser)
        println(read[MapWrap](ser))

    }
}

println(read[MapWrap](ser)) 行导致投诉“net.liftweb.json.MappingException: No usable value for data。”

如何反序列化这个案例类包装器(或实现我的最终目标:read(write(Map("key" -> "value"))))?

【问题讨论】:

    标签: json serialization scala lift


    【解决方案1】:

    如果您将 Map 更改为 Map[String, String],则此示例有效。然后序列化程序知道您期望 String 值。如果您的 Map 值是多态的,则需要类型提示。像地图[字符串,动物];狗延伸动物; Cat 扩展了 Animal 等。现在 Animal 类型需要类型提示。它在 JSON 中添加了“jsonClass”字段,用于确定具体的目标类型。

    如果你可以升级到2.3-M1,那么你不再需要包装Map,而是可以直接序列化Map:

    http://www.scala-tools.org/repo-releases/net/liftweb/lift-json_2.8.1/2.3-M1/

    【讨论】:

    • 谢谢。在这种情况下,map 确实是 [String, Any],“string” -> “string” 只是作为示例。我尝试为 Any 和 AnyRef 添加简短和完整的类型提示,但没有这样做。我是否仍然缺少类型提示?
    • 好的,我明白了。像这样反序列化无类型结构的最简单方法是解析 JSON 并获取 JSON 对象的值。 (JsonParser.parse(ser) \ "data").values 或者如果您升级到没有包装器的 2.3: JsonParser.parse(ser).values 。你甚至不需要使用类型提示。
    【解决方案2】:

    或者,您可以使用将案例类参数设置为 JObject 并使用 .values 方法:

    import org.junit.{Test, Assert, Before}
    import org.junit.Assert._
    import net.liftweb.json._
    
    case class Element(title:String, params:JObject)
    @Test
    class JsonParserTest{
     implicit val formats = Serialization.formats(NoTypeHints)
    
     @Test
      def testLiftMapToAny{
        val result = parse("""{"title":"foobar","params":{"one":1,"two":2, "other": "give"}}""").extract[Element]
    
        assertEquals("foobar", result.title)
        assertEquals(Map("one" -> 1, "two" -> 2, "other" -> "give"), result.params.values)
      }
    }
    

    【讨论】:

      猜你喜欢
      • 2011-06-29
      • 2014-11-13
      • 1970-01-01
      • 1970-01-01
      • 2011-11-08
      • 2015-10-16
      • 2021-01-26
      • 2012-07-08
      • 2017-06-09
      相关资源
      最近更新 更多