我有一个用Scala编写的HTTP客户端,它使用json4s/jackson来序列化和反序列化HTTP有效负载。现在我只使用Scala case类作为模型,一切工作正常,但现在我必须与第三方服务进行通信。他们为我提供了他们自己的模型,但它是用Java编写的,所以现在我需要将jsons反序列化为Java类。它看起来可以很好地处理简单的类,但是当类包含列表或地图之类的集合时,json4s就会出现问题,并将所有这些字段都设置为null。
有没有办法处理这类情况?也许我应该使用不同的格式(我使用DefaultFormats +一些自定义格式)。测试问题示例:
import org.json4s.DefaultFormats
import org.json4s.jackson.Serialization.read
import org.scalatest.{FlatSpec, Matchers}
class JavaListTest extends FlatSpec with Matchers{
implicit val formats = DefaultFormats
"Java List" should "be deserialized properly" in {
val input = """{"list":["a", "b", "c"]}"""
val output = read[ObjectWithList](input)
output.list.size() shouldBe 3
}
}和示例Java类:
import java.util.List;
public class ObjectWithList {
List<String> list;
}我还注意到,当我试图反序列化到包含java.util.List[String]类型字段的Scala case类时,会得到一个类型为:org.json4s.package$MappingException: Expected collection but got List[String]的异常
发布于 2017-10-19 21:09:06
解决问题的关键是格式化程序的组合。基本上,您希望将JList格式化程序定义为由toJList函数组成的列表格式化程序。不幸的是,json4s Formatters非常难以编写,所以我使用了Readers来帮助您获得一个想法。我还简化了一个例子,只有java list:
import DefaultReaders._
import scala.collection.JavaConverters._
implicit def javaListReader[A: Reader]: Reader[java.util.List[A]] = new Reader[util.List[A]] {
override def read(value: JValue) = DefaultReaders.traversableReader[List, A].read(value).asJava
}
val input = """["a", "b", "c"]"""
val output = Formats.read[java.util.List[String]](parse(input))据我所知,json4s阅读器不能使用开箱即用的Serializer[JList[_]]类,因此您可能需要以相同的方式实现java类,或者将java类与case类进行镜像并在域中使用它们。
另外,强烈建议您切换到circe或argonaut,这样您就会忘记json的最大问题。
https://stackoverflow.com/questions/46829146
复制相似问题