我正在尝试使用reader / combinator来解析包含混合数据类型的数组,但我不确定如何为这样的事情指定一个阅读器。我有一些像这样的JSON:
{
"stuff": [1, 2, true, null, "false", "hahaha", 5, "8"]
}
我想将所有这些解析成字符串表示,但是当我尝试使用List[String]
的读者时,我得到了解析异常。我想象这样的事情:
implicit val mixedArrayReader = (
(__ \ 'not).readNullable[List[JsValueWrapper]].map(opt => opt.map(list =>
list.map { wrapper : JsValueWrapper =>
val parsed : String = wrapper match {
case b : JsBoolean => if (b.value) "1" else "0"
case n : JsNumber => n.value.toString
case s : JsString => s.value
case JsNull => "null"
case u => u.toString // unknown
}
parsed
}
))
)
但是,由于JsValueWrapper
没有读者,我不知道从哪里开始。非常感谢任何帮助。
谢谢!
答案 0 :(得分:3)
首先实现自定义的Reads [String],然后使用Reads.list
将其转换为List[String]
的阅读器,然后像往常一样使用该阅读器。希望明确地传递这些特定的读者而不是为他们定义隐含,以便不隐藏Play的默认Reads[String]
。
import play.api.libs.json.Reads
val myReader: Reads[String] = Reads[String](value => JsSuccess(value match {
case b : JsBoolean => if (b.value) "1" else "0"
case n : JsNumber => n.value.toString
case s : JsString => s.value
case JsNull => "null"
case u => u.toString // unknown
}))
val listReads = Reads.list[String](myReader)
然后,在组合阅读器中,您可以编写如下内容:
implicit val objReader =
(__ \ 'not).readNullable(listReads)
答案 1 :(得分:1)
同样的解决方案可能是最直接的。我认为如果你使用.readNullable[List[JsValue]]
,你的解决方案将会起作用,JsValue
是所有Js *类型的超类型,你永远不需要直接使用的包装器,它只是为了帮助轻松创建JSON对象而存在和数组。
另一个更实用,更灵活的解决方案(请注意,此解决方案可以更好地处理错误),您可以使用:
val anyValueAsStringReader =
implicitly[Reads[BigDecimal]].map(_.toString) or
implicitly[Reads[String]] or
implicitly[Reads[Boolean]].map(if (_) "1" else "0") or
implicitly[Reads[JsValue]].map(_.toString)
val mixedArrayReader = (__ \ 'not).readNullable(Reads.list(anyValueAsStringReader))