11

DecodeJson不完全な json (一部のフィールドが欠落している) が与えられた場合、ケース クラス インスタンス (必要な s が暗黙的に派生したもの) から更新されたインスタンスを作成する必要があります。これは、Argonaut (できれば) または Circe (必要な場合) でどのように達成できますか?

例:

case class Person(name:String, age:Int)
val person = Person("mr complete", 42)
val incompletePersonJson = """{"name":"mr updated"}"""
val updatedPerson = updateCaseClassFromIncompleteJson(person, incompletePersonJson)

println(updatedPerson)
//yields Person(mr updated, 42) 

json を json AST に解析し、それを Shapeless に変換してからLabelledGeneric、何らかの方法で Shapeless update を使用してケース クラス インスタンスを更新する必要があると確信しています。


編集 2

Shapeless ソースを読んだ後、独自の「デフォルト」オブジェクトを生成できることがわかりました。JSONの解析中にケースクラスのインスタンスが存在することを必要とするソリューションを作成することができました。これを回避し、代わりにインスタンスを後で提供することを望んでいました。とにかくここにあります:

import shapeless._
import argonaut._
import ArgonautShapeless._
import shapeless.ops.hlist.Mapper

case class Person(name: String, age: Int)

object MkDefault {

  object toSome extends Poly1 {
    implicit def default[P] = at[P](Some(_))
  }

  def apply[P, L <: HList, D <: HList]
  (p: P)
  (implicit
   g: Generic.Aux[P, L],
   mpr: Mapper.Aux[toSome.type, L, D]
  ): Default.Aux[P, mpr.Out] =
    Default.mkDefault[P, D](mpr(g.to(p)))
}


object Testy extends App {
    implicit val defs0 = MkDefault(Person("new name? NO", 42))
    implicit def pd = DecodeJson.of[Person]
    val i = """{"name":"Old Name Kept"}"""
    val pp = Parse.decodeOption[Person](i).get
    println(pp)
}

これにより が得られPerson(Old Name Kept,42)ます。

4

2 に答える 2

16

完全を期すために: このような「パッチ適用」インスタンスのサポートは、0.2 リリース以降、circe で提供されています。

import io.circe.jawn.decode, io.circe.generic.auto._

case class Person(name: String, age: Int)

val person = Person("mr complete", 42)
val incompletePersonJson = """{"name":"mr updated"}"""

val update = decode[Person => Person](incompletePersonJson)

その後:

scala> println(update.map(_(person)))
Right(Person(mr updated,42))

この手法に関する私の最初のブログ投稿では Argonaut を使用しており (主に、Circe に取り組み始める数か月前に書いたため)、その実装はライブラリとして入手できますが、どこにも公開したことはありません。

于 2016-09-22T12:42:49.900 に答える