JSON parser ?
Is there somebody out there who worked on a JSON parser in Javascript ? I don't fully understand things on json.org, so maybe someone already got examples on how to implement JSON in Javascript for Max ?
How to use it ? What to do with the json2.js ? the json_parse.js ?
How to load a .maxpat into a JSON Object ?
best wishes
f.e
I haven't tried but it looks like you should be able to copy the contents of json_parse.js (http://www.json.org/json_parse.js) into the top of your max js file (since Max js does not have an include file function), and then somewhere after that code you call:
var myObject = json_parse(myJsonText);
You may also want to try this one: http://code.google.com/p/json-sans-eval/source/browse/trunk/src/json_sans_eval.js which claims to be faster, see http://code.google.com/p/json-sans-eval/
That one looks like you call
var myObject = jsonParse(myJsonText);
If you don't care about security, you can just do:
var myObject = eval('(' + myJSONtext + ')');
But since Max js can do file I/O, there is a very real security risk here: if you load in untrusted JSON someone could potentially wipe your hard drive or install malware (probably unlikely though?). In any case, it's for this reason I would not use json2.js either, it falls back to eval() in some cases so there's probably a security hole there.
Thanks a lot Adam. I was precisely wondering about the includes in a js. Now i got my answer. I'll try with the sans_eval, then.
best wishes
f.e
I'm struggling with something similar currently. Did you get this up and running smoothly with any of the parsing methods?
lh
i am using this code without any problem.
http://www.json.org/json2.js
Ah, it seems my problem is with importing files to read. I've tried a few things: chopping the whitespace, escaping quotes etc. If I parse the text then output it to a message and send it back in it works fine, but not if I do all from within the code. The json2 code is throwing the final error indicating the input is malformed but I'm not sure where along the line this is happening. Is there anything I should look out for when reading a JSON file into my [js] line by line then JSON.parse()-ing it?
lh
i also use the JSON format to store data into a textfile and read
it afterwards.
my datastructures are moredimensional arraays containing
ints, floats and strings.
i am using the js method: readFile()
the problem with this method is, that you get problems,
if there are more than 2000 chars inside your file.
but you can read it in chunk parts.
only tested in max 4.6.3.
perhaps this is fixed in max5 ...
short example:
whichFilePath is the file you want to read.
theFlag = fileExists( whichFilePath );
if ( theFlag == 0 ){
return ""
}
f = new File( whichFilePath, "readwrite", []);
f.open( whichFilePath );
theMaxChars = 1800;
theDivisions = f.eof / theMaxChars;
f.position = 0;
theContent = "";
for ( var i=0; i
theNewStringContent = f.readstring( theMaxChars );
theContent = theContent + theNewStringContent;
f.position = theMaxChars * (i+1);
}
f.close()
return theContent
Here is some code I wrote for the same purpose some months ago (reading and writing .json setup files from disc).
At the bottom is a minified version of the json2 parser.
/**
* Loads the setup file and initializes the setup object.
*/
function loadSetup() {
/*
* Look for a setup file in the same folder as the patch.
*/
var folder = new Folder(stripFileName(patcher.filepath));
var endings = SETUP_FILE_ENDINGS;
var setupFile = new File();
for ( ;!folder.end; folder.next() ) {
for (i in endings) {
/*
* Match files in folders with the given name and endings.
*/
var name = SETUP_FILE_NAME + "." + endings[i];
if (folder.filename == name) {
var fullName = folder.pathname + DIRECTORY_SEPARATOR + name;
/*
* Found, open file.
*/
setupFile = new File(fullName);
loadedSetupFile = name;
// setupFile.byteorder = SETUP_BYTEORDER;
setupFile.linebreak = SETUP_LINEBREAK_STYLE;
}
}
}
if (!setupFile.isopen) {
throw "Could not read setupFile file.";
}
/*
* Init a string buffer for the contents of the file.
*/
var setupBuf = "";
/*
* Read file in chunks.
*/
while (setupFile.position < setupFile.eof) {
var setupBuf = setupBuf + setupFile.readline(256) + LINE_BREAK;
}
/*
* Prepare code for parsing.
*/
setupBuf = (removeComments(setupBuf));
setupBuf = (compressWhiteSpace(setupBuf));
/*
* Run in standard JSON parser.
*/
setup = JSON.parse(setupBuf, null);
}
/**
* Removes JavaScript comments from a string.
*/
function removeComments(s) {
var lines, i, t;
/*
* Remove '//' comments from each line.
*/
lines = s.split("n");
t = "";
for (i = 0; i < lines.length; i++)
t += lines[i].replace(/([^x2f]*)x2fx2f.*$/, "$1");
/*
* Replace newline characters with spaces.
*/
t = t.replace(/(.*)n(.*)/g, "$1 $2");
/*
* Remove C-style comments.
*/
lines = t.split("*/");
t = "";
for (i = 0; i < lines.length; i++)
t += lines[i].replace(/(.*)x2fx2a(.*)$/g, "$1 ");
return t;
}
/**
* Removes whitespace from a string.
*/
function compressWhiteSpace(s) {
/*
* Condense white space.
*/
s = s.replace(/s+/g, " ");
s = s.replace(/^s(.*)/, "$1");
s = s.replace(/(.*)s$/, "$1");
/*
* Remove uneccessary white space around operators, braces and parentices.
*/
s = s.replace(/s([x21x25x26x28x29x2ax2bx2cx2dx2fx3ax3bx3cx3dx3ex3fx5bx5dx5cx7bx7cx7dx7e])/g, "$1");
s = s.replace(/([x21x25x26x28x29x2ax2bx2cx2dx2fx3ax3bx3cx3dx3ex3fx5bx5dx5cx7bx7cx7dx7e])s/g, "$1");
return s;
}
/*
* JSON parser
* From http://json.org/json2.js
*/
/*
* Note: mind js semicolon insertion. Do NOT edit line breaks.
*/
if(!this.JSON){JSON={};}
(function(){function f(n){return n
if(typeof Date.prototype.toJSON!=='function'){Date.prototype.toJSON=function(key){return this.getUTCFullYear()+'-'+
f(this.getUTCMonth()+1)+'-'+
f(this.getUTCDate())+'T'+
f(this.getUTCHours())+':'+
f(this.getUTCMinutes())+':'+
f(this.getUTCSeconds())+'Z';};String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(key){return this.valueOf();};}
var cx=/[u0000u00adu0600-u0604u070fu17b4u17b5u200c-u200fu2028-u202fu2060-u206fufeffufff0-uffff]/g,escapable=/[\"x00-x1fx7f-x9fu00adu0600-u0604u070fu17b4u17b5u200c-u200fu2028-u202fu2060-u206fufeffufff0-uffff]/g,gap,indent,meta={'b':'\b','t':'\t','n':'\n','f':'\f','r':'\r','"':'\"','\':'\\'},rep;function quote(string){escapable.lastIndex=0;return escapable.test(string)?'"'+string.replace(escapable,function(a){var c=meta[a];return typeof c==='string'?c:'\u'+('0000'+a.charCodeAt(0).toString(16)).slice(-4);})+'"':'"'+string+'"';}
function str(key,holder){var i,k,v,length,mind=gap,partial,value=holder[key];if(value&&typeof value==='object'&&typeof value.toJSON==='function'){value=value.toJSON(key);}
if(typeof rep==='function'){value=rep.call(holder,key,value);}
switch(typeof value){case'string':return quote(value);case'number':return isFinite(value)?String(value):'null';case'boolean':case'null':return String(value);case'object':if(!value){return'null';}
gap+=indent;partial=[];if(Object.prototype.toString.apply(value)==='[object Array]'){length=value.length;for(i=0;i
v=partial.length===0?'[]':gap?'[n'+gap+
partial.join(',n'+gap)+'n'+
mind+']':'['+partial.join(',')+']';gap=mind;return v;}
if(rep&&typeof rep==='object'){length=rep.length;for(i=0;i
v=partial.length===0?'{}':gap?'{n'+gap+partial.join(',n'+gap)+'n'+
mind+'}':'{'+partial.join(',')+'}';gap=mind;return v;}}
if(typeof JSON.stringify!=='function'){JSON.stringify=function(value,replacer,space){var i;gap='';indent='';if(typeof space==='number'){for(i=0;i
rep=replacer;if(replacer&&typeof replacer!=='function'&&(typeof replacer!=='object'||typeof replacer.length!=='number')){throw new Error('JSON.stringify');}
return str('',{'':value});};}
if(typeof JSON.parse!=='function'){JSON.parse=function(text,reviver){var j;function walk(holder,key){var k,v,value=holder[key];if(value&&typeof value==='object'){for(k in value){if(Object.hasOwnProperty.call(value,k)){v=walk(value,k);if(v!==undefined){value[k]=v;}else{delete value[k];}}}}
return reviver.call(holder,key,value);}
cx.lastIndex=0;if(cx.test(text)){text=text.replace(cx,function(a){return'\u'+
('0000'+a.charCodeAt(0).toString(16)).slice(-4);});}
if(/^[],:{}s]*$/.test(text.replace(/\(?:["\/bfnrt]|u[0-9a-fA-F]{4})/g,'@').replace(/"[^"\nr]*"|true|false|null|-?d+(?:.d*)?(?:[eE][+-]?d+)?/g,']').replace(/(?:^|:|,)(?:s*[)+/g,''))){j=eval('('+text+')');return typeof reviver==='function'?walk({'':j},''):j;}
throw new SyntaxError('JSON.parse');};}}());
/*
* End parser
*/
Darn, why does the new board remove trailing whitespace inside tags...?
whoa that last code crashed live and max as soon as I hit save!
I'm wondering if you guys figured out a good way to replace or remove json objects. I can only see writeline and readline.. what about splice, delete, etc? I'm having a major issue where I can replace data inside an object if it's named the same, but if the replaced data has a lower character count, the format of the json object gets completely fckd up.
For example, replacing {"0":{"1":[[60,64,0,127,0,127,0,64]]}} with {"0":{"1":[[60,64]]}} leaves me a fckd up json file like: {"0":{"1":[[60,64]]}} ,0,127,0,127,0,64]]}}
Any help would be appreciated! I just can't figure out how JSON files are useful if you can't read and write and replace and reorder etc. Thank you!
I figured it out. Turns out the File Object has limitations that, to me, make it only useful to read files, and write files only once and completely. For what I was trying to do, it looks like it's not the right tool for the job.. phew it took me a long time to figure this out. But anyway, Node for Max allows you to use fs, which is a much more robust tool for reading and writing with no formatting errors. Also, it comes with json parsers built in. So no copying entire parsers at the bottom of the JS file with Node. I didn't think I'd like it as much as I do but Node's really opened some functionality that's more universal which is great. For anyone interested here's the thread where I put some ideas down: https://cycling74.com/forums/sharing-is-fun-example-write-and-read-json-in-javascript