如何解析包含函数的 JSON 字符串

How can I parse a JSON string containing functions?

本文关键字:JSON 字符串 函数 何解析 包含      更新时间:2023-09-26

我有一个JSON对象,看起来像这样:

string str = '[
  {
    "name": "data-input1",
    "type": "Element [in]",
    "description": "data-input1",
    "getConnectorPosition": "function (element) { return {x: 0, y: Math.floor(element.rectangle.width / 2)} }"
  },
  {
    "name": "data-output1",
    "type": "Element [out] [array]",
    "description": "data-output1",
    "getConnectorPosition": "function (element) { return {x: Math.floor(element.rectangle.width), y: Math.floor(element.rectangle.height / 2)} }"
  }
  ]';

我想将此字符串解析为一个对象。

我收到此错误:

Uncaught TypeError: string is not a function

当调用方法 getConnectorPosition 时。

阅读之前的问题,我已经了解到 JSON 中的函数并不完全"合法",错误也表明了这一点。

究竟如何正确解析包含函数(如上所述)的 JSON 对象,然后调用这些函数?

你的错误被抛出是因为在 JavaScript 中你没有将变量声明为某种类型,你总是使用 var 关键字。如果将string str更改为var str则当前错误将消失。

然后,您需要确保字符串是单行的,或者转义文字换行符,因为 JavaScript 无法处理多行字符串:

     var str = '['
        { "name": "data-input1", '
         "type": "Element [in]", '

无论如何,假设您正确声明str,并且单行或转义换行符,您可以正常解析它:

var obj = JSON.parse(str);

并以字符串形式访问您的函数,如下所示:

obj[0].getConnectorPosition;

要实际使用您的函数,您必须评估它们:

eval(obj[0].getConnectorPosition)

function (element) { return { x: 0, y: Math.floor(element.rectangle.width / 2) } }
<小时 />

更现代的更新 (ES6+):

您可以使用 letconst 来定义变量,声明const变量以后无法更改,并且let优先于var,因为它的作用域更安全。

还可以将模板字符串文本用于多行字符串。

所以你可以写:

const str = `[
  {
    "name": "data-input1",
    "type": "Element [in]",
    "description": "data-input1",
    "getConnectorPosition": "function (element) { return {x: 0, y: Math.floor(element.rectangle.width / 2)} }"
  },
  {
    "name": "data-output1",
    "type": "Element [out] [array]",
    "description": "data-output1",
    "getConnectorPosition": "function (element) { return {x: Math.floor(element.rectangle.width), y: Math.floor(element.rectangle.height / 2)} }"
  }
  ]`;

你得到的实际错误是因为你应该写var str = ...而不是string

您可以获取包含该函数的子字符串,并使用 eval 将它们作为函数进行评估。但是,这可能会导致严重的安全问题和其他问题。引用道格拉斯·克罗克福德的话:

eval 函数(及其相关函数 Function、setTimeout 和 setInterval)提供对 JavaScript 编译器的访问。这有时是必要的,但在大多数情况下,它表明存在极其糟糕的编码。eval 函数是 JavaScript 中最容易被滥用的特性。

如果你真的想走这条路,你可以用eval来做,但你已经被警告:)

顺便说一下,如果你已经解析了你的JSON,你可以这样做:

obj[0].getConnectorPosition = eval(obj[0].getConnectorPosition);

因此,您将以前的字符串替换为计算的方法。

下面是一个将包含函数的 json 字符串转换回具有有效函数声明的 json 对象的示例。

var jsonstring = "{'"schema'": {'"title'": '"User Feedback'",        '"description'":'"so'", '"type'":'"object'", '"properties'":{'"name'":{'"type'":'"string'"}}}," + "'"options'":{ '"form'":{'"attributes'":{}, '"buttons'":{ '"submit'":{ '"title'":'"It'", '"click'":'"function(){alert('hello');}'" }}} }}";
var jsonData = JSON.parse(jsonstring);
function Iterate(data)
{
      jQuery.each(data, function (index, value) {
        if (typeof value == 'object') {
            Iterate(value);
        }
        else {
            if (value.indexOf("function()") > -1)
                data[index] = eval("(" + value + ")");
        }
    });
};
Iterate(jsonData);
//call the embedded function 
jsonData.options.form.buttons.submit.click();