我正在使用Scala / Play Framework和Reactive Mongo构建一个Web应用程序,我希望在数据库中定义模型,而不是让它们硬编码。 为此,我正在编写一个使用FieldInstance序列的类EntityInstance:
case class EntityInstance(fields: Seq[FieldInstance])
我正在尝试接受来自任何类型的字段并将它们转换为Json:example
new FieldInstance("name", "John") | json: { "name": "John" }
new FieldInstance("age", 18) | json: { "age": 18 }
目前我正在尝试接受字符串,布尔值和整数,如果不支持该类型,我会写一些错误:
new FieldInstance("profilePicture", new Picture("john.jpg") | json: { "profilePicture": "Unsupported type
我写了一个FieldInstance类,将fieldName作为String,将值作为任何类型。一旦该类被实例化,我就将值转换为已知类型或描述错误的String。
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
)
}
}
我创建了一个带有隐式写入json的伴随对象,因此我可以在FieldInstance的实例上调用“Json.toJson()”并获取json,如上面的示例所述。
我收到错误:found: Any required: play.api.libs.json.Json.JsValueWrapper
我知道它来自于我的值是Any类型的事实,但我认为演员会将Any更改为String ||布尔||在击中作家之前的Int。
PS:忽略类的错误命名,我无法命名EntityInstance和FieldInstance,Entity和Field,因为这些是我用来描述模型的类。
答案 0 :(得分:0)
我找到了解决问题的方法: 我在类中进行的类型匹配应该在隐式Write!
中完成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")
}
}
}
此代码现在允许用户使用任何类型的字段创建EntityInstance:
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))
打印:{"entity":[{"name":"George"},{"age":25},{"married":true}]}
如果您要测试它,请参阅我的EntityInstance代码:
case class EntityInstance(fields: Seq[FieldInstance])
object EntityInstance {
implicit val EntityInstanceWrites = new Writes[EntityInstance] {
def writes(entityInstance: EntityInstance) =
Json.obj("entity" -> entityInstance.fields)
}
}
答案 1 :(得分:-1)
返回String,Int或Boolean但Json.obj期望类型的值参数(String, JsValueWrapper )
def obj(fields: (String, JsValueWrapper)*): JsObject = JsObject(fields.map(f => (f._1, f._2.asInstanceOf[JsValueWrapperImpl].field)))
快速修复可以将匹配的值v
转换为toJson,前提是类型T的隐式Writes [T]可用(它们用于String,Int和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")
}
}
如果您想查看哪些DefaultWrit可用,可以在play.api.libs.json
trait DefaultWrites
包中浏览它们
例如:
/**
* Serializer for Boolean types.
*/
implicit object BooleanWrites extends Writes[Boolean] {
def writes(o: Boolean) = JsBoolean(o)
}