我有用Scala编写的HTTP客户端,它使用json4s / jackson来序列化和反序列化HTTP有效负载。目前我只使用Scala案例类作为模型,一切正常,但现在我必须与第三方服务进行通信。他们为我提供了自己的模型,但它是用Java编写的,所以现在我需要将jsons反序列化为Java类。它接缝可以很好地处理简单的类,但是当类包含像Lists或Maps这样的集合时,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案例类时,我会得到类型的异常:org.json4s.package$MappingException: Expected collection but got List[String]
答案 0 :(得分:2)
解决问题的关键是格式化程序的组合。基本上,您希望将JList格式化程序定义为由class DictionaryDecoder: Decoder {
var codingPath: [CodingKey]
var userInfo: [CodingUserInfoKey : Any]
func container<Key>(keyedBy type: Key.Type) throws -> KeyedDecodingContainer<Key> where Key : CodingKey {
}
func unkeyedContainer() throws -> UnkeyedDecodingContainer {
}
func singleValueContainer() throws -> SingleValueDecodingContainer {
}
}
函数组成的列表格式化程序。
不幸的是,toJList
格式化程序非常难以编写,因此我使用json4s
为您提供了一个想法。我还简化了一个例子,只有java list:
Reader
据我所知,json4s读者无法使用开箱即用的java类,因此您可能需要以相同的方式实现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))
,或者使用case类镜像您的java类并在您的域中使用它们
P.S。 强烈建议你切换到circe或argonaut,然后你会忘记jsons的大多数问题。