Jscript with JSON

I'm just writing a script in jscript which downloads information from discogs.com via their API - which sends the data in JSON format. (when finished I want to give it into the forum ...).

I've tried the jscript JSON.parse but it does not work.

See the MS jscript reference here: http://msdn.microsoft.com/en-us/library/cc836466(v=vs.84).aspx.

When I try the first example

[code]@script:jscript
DOpus.ClearOutput();
DOpus.Output("jscript version: " + ScriptEngineMajorVersion() + "." + ScriptEngineMinorVersion());

var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
var contact = JSON.parse(jsontext);
var fullname = contact.surname + ", " + contact.firstname;
DOpus.Output("Full: " + fullname);
[/code]

with a DO 11.4 button I get this:

jscript version: 5.8 Error at line 6, position 1 'JSON' is undefined (0x800a1391)

Please read the "Requirements Note" on the MS link above.

When I understand "Windows Script interface host has to invoke IActiveScriptProperty::SetProperty." right, then DO has to invoke this: http://msdn.microsoft.com/en-us/library/cc512774(v=vs.84).aspx before running jscript?

Otherwise JSON.parse won't be supported?

Or must I do something? Any help would be really great asap. :smiley:

fyi: I also googled this: http://blogs.msdn.com/b/jscript/archive/2009/04/17/versioning-language-features-in-jscript.aspx

At the bottom:

Byron 20 May 2011 8:42 AM # 

The undocumented "feature" of the SetProperty with SCRIPTPTOP_INVOKEVERSIONING is that the value must be a VT_I4 or VT_I2 - any other integer type will be rejected as invalid. 

Here's the code scrap where I create my language engine.

HRESULT result = CoCreateInstance(m_LanguageId, 0, CLSCTX_ALL, IID_IActiveScriptProperty, (LPVOID*) &m_pScriptProperty);

if (result == S_OK && m_LanguageId == CLSID_JScript)

{

 VARIANT set;

 set.vt = VT_I4;

 set.intVal = SCRIPTLANGUAGEVERSION_5_8;

 if (m_pScriptProperty->SetProperty(SCRIPTPROP_INVOKEVERSIONING, NULL, &set) != S_OK)

 m_bLoadJSONLibrary = true;

}

Has something like this to be done to get the "real full" 5.8 jscript language running within DO?

I also tried to call it from CMD but without sucess:

cscript //E:jscript jstest.cscript
Microsoft (R) Windows Script Host Version 5.8
Copyright (C) Microsoft Corporation. All rights reserved.

jstest.cscript(2, 1) Microsoft JScript runtime error: 'JSON' is undefined

Hmm ... asking MS how to run it as CMD variant? :question:

Beside missing the built-in JSON support (see above - still a feature request :grin:),

I found this great json2.js parser here: https://github.com/douglascrockford/JSON-js

With the help of loading the json2.js into the current own script this example works:

Download the file "json2.js" and save it as e.g. "C:\json2.js".

Then run this code/button:

@script:jscript
DOpus.ClearOutput();
DOpus.Output("jscript version: " + ScriptEngineMajorVersion() + "." + ScriptEngineMinorVersion());

// Load libraries
eval(includeFile("C:\\json2.js"));

// Begin
var jsontext = '{"firstname":"Jesper","surname":"Aaberg","phone":["555-0100","555-0120"]}';
var contact = JSON.parse(jsontext);
var fullname = contact.surname + ", " + contact.firstname;
DOpus.Output("Full Name: " + fullname);

function includeFile(filename)
{
  var fso = new ActiveXObject("Scripting.FileSystemObject");
  var fileStream = fso.openTextFile(filename);
  var fileData = fileStream.readAll();
  fileStream.Close();
  return fileData;
}

Result:

jscript version: 5.8
Full Name: Aaberg, Jesper

However - invoking the full jscript 5.8 support (the actual printed 5.8 is only 5.7!) and to support the MS built-in JSON.parse would be prefered. Maybe in one of the next DO releases (maybe enabling by default, but disabling in the advanced menu) :smiley:

You know that eval() is basically all you need to "parse" any JSON?
It is not the best option regarding possible jscript code injection, but should get the job done.

Just in case you like to come around that JSON object inclusion clutter.. o)

No, I didn't ... just started programming jscript a few days ago.

