【问题标题】:Transforming Scala case class into JSON将 Scala 案例类转换为 JSON
【发布时间】:2017-06-16 13:34:33
【问题描述】:

我有两个案例类。主要的Request 包含两张地图。 第一个映射具有键和值的字符串。 第二个映射有一个字符串键和值,它是第二个案例类的实例,KVMapList

case class Request (var parameters:MutableMap[String, String] = MutableMap[String, String](), var deps:MutableMap[String, KVMapList] = MutableMap[String, KVMapList]())

case class KVMapList(kvMap:MutableMap[String, String], list:ListBuffer[MutableMap[String, String]])

要求是将Request 转换为 JSON 表示。 以下代码正在尝试执行此操作:

import com.fasterxml.jackson.annotation.PropertyAccessor
import com.fasterxml.jackson.module.scala.experimental.ScalaObjectMapper
import com.fasterxml.jackson.annotation.JsonAutoDetect.Visibility
import com.fasterxml.jackson.databind.ObjectMapper

def test(req:Request):String {
  val mapper = new ObjectMapper() with ScalaObjectMapper
  mapper.setVisibility(PropertyAccessor.ALL,  Visibility.ANY)
  var jsonInString: String = null
  try {
    jsonInString = mapper.writeValueAsString(request)
  }
  catch {
    =case e: IOException => {
      e.printStackTrace
   }
  jsonString
}

但是这不起作用。即使填充了 Request 类,输出也是:

{"parameters":{"underlying":{"some-value":""},"empty":false,"traversableAgain":true},"deps":{"sizeMapDefined":false,"empty":false,"traversableAgain":true}}

将 JSON 对象映射器与相应的 Java 类一起使用很简单,但还没有让它在 Scala 中工作。非常感谢任何帮助。

【问题讨论】:

    标签: scala


    【解决方案1】:

    在某种程度上,杰克逊在 Scala 中更像是一个糟糕的旧记忆。您应该使用原生 Scala 库进行 JSON 处理,尤其是一个非常擅长 JSON 序列化程序的编译时派生的库,例如 circe

    我知道这并不能直接回答你的问题,但是在使用 circe 之后我再也不会回到其他任何事情了。

    import io.circe.generic.auto._
    import io.circe.parser._
    import io.circe.syntax._
    
    val req = new Request(...)
    val json = req.asJson.noSpaces
    val reparsed = decode[Request](json)
    

    另一方面,在案例类中使用可变映射是非常不习惯的,使用自动生成的 copy 方法为您的映射实现不可变操作应该非常简单。

    case class Request(parameters: Map[String, String] {
      def +(key: String, value: String): Request = {
        this.copy(parameters = parameters + (key -> value))
      }
    }
    

    你应该尽可能地避免可变性,而且看起来在这里避免它根本没有太多工作。

    【讨论】:

    • 编译 req.asJson.noSpaces 时出现 maven 构建失败:error: scala.MatchError: true (of class scala.reflect.internal.Trees$Literal)。我正在使用罐子 circe-parse_sjs0.6_2.11 和 circe-generic_2.11 (都来自组 io.circe)。谢谢!
    【解决方案2】:

    我不确定这个ScalaObjectMapper 是做什么的,看起来没用。 如果你在开头添加mapper.registerModule(DefaultScalaModule),它应该可以工作......假设MutableMap你的意思是mutable.Map,而不是某种自制课程(因为,如果你这样做,你必须提供自己的序列化程序)。

    DefaultScalaModulejackson-module-scala 库中。如果您还没有,只需将其添加到您的构建中)。

    【讨论】:

    • 调用 registerModule 时抛出此异常:线程“main”中的异常 java.lang.VerifyError: com.fasterxml.jackson.module.scala.ser.ScalaIteratorSerializer 类覆盖 final 方法 withResolved.(Lcom /fasterxml/jackson/databind/BeanProperty;Lcom/fasterxml/jackson/databind/jsontype/TypeSerializer;Lcom/fasterxml/jackson/databind/JsonSerializer;)Lcom/fasterxml/jackson/databind/ser/std/AsArraySerializerBase;
    • 您一定是使用了错误的版本。 jackson core和scala模块库的版本必须一致。
    • 谢谢迪玛。修复了另一个问题,现在这是错误:Scala 模块 2.9.0 需要 Jackson Databind 版本 >= 2.9.0 和
    • 给它需要的版本?那是什么'pr3'的东西?摆脱它
    • 谢谢迪玛。它现在有点工作,所有的值都被写出来了。问题是 JSON 还包含 KVMapList,即类的名称,它应该只包含该类中的值。在 Java 中,这是通过使用 @JsonValue 注释相应的(内部)类来解决的。这似乎在 Scala 中不起作用。
    猜你喜欢
    • 2016-07-27
    • 2014-12-18
    • 1970-01-01
    • 2014-01-08
    • 1970-01-01
    • 2013-04-13
    • 1970-01-01
    • 1970-01-01
    • 2015-06-16
    相关资源
    最近更新 更多