Grails json rendering as map - json

I am trying to render a json response from grails controller action. Here is my code:
render ([message:"voila Sent Successfully!"]) as JSON
But in the gsp, it is rendering like:
['message':'Email Sent Successfully!']
Above text is actually a string(as its typeof in jquery ajax call gives a string in the success event handler), so how do I render it as a JSON?
I am using grails 2.4.5 and the JSON class is actually grails.converters.JSON (not grails.converters.deep.JSON)

Just do as
render ([message:"voila Sent Successfully!"] as JSON ) i.e inserting as JSON
within parentheses.

I'd like to expose another answer, which avoids an issue like one that I already found in IE. Some older IE versions could try to download your JSON as a file.
Generate your JSON response from your collection/map and then render it as a string, so:
import grails.converters.JSON
def YourService
def yourControllerNameHere(){
def result = YourService.generatesYourResult(),
resultJSON = result as JSON
render resultJSON.toString()
}
Then, in your ajax, parse this string as JSON-object using jQuery, that is:
$.ajax({
url : WEB_ROOT + 'yourUrl/yourControllerNameHere',
type : 'post',
dataType: 'text',
success : function(resultStr) {
var result = $.parseJSON(resultStr);
alert('this is your response type: ' + (typeof result));
// this is your response type: object
}
});

Related

Play Framework 2.5 ajax json route parameter async MongoDB

POST ing json from javascript to server in Play Framework:
var myJson = {"name": "joe", "age":20};
var obj = JSON.parse(myJson);
$.ajax(jsRoutes.controllers.MyController.create(obj));
Now, I have the javascript router configured fine. If i recieve the obj as a string I can print it out to the console just fine.
routes.conf:
POST /person/add controllers.MyController.createFromAjax(ajax: String)
BUT, I want to write the json to MongoDB using an Async promise which Activator gives the compile time error:
scala.concurrent.Future[play.api.mvc.Result][error] cannot be applied to (String)
I have other routes that take no parameters that receive json using Postman and write it to MongoDB just fine
routes.conf
POST /heartrates/bulk controllers.HRController.createFromJson
If I omit the parameter on the route that receives the json from Ajax instead of using Postman I get a HTTP 400 error in the browser.
POST http://localhost:9000/person/add 400 (Bad Request)
SO, my question is, Ajax needs a parameter but String wont work. Play documentation says json is always received as a String. What am I doing wrong here?
Scala Controller Code taken from 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")
}
}
I think you're getting mixed up between the parameters you pass to your Action as part of the jsRoutes call, and parameters that get passed to endpoints (i.e. the query string, query parameters etc).
Play will return a 400 Bad Request if you've declared a non-optional parameter (like you did with ajax: String) and you don't then actually supply it in your request.
While conceptually you are passing obj to your action, it's not as a query parameter - you've declared that your endpoint expects an HTTP POST - so the JSON should be in the HTTP request body. Notice your other endpoints don't take any query parameters.
So step 1 is to fix your routes file (I've renamed your method to match your other existing working one):
POST /person/add controllers.MyController.createFromJson
If you look at the Play documentation for the Javascript reverse router, you'll see that you'll need to set the type (aka HTTP method) if you're doing something other than a GET. So, step 2, here's what your Javascript should look like to achieve a POST:
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 });
After those changes you should be good; your controller code looks fine. If you still get 400 Bad Request responses, check that jQuery is setting your Content-Type header correctly - you may need to use the contentType option in the jQuery $.ajax call.
Edit after still getting 400 errors:
I've just noticed that you were using JSON.parse in your Javascript - as per this answer you should be using JSON.stringify to convert an object into something jQuery can send - otherwise it may try to URLEncode the data and/or send the fields as query parameters.
The other thing to look at is whether the JSON you are sending actually agrees with what you're trying to parse it as. I'm not sure if you've provided a simplified version for this question but it looks like you're trying to parse:
{"name": "joe", "age":20}
Using:
request.body.asOpt[JsArray]
Which will always result in a None - you didn't give it an array.
The Answer to ajax javascript routes in Play Framework 2.5 for ReativeMongo:
routes.conf:
GET /javascriptRoutes controllers.HRController.javascriptRoutes
HRController:
def javascriptRoutes = Action { implicit request =>
Ok(
JavaScriptReverseRouter("jsRoutes")(
routes.javascript.HRController.createBulkFromAjax
)
).as("text/javascript")
}
routes.conf:
POST /heartrates/add controllers.HRController.createBulkFromAjax
main.scala.html:
<script type="text/javascript" src="#routes.HRController.javascriptRoutes"></script>
javascript:
var r = jsRoutes.controllers.HRController.createBulkFromAjax();
$.ajax({url: r.url, type: r.type, contentType: "application/json", data: JsonString });
HRController:
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")
}
}
HRController.createBulkFromAjax was built from a Lightbend activator ui seed example called play.ReactiveMogno

How to get indented JSON output in asp.net MVC 5 to view in browser?

