eir*_*lar 10 json scala shapeless argonaut circe
我需要从一个case类实例创建一个更新的实例(带有任何需要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)
Run Code Online (Sandbox Code Playgroud)
我很确定我必须将json解析为json AST,然后将其转换为Shapeless LabelledGeneric,然后以某种方式使用Shapeless更新来更新case类实例.
编辑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)
}
Run Code Online (Sandbox Code Playgroud)
这产生了Person(Old Name Kept,42).
Tra*_*own 15
为了完整起见:自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)
Run Code Online (Sandbox Code Playgroud)
然后:
scala> println(update.map(_(person)))
Right(Person(mr updated,42))
Run Code Online (Sandbox Code Playgroud)
我关于这种技术的原始博客帖子使用的是Argonaut(大部分是因为我在开始编写circe之前几个月写了它),并且该实现可以作为库使用,尽管我从未在任何地方发布它.
| 归档时间: |
|
| 查看次数: |
1480 次 |
| 最近记录: |