使用Jackson来(De) – 将Scala案例类序列化

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

DeserializeTest.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 } """ } 

当我运行Java类的上述main时,抛出了exception:

 [error] Exception in thread "main" org.codehaus.jackson.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) ) 

我如何(de)-serial化Scala案例类?

Jackson希望你的类成为一个JavaBean,这意味着它希望类具有每个属性的getX()和/或setX()。

选项1

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

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

在这种情况下,val将仅表示定义了一个吸气剂。 如果需要用于反序列化的setter,则将属性定义为var。

选项2

虽然选项1可以工作,但如果你真的想使用Jackson,那么有一些包装器可以处理Scala类,比如FasterXML的scala模块 ,这可能是一种更好的方法。 我没有使用它,因为我刚刚使用内置的Json库来播放。

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

我使用了一个scala模块用于jackson – jackson-module-scala。

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

我不得不用@JsonProperty在我的case类中注释字段。

这就是我的案例类:

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

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

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

序列化更容易:

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

想澄清我正在使用

 com.fasterxml.jackson.databind.ObjectMapper 

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

 org.codehaus.jackson.map.ObjectMapper 

这不适用于ScalaObjectMapper。

根据Priyank Desai的回答,我创建了一个将json string转换为case class的generics函数

 import com.fasterxml.jackson.annotation.JsonProperty import com.fasterxml.jackson.databind.ObjectMapper import com.fasterxml.jackson.module.scala.DefaultScalaModule import com.fasterxml.jackson.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) } 

用法:

 case class Person(@JsonProperty("name") Name:String, @JsonProperty("age") Age:Int) val personName = jsonToType[Person](jsonString).name