I've googled around and always found javascript and json ... so why this module when not needed?

Do you have any small example (without json*.js)?

Thanks a lot!

Ok, JSON basically is straight jscript/javascript code, so you can eval() it directly like so e.g.:

json = "{ var1 : 'value1', var2 : 'value2' }"; eval("jsObject="+json); WScript.Echo(jsObject.var1);

The example uses JSON-data stored in the variable "json" and simply echoes the value of var1, which is a property of the object returned.
I used WScript.Echo() to print the value, which is available only if you run the script directly by the windows scripting host (open a cmd-prompt for this).

cscript.exe <scriptfile>

If you'd like to test this within the DO environment, you need to use "DOpus.Output()" to get the string printed to the DO console (WScript does not exist within DO context).

More complex scripts I always testdrive outside of DO first with just "cscript.exe". It makes life easier for developing different parts of a script, which do not relate directly to DO and its objects.
An editor like Editplus which supports calling of cscript.exe or other interpreters right from the GUI, while fetching the output is handy here as well:


Why JSON-object when not needed: This is basically because of possible code injection into the json-data (I think).
As I said, JSON is code, so to avoid running code downloaded from the internet, while eval()ing it, it probably needs a dedicated parser which checks for non-data things in the JSON stream first.

See this snippet (slighty modified, it uses the return-value of WScript.Echo('Gotcha') to fill "var3".
The moment you eval() this, the code within the json will be run, doing things you possibly don't want to happen. o)

json = "{ var1 : 'value1', var2 : 'value2', var3 : WScript.Echo('Gotcha!')}"; eval("jsObject="+json); WScript.Echo(jsObject.var1);

The output of this is:

Gotcha! value1

Another reason for the existence of JSON in current versions of browsers/server-side things is the easy way of creating a JSON stream.
That JSON object you encountered has an easy to use "stringify" method or something, which converts living objects into JSON-textstreams, some kind of serialization for j(ava)script so to say.

Without JSON-object you'd need a huge amount of code, lots of string operations and loops to convert an object to a json-textstream. As this was something every web-developer once did, they invented the JSON object to save you some time and supply additional safety when parsing content.

Thanks a lot tbone! I only load from discogs.com via their API so I could trust their code.

Do so, but you have been warned, in case discogs get hijacked or something! o))

What are you planning on doing with the discogs data?

I have thousands CDs which I rip with EAC (Exact Audio Copy) and want to auto-rename the directory and files (depending on misc. things).

[ol]
[li] I look for the relesae id on discogs.com
[/li][li] I create the directory with that release id number
[/li][li] I rip the CD with EAC into this directory (possible subdirectories CD1, CD2, etc.)
[/li][li] After ripping a bunch of CDs I start my jscript which ...
[/li][li] ... reads the data of this release id
[/li][li] ... prepares the values how I want them
[/li][li] ....... (e.g. I replace "Version" by "Mix, split "title" into "title" and "mix", only use artist and not ANV artist, etc.
[/li][li] ... renames the directory into "artist_title_releaseid_releaseyear"
[/li][li] ... renames the files from "Trackxx.wav" (Yes, WAV only) into "artist_title_(mix)_[releaseid].wav"
[/li][li] ... then I import this filename data with Tag & Rename into the tags.[/li][/ol]

I'm also planning another one:

Exporting the tag data with Tag & Rename into .csv/.xls, reading this file, download other info I want (SPARS Code, Mastered By, etc.), write it back into the .csv/.xls and re-import the updated tags with Tag & Rename, also checking if the release id still exists, etc. (this script could be also written in another language of course).

Got it.

In case you are interested in avoiding some of this reinvention, I've already created a Discogs script that does what you're looking for. It works with JRiver Media Center. The script is available here:

yabb.jriver.com/interact/index.php?topic=87032.0

I think you'll find the combination of the two does everything you need.

We've made to suggested change so that JSON.parse and other JScript 5.8 features will work in the next release:


Thanks for all the details and MSDN links, which made this a quick and easy change!

:open_mouth: :astonished: :smiley: :grin: :thumbsup:

1 Like

Also thanks to MrC ... will check the source after the kids are in the bed - or I will look the last episodes of Breaking Bad :wink:

Thanks! Being able to use JSON is of course more elegant than anything evil-eval() related. o)