Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/windows/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 使用Jackson(反序列化)Scala案例类_Java_Json_Scala_Serialization_Jackson - Fatal编程技术网

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

Java 使用Jackson(反序列化)Scala案例类,java,json,scala,serialization,jackson,Java,Json,Scala,Serialization,Jackson,我使用Jackson测试了Scala case类的序列化 反序列化test.java public static void main(String[] args) throws Exception { // being lazy to catch-all final ObjectMapper mapper = new ObjectMapper(); final ByteArrayOutputStream stream = new Byt

我使用Jackson测试了Scala case类的序列化

反序列化test.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());
    }
}
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 } """
}
Foo.scala

    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());
    }
}
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
时,引发了一个异常:

[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) )

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

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

选项1

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

范例

case class Person(
   @BeanProperty val name: String, 
   @BeanProperty val age: Int, 
   @BeanProperty val hobbies: Option[String]
)
在这种情况下,val意味着只定义了一个getter。如果需要设置器进行反序列化,则将属性定义为var

选项2


虽然选项1可以工作,但如果您真的想使用Jackson,有一些包装器允许它处理Scala类,这可能是一种更好的方法。我没有使用它,因为我只是使用内置的Json库来播放

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

我为jackson使用了一个scala模块-jackson模块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字符串
转换为
案例类

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
  • 我创建了一个通用函数来将
    JSON字符串转换为Case类/对象
    ,并将
    Case类/对象转换为JSON字符串

  • 请找到一个工作和详细的答案,我已经使用泛型提供


    • 与Jackson相比,对对象进行反序列化要容易得多。下面是一个例子:

      案例类城市(名称:String,活动:String,纬度:Double)
      隐式val cityRW=upickle.default.macroRW[City]
      val str=“”{“名称”:“巴塞罗那”,“娱乐活动”:“吃塔帕斯”,“纬度”:41.39}”
      val barcelona=upickle.default.read[City](str)
      

      杰克逊的解决方案更加冗长。请参阅此处了解有关此方法的更多信息。

      如果您使用的是Spring MVC,请使用如下配置:

      import java.util.List
      @配置
      @EnableWebMvc
      类WebConfig扩展了WebMVCConfiguer{
      覆盖def configureMessageConverters(转换器:列表[HttpMessageConverter[\u]]):单位={
      val conv=新映射Jackson2HttpMessageConverter();
      val mapper=JsonMapper.builder()
      .addModule(DefaultScalaModule)
      .build();
      conv.setObjectMapper(映射器);
      转换器。添加(conv);
      }
      }
      

      然后,序列化/反序列化纯case类和集合类型将按预期工作。

      Jackson有几个很好的Scala包装器;你至少应该考虑使用其中一个。Play json恰好是我使用的。好的方法(IMO)使用基于类型类的反序列化,您可以向case类的伴生对象添加成员,告诉它如何来回映射到JSON,并提供很好的习惯用法。您的解决方案没有涉及“嗜好:选项[String]”属性,我认为他的部分问题在于将json字符串属性作为选项[String]处理。Jackson需要知道如何将选项[String]解释为Some[String]或noneer注意:1)@JsonProperty在case类上是不必要的,特别是当属性名与字段名相同时。2) 您应该尝试使用与jackson core相同版本的jackson module scala。3) Jackson 2.0被重新打包为com.fasterxml,但在其他方面的效果与Jackson 1.0一样好(如果不是更好的话)。对于选项1,只需输入一个小的输入参数
      name
      ,而不是
      name
      ,您需要在case类中添加一个无参数构造函数,如下所示:
      {def this()=this(“,0,None)}
      既然从最初的问题开始已经五年了,我应该补充一点,这个答案以前可能是有效的,但是我现在使用Scala
      2.13.4
      jackson模块Scala 2.11.3
      jackson数据格式csv 2.11.3
      ,这是必要的,否则我会得到消息
      “无法构造`Person`的实例(不存在像默认构造函数那样的创建者)”