cscript jscript JSON

时间:2013-10-18 08:40:34

标签: json jscript wsh

这是一个非常非常(非常!!!)奇怪的问题。

我在一个名为CSCRIPT的文件中使用dos testJSON.js在Windows XP和7上运行这个JSCRIPT。

if ( ! this.JSON ) WScript.Echo("JSON DOESN'T EXISTS");

而且,消息出现了,但这是JSCRIPT的意外行为,因为JSON(如MSDN documentation所说)是JSCRIPT 5.8中的默认对象之一,而我的Windows 7系统运行完全JSCRIPT 5.8

现在,我通过创建一个新的文本文件并手动编写一个有效的JSON字符串来临时解决了这个问题(在一个复杂的小脚本中)(显然,即使系统没有,一切也能正常工作) JSON要求的JSCRIPT 5.8但我主要想知道两件事:

第一为什么即使我的JSCRIPT版本支持该对象,我也无法使用JSON对象?

第二次我的JSCRIPT环境中有read something about the "enabling" of the JSON (and other) unavailable object,但所有示例都是针对C#的,我想知道是否存在一些JSCRIPT的等效代码。

3 个答案:

答案 0 :(得分:17)

您可以使用eval()来达到与JSON.parse()类似的效果。

eval('obj = {' + JSONstring + '}');

之后,obj.toString()会让您检索类似JSON.stringify()的数据(只是没有美化选项)。 See this answer在野外举个例子。关键是,您可以从JSON文本创建对象,而无需加载任何外部库或切换解释器引擎。

大胖警告!!!

这会在运行代码的工作站中引入漏洞。如果您不控制要解析的JSON的生成,或者第三方可能在其生成及其解释之间修改JSON,请考虑遵循Helen's advice。如果JSON中有不好的东西,它可能会导致你的WScript做坏事。例如,如果您的JSON字符串或文件包含以下内容:

};
var oSH = WSH.CreateObject("wscript.shell"),
    cmd = oSH.Exec("%comspec%");
