Java 使用 Jackson 对 Scala 案例类进行(反)序列化

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/28270621/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 05:53:36  来源:igfitidea点击:

Using Hymanson to (De)-serialize a Scala Case Class

javajsonscalaserializationHymanson

提问by Kevin Meredith

I tested out the serialization of a Scala case class using Hymanson.

我使用 Hymanson 测试了 Scala 案例类的序列化。

DeserializeTest.java

反序列化测试.java

    public static void main(String[] args) throws Exception { // being lazy to catch-all

        final ObjectMapper mapper          = new ObjectMapper();
        final ByteArrayOutputStream stream = new ByteArrayOutputStream();

        mapper.writeValue(stream, p.Foo.personInstance());

        System.out.println("result:" +  stream.toString());
    }
}

Foo.scala

富斯卡

object Foo {
  case class Person(name: String, age: Int, hobbies: Option[String])
  val personInstance = Person("foo", 555, Some("things"))
  val PERSON_JSON = """ { "name": "Foo", "age": 555 } """
}

When I ran the above mainof the Java class, an exception was thrown:

当我运行上面main的Java类时,抛出了一个异常:

[error] Exception in thread "main" org.codehaus.Hymanson.map.JsonMappingException: 
 No serializer found for class p.Foo$Person and no properties discovered 
 to create BeanSerializer (to avoid exception, 
 disable SerializationConfig.Feature.FAIL_ON_EMPTY_BEANS) )

How can I (de)-serialize Scala case classes?

我如何(反)序列化 Scala 案例类?

采纳答案by Lionel Port

Hymanson is expecting your class to be a JavaBean, which means its expects the class to have a getX() and/or setX() for every property.

Hymanson 希望您的类是 JavaBean,这意味着它希望该类的每个属性都有一个 getX() 和/或 setX()。

Option 1

选项1

You can create JavaBean classes in Scala using the annotation BeanProperty.

您可以使用注释BeanProperty在 Scala 中创建 JavaBean 类。

Example

例子

case class Person(
   @BeanProperty val name: String, 
   @BeanProperty val age: Int, 
   @BeanProperty val hobbies: Option[String]
)

In this case a val will mean only a getter is defined. If you want setters for deserialization you defined the properties as var.

在这种情况下,val 意味着只定义了一个 getter。如果你想要反序列化的 setter,你可以将属性定义为 var。

Option 2

选项 2

While option 1 will work, if you really want to use Hymanson there are wrappers that allow it to deal with Scala classes like FasterXML's scala modulewhich might be a better approach. I haven't used it as I've just been using the Json library built in to play.

虽然选项 1 可以工作,但如果您真的想使用 Hymanson,则可以使用包装器来处理 Scala 类,例如FasterXML 的 scala 模块,这可能是更好的方法。我没有使用它,因为我只是使用内置的 Json 库来播放。

回答by Priyank Desai

Found a solution that works with Hymanson and scala case classes.

找到了一个适用于 Hymanson 和 scala case 类的解决方案。

I used a scala module for Hymanson - Hymanson-module-scala.

我为 Hymanson 使用了一个 scala 模块 - Hymanson-module-scala。

libraryDependencies ++= Seq(
 "com.fasterxml.Hymanson.core" % "Hymanson-databind" % "2.5.3",
 "com.fasterxml.Hymanson.module" %% "Hymanson-module-scala" % "2.2.2"
)

I had to annotate fields in my case class with @JsonProperty.

我必须用@JsonProperty 注释我的案例类中的字段。

This is what my case class looks like:

这是我的案例类的样子:

case class Person(@JsonProperty("FName") FName: String, @JsonProperty("LName") LName: String)

And this is how I deserialize:

这就是我反序列化的方式:

val objectMapper = new ObjectMapper() with ScalaObjectMapper
objectMapper.registerModule(DefaultScalaModule)
val str = """{"FName":"Mad", "LName": "Max"}"""
val name:Person = objectMapper.readValue[Person](str)

Serialization is easier:

序列化更容易:

val out = new ByteArrayOutputStream()
objectMapper.writeValue(out, name)
val json = out.toString

Would like to clarify that I am using

想澄清一下我正在使用

com.fasterxml.Hymanson.databind.ObjectMapper

In the question, it seems he is using

在问题中,他似乎正在使用

org.codehaus.Hymanson.map.ObjectMapper 

which won't work with ScalaObjectMapper.

这不适用于 ScalaObjectMapper。

回答by faisal00813

Based on Priyank Desai's answer I have created a generic function to convert json stringto case class

根据 Priyank Desai 的回答,我创建了一个通用函数来转换json stringcase class

import com.fasterxml.Hymanson.annotation.JsonProperty
import com.fasterxml.Hymanson.databind.ObjectMapper
import com.fasterxml.Hymanson.module.scala.DefaultScalaModule
import com.fasterxml.Hymanson.module.scala.experimental.ScalaObjectMapper

def jsonToType[T](json:String)(implicit m: Manifest[T]) :T = {
   val objectMapper = new ObjectMapper() with ScalaObjectMapper
   objectMapper.registerModule(DefaultScalaModule)
   objectMapper.readValue[T](json)
}

Usage:

用法:

case class Person(@JsonProperty("name") Name:String, @JsonProperty("age") Age:Int)

val personName = jsonToType[Person](jsonString).name

回答by Keshav Lodhi

  • I have created a generic function to convert JSON String to Case Class/Objectand Case Class/Object to JSON String.

  • Please find a working and detailed answer which I have provided using generics here.

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

  • 在此处找到我使用泛型提供的有效且详细的答案。