我需要一个包含名称/值对的JSON结构......值可能是String
或List[String]
:
{
"name":"id",
"value":"55e9cf3e0100003700dd2134"
}
{
"name":"id",
"value":["55e9cf3e0100003700dd2134","55e9e3430100004000d73b59"]
}
下面是我用来处理这种结构的类:
class NameValue protected(protected var json: JsValue) {
def name = json as (__ \ 'name).read[String]
def name_= (v: String) = setValue((__ \ 'name), Json.toJson(v))
def value = json \ "value" match {
case v: JsString => v.value
case v => v.as[List[String]].head
}
def value_= (v: String) = setValue((__ \ 'value), Json.toJson(v))
def multiValue = json \ "value" match {
case v: JsString => List(v.value)
case v => v.as[List[String]]
}
def multiValue_= (v: List[String]) = setValue((__ \ 'value), Json.toJson(v))
}
value
方法返回
String
List[String]
multiValue
方法返回
List[String]
List[String]
String
醇>
下面是创建NameValue
个实例并验证其JSON的伴随对象:
object NameValue {
import play.api.libs.functional.syntax._
import play.api.libs.json.Reads._
def apply(json: JsValue): JsResult[NameValue] = {
validateNameValue.reads(json).fold(
valid = { validated => JsSuccess(new NameValue(validated)) },
invalid = { errors => JsError(errors) }
)
}
def apply(name: String, value: String): NameValue = new NameValue(
nameValueWrites.writes(name, Some(value), None)
)
def apply(name: String, multiValue: List[String]): NameValue = new NameValue(
nameValueWrites.writes(name, None, Some(multiValue))
)
def unapply(nameValue: NameValue) = {
if (nameValue eq null) None
else {
val multiValue = rameValue.multiValue
Some((
nameValue.name,
if (multiValue.length > 1) multiValue else multiValue.head
))
}
}
implicit val nameValueFormat = new Format[NameValue] {
def reads(json: JsValue) = NameValue(json)
def writes(nameValue: NameValue) = nameValue.json
}
private val nameValueWrites = (
(__ \ 'name).write[String] ~
(__ \ 'value).writeNullable[String] ~
(__ \ 'value).writeNullable[List[String]]
).tupled
private val multiValue: Reads[JsArray] = {
(__ \ 'value).json.pick[JsArray] andThen verifying[JsArray](_.value.nonEmpty)
}
val validateNameValue = (
((__ \ 'name).json.pickBranch) ~
((__ \ 'value).json.pickBranch)
).reduce
// how do I integrate this in `validateNameValue`?
val validateNameValue2 = (
((__ \ 'name).json.pickBranch) ~
((__ \ 'value).json.copyFrom(multiValue))
).reduce
}
一切正常......但无论value
属性是String
还是List[String]
,我都只想拥有一个验证器。如何创建一个替换validateNameValue
和validateNameValue2
?
答案 0 :(得分:0)
将值区分为String并且String列表不是一个好习惯。 List也可以包含单个元素。
此外,您可以使用 Json.format 来删除为案例类定义读者和编写者的样板代码。
import play.api.libs.json.Json
object NameValue {
implicit val format = Json.format[NameValue]
}