在 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)
}

也许这对遇到类似问题的人有帮助 :)