2016-12-01 2 views
0

Ich empfange JSON-Antwort von einem Upstream-Server, auf den ich kein Steuerelement habe, zur Änderung.Abspielen von JSON JsPath-bedingten Typen

Die JSON könnte das folgende Format

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

Oder es könnte auch auf, als

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

zeigen oder es könnte als eine Kombination der beiden auftauchen.

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

Einzeln kann ich die READS für jedes Format definieren, wenn sie nicht mischen. Da die Daten jedoch gemischt formatiert sein können, kann ich nicht genau sagen, wie die Lesevorgänge geschrieben werden sollten, um vor der Umwandlung zu überprüfen, ob der zugrunde liegende Typ eine Zeichenfolge oder ein Array ist.

Ist es möglich, zu sagen, so etwas wie

(
    (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) 

Wie kann ich dieses Problem der Deserialisieren nähern?

+0

Ich habe eine ziemlich gute Idee, wie es geht, aber könnten Sie die zugrunde liegende Klasse verknüpfen, auf die sie abgebildet werden soll? –

+0

Sicher Sache, ich habe nichts gegen ein Format für die zugrunde liegende Klasse, wenn es das Problem bezüglich Deserialisierung löst. Zur Zeit verwende ich die folgende Fallklasse 'Fallklasse SomeGloriousCaseClass (initialPart: String, booleanPart: Boolean, theDifficultPart: Seq [String]) '. Es macht mir nichts aus, wenn alles in eine Sequenz umgewandelt wird – Serendipity

+0

'(_ \" data "). Lesen [JsArray] .flatMap {jsa => ??? } ' – cchantep

Antwort

1

Zum Spaß habe ich eine Lösung implementiert. Möglicherweise müssen Sie es ein wenig zwicken:

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) 
    } 

Ich hoffe, es hilft und würde mich freuen, weitere Erläuterungen bei Bedarf zur Verfügung zu stellen.

+0

Als Randnotiz möchte ich erwähnen, dass ich 'sequence' reimplementiert habe, weil ich keine Ahnung habe, ob es da ist ist eine existierende –

+0

Obwohl dies nicht das ist, was ich schließlich verwendet habe, hat mir das dabei geholfen, herauszufinden, wie ich das Problem lösen kann. Danke Louis! – Serendipity