2016-12-01 40 views
0

我從沒有控制權的上游服務器接收JSON響應,進行修改。播放JSON JsPath有條件類型

的JSON可能具有以下格式

{"data":[["Some_text","boolean",["key_string1","key_string2"]]]} 

或者它也可能顯示爲

{"data":[["Some_text","boolean","key_string2"]]} 

或者,它可能顯示爲兩者的組合。

{"data":[["Some_text","boolean",["key_string1","key_string2"]],["Some_text","boolean","key_string2"]]} 

個別我可以定義每種格式的READS,如果他們不混合。 但是,由於數據可能是混合格式,因此我無法圍繞如何編寫Read來檢查底層類型是字符串還是數組,然後再進行轉換?

是否可以這樣說

(
    (JsPath)(0).read[String] and 
    (JsPath)(1).read[Boolean] and 
    (JsPath)(2).read(**if type is simple, String OR if type is array, then seq**) 
)(SomeGloriousCaseClass) 

我如何能接近反序列化的這個問題呢?

+0

我有一個很好的想法,如何做到這一點,但你可以鏈接你想要映射到底層類? –

+0

當然,如果它解決了有關反序列化的問題,我不介意底層類的任何格式。目前,我正在使用下面的案例類case case SomeGloriousCaseClass(initialPart:String,booleanPart:Boolean,theDifficultPart:Seq [String])''。我甚至不介意是否所有東西都被轉換成了一個序列 – Serendipity

+0

'(_ \「data」)。read [JsArray] .flatMap {jsa => ??? }' – cchantep

回答

1

爲了好玩,我實施了一個解決方案。您可能需要調整它一點:

private def toSeq(jsValue: JsValue): JsResult[Seq[String]] = { 
    jsValue match { 
     case JsArray(es:Seq[JsValue]) ⇒ sequence(es.map(e ⇒ toSeq(jsValue))).map(_.flatten) 
     case JsString(s) ⇒ JsSuccess(s :: Nil) 
     case _ ⇒ JsError("INVALID") 
    } 
    } 

    private def sequence[A](seq:Seq[JsResult[A]]):JsResult[Seq[A]] = { 
    seq.foldLeft(JsResult.applicativeJsResult.pure(Seq[A]()))((acc, next) ⇒ for(acc2 ← acc; next2 ← next) yield acc2 :+ next2) 
    } 

希望它可以幫助和會很高興,如果需要提供進一步的解釋。

+0

作爲一個側面說明,我想提一下,我重新實現'sequence',因爲我不知道如果有是現有的 –

+0

雖然這不是我最終使用的,但這確實幫助我弄清楚瞭如何解決問題。謝謝路易斯! – Serendipity