簡體   English   中英

使用Argonaut或Circe更新不完整JSON的案例類

[英]Update case class from incomplete JSON with Argonaut or Circe

我需要從案例類實例(隱式派生任何所需的DecodeJson )創建一個更新的實例,給定一個不完整的json(缺少某些字段)。 如何通過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,然后將其轉化為無形LabelledGeneric ,然后用無形的更新以某種方式來更新案例類的實例。


編輯2

在閱讀了Shapeless源代碼后,我發現我可以生成自己的“默認”對象。 我設法創建了一個解決方案,它需要在解析json時出現case類的實例。 我希望避免這種情況,而是稍后提供實例。 無論如何它是:

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)

為了完整起見:自0.2版本發布以來,已經提供了對此類“修補”實例的支持:

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之前幾個月寫了它),並且該實現可以作為庫使用 ,盡管我從未在任何地方發布它。

您可以在Person上生成帶有宏注釋的implicit val defs / pd (例如,在object Person ,並import Person._以召喚implicits)。 在scalameta中看到這個未完成的Simulacrum(scala-reflect也很好,但看起來scalameta就足夠了)用於舉例。 此外,您必須在某處指定缺少的默認值( 42 ),例如,在案例類構造函數中( age: Int = 42 ,也可以在宏中完成識別)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM