2016-05-24 9 views
4

Ich habe eine Reihe von json Einstellungen wie so:ein JSON-Array des Objekts in die entsprechenden Fallklasse Parse

[ 
    { 
    "name": "Company Name", 
    "key": "company_name", 
    "default": "Foo" 
    }, { 
    "name": "Deposit Weeks", 
    "key": "deposit_weeks", 
    "default": 6 
    }, { 
    "name": "Is VAT registered", 
    "key": "vat_registered", 
    "default": false 
    } 
] 

ich dies in eine Seq von Setting Objekte analysieren möchten. Ich habe versucht, mein JSON-Format zu definieren, indem ein Merkmal unter Verwendung und Definition der verschiedenen Fallklassen entsprechend den Datentyp im JSON-Objekt:

sealed trait Setting 
case class StringSetting(name: String, key: String, default: String) extends Setting 
case class IntSetting(name: String, key: String, default: Int) extends Setting 
case class BoolSetting(name: String, key: String, default: Boolean) extends Setting 

Jetzt versuche ich die json zu analysieren:

val json = Json.parse(jsonStr) 
implicit val jsonFormat: Format[Setting] = Json.format[Setting] 

val result = Try(json.as[Seq[Setting]]) 

hier bekomme ich einen Compiler-Fehler:

Error:(19, 61) No unapply or unapplySeq function found implicit val jsonFormat: Format[Setting] = Json.format[Setting]

gibt es eine Möglichkeit um jede Einstellung zu seiner entsprechenden Fallklasse abzubilden?

+1

Mögliche Duplikat [Rausch frei JSON-Format für versiegelte Züge mit Play 2.2 Bibliothek] (http://stackoverflow.com/questions/17021847/noise- free-json-format-for-sealed-traits-mit-play-2-2-library) –

Antwort

3
  1. Der naive Ansatz Reads [Einstellungen] zu schaffen, wäre (wenn Ihr Ziel json konvertieren nur auf Objekt), so dass JSON Deserializer Lage, die richtige Variante der Umgebung zu bauen.

    import play.api.libs.json._ 
    import play.api.libs.functional.syntax._ 
    
    implicit val settingReads: Reads[Setting] = (__ \ "default").read[String].map[Setting](StringSetting) | 
                (__ \ "default").read[Int].map[Setting](IntSetting) | 
                (__ \ "default").read[Boolean].map[Setting](BoolSetting) 
    

Dies würde jedoch nicht funktionieren, wenn Sie denselben Typ haben für ‚default‘ in verschiedenen Unterklassen. In diesem Fall kann der JSON-Deserializer nicht zwischen diesen beiden Fallklassen unterscheiden.

  1. Ein anderer Ansatz ist die Verwendung der play json variant library.

    import julienrf.variants.Variants 
    
    sealed trait Setting 
    case class StringSetting(name: String, key: String, default: String) extends Setting 
    case class IntSetting(name: String, key: String, default: Int) extends Setting 
    case class BoolSetting(name: String, key: String, default: Boolean) extends Setting 
    
    object Setting { 
        implicit val format: Format[Setting] = Variants.format[Setting] 
    } 
    

    Variant.format bietet sowohl Lesen als auch Schreiben für Einstellungen. Stellen Sie sicher, dass die Zuweisung des impliziten Val-Formats erfolgt, nachdem alle möglichen Unterklassen deklariert wurden.

Weitere Informationen zur Wiedergabe json Variantenbibliothek click here

+0

Dies ist eine sehr gute Antwort, gutes Zitat und ein klares Verständnis des Themas. Original-Poster war so nah; Das KISS-Prinzip, das auf dieser Seite angewendet wird, ist ziemlich erfrischend. –