2017-01-09 13 views
1

使用瑟茜,這是很容易的Json的情況下,類解碼:在Circe中解碼未使用的值是否是一種警告方式?

import io.circe._, io.circe.generic.auto._, io.circe.parser._, io.circe.syntax._ 


case class Bar(xs: List[String]) 


scala> decode[Bar]("{\"xs\":[\"a\",\"b\"]}") 
res2: Either[io.circe.Error,Bar] = Right(Bar(List(a, b))) 

scala> decode[Bar]("{\"xs\":[\"a\",\"b\"],\"addedField\":true}") 
res3: Either[io.circe.Error,Bar] = Right(Bar(List(a, b))) 

但我可以看到一個方法來檢查是否所有的領域都得到了使用和結果映射。

目前,檢查一個方式,如果有些信息已經丟失是重新轉換的結果和JSON差異比較的jsons(與Json4)

scala> val Diff(_,_,removed) = parse(input) diff parse(result.asJson.noSpaces) 
removed: org.json4s.JsonAST.JValue = JObject(List((addedField,JBool(true)))) 

val noLoss = removed == JNothing 

有沒有一種方法,以直接在瑟茜?

回答

2

主要問題在這裏,有不明確的方法來確定字段是否是由您的解碼器消耗。
如果我們將嘗試定義這種消費觀念的一些,如預期的case class ES工作:

import shapeless._ 
import shapeless.labelled.FieldType 

trait FieldNames[T] { 
    def names: Set[String] 
} 

object FieldNames { 
    implicit val hNilNames = new FieldNames[HNil] { 
    def names = Set.empty 
    } 

    implicit def hConsNames[S <: Symbol, A, T <: HNil] 
    (implicit witness: Witness.Aux[S], tail: FieldNames[T]) = new FieldNames[FieldType[S, A] :: T] { 
    lazy val names = tail.names + witness.value.name 
    } 

    implicit def ccNames[CC, Out <: HList] 
    (implicit lgen: LabelledGeneric.Aux[CC, Out], genNames: Lazy[FieldNames[Out]]) = new FieldNames[CC] { 
    lazy val names = genNames.value.names 
    } 
} 

我們現在可以代表一些其餘捕手包裝和相應的解碼器:

case class Tidy[X](value: X, remains: Option[JsonObject] = None) 

object Tidy { 
    implicit def tidyDecoder[X](implicit decoder: Decoder[X], fields: FieldNames[X]) = 
    Decoder.instance[Tidy[X]] { cur => 
     decoder(cur) map { x => 
     Tidy(x, cur.focus.asObject.flatMap { obj => 
      Some(obj.filterKeys(!fields.names.contains(_))).filter(_.nonEmpty) 
     }) 
     } 
    } 
} 

有這個,你可以嘗試提取重新生成字段:

val json1 = 
    """{ 
    "xs" : ["a", "b"] 
    } 
    """ 

val json2 = 
    """{ 
    "xs" : ["a", "b"], 
    "addedField": true 
    } 
    """ 

decode[Tidy[Bar]](json1) // Right(Tidy(Bar(List(a, b)),None)) 
decode[Tidy[Bar]](json2) // Right(Tidy(Bar(List(a, b)),Some(object[addedField -> true]))) 
+0

謝謝,這很有道理。它可能會減少一半的表現,但它組成非常好。對於嵌套結構(超出了curent問題的範圍),它只需要創建一個類型類'''JsonPaths''來代替''FieldNames'''來過濾掉這些路徑。 – jwinandy

0

沒有簡單的內置方式。

您可以參考this issue,瞭解本主題中circe main維護者和貢獻者之間的討論。

免責聲明:沒有明確的結論^^

+0

你忘了鏈接。 – Reactormonk

+0

@Reactormonk:謝謝,我編輯:) – C4stor

相關問題