【问题标题】:How to get JSON type as JSON instead of String from Nodejs Mysql如何从 Nodejs Mysql 获取 JSON 类型作为 JSON 而不是 String
【发布时间】:2018-09-26 21:23:37
【问题描述】:

我在 MySQL 5.7 中有表说 TEST(id INT, attribute JSON)

当我尝试使用mysql包查询Nodejs中的表时,如下所示

con.query("select * from TEST where id=?", [req.params.id], function (err, results) {
    if (err) throw err;
    console.log(results);
  });

我得到以下输出

[
   {
        "id": 2,
        "package": "{\"tag\": \"tag1\", \"item\": \"item1\"}"
    }
]

有没有办法在不迭代数组的情况下将上述结果中的包项作为 JSON 对象而不是字符串获取并执行 JSON.parse 将字符串转换为 JSON?

预期输出

[
       {
            "id": 2,
            "package": {"tag": "tag1", 
                        "item": "item1"}
        }
    ]

【问题讨论】:

    标签: mysql node.js mysql-5.7


    【解决方案1】:

    我想你需要做的就是JSON.parse(results)

    con.query("select * from TEST where id=?", [req.params.id], function (err, results) {
    if (err) throw err;
    console.log(JSON.parse(results));
    

    });

    编辑!评论者指出您需要遍历结果,我的回答很仓促并且行不通:

    con.query("select * from TEST where id=?", [req.params.id], function (err, results) {
    if (err) throw err;
    results = results.map(row => (row.package = JSON.parse(row.package), row));
    

    });

    【讨论】:

    • results 已经是一个数组,这将不起作用。他必须迭代并JSON.parse每个包。
    • 仍然无法工作:P,您需要在每一行 package 上使用 JSON.parse。所以results = results.map(row => (row.package = JSON.parse(row.package), row))
    • 超越了自己,@MarcosCasagrande,ty
    【解决方案2】:

    有没有办法将上述结果中的包裹项获取为 JSON 对象而不是字符串而不迭代数组并执行 JSON.parse 将字符串转换为 JSON?

    MySQL 5.7 支持JSON data type,因此您可以将包类型更改为JSON,如果您的客户端支持此数据类型,您不必在每一行上迭代和执行JSON.parse

    请记住,mysql 包不支持它,但 mysql2 支持。

    CREATE TABLE `your-table` (
      `id` int(11) NOT NULL AUTO_INCREMENT,
      `package` json DEFAULT NULL,
      PRIMARY KEY (`id`)
    ) ENGINE=InnoDB;
    

    现在包将是一个数组/对象:

    con.query("select * from TEST where id=?", [req.params.id], function (err, results) {
        if (err) throw err;
        console.log(results[0].package.tag); // tag1 using mysql2
        console.log(results[0].package.item); // item1 using mysql2
    });
    

    如果您运行的 MySQL 版本低于 5.7,或者您不想使用 JSON 类型,则需要自己迭代和解析。

    你可以使用这一个班轮:

    results = results.map(row => (row.package = JSON.parse(row.package), row));
    

    如果您想知道是否应该或不应该将 JSON 存储在关系数据库中,可以在这个问题中进行很好的讨论:

    Storing JSON in database vs. having a new column for each key

    【讨论】:

    • 感谢马科斯的回复。我使用 JSON 作为我的问题中提到的数据类型。默认情况下,mysql 查询节点模块的结果会自动转换为 STRING,即我不能直接作为 JSON 对象访问。我需要做 JSON.parse(results[0].package)...
    • @Deepan 检查我更新的答案,你必须使用mysql2 包!而且您没有提到您使用的是 JSON 数据类型。
    • 谢谢马库斯。 mysql2 包完成了这项工作。我用mysql2节点包替换了mysql。
    • 关键是mysql2包。谢谢!
    【解决方案3】:

    您可以将 typeCast 函数传递给您的 mysql 连接/池。就我而言,如果可能,我想将所有长文本字段转换为 JSON。在失败的情况下,你仍然会得到原始值。

    let auth = {database:'db', password:'pw', user:'u', host:'host.com' };
    auth.typeCast = function(field, next) {
        if (field.type == 'BLOB' && field.length == 4294967295) {
            let value = field.string();
            try {
                return JSON.parse(value);
            } catch (e) {
                return value;
            }
        }
        return next();
    };
    let connection = mysql.createConnection(auth);
    

    【讨论】:

      【解决方案4】:

      您可以使用包mysql2 代替mysql。它会默认解析结果。

      【讨论】:

        【解决方案5】:

        这与 Tanner 的回答略有不同,但是,如果您使用节点 mysql 库并且您已使用 MySQL 的 JSON 数据类型在数据库中定义字段,则可以在最初设置时使用“类型转换”将任何查询返回的任何 JSON 类型的值转换为 JSON 对象的连接:

        let connection = mysql.createConnection(
          {typeCast: function (field, next) {
            if (field.type === "JSON") {
              return JSON.parse(field.string());
            } else {
              return next();
            }
          }}
        );
        

        【讨论】:

          猜你喜欢
          • 2020-11-25
          • 2020-05-26
          • 1970-01-01
          • 2016-04-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2020-03-01
          • 2021-09-21
          相关资源
          最近更新 更多