Play Framework 2.5 ajax json路由参数异步MongoDB

Play Framework 2.5 ajax json路由参数异步MongoDB,json,ajax,routes,playframework-2.5,Json,Ajax,Routes,Playframework 2.5,在Play Framework中将json从javascript发布到服务器: var myJson = {"name": "joe", "age":20}; var obj = JSON.parse(myJson); $.ajax(jsRoutes.controllers.MyController.create(obj)); 现在,我已经很好地配置了javascript路由器。如果我以字符串形式接收obj,我可以将其打印到控制台上 routes.conf: POST /person

在Play Framework中将json从javascript发布到服务器:

var myJson = {"name": "joe", "age":20};
var obj = JSON.parse(myJson);

$.ajax(jsRoutes.controllers.MyController.create(obj));
现在,我已经很好地配置了javascript路由器。如果我以字符串形式接收obj,我可以将其打印到控制台上

routes.conf:

POST    /person/add     controllers.MyController.createFromAjax(ajax: String)
但是,我想使用异步承诺将json写入MongoDB,Activator会给出编译时错误:

scala.concurrent.Future[play.api.mvc.Result][error]  cannot be applied to (String)
我还有其他不带参数的路由,它们使用Postman接收json并将其写入MongoDB

routes.conf

POST    /heartrates/bulk            controllers.HRController.createFromJson 
如果忽略从Ajax接收json的路由上的参数,而不是使用Postman,则浏览器中会出现HTTP 400错误

POST http://localhost:9000/person/add 400 (Bad Request)
所以,我的问题是,Ajax需要一个参数,但字符串不能工作。播放文档说json总是作为字符串接收。我做错了什么

Scala控制器代码取自Lightbend seed Play.Reactive.MongoDB:

def createBulkFromAjax = Action.async(parse.json) { request =>

val documents = for {
  heartRate        <- request.body.asOpt[JsArray].toStream
  maybeHeartRate   <- heartRate.value
  validHeartRate   <- maybeHeartRate.transform(transformer).asOpt.toList
} yield validHeartRate

for {
  heartRate <- hrFuture
  multiResult <- heartRate.bulkInsert(documents = documents, ordered = true)
} yield {
  Logger.debug(s"Successfully inserted with multiResult: $multiResult")
  Created(s"Created ${multiResult.n} heartRate")
}
}
def createBulkFromAjax=Action.async(parse.json){request=>
val文档=用于{

心率我认为您正在混淆作为
jsRoutes
调用的一部分传递给
Action
的参数和传递给端点的参数(即查询字符串、查询参数等)

如果您声明了一个非可选参数(就像您在
ajax:String
中所做的那样),并且您没有在请求中实际提供它,Play将返回一个
400错误请求

从概念上讲,您正在将
obj
传递给您的操作,但它不是作为查询参数—您已经声明您的端点需要HTTP POST—因此JSON应该在HTTP请求正文中。请注意,您的其他端点不接受任何查询参数

因此步骤1是修复您的
路由
文件(我已重命名您的方法以匹配其他现有工作方法):

如果查看,您会发现如果您正在执行GET以外的操作,则需要设置
类型(也称为HTTP方法)。因此,步骤2,下面是实现POST的Javascript外观:

var myJson = {"name": "joe", "age":20};
var obj = JSON.stringify(myJson);

var r = controllers.MyController.createFromJson;
$.ajax({url: r.url, type: r.type, data: obj });
在这些更改之后,您应该很好;您的控制器代码看起来很好。如果您仍然收到
400个错误请求
响应,请检查jQuery是否正确设置了
内容类型
标题-您可能需要这样做

仍然收到400个错误后进行编辑:

我刚刚注意到您在Javascript中使用了
JSON.parse
——您应该使用
JSON.stringify
将对象转换为jQuery可以发送的内容——否则它可能会尝试对数据进行URL编码和/或将字段作为查询参数发送

另一个需要注意的问题是,您发送的JSON是否与您试图解析的内容一致。我不确定您是否提供了这个问题的简化版本,但看起来您正在尝试解析:

{"name": "joe", "age":20}
使用:

request.body.asOpt[JsArray]

这将始终导致一个
-您没有给它一个数组。

在CreativeMongo的Play Framework 2.5中对ajax javascript路由的回答:

routes.conf:

GET     /javascriptRoutes      controllers.HRController.javascriptRoutes
POST    /heartrates/add     controllers.HRController.createBulkFromAjax
人力资源控制员:

def javascriptRoutes = Action { implicit request =>
Ok(
  JavaScriptReverseRouter("jsRoutes")(
    routes.javascript.HRController.createBulkFromAjax
  )
).as("text/javascript")
def createBulkFromAjax = Action.async(parse.json) { request =>
//Transformation silent in case of failures.
val documents = for {
  heartRate        <- request.body.asOpt[JsArray].toStream
  maybeHeartRate   <- heartRate.value
  validHeartRate   <- maybeHeartRate.transform(transformer).asOpt.toList
} yield validHeartRate

for {
  heartRate <- hrFuture
  multiResult <- heartRate.bulkInsert(documents = documents, ordered = true)
} yield {
  Logger.debug(s"Successfully inserted with multiResult: $multiResult")
  Created(s"Created ${multiResult.n} heartRate")
}
}
}

routes.conf:

GET     /javascriptRoutes      controllers.HRController.javascriptRoutes
POST    /heartrates/add     controllers.HRController.createBulkFromAjax
main.scala.html:

<script type="text/javascript" src="@routes.HRController.javascriptRoutes"></script>
人力资源控制员:

def javascriptRoutes = Action { implicit request =>
Ok(
  JavaScriptReverseRouter("jsRoutes")(
    routes.javascript.HRController.createBulkFromAjax
  )
).as("text/javascript")
def createBulkFromAjax = Action.async(parse.json) { request =>
//Transformation silent in case of failures.
val documents = for {
  heartRate        <- request.body.asOpt[JsArray].toStream
  maybeHeartRate   <- heartRate.value
  validHeartRate   <- maybeHeartRate.transform(transformer).asOpt.toList
} yield validHeartRate

for {
  heartRate <- hrFuture
  multiResult <- heartRate.bulkInsert(documents = documents, ordered = true)
} yield {
  Logger.debug(s"Successfully inserted with multiResult: $multiResult")
  Created(s"Created ${multiResult.n} heartRate")
}
}
def createBulkFromAjax=Action.async(parse.json){request=>
//发生故障时,转换保持沉默。
val文档=用于{

心率您能给我们看一下您的控制器代码吗?添加了Scala控制器代码。我根据播放文档设置了jsrouter,所以javascript不会抱怨的唯一路由是:var r=jsRoutes.controllers.MyController.createFromJson();$.ajax({url:r.url,contentType:“application/json”,type:r.type,data:JsonObj});如上所述,我已将contentType参数添加到ajax中,但仍然得到错误400 jsrouter似乎工作正常:POST 400(错误请求)任何进一步的帮助都将不胜感激。谢谢。嘿嘿,这是有效的。我正在简化这个问题的代码,但我发现我的问题是route.conf中的一个重复路由,从我将json作为参数传递时开始。删除了路由,它可以与json.parse一起工作,也可以不与json.parse一起工作,因为我在方括号中进行了硬编码。我不知道stringify.T谢谢你的帮助@millhouse。我肯定我会有更多的问题要问。更正,你关于json.parse的说法是对的。我已经删除了它。它很有效。