Client-side: JSON Server + MooTools //+// JSON String as a JSON Server Argument
(Update: See subsequent comments regarding JSON String as JSON Server Argument issue. Applies to all JavaScript devs using JSON.)
////// JSON Server + MooTools Request.JSON
var jsonRequest = new Request.JSON({
url: "http://yourdomain.com/services/json",
onSuccess: function(response){
var myDataArray = response['#data'];
// Manipulate data as necessary
}
}).send({ 'data': {
'method': 'yourservice.new',
'argument_1': 'your argument',
'argument_2': 'your argument'
}
});
// Class: http://mootools.net/docs/core/Request/Request.JSONGroups:
Login to post comments

One challenge
This works beautifully, but last night I ran into a challenge in sending JSON strings. I'm working on it right now and will update once I know what's wrong. In the meantime, if anyone picks this up and has insight, I'd love to hear it.
Problem
I can store regular strings without problem. I can receive JSON strings from services/database, no problem.
I can ~send JSON strings, no problem. (The string appears fine in the post (via Firebug)).
No errors are reported.
HOWEVER, the JSON string does not write to the database via JSON server.
The exact same string DOES write to the database, if using the admin/build/services drupal interface. It appears as though JSON server is choking on the string somewhere during the process.
Challenge Update
An attempt to be clearer:
I'm passing data from my JS app back and forth from the database. No problem.
However -- as well as sending regular string arguments in the POST object, I'd like to include a JSON string argument.
The regular arguments write to corresponding table fields in the DB as normal. ** The JSON argument (containing a lengthy string of fields) would write and be called to a single table field in the DB.
I'm running into a problem with the parsing of the JSON server data object. It seems to choke when it contains a sub object such as my JSON string.
I'm working on it. Any ideas in the meantime would be appreciated.
Update
Cataloging this process is helping me think through it. Here's what I've got so far...
After encoding the object into a string, it seems mandatory to escape the first curly bracket with another character. Anything other than ' [ ' or ' { ' which confuse the JSON parser.
So, as of now I'm writing strings like:
var myMash = "#{'foo','bar'}";and it's working but not overly ideal.
Final (and easy) Client-side Solution
Here's the entire script to post to services via JSON server, using Javascript (MooTools). Data includes a few variables, as well as a JSON object string.
Included are two client-side options for solving the (current) problem of JSON string arguments not being parsed properly by JSON server.
//////// Set regular arguments
var title = 'Bob\'s Fish Diary - Day 82';
var body = 'Today I went fishing at the North Point and South Point. Check out what I caught below. – Bob';
var fish = {
'trout':'at the north point',
'perch':'at the south point',
'trout':'at the south point'
};
//////// Set JSON argument
fishJSONstring = JSON.encode(fish); // This is a MooTools specific class, but similar functions are freely available
// We must escape the object and array brackets,
// otherwise some part of JSON Server does not pass the variable properly to Services.
// As of today, anyway :)
// -- Two options to escape that works with JSON server
// -- -- Slim (but dirty(it appears to work in this use case, but would need to review for others)?) single character escape
var fishJSONstringESC = '#'+fishJSONstring;
// -- Alternatively, you can use the (more proper?) encodeURI()
// var fishJSONstringESC = encodeURI(fishJSONstring);
// -- This option obfuscates and lengthens the data, which may or may not be desirable for you
// -- -- For example " { 'foo':'bar' } becomes %7B%22foo%22:%22bar%22%7D
// -- -- -- (Personally, one of my favourite things about JSON data is that it is naturally easy to read. )
// Final product
fish = fishJSONstringESC;
//////// Send Request (Using the MooTools Request.JSON class (link at top of this post))
var jsonRequest = new Request.JSON({
url: "http://yourdomain.com/services/json",
onSuccess: function(response){
// console.log('success');
}
}).send({ 'data': {
'method': 'fishblog.new',
'title': title,
'body': body,
'fish': fish
}
});
//////// Unescaping Your JSON Object After
////////
// Assuming you've pulled the same data back using a 'get' service on the JSON Server:
// -- First Option (where you added "#" to the beginning of the fish JSON string)
var unescapedString = fish.replace( /#/, "" ); // This only removes the first '#', not subsequents
// -- Second Option (the encodeURI method)
var unescapedString = decodeURI(fish);
mooTools encode vs serialize
Hi ninjay,
I have no experience with mooTools, but it seems to me that you are mistaking "encode" with "serialize" functions. I think that what you want to do is serialize your JSON data to a string, not "encode" it.
If you google for "mooTools encode vs serialize" you will find quite a bit of discussion about this distinction. For example, the first two results from this google search are:
"JavaScript Form Serialization Comparison
In summary, mootools does not support semantic serialization and it incorrectly ... tested use JavaScript's encodeURIComponent function to encode form data. ...
malsup.com/jquery/form/comp/ - Cached - Similar - "
and
"PHP Serialize() & Unserialize Issues
If you encode the serialized array, you'll have to decode the array ... I'm a 26 year old Web Developer and jQuery & MooTools Consultant ...
davidwalsh.name/php-serialize-unserialize-issues - Cached - Similar - "
Hope this helps.
Mike
Nah
Hi Mike
Thanks for taking the time. I'm not mistaking anything.
MooTools' encode function takes a JavaScript OBJECT and converts it to a JSON STRING. The function I'm using is the correct one. Not knowing if you are familiar with JS, let me give you a quick example.
var myObject = {
foo: 'bar'
};
var string = JSON.encode(myObject);
console.log(string);
// Returns --> {"foo":"bar"}
The string that it returns is a JSON string. It's my expectation that this string should be able to be passed as an argument.
However, this fails, hence the need to escape the curly bracket.
Since writing this I've discovered that MooTools has a function to do this properly.
// string.escapeRegExp();
console.log(string.escapeRegExp());
// Returns --> backslash{ "foo":"bar" backslash}
// (note I've written backslash as in the comment preview it seems that the slash is being dropped)
Escaping it is fine. I simply think it is an unexpected and unnecessary step.
node.save Sting/Object problem
So my my next issue brought me back to the same thread. I think it is the same as what you experienced however i am getting an error.
Here is my request:
callback Request.JSONP.request_map.request_1
method node.save
sessid 123123123123123
node {"type":"blog","title":"New Title","body":"This is the blog body"}
Here is my result
HTTP/1.0 500 Internal Server Error
I got this working before, but i used AMFPHP and was able to send objects to drupal. I am guessing that this has to do with Drupal expecting an object, but since it is a GET it gets transformed as a string. Is there any way of getting around this with out hacking the code?
Here is my code:
$('newBlogSubmit').addEvent('click', function()
{
var node = {
type : "blog",
title:"New Title",
body :"This is the blog body"
}
var string = JSON.encode(node);
string.escapeRegExp()
var sessID = _sessID;
DrupalService.getInstance().node_save(string, sessID, drupal_handleBlogSubmit);
});
My Drupal Service JS Code:
//NODE
DrupalService.prototype.node_save = function(node, sessid, callback){
var dataObj = {
method : "node.save",
sessid : sessid,
node : node
}
DrupalService.getInstance().request(dataObj, callback);
}
//SEND REQUEST AND CALLBACK FUNCTION
DrupalService.prototype.request = function(dataObject, callback){
new JsonP('http://myDrupalSite.com/services/json', {data: dataObject,onComplete: callback}).request();
}
If there is anyway around this please let me know. Once again, thanks so much
PS, decode
PS: Conversely, to decode a string is to convert a JSON STRING to a JS OBJECT. To anyone reading, these are the exact functions you would want to use to convert objects to strings and vice versa.
More issues then tissues :)
Having an issue, and not sure what i am doing wrong. I keep on getting "Invalid method" as a result. Am i missing something?
Using: mootools-1.2.3-core-yc.js
window.addEvent('domready', function() {
});
Charles Returns
error Boolean true
data String Invalid method
Tested Positive
Hey Alex,
I just responded via email with my solution. I see here that you've tested pretty much the same thing I've sent you.
Mine works fine however...
var jsonRequest = new Request.JSON({
url: "http://domain.com/services/json",
onSuccess: function(response){
console.log(response);
}
}).send({
data: { method: 'system.connect' }
});
Hmm... I'm also using 1.2.3-core. Have you tested your services setup through the Drupal admin? Or any other service method?
Services version
Note that my module versions are Services 6.x-2.x-dev / JSON server 6.x-1.x-dev and I haven't updated in a while. That would be the uber suck to learn that it's broken with the newest dev release. Though of course there will be a workaround.
I'll test the newest releases and update the code if need be. Sometime in the next few days.
If you are still having trouble I can send you the older modules I have if you want to troubleshoot that way.
I will swap out my Services
I will swap out my Services and JSON_Server mods with the one's you sent me, and will let you know how that goes. Should I expect this to work crossdomain (JSON/P), or was that not originally supported? I'm not totally sure on this, but i did test JSON server on the same domain that my drupal instance is installed on and it seemed to work fine. However, if I run the same script and make an HTTP request from outside of the domain then i start to see issues. I was hoping that it would be possible to pass (callback=CALLBACK) similar to the way that Del.icio.us handles it
http://del.icio.us/feeds/json/singpolyma.techblog/
http://del.icio.us/feeds/json/singpolyma.techblog/?callback=CALLBACK
As side note question regarding JSON/P: Since i am a bit of a noob in the Drupal world, how would Drupal deal with (?callback=CALLBACK) when cleanURLs are setup? Just curious and wanted to make sure that wasn't the source of my issues also.
Ahh. My solution is
Ahh. My solution is same-domain. I believe GET is officially unsupported and in the modules I sent you cross-domain definitely will not work. I suppose this is why you're having trouble. I just saw the JSON/P post below this comment. I'll add a bit of info there.
JSONP
I modified the JSON server module to handle JSONP and GET/POST. When I was about to post the code, dmitrig01 asked me not to. Unfortunatelly my emails have gone unanswered and I wasn't able to convince him to update the changes to the JSON server module. Anyhow, the code lives here:
http://drupal.org/node/477012#comment-2050614
It's very basic and doesn't change anything fundamental. But if you need help, let me know.
Thanks, I will check this
Thanks, I will check this out. Would i need to upgrade to Drupal 7 or is this code compatible with 6.14?
Compatible
It's compatible with Drupal 6. Just be sure to change the json_server.info file appropriately.
Or, if you want, just make the following modifications to your current json_server.module file:
1) Replace all $_POST for $_REQUEST.
2) Changed the code so that if a callback is set, it will handle JSONP:
$callback = $_REQUEST['callback'];
if ($callback) {
header("Content-type: text/javascript");
return $callback ."(". $json .");";
} else {
header("Content-type: application/json");
return $json;
}
As you can see, these changes are easy and straight forward. I sure would love them to make it into the official JSON server module.
I saw the beginnings of a
I saw the beginnings of a process to support cross-domain but I haven't been following over the past couple months to know where the maintainer of JSON server stands. I must say... the official support for this module has seemed a bit weak, and communication has been terrible. Sorry to hear you've hit a road-block.
This weekend I intend to get caught up and perhaps I'll give your mods a shot as well.
#
To abritz and anyone else who's looking to use MooTools, my edit to the original class was to make it work for Post.
If Get is supported go ahead and use the original MooTools code swapping SEND for GET:
http://mootools.net/docs/core/Request/Request.JSON
MooTools also has a JSONP class:
http://mootools.net/docs/more/Request/Request.JSONP
#
I'll test the newest dev releases as well as nickvidal's changes this weekend and post back here with my working code.
Cross-Domain
BTW, I've already tested cross-domain and it works as expected. The neat thing with GET support is that you can type the URL in the browser and see the result right there. Be sure to use content-type as text/plain when testing.
Hey Nick, I stumbled on this
Hey Nick,
I stumbled on this competing project Web Services. Essentially one of the biggest contribs to Services had a conflict in core ideology, and perhaps, a feeling of outpacing the Services maintainers and/or community.
http://drupal.org/project/webservices
There's a more blunt list of benefits list here:
http://drupal.org/node/305523#comment-1000959
A reasonable controversy, there's been a year's worth of discussion. I threw my 2 cents in and alluded to our recent discussion.
Thanks!
Very appreciative for both of your your help just to sum up for anyone else's benefit.
Here is the MooTools JS i used:
window.addEvent('domready', function() {
$('myElement').addEvent('click', function(){
new JsonP('http://ExternalDomain.com/services/json', {
data: {
method: 'system.connect'
},
onComplete: function(data){
var results = eval(data);
alert(results["#data"].sessid)
}
}).request(); //alerts 8.3 - the rating of the ipod
});
});
Here is my edit as per nick's advice using json_server.module,v 1.6
function json_server_server() {
if (!isset($_REQUEST)) {
return drupal_to_js(array('#error' => TRUE, '#data' => "JSON server accepts GET requests only."));
}
}
Glad to know your problem is
Glad to know your problem is solved Alex!
Small edit request (to keep this thread usable): please add the CODE tags before and after your JavaScript code to make it more legible for people.
You may also want to use a comment to differentiate your problem solving code from the MooTools domready event function.
JSONP
IMPORTANT NOTE FOR ALL
As of November 2009
The code shown here is not an official contribution to the JSON Server module, as noted in the comments above. If anyone finds it useful, perhaps you can chime in on the discussion to have it recognized by the maintainer.
http://drupal.org/node/477012#comment-2050614