- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在使用多个 Reads[T]
读取嵌套的 JSON 文档但是,我坚持使用以下子对象:
{
...,
"attributes": {
"keyA": [1.68, 5.47, 3.57],
"KeyB": [true],
"keyC": ["Lorem", "Ipsum"]
},
...
}
JsArray
实例,但大小和类型不同(但是,特定数组的所有元素必须具有相同的
JsValue
类型)。
case class Attribute[A](name: String, values: Seq[A])
// 'A' can only be String, Boolean or Double
Reads[Seq[Attribute]
] 在转换整个文档时可用于“属性”字段(请记住,“属性”只是一个子文档)。
val required = Map(
"KeyA" -> "Double",
"KeyB" -> "String",
"KeyD" -> "String",
)
Reads
应该会产生两个错误:
Reads
.我作为第一步尝试的第一件事,从外部
Reads
的角度来看:
...
(__ \ "attributes").reads[Map[String, JsArray]]...
...
String
的对象s 和
JsArray
s 作为键值对,然后是
Reads
失败并显示正确的错误消息。它有效,但是:我不知道如何从那里继续。当然,我可以创建一个方法来转换
Map
成
Seq[Attribute]
,但是这个方法应该返回一个
JsResult
,因为还有进一步的验证要做。
val attributeSeqReads = new Reads[Seq[Attribute]] {
def reads(json: JsValue) = json match {
case JsObject(fields) => processAttributes(fields)
case _ => JsError("attributes not an object")
}
def processAttributes(fields: Map[String, JsValue]): JsResult[Seq[Attribute]] = {
// ...
}
}
processAttributes
内手动验证 map 的每个元素.但我觉得这太复杂了。任何帮助表示赞赏。
required
用于验证。这听起来很矛盾,但事实是:
required
特定于每个文档/请求,并且在编译时也不知道。但是您不必担心这一点,只需假设对于每个请求都是正确的
required
已经在范围内可用。
最佳答案
你对任务太困惑了
The keys ("keyA", "keyB"...) as well as the amount of keys are not known at compile time and can vary
So in the case of the JSON shown above, the Reads should create two errors:
"keyB" does exist, but has the wrong type (expected String, was boolean).
"keyD" is missing (whereas keyC is not needed and can be ignored).
Reads[Attribute]
用
Reads.list(Reads.of[A])
为您的每把 key (此读取将检查类型和必需)并跳过省略(如果不需要)
Reads.pure(Attribute[A])
.然后元组转换为列表(
_.productIterator.toList
),你会得到
Seq[Attribute]
val r = (
(__ \ "attributes" \ "keyA").read[Attribute[Double]](list(of[Double]).map(Attribute("keyA", _))) and
(__ \ "attributes" \ "keyB").read[Attribute[Boolean]](list(of[Boolean]).map(Attribute("keyB", _))) and
((__ \ "attributes" \ "keyC").read[Attribute[String]](list(of[String]).map(Attribute("keyC", _))) or Reads.pure(Attribute[String]("keyC", List()))) and
(__ \ "attributes" \ "keyD").read[Attribute[String]](list(of[String]).map(Attribute("keyD", _)))
).tupled.map(_.productIterator.toList)
scala>json1: play.api.libs.json.JsValue = {"attributes":{"keyA":[1.68,5.47,3.57],"keyB":[true],"keyD":["Lorem","Ipsum"]}}
scala>res37: play.api.libs.json.JsResult[List[Any]] = JsSuccess(List(Attribute(keyA,List(1.68, 5.47, 3.57)), Attribute(KeyB,List(true)), Attribute(keyC,List()), Attribute(KeyD,List(Lorem, Ipsum))),)
scala>json2: play.api.libs.json.JsValue = {"attributes":{"keyA":[1.68,5.47,3.57],"keyB":[true],"keyC":["Lorem","Ipsum"]}}
scala>res38: play.api.libs.json.JsResult[List[Any]] = JsError(List((/attributes/keyD,List(ValidationError(List(error.path.missing),WrappedArray())))))
scala>json3: play.api.libs.json.JsValue = {"attributes":{"keyA":[1.68,5.47,3.57],"keyB":["Lorem"],"keyC":["Lorem","Ipsum"]}}
scala>res42: play.api.libs.json.JsResult[List[Any]] = JsError(List((/attributes/keyD,List(ValidationError(List(error.path.missing),WrappedArray()))), (/attributes/keyB(0),List(ValidationError(List(error.expected.jsboolean),WrappedArray())))))
def attributesReads(required: Map[String, String]) = Reads {json =>
type Errors = Seq[(JsPath, Seq[ValidationError])]
def locate(e: Errors, idx: Int) = e.map { case (p, valerr) => (JsPath(idx)) ++ p -> valerr }
required.map{
case (key, "Double") => (__ \ key).read[Attribute[Double]](list(of[Double]).map(Attribute(key, _))).reads(json)
case (key, "String") => (__ \ key).read[Attribute[String]](list(of[String]).map(Attribute(key, _))).reads(json)
case (key, "Boolean") => (__ \ key).read[Attribute[Boolean]](list(of[Boolean]).map(Attribute(key, _))).reads(json)
case _ => JsError("")
}.iterator.zipWithIndex.foldLeft(Right(Vector.empty): Either[Errors, Vector[Attribute[_ >: Double with String with Boolean]]]) {
case (Right(vs), (JsSuccess(v, _), _)) => Right(vs :+ v)
case (Right(_), (JsError(e), idx)) => Left(locate(e, idx))
case (Left(e), (_: JsSuccess[_], _)) => Left(e)
case (Left(e1), (JsError(e2), idx)) => Left(e1 ++ locate(e2, idx))
}
.fold(JsError.apply, { res =>
JsSuccess(res.toList)
})
}
(__ \ "attributes").read(attributesReads(Map("keyA" -> "Double"))).reads(json)
scala> json: play.api.libs.json.JsValue = {"attributes":{"keyA":[1.68,5.47,3.57],"keyB":[true],"keyD":["Lorem","Ipsum"]}}
scala> res0: play.api.libs.json.JsResult[List[Attribute[_ >: Double with String with Boolean]]] = JsSuccess(List(Attribute(keyA,List(1.68, 5.47, 3.57))),/attributes)
关于json - Play JSON : Reading and validating a JsObject with unknown keys,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36670756/
JSObject.equals 的文档说: Determines if two JSObject objects refer to the same instance. 相反,以下表达式的计算结果为
在 Javascript 中,我有以下代码: var r=applet.foo({var0:99,var1:'foo',var2:applet}); 在我的 Java 小程序中,我有以下内容: pub
我动态生成一堆Reads[JsObject]然后我在 Seq[Reads[JsObject]] .为了实际应用所有这些单Reads[JsObject] ,我必须将它们与 and 合并合二为一Reads
我有 JsObject动态内容,例如可能如下所示: { "foo": "bar", "viewedTaskIds": [1, 2, 3, 4] } viewedTaskIds是一个整数
我正在尝试使 Java 小程序在其封闭环境中通过 javascript 进行交互。 到现在为止,我一直使用netscape.javascript.JSObject作为处理从JS调用Java函数的类型,
我正在尝试创建一个具有此结构的 JS 对象 { node1: [ 'test1.1', 'test1.2'], node2: ['test2.1', 'test2.2'] }
我正在尝试一些 Java/JavaScript 编码,但似乎遇到了困难。我试图将参数从 Java 传递到 JavaScript,但无论我做什么“JSObject jso = JSObject.getW
我正在使用 nashorn 脚本引擎,并且 JSObject 接口(interface)有问题。我创建了一个基类,通过成员的 HashMap 手动将函数添加到 JSObject: public abs
我有很多链接可以从 Web 获取数据,因此我想使用循环来检索每个 URL 的数据,但是我在将 JSObject 制作为数组时遇到了麻烦。 JSONObject[] jsObjectallnewstyp
我正在制作一个带有 Awesomium 网络浏览器的 C# Windows 窗体应用程序。 我正在尝试从表中获取一些行并将它们解析为数组。 JSPart 在浏览器中运行良好。 这是我在 C# 中使用的
我在 C# 中的表单上使用 Awesomium WebControl,我试图将信息传递到浏览器,表明已插入 USB 设备我的 USB 检测工作正常,但由于某种原因我无法构建 JSObject() 以及
我正在制作一个基于 Java 的基于网络的应用程序,它支持某些特定的请求(例如,每次打印时无需选择打印机),有些东西让我发疯。 我使用 JavaFX 实例化浏览器对象,一切正常,但当然我需要从 Jav
是否可以向 JsObject 添加新字段? val jsonObj = Json.obj() jsonObj.put("field" -> 100) JsString("Kip")) // newO
给定 Dart 代码 class LandingController { bool hideDiv = false; void doit() { new JsObject(cont
我有两个从案例类创建的 JsValue,即书籍和书籍详细信息 val bookJson = Json.tojson(Book) val bookDetailJson = Json.tojson(Boo
我有一个通过 Webswing 在网络上运行的 Java 应用程序服务器。Webswing 服务器将 Java 转换为 HTML5,以实现安全的 Web 使用。 我使用 netscape.javasc
applet javascript 调用是否以任何正确的方式序列化?我正在考虑实现一个模型,其中两个线程发送 javascript 命令。一个响应来自浏览器(js)的请求,另一个周期性地访问浏览器。我
我想创建一个 JSObject 并用属性填充它(有点像 HashMap),但不转换 eval("({})") 的结果,因为我认为不断评估这样的东西会确实对性能有影响。有办法吗? 最佳答案 如果你想使用
我的 xhtml 页面中有一个 Javascript 函数,它执行以下操作: HTML 文件: function getData(){ var data = document.getElemen
这个问题在这里已经有了答案: Why is getWindow() not able to be resolved? (3 个答案) 关闭 8 年前。 我试图在 JApplet 的 init 方法中
我是一名优秀的程序员,十分优秀!