Kev*_*ith 12 java serialization json scala jackson
我使用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());
}
}
Run Code Online (Sandbox Code Playgroud)
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 } """
}
Run Code Online (Sandbox Code Playgroud)
当我运行上面main
的Java类时,抛出了一个异常:
[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) )
Run Code Online (Sandbox Code Playgroud)
我如何(de)-serial化Scala案例类?
Lio*_*ort 19
Jackson期望你的类成为一个JavaBean,这意味着它希望类具有每个属性的getX()和/或setX().
选项1
您可以使用注释BeanProperty在Scala中创建JavaBean类.
例
case class Person(
@BeanProperty val name: String,
@BeanProperty val age: Int,
@BeanProperty val hobbies: Option[String]
)
Run Code Online (Sandbox Code Playgroud)
在这种情况下,val将仅表示定义了一个吸气剂.如果需要用于反序列化的setter,则将属性定义为var.
选项2
虽然选项1可行,但如果你真的想使用Jackson,那么有一些包装器可以让它处理像FasterXML的scala模块这样的Scala类,这可能是一种更好的方法.我没有使用它,因为我刚刚使用内置的Json库来玩.
Pri*_*sai 13
找到了一个适用于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"
)
Run Code Online (Sandbox Code Playgroud)
我必须使用@JsonProperty在我的case类中注释字段.
这就是我的案例类:
case class Person(@JsonProperty("FName") FName: String, @JsonProperty("LName") LName: String)
Run Code Online (Sandbox Code Playgroud)
这就是我反序列化的方式:
val objectMapper = new ObjectMapper() with ScalaObjectMapper
objectMapper.registerModule(DefaultScalaModule)
val str = """{"FName":"Mad", "LName": "Max"}"""
val name:Person = objectMapper.readValue[Person](str)
Run Code Online (Sandbox Code Playgroud)
序列化更容易:
val out = new ByteArrayOutputStream()
objectMapper.writeValue(out, name)
val json = out.toString
Run Code Online (Sandbox Code Playgroud)
想澄清我正在使用
com.fasterxml.jackson.databind.ObjectMapper
Run Code Online (Sandbox Code Playgroud)
在这个问题中,似乎他正在使用
org.codehaus.jackson.map.ObjectMapper
Run Code Online (Sandbox Code Playgroud)
这不适用于ScalaObjectMapper.
根据 Priyank Desai 的回答,我创建了一个通用函数来转换json string
为case class
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)
}
Run Code Online (Sandbox Code Playgroud)
用法:
case class Person(@JsonProperty("name") Name:String, @JsonProperty("age") Age:Int)
val personName = jsonToType[Person](jsonString).name
Run Code Online (Sandbox Code Playgroud)