WSH(JScript)でJSONを使う

WSH(JScript)でコードを書いてみる」のJSON記事を分離したものです。

JSON

WSH(JScript)は、JavaScriptですが標準で、JSONが存在しません。そのため、JSON.stringify()JSON.parse()を使用できません。JSON使用したい場合、polyfillを導入するかCOMオブジェクトから取得する必要があります。

JSONの使用方法としては、以下のようなものがあります。

  • JSON
    • 40行
    • eval()使用あり
    • JSON.stringify(obj.prototype);等で意図しない表示となる
    • サンプル
  • json2.js
    • 37KB
    • eval()使用あり
  • json3.js
  • htmlfileのJSON(COMオブジェクトから取得)
    • 数行
    • COMオブジェクトから取得するため、重い?
    • サンプル

それぞれ、一長一短があるので条件に合うものを選びましょう。

サンプル:JSON

JSON.wsf<?xml version="1.0" encoding="UTF-16" standalone="yes" ?>
<package>
  <job>
    <script language="JavaScript">
//<![CDATA[
(function() {
  "use strict";

  var global = Function('return this')();
  if (!global.JSON) {
    global.JSON = {
      parse: function(sJSON) { return eval('(' + sJSON + ')'); },
      stringify: (function () {
        var toString = Object.prototype.toString;
        var hasOwnProperty = Object.prototype.hasOwnProperty;
        var isArray = Array.isArray || function (a) { return toString.call(a) === '[object Array]'; };
        var escMap = {'"': '\\"', '\\': '\\\\', '\b': '\\b', '\f': '\\f', '\n': '\\n', '\r': '\\r', '\t': '\\t'};
        var escFunc = function (m) { return escMap[m] || '\\u' + (m.charCodeAt(0) + 0x10000).toString(16).substr(1); };
        var escRE = /[\\"\u0000-\u001F\u2028\u2029]/g;
        return function stringify(value) {
          if (value == null) {
            return 'null';
          } else if (typeof value === 'number') {
            return isFinite(value) ? value.toString() : 'null';
          } else if (typeof value === 'boolean') {
            return value.toString();
          } else if (typeof value === 'object') {
            if (typeof value.toJSON === 'function') {
              return stringify(value.toJSON());
            } else if (isArray(value)) {
              var res = '[';
              for (var i = 0; i < value.length; i++)
                res += (i ? ', ' : '') + stringify(value[i]);
              return res + ']';
            } else if (toString.call(value) === '[object Object]') {
              var tmp = [];
              for (var k in value) {
                // in case "hasOwnProperty" has been shadowed
                if (hasOwnProperty.call(value, k))
                  tmp.push(stringify(k) + ': ' + stringify(value[k]));
              }
              return '{' + tmp.join(', ') + '}';
            }
          }
          return '"' + value.toString().replace(escRE, escFunc) + '"';
        };
      })()
    };
  }

  function main() {
    var obj = {a:"abc"};
    var text = JSON.stringify(obj);

    WScript.Echo(text);   // {"a":"abc"}

    var obj2 = JSON.parse(text);

    WScript.Echo(obj2.a); // abc
  }

  main();
})();
//]]>
    </script>
  </job>
</package>

サンプル:json3.js

json3.wsf<?xml version="1.0" encoding="UTF-16" standalone="yes" ?>
<package>
  <job>
    <script language="JavaScript" src="../lib/json3.js"/>
    <script language="JavaScript">
//<![CDATA[
(function() {
  "use strict";

  function main() {
    var obj = {a:"abc"};
    var text = JSON.stringify(obj);

    WScript.Echo(text);   // {"a":"abc"}

    var obj2 = JSON.parse(text);

    WScript.Echo(obj2.a); // abc
  }

  main();
})();
//]]>
    </script>
  </job>
</package>

サンプル:htmlfile

htmlfile.wsf<?xml version="1.0" encoding="UTF-16" standalone="yes" ?>
<package>
  <job>
    <script language="JavaScript">
//<![CDATA[
(function() {
  "use strict";

  var global = Function('return this')();
  if (!global.JSON) {
    var html = new ActiveXObject('htmlfile');
    html.write('<meta http-equiv="x-ua-compatible" content="IE=11" />');
    global.JSON = html.parentWindow.JSON;
    html.close();
    html = null;
  }

  function main() {
    var a = '{"test":"Hello World"}';
    var b = JSON.parse(a);
    WScript.Echo(b.test);       // Hello World
    var c = JSON.stringify(b);
    WScript.Echo(c);            // {"test":"Hello World"}
  }

  main();
})();
//]]>
    </script>
  </job>
</package>