WSH.Sleep(250);
cmd.StdIn.WriteLine("net user pwnd password /add");
WSH.Sleep(250);
cmd.StdIn.WriteLine("net group Administrators pwnd /add");
WSH.Sleep(250);
cmd.Terminate();
var obj = {
    "objName": {
        "item1": "value 1",
        "item2": "value 2"
    }

...然后使用eval解析它将刚刚为您的计算机添加了一个新的管理员,而没有任何视觉指示它发生。

我的建议是随意使用eval私人或临时使用;但是对于广泛部署,请考虑包括json2.js,正如海伦建议的那样。 修改:或......

htmlfile COM对象

您可以通过调用htmlfile COM对象并通过<META>标记将其强制转换为IE9(或更高版本)兼容模式来导入JSON方法:

var htmlfile = WSH.CreateObject('htmlfile'), JSON;
htmlfile.write('<meta http-equiv="x-ua-compatible" content="IE=9" />');
htmlfile.close(JSON = htmlfile.parentWindow.JSON);

使用这三行,JSON对象和方法被复制到JScript运行时,允许您在不使用eval()或下载json2.js的情况下解析JSON。你现在可以做这样的事情:

var pretty = JSON.stringify(JSON.parse(json), null, '\t');
WSH.Echo(pretty);

以下是细分:

// load htmlfile COM object and declare empty JSON object
var htmlfile = WSH.CreateObject('htmlfile'), JSON;

// force htmlfile to load Chakra engine
htmlfile.write('<meta http-equiv="x-ua-compatible" content="IE=9" />');

// The following statement is an overloaded compound statement, a code golfing trick.
// The "JSON = htmlfile.parentWindow.JSON" statement is executed first, copying the
// htmlfile COM object's JSON object and methods into "JSON" declared above; then
// "htmlfile.close()" ignores its argument and unloads the now unneeded COM object.
htmlfile.close(JSON = htmlfile.parentWindow.JSON);

See this answer用于其他方法(通过XHR下载json2.js,InternetExplorer.Application COM对象,HTA混合方法和另一个htmlfile示例。

答案 1 :(得分:9)

  

为什么即使我的JSCRIPT版本支持该对象,我也无法使用JSON对象?

根据MSDN,Windows脚本宿主默认使用JScript 5.7功能集来实现向后兼容。 JScript 5.8功能集仅在IE8 +标准文档模式的Internet Explorer中使用。

您有以下选择:

  1. 在您的脚本中加入json2.js。有关在JScript脚本中包含外部脚本的选项,请参阅this question

  2. 将注册表修改为expose IE9's JScript engine to Windows Script Host UPD:此解决方案使用IE的JScript DLL,但不激活5.8功能集。

  3. Create a JScript execution host programmatically使用Active Script界面​​并使用IActiveScriptProperty::SetProperty强制使用JScript 5.8功能集(SCRIPTLANGUAGEVERSION_5_8)。 Here's a C++ example

  4.   

    我已经阅读了关于在JSCRIPT环境中“启用”JSON(和其他)不可用对象的内容,但所有示例都是针对C#的,我想知道是否存在一些JSCRIPT的等效代码。

    自定义脚本执行主机只能使用具有适当COM支持的语言创建,例如C ++,C#等.JScript不能用于此,因为,例如,它不支持输出参数。

答案 2 :(得分:0)

JSON编码,无需默认解析器即可解码:official documentation states

var $ = {};

/**
 * Decode JSON
 *
 * @param string jsonString - JSON text
 *
 * @return object
 */
$.json.decode = function(jsonString) {
    return (new Function("return " + jsonString)());
};

/**
 * Encode JSON
 *
 * @param object obj - Key/Value object
 *
 * @return string
 */
$.json.encode = function(obj) {
    var items = [];
    var isArray = (function(_obj) {
        try {
            return (_obj instanceof Array);
        } catch (e) {
            return false;
        }
    })(obj);
    var _toString = function(_obj) {
        try {
            if(typeof(_obj) == "object") {
                return $.json.encode(_obj);
            } else {
                var s = String(_obj).replace(/"/g, '\\"');
                if(typeof(_obj) == "number" || typeof(_obj) == "boolean") {
                    return s;
                } else {
                    return '"' + s + '"';
                }
            }
        } catch (e) {
            return "null";
        }
    };

    for(var k in obj) {
        var v = obj[k];

        if(!isArray) {
            items.push('"' + k + '":' + _toString(v));
        } else {
            items.push(_toString(v));
        }
    }

    if(!isArray) {
        return "{" + items.join(",") + "}";
    } else {
        return "[" + items.join(",") + "]";
    }
};

/**
 * Test JSON
 *
 * @param object obj - Key/Value object
 *
 * @return boolean
 */
$.json.test = function(obj) {
    var t1 = obj;
    var t2 = $.json.encode(obj);
    $.echo($.json.encode(t1));

    var t3 = $.json.decode(t2);
    var t4 = $.json.encode(t3);
    $.echo(t4);

    if(t2 == t4) {
        $.echo("success");
        return true;
    } else {
        $.echo("failed");
        return false;
    }
};

/**
 * Echo
 *
 * @param string txt
 *
 * @return void
 */
$.echo = function(txt) {
    if($.isWScript()) {
        WScript.Echo(txt);
    } else {
        try {
            window.alert(txt);
        } catch (e) {
            console.log(txt);
        }
    }
};

/**
 * Check if WScript
 *
 * @return bool
 */
$.isWScript = function() {
    return typeof(WScript) !== "undefined";
}

// test your data
var t1 = {"a": 1, "b": "banana", "c": {"d": 2, "e": 3}, "f": [100, 200, "3 hundreds", {"g": 4}]};
$.json.test(t1);