在 Scala 中修改 Future[JsArray]
Modify Future[JsArray] in Scala
我使用 Play 2.0 框架从 MongoDB 获取数据。
这是通过以下代码完成的:
def getTopicsInAppFormat = Action.async {
// let's do our query
val cursor: Cursor[TopicModel] = topicCollection.find(Json.obj()).cursor[TopicModel]
// gather all the JsObjects in a list
val futureTopicsList: Future[List[TopicModel]] = cursor.collect[List]()
// transform the list into a JsArray
val futurePersonsJsonArray: Future[JsArray] = futureTopicsList.map { topics =>
Json.arr(topics)
}
// everything's ok! Let's reply with the array
futurePersonsJsonArray.map {
topics =>
Ok(topics(0))
}
}
但问题是我希望函数 return 数据的另一种表示形式。因此,例如,我想更改属性的数量等。实现该目标的好方法是什么?我试图在最后一步修改数据(分别创建一个新格式的新数组),就在 Ok() 函数之前。但是,我没有任何进展:/
编辑:
目前我正在尝试创建新的 JSON 对象,但我在从原始对象获取数据时遇到了困难...
我当前的代码如下所示:
futurePersonsJsonArray.map {
topics =>
/* Access a attribute */
println(topics(0).\("content"))
/* However: error: JsUndefined('content' is undefined on object */
/* Could be used to set the new attributes */
val myNewJson = Json.obj(
"name" -> "JohnDoe",
"age" -> "123",
"created" -> new java.util.Date().getTime())
Ok(/*topics(0)*/myNewJson)
}
您可能误解了 topics
的格式。您收到的消息告诉您 topics
数组的第一个元素上没有 content
属性。这是一个简化的例子:
val myObject = Json.obj("a" -> 1, "b" -> 2)
myObject \ "a" //JsNumber(1)
myObject \ "c" //JsUndefined('c' is undefined on object...)
这是有道理的,因为我们在尝试读取不存在的 属性 时在 Javascript 中得到 undefined
。在 Play Json 库中,\
总是 returns 一个 JsValue
,它的子类型之一是 JsUndefined
。
您应该重新检查 topics
数组中对象的格式并重新评估如何访问其值。
现在,我对问题 "modify the data just before returning" 的最终解决方案如下所示:
futurePersonsJsonArray.map {
topics =>
def createNewFormat(uID: JsValue, name: JsValue, content: JsValue, lat: JsValue, lng: JsValue): JsObject = {
return Json.obj(
"id" -> uID,
[...]
}
/* Access the needed attributes */
val uIDs = topics(0).\("uID")
val names = topics(0).\("name")
val content = topics(0).\("content")
val gps = topics(0).\("gps")
var dataArray = new JsArray()
/* create new Array */
for( i <- 0 to uIDs.length-1){
dataArray = dataArray.append(createNewFormat(uIDs(i),names(i),content(i),gps(i)(0),gps(i)(1)))
}
/* put this into a new JSObject */
var returnThis = Json.obj("data" -> dataArray)
Ok(returnThis)
}
也许这对遇到类似问题的人有帮助 :)
我使用 Play 2.0 框架从 MongoDB 获取数据。
这是通过以下代码完成的:
def getTopicsInAppFormat = Action.async {
// let's do our query
val cursor: Cursor[TopicModel] = topicCollection.find(Json.obj()).cursor[TopicModel]
// gather all the JsObjects in a list
val futureTopicsList: Future[List[TopicModel]] = cursor.collect[List]()
// transform the list into a JsArray
val futurePersonsJsonArray: Future[JsArray] = futureTopicsList.map { topics =>
Json.arr(topics)
}
// everything's ok! Let's reply with the array
futurePersonsJsonArray.map {
topics =>
Ok(topics(0))
}
}
但问题是我希望函数 return 数据的另一种表示形式。因此,例如,我想更改属性的数量等。实现该目标的好方法是什么?我试图在最后一步修改数据(分别创建一个新格式的新数组),就在 Ok() 函数之前。但是,我没有任何进展:/
编辑: 目前我正在尝试创建新的 JSON 对象,但我在从原始对象获取数据时遇到了困难... 我当前的代码如下所示:
futurePersonsJsonArray.map {
topics =>
/* Access a attribute */
println(topics(0).\("content"))
/* However: error: JsUndefined('content' is undefined on object */
/* Could be used to set the new attributes */
val myNewJson = Json.obj(
"name" -> "JohnDoe",
"age" -> "123",
"created" -> new java.util.Date().getTime())
Ok(/*topics(0)*/myNewJson)
}
您可能误解了 topics
的格式。您收到的消息告诉您 topics
数组的第一个元素上没有 content
属性。这是一个简化的例子:
val myObject = Json.obj("a" -> 1, "b" -> 2)
myObject \ "a" //JsNumber(1)
myObject \ "c" //JsUndefined('c' is undefined on object...)
这是有道理的,因为我们在尝试读取不存在的 属性 时在 Javascript 中得到 undefined
。在 Play Json 库中,\
总是 returns 一个 JsValue
,它的子类型之一是 JsUndefined
。
您应该重新检查 topics
数组中对象的格式并重新评估如何访问其值。
现在,我对问题 "modify the data just before returning" 的最终解决方案如下所示:
futurePersonsJsonArray.map {
topics =>
def createNewFormat(uID: JsValue, name: JsValue, content: JsValue, lat: JsValue, lng: JsValue): JsObject = {
return Json.obj(
"id" -> uID,
[...]
}
/* Access the needed attributes */
val uIDs = topics(0).\("uID")
val names = topics(0).\("name")
val content = topics(0).\("content")
val gps = topics(0).\("gps")
var dataArray = new JsArray()
/* create new Array */
for( i <- 0 to uIDs.length-1){
dataArray = dataArray.append(createNewFormat(uIDs(i),names(i),content(i),gps(i)(0),gps(i)(1)))
}
/* put this into a new JSObject */
var returnThis = Json.obj("data" -> dataArray)
Ok(returnThis)
}
也许这对遇到类似问题的人有帮助 :)