【问题标题】:Small Example of Jackson Scala Module?Jackson Scala 模块的小例子?
【发布时间】:2013-06-02 17:39:57
【问题描述】:

谁能指出一个简单的 Jackson 序列化/反序列化示例以及他们的 Scala 2.10 模块?我正在寻找不需要逐字段注释或赋值的基于反射的 JSON,它似乎可以做到这一点,但他们的文档不包含示例。

如果我有一个案例类:

case class Person(name:String, age:Int)
val person = Person("Fred", 65)

所以从他们的 github 自述文件中:

val mapper = new ObjectMapper()
mapper.registerModule(DefaultScalaModule)

好的,现在...?如何将 p 转换为 JSON?

【问题讨论】:

    标签: json scala jackson


    【解决方案1】:

    试一试:

    val person = Person("fred", 25)
    val mapper = new ObjectMapper()
    mapper.registerModule(DefaultScalaModule)    
    
    val out = new StringWriter
    mapper.writeValue(out, person)
    val json = out.toString()
    println(json)
    
    val person2 = mapper.readValue(json, classOf[Person])
    println(person2)
    

    编辑

    请务必将Person 类声明为顶级,否则它将不起作用。

    【讨论】:

    • 我只是尝试了这个没有运气 - readValue 调用失败:com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize Class com.example.JacksonTest$Person$3 (of type local/匿名)作为 Bean。我错过了什么? Person 可以完全声明为:case class Person(name:String, age:Int) 吗?
    • @cmbaxter,有没有办法加快速度或者这是他们推荐的方式?即你能注释以加快速度吗?
    • @Blankman,如果我错了,请纠正我,但 java 中的运行时注释是通过反射提供的,因此使用它们不会帮助您避免反射。有一些基于宏的 scala json 框架通过宏生成 ser/deser 代码并避免反射。我认为 Play 和 Scala Pickling 都有基于宏的 json 处理,而且可能还有更多。
    • @DeanHiller,该解决方案运行良好。我的猜测是 user48956,我唯一能看到有问题的,没有将 Person 案例类声明为顶级类,而是将其嵌套在另一个类/对象中。你不能这样做,因为我不相信需要访问的东西(构造函数)是。如果您将 Person 声明为顶级,则一切正常(或者至少在一年前我发布此答案时他们做得很好)。不确定这是否真的值得一票否决...
    • 如果你想要即时字符串输出,你可以简单地使用mapper.writeValueAsString(person)
    【解决方案2】:

    这是一个完整的例子:

    package com.example.samples
    
    import org.junit.Test
    import com.fasterxml.jackson.databind.ObjectMapper
    import org.springframework.context.annotation.Bean
    import java.io.File
    import com.fasterxml.jackson.module.scala.DefaultScalaModule
    import java.io.StringWriter
    
    class JacksonTest {
    
      @Test
      @throws[Exception] def jacksonTest(): Unit = {
    
        //case class Person(var name: String = "", var age: Int = 0)
        //case class Person(@Bean var name: String, @Bean var age: Int)
        case class Person( name: String, age: Int )
    
        val person = Person("fred", 25)
        val mapper = new ObjectMapper()
        mapper.registerModule(DefaultScalaModule)
    
        val out = new StringWriter
        mapper.writeValue(out, person)
        val json = out.toString()
        println(json)
    
        val person2 = mapper.readValue(json, classOf[Person])
        println(person2)
      }
    }
    

    但是,这在 mapper.readValue 处失败。

    这是我的配置:

    <!-- Jackson libraries for JSON marshalling and unmarshalling -->
    <dependency>
        <groupId>com.fasterxml.jackson.core</groupId>
        <artifactId>jackson-databind</artifactId>
        <version>2.2.3</version>
    </dependency>
    
    <!-- Jackson module for scala object marshalling and unmarshalling -->
    <dependency>
        <groupId>com.fasterxml.jackson.module</groupId>
        <artifactId>jackson-module-scala_2.10</artifactId>
        <version>2.2.2</version>
    </dependency>
    
    <!-- Scala Compiler -->
    <dependency>
        <groupId>org.scala-lang</groupId>
        <artifactId>scala-compiler</artifactId>
        <version>2.10.2</version>
    </dependency>
    

    任何想法为什么会失败?我看不出与工作示例有什么不同。

    【讨论】:

    • 你有没有让这个解决方案以某种方式工作?
    • 好的,我不得不将我的案例类移到我的类和其他函数之外,所以它是一个完整的顶级类,并且由于某种原因解决了这个问题。
    • 之所以把case类移到外面是因为你在测试中定义case类的时候,其实是一个内部类。这意味着它需要引用父类,这就是事情变得复杂的地方(在 java 中使用内部类时也有类似的问题)。您发现将其作为顶级课程的解决方案是一种解决方案。另一个是将案例类放在一个对象中,使其成为一个静态类,一切都很好。
    【解决方案3】:

    我创建了一个通用函数来转换JSON String to Case Class/ObjectCase Class/Object to JSON String

    build.sbt 文件中所需的 SBT 依赖项:

    name := "jackson-example"
    
    scalaVersion := "2.12.11"
    
    libraryDependencies += "com.fasterxml.jackson.module" %% "jackson-module-scala" % "2.10.1"
    libraryDependencies += "com.fasterxml.jackson.core" % "jackson-databind" % "2.10.1"
    

    JSON 字符串到案例类/对象

    def fromJson[T](json: String)(implicit m: Manifest[T]): Option[T] = {
        Try {
          lazy val mapper = new ObjectMapper() with ScalaObjectMapper
          mapper.registerModule(DefaultScalaModule)
          mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
          mapper.readValue[T](json)
        } match {
          case Success(x) => Some(x)
          case Failure(err) => {
            logger.error("@@@@Got " + err.getMessage() + " while JSON to Object:--> " + json)
            None
          }
        }
      }
    

    案例类/对象到 JSON 字符串

    def toJson[T](obj: T)(implicit m: Manifest[T]): Option[String] = {
        Try {
          lazy val mapper = new ObjectMapper() with ScalaObjectMapper
          mapper.registerModule(DefaultScalaModule)
          mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false)
          mapper.writeValueAsString(obj)
        } match {
          case Success(x) => Some(x)
          case Failure (err) => {
            logger.error("@@@@Got " + err.getMessage() + " while converting object  to JSON:--> " + obj)
            None
          }
        }
      }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-08-25
      • 1970-01-01
      • 1970-01-01
      • 2013-08-04
      相关资源
      最近更新 更多