2017-10-19 15 views
1

json4s/jacksonを使用してHTTPペイロードを直列化および逆シリアル化するScalaで書かれたHTTPクライアントがあります。今はScalaのケースクラスだけをモデルとして使用していましたが、すべてうまくいっていましたが、今はサードパーティのサービスと通信する必要があります。彼らは私に独自のモデルを提供しましたが、Javaで書かれていました。だから、Javaクラスにjsonsを非直列化する必要があります。シンプルなクラスではうまく動作しますが、クラスにリストやマップなどのコレクションが含まれている場合、json4sに問題があり、そのようなフィールドはすべてnullに設定されます。Scalaとjson4sを使ってJavaオブジェクトにデシリアライズ

このようなケースを処理する方法はありますか?たぶん私は別の形式を使用する必要があります(私は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クラス:私も、私は私がよフィールドのjava.util.List[String]タイプを含むScalaのケースクラスにデシリアライズしようとするでしょう時に気づいている

import java.util.List; 

public class ObjectWithList { 
    List<String> list; 
} 

タイプの例外を受け取ります:org.json4s.package$MappingException: Expected collection but got List[String]

答えて

1

フォーマットの作成者です。基本的には、JListフォーマッタをtoJList関数で構成されたリストフォーマッタとして定義します。 残念なことに、json4sフォーマッタは非常に作成が難しいので、私はReaderを使ってアイデアを得ました。私はまた、唯一の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)) 

あなたはSerializer[JList[_]]同じように、またはミラーを実装する必要があるかもしれませんどちらかのように、読者は、箱から出してのJavaクラスでは動作しませんjson4sあなたのJavaクラスはケースクラスを持ち、あなたのドメイン内でそれらを使用します。

P.S. circeまたはargonautに切り替えることを強くお勧めします。すると、jsonsの問題のほとんどを忘れてしまいます。

+1

あまりにも正直なところ私はcirce(長いコンパイルの問題のためjson4sに置き換えられました)を使用しようとしましたが、私のScalaの専門知識のレベルを理解するのが難しいと感じています。私は 'io.circe.generic.auto._'からのデコーダを使用していましたが、それらはJavaデコーダを含んでいません。あなたがcirceにjavaクラスのデコーダがあるかどうか知っていますか?または私がcirceに戻ることにしたら私自身のカスタムデコーダを実装する必要がありますか? –

+1

私が知っている 'generic.auto._'は、' HList'への変換と、 'shapeless'から' Coproduct'を使用しています。これはJavaクラスでは動作しません。私はあなたがcirceでJavaクラスのための独自のデコーダを実装する必要があることが怖いです。 –

関連する問題