This is only for debugging purpose. Only returning JSON, outputs unreadable JSON string on webpage. Is there any quick solution to view formatted json on webpage?
Looking for a C# function that will take json object and return formatted output as string from my action method.
Just change JSON global settings in your Global.asax file.
GlobalConfiguration.Configuration.Formatters.JsonFormatter.SerializerSettings = new JsonSerializerSettings
{
Formatting = Formatting.Indented
};
It should produce indented JSON for all your Web API endpoints.
Then you can inspect resulting JSON directly in browser or using some HTTP traffic capturing tool like Fiddler.
Use the JavaScript JSON.Stringify() function. Example:
$.ajax({
method: "POST",
url: "/yourController/yourAction",
data: { name: "John", location: "Boston" }
}).done(function( data ) {
alert(JSON.Stringify(data));
});

Angular $http get parameters conversion

When I have this kind of object:
myObj = {
accountNumber:"12345",
limit:"10",
offset:"0",
serviceProduced: {
min:"2015-03-01"
}
}
and I pass it via $http get as params:
$http({
url: '/foo'
method: 'GET'
params: myObj
});
for some reason it comes to server like this after its JSONified by $http:
{"accountNumber":"1191009461","limit":"10","offset":"0","serviceProduced":"{\"min\":\"2015-03-01\"}"}
How can I prevent the 'serviceProduced' not to be converted to string? So that it would be like this (correct):
{"accountNumber":"1191009461","limit":"10","offset":"0","serviceProduced":{"min":"2015-03-01"}}
I think you are miss using http get. It is not supposed to support nested objects.
It should be in the following format: ?accountNumber=1191009461&limit=10&...
However, if you want to achieve what you are looking for, you can configure your object to be like:
myObj = {
accountNumber:"12345",
limit:"10",
offset:"0",
"serviceProduced.min": "2015-03-01", // you should be able to handle this format server side.
// OR
"serviceProduced[min]": "2015-03-01"
}
try:
$http.get("#{url}", myObj)...
it should work.

OpenERP #http.route('demo_json', type="json") URL not displaying JSON Data

I am create controller in OpenERP Framework. Following is my code and i set http.route type="http",
import openerp.http as http
from openerp.http import request
class MyController(http.Controller):
#http.route('demo_html', type="http")
def some_html(self):
return "<h1>This is a test</h1>"
Above code work perfect once i login into openerp after i modify URL http://localhost:8069/demo_html show me return result This is a test in h1 heading tag.
But same way i try to type="json" and add following json code and again try to call URL http://localhost:8069/demo_json Its not work properly and show me error "Internal Server Error".
import openerp.http as http
from openerp.http import request
class MyController(http.Controller):
#http.route('demo_html', type="http") // Work Pefrect when I call this URL
def some_html(self):
return "<h1>This is a test</h1>"
#http.route('demo_json', type="json") // Not working when I call this URL
def some_json(self):
return {"sample_dictionary": "This is a sample JSON dictionary"}
So my question is how to route json. Any help would be appreciate Thank you.
This is because there is difference between type="json" and type="http".
type="json":
it will call JSONRPC as an argument to http.route() so here , there will be only JSON data be able to pass via JSONRPC, It will only accept json data object as argument.
type="http":
As compred to JSON, http will pass http request arguments to http.route() not json data.
I think , you need to do some extra stuff while working with type="json",you have to trigger that method using json rpc from js.
like :
$(document).ready(function () {
openerp.jsonRpc("demo_json", 'call', {})
.then(function (data) {
$('body').append(data[0]);
});
return;
})
and yes do not forget to return your dictionary in list like
#http.route('demo_json', type="json")
def some_json(self):
return [{"sample_dictionary": "This is a sample JSON dictionary"}]

How to parse ASP.NET JSON Date format with GWT

ASP.NET JSON serialize DateTime to the following format "/Date(1251877601000)/". Pls, help parse this string into the java(GWT) Date object.
At this time the solution I came with is parsing with regex, extract long.. but then I cannot push long through JSNI.
function FixJsonDates(data) {
//microsoft script service perform the following to fix the dates.
//json date:\/Date(1317307437667-0400)\/"
//javasccript format required: new Date(1317307437667-0400)
//copied from micrsoft generated fiel.
var _dateRegEx = new RegExp('(^|[^\\\\])\\"\\\\/Date\\((-?[0-9]+)(?:[a-zA-Z]|(?:\\+|-)[0-9]{4})?\\)\\\\/\\"', 'g');
var exp = data.replace(_dateRegEx, "$1new Date($2)");
return eval(exp);
}
The answer to this question is, use nuget to obtain JSON.NET then use this inside your JsonResult method:
return Json(JsonConvert.SerializeObject(/* JSON OBJECT TO SEND TO VIEW */));
inside your view simple do this in javascript:
JSON.parse(#Html.Raw(Model.data))
If it comes via a view model that is or if it is an ajax call:
var request = $.ajax({ url: "#Url.Action("SomeAjaxAction", "SomeController")", dataType: "json"});
request.done(function (data, result) { JSON.parse(data); });