10

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

我有这个在 Windows XP 和 7 上运行的 JSCRIPT,它CSCRIPT在一个名为testJSON.js.

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

而且,该消息出现了,但是 JSCRIPT 的意外行为,因为 JSON(如MSDN文档所述)是 Windows 7 上的默认对象之一,JSCRIPT 5.8并且我的系统在 Windows 7 上完全运行JSCRIPT 5.8

现在,我通过创建一个新的文本文件并手动组合一个有效的 JSON 字符串临时解决了这个问题(在一个有点复杂的脚本中)(而且,很明显,即使系统没有JSCRIPT 5.8JSON 的请求,这也使一切正常) 但我主要想知道两件事:

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

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

4

3 回答 3

19

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

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

之后,obj.toString()将让您检索类似的数据JSON.stringify()(只是没有美化选项)。有关野外示例,请参见此答案。关键是,您可以从 JSON 文本创建对象,而无需加载任何外部库或切换解释器引擎。

大胖警告!!!

这会在运行您的代码的工作站中引入一个漏洞。如果您不控制要解析的 JSON 的生成,或者第 3 方可能会在生成和解释之间修改 JSON,请考虑遵循Helen 的建议。如果 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私人或休闲用途;但对于广泛部署,请考虑按照 Helen 的建议 包含json2.js 。编辑:或者...

htmlfile COM 对象

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

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);

有关其他方法(通过 XHR 下载 json2.js、InternetExplorer.ApplicationCOM 对象、HTA 混合方法和另一个示例),请参见此答案htmlfile

于 2014-12-25T00:41:51.123 回答
10

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

根据MSDN,Windows Script Host 默认使用 JScript 5.7 功能集以实现向后兼容性。JScript 5.8 功能集仅在 IE8+ 标准文档模式下的 Internet Explorer 中使用。

您有以下选择:

  1. 在您的脚本中包含json2.js 。有关在 JScript 脚本中包含外部脚本的选项,请参阅此问题

  2. 修改注册表以向 Windows Script Host 公开 IE9 的 JScript 引擎UPD:此解决方案使用 IE 的 JScript DLL,但不激活 5.8 功能集。

  3. 使用 Active Script 接口以编程方式创建 JScript 执行主机IActiveScriptProperty::SetProperty,并用于强制 JScript 5.8 功能集 ( SCRIPTLANGUAGEVERSION_5_8)。这是一个 C++ 示例

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

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

于 2013-10-21T07:43:54.417 回答
0

JSON 编码,无需默认解析器即可解码:https ://gist.github.com/gnh1201/e372f5de2e076dbee205a07eb4064d8d

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);
于 2019-07-24T08:26:52.677 回答