2016-04-09 11 views
1

Ich baue eine Webanwendung mit Scala/Play Framework und Reactive Mongo und möchte, dass die Modelle in der Datenbank definiert werden sie hart codieren lassen. so zu tun, ich bin eine Klasse EntityInstance Schreiben eine Sequenz von FieldInstance unter:ScalaJson impliziter Schreibvorgang, gefunden: Beliebig erforderlich: play.api.libs.json.Json.JsValueWrapper

case class EntityInstance(fields: Seq[FieldInstance]) 

I Felder von irgendwelchen Typen zu akzeptieren, ich versuche, und sie zu Json zu konvertieren: Beispiel

new FieldInstance("name", "John") | json: { "name": "John" } 
new FieldInstance("age", 18) | json: { "age": 18 } 

Bei der Moment versuche ich, Streicher, Boolesche Werte und Ganze Zahlen zu akzeptieren und, wenn der Typ nicht unterstützt wird schreibe ich einige Fehler:

new FieldInstance("profilePicture", new Picture("john.jpg") | json: { "profilePicture": "Unsupported type 

ich schrieb eine FieldInstance Klasse ta king ein FieldName als String und einen Wert als einen beliebigen Typ. Sobald diese Klasse instanziiert wird, übergebe ich den Wert auf einen bekannten Typ oder auf den String, der den Fehler beschreibt.

class FieldInstance(fieldNamec: String, valuec: Any) { 
    val fieldName = fieldNamec 
    val value = valuec match { 
    case v: Int => v 
    case v: String => v 
    case v: Boolean => v 
    case _ => "Unrecognized type" 
    } 
} 
object FieldInstance { 
    implicit val fieldInstanceWrites = new Writes[FieldInstance] { 
    def writes(fieldInstance: FieldInstance) = Json.obj(
     fieldInstance.fieldName -> fieldInstance.value 
    ) 
    } 
} 

habe ich ein Begleitobjekt mit einem impliziten Schreibe JSon so kann ich „Json.toJson()“ auf eine Instanz von FieldInstance anrufen und eine json erhalten, wie oben auf meine Beispiele beschrieben.

Ich erhalte einen Fehler: found: Any required: play.api.libs.json.Json.JsValueWrapper Ich verstehe, dass es von der Tatsache kommt, dass mein Wert vom Typ Any ist, aber ich dachte, der Cast würde Any zu String || ändern Boolesch || Int vor dem Schlagen des Verfassers.

PS: Ignorieren Sie die schlechte Benennung der Klassen, ich konnte EntityInstance und FieldInstance, Entity und Field nicht nennen, da dies die Klassen sind, die ich verwende, um meine Modelle zu beschreiben.

Antwort

0

ich ein Update zu meinem Problem gefunden: Die Art Matching, dass ich in der Klasse zu tun soll getan im impliziten Schreiben!

class FieldInstance(fieldNamec: String, valuec: Any) { 
    val fieldName = fieldNamec 
    val value = valuec 
    override def toString(): String = "(" + fieldName + "," + value + ")"; 
} 
object FieldInstance { 
    implicit val fieldInstanceWrites = new Writes[FieldInstance] { 
    def writes(fieldInstance: FieldInstance) = 
     fieldInstance.value match { 
     case v: Int => Json.obj(fieldInstance.fieldName -> v.asInstanceOf[Int]) 
     case v: String => Json.obj(fieldInstance.fieldName -> v.asInstanceOf[String]) 
     case v: Boolean => Json.obj(fieldInstance.fieldName -> v.asInstanceOf[Boolean]) 
     case _ => Json.obj(fieldInstance.fieldName -> "Unsupported type") 
     } 
    } 
} 

Mit diesem Code kann nun ein Benutzer eine EntityInstance mit Feldern Jede Art erstellen:

val ei = new EntityInstance(Seq[FieldInstance](new FieldInstance("name", "George"), new FieldInstance("age", 25), new FieldInstance("married", true))) 

println("-- TEST ENTITY INSTANCE TO JSON --") 
println(Json.toJson(ei)) 

druckt: {"entity":[{"name":"George"},{"age":25},{"married":true}]}

Hier Code meiner EntityInstance wenn Sie testen wollen es:

case class EntityInstance(fields: Seq[FieldInstance]) 
object EntityInstance { 
    implicit val EntityInstanceWrites = new Writes[EntityInstance] { 
    def writes(entityInstance: EntityInstance) = 
     Json.obj("entity" -> entityInstance.fields) 
    } 
} 
-1

Es ist einen String zurückkehrt, Int oder Boolean aber Json.obj den Wert Parameter des Typs erwartet (String, JsValueWrapper)

def obj(fields: (String, JsValueWrapper)*): JsObject = JsObject(fields.map(f => (f._1, f._2.asInstanceOf[JsValueWrapperImpl].field))) 

eine schnelle Lösung des angepassten Wert zu konvertieren sein könnte v mit toJson sofern die implizite Writes [T] für Typ T verfügbar ist (was sie sind für String, Int und Boolean)

class FieldInstance(fieldNamec: String, valuec: Any) { 
    val fieldName = fieldNamec 
    val value = valuec match { 
    case v: Int => Json.toJson(v) 
    case v: String => Json.toJson(v) 
    case v: Boolean => Json.toJson(v) 
    case _ => Json.toJson("Unrecognized type") 
    } 
} 

Wenn Sie möchten, dass s ee das DefaultWrites verfügbar sind, können Sie diese in dem in zum Beispiel trait DefaultWrites

play.api.libs.json Paket durchsuchen:

/** 
    * Serializer for Boolean types. 
    */ 
    implicit object BooleanWrites extends Writes[Boolean] { 
    def writes(o: Boolean) = JsBoolean(o) 
    } 
+0

Schreibt kann jeden Scala-Typ annehmen, zum Beispiel kann er mein fieldName-Attribut analysieren, das Problem hier ist, dass der Wert immer noch vom Typ Any ist, wenn er vom Typ Int/String oder Boolean sein sollte. – Daniel

Verwandte Themen