使用Scala和json4s反序列化为java对象

时间:2017-10-19 11:46:27

标签: json scala deserialization json4s

我有用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]

1 个答案:

答案 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的大多数问题。