如何将 JSON 对象与来自 MySQL ('Concat') 的数组嵌入到 NodeJS 中的 EJS 文件中?

How to embed a JSON object with arrays from MySQL ('Concat') into a EJS-File in NodeJS?

出于测试目的,我在 demo.js 中创建了一个 JSON 对象,它应该集成到 ejs 模板中。

如果我这样做,在 ejs 页面中一切正常。 但是我创建了 JSON 对象动态。来自 SQL 查询(见下文)。

这是我的设置:

demo.js

function gameData() {

    return {
        id: 13,
        round: 1,
        user: [{
            id: 4711,
            player_id: 1,
            name: "John",
            value: 3,
            active: 1
        }, {
            id: 4712,
            player_id: 2,
            name: "Phil",
            value: 3,
            active: 0
        }]
    }
}

module.exports = {
    gameData: gameData
}

app.js

let gameDemo = require('./demo');

app.get('/game', (req, res) => {
    res.render('pages/game', {
        utils: gameDemo
    });
})

ejs 站点

<% utils.gameData().user.forEach(function(element, index, item){ %>
    <%= element.player_id %>
<% }); %>

在这里,我创建了一个 MySQL 数据库 (5.7) 连接,并得到 JSON 对象作为结果。不幸的是,它不适用于那个。

app.js

app.get('/game', (req, res) => {

    ...

    db.getConnection((error, connection) => {
        
        let sqlQuery = `SELECT
                            CONCAT("{",
                            CONCAT("id:" , g.id, ","),
                            CONCAT("round:" , g.round, ","),
                            CONCAT("user:", "[",
                                GROUP_CONCAT(
                                CONCAT("{"),
                                    CONCAT("id:" , gd.id, ","),
                                    CONCAT("player_id:" , gd.player_id, ","),
                                    CONCAT("name:" , gd.name, ","),
                                    CONCAT("value:" , gd.value, ","),
                                    CONCAT("active:" , gd.active, ","),
                                CONCAT("}")
                                )
                            ,"]")
                            ,"}")
                        AS json FROM game_data gd
                            INNER JOIN games g
                            ON g.game_id = gd.game_id
                        WHERE gd.game_id = '235816ab-2ad8-41b2-8375-d980e207e43f'`

        connection.query(sqlQuery, (err,row, fields) => { 
        
            res.render('pages/game', {
                utils: row[0].json
            });

        })
        connection.release();

    })
     
 })

index.ejs

<% utils.gameData().user.forEach(function(element, index, item){ %>
     <%= element.player_id %>
<% }); %>

我收到错误:“无法读取未定义的 属性 'forEach'”

如果我在 ejs 中调用 <% = utils %>,我会得到字符串形式的 JSON 对象。

然后我尝试 JSON.parse(row[0].json) 并得到 SyntaxError: Unexpected token t in JSON at position 1 在 JSON.parse ()

JSON.parse(result) 显示错误 undefined:1 [object Object]

然后我尝试了

app.get('/game', (req, res) => {

    ...

    db.getConnection((error, connection) => {
        
        let sqlQuery = `SELECT
                            CONCAT("{",
                            CONCAT("id:" , g.id, ","),
                            CONCAT("round:" , g.round, ","),
                            CONCAT("user:", "[",
                                GROUP_CONCAT(
                                CONCAT("{"),
                                    CONCAT("id:" , gd.id, ","),
                                    CONCAT("player_id:" , gd.player_id, ","),
                                    CONCAT("name:" , gd.name, ","),
                                    CONCAT("value:" , gd.value, ","),
                                    CONCAT("active:" , gd.active, ","),
                                CONCAT("}")
                                )
                            ,"]")
                            ,"}")
                        AS json FROM game_data gd
                            INNER JOIN games g
                            ON g.game_id = gd.game_id
                        WHERE gd.game_id = '235816ab-2ad8-41b2-8375-d980e207e43f'`

        connection.query(sqlQuery, (err, result) => { 

            res.render('pages/game', {
                utils: result[0].json // JSON Object
            });

        })
        connection.release();

    })
     
 })

在 ejs 文件中我得到一个 json 对象

console.log(<%= utils %>) // JSON Object in console OK
console.log(typeof <%= utils %>) // Object

如果我在 javascript 区域创建一个变量 let obj = <%= utils %>; 我可以完全访问数据。

但是,如何从 ejs 的数组中获取任何值?

我发现,如果查询有“大”结果(超过 10 个 key/val),key/value 对有时会换行。请参阅用户密钥 9。没有可识别的错误模式。

结果的奇怪行为。该错误仅在用户数组中的对象中发生一次。但并不是每个对象都会受到影响。

从 sql 结果中提取:

{
    "id": 13,
    "round": 1,
    "user": [{
        "1": 8,
        "2": 9,
        "3": 10,
        "4": 0,
    "5": 8,
    "6": 9,
    "7": 10,
    "8": 0,
    "9": 
    8,
    "10": 9,
    "11": 10,
    "12": 0,
    "13": 8,
    "14": 9,
    "15": 10
    }]
}

解决方案

我将 SQL 查询放在双引号中并对其进行了转义。 将 SQL 结果(字符串类型)解析为对象,仅此而已。

db.getConnection((error, connection) => {

    let sqlQuery = `SELECT
      CONCAT("{",
        CONCAT("\"id\":" , g.id, ","),
        CONCAT("\"round\":" , g.round, ","),
        CONCAT("\"user\":", "[",
            GROUP_CONCAT(
              CONCAT("{"),
                  CONCAT("\"id\":" , gd.id, ","),
                  CONCAT("\"player_id\":" , gd.player_id, ","),
                  CONCAT("\"name\":" , gd.name, ","),
                  CONCAT("\"value\":" , gd.value, ","),
                  CONCAT("\"active\":" , gd.active, ","),
              CONCAT("}")
            )
        ,"]")
      ,"}")
  AS json FROM game_data gd
  INNER JOIN games g ON g.game_id = gd.game_id
  WHERE gd.game_id = '235816ab-2ad8-41b2-8375-d980e207e43f'`

    connection.query(sqlQuery, (err, result) => {

        let stringRes = result[0].json
        let obj = JSON.parse(stringRes)

        res.render('pages/game', {
            gamedata: obj
        });

    })
    connection.release();

})

现在我可以完全访问 ejs 文件中的 JSON-Object。

对象内的值:<%= gamedata.id %>

用户数组中的值:<%= gamedata.user[0].player_id %>

用户数组中每个对象的值:

<% for (var i = 0, l = gamedata.user.length; i < l; i++) {
  var obj = gamedata.user[i];
%>
  <option value="<%= i %>"><%= obj.player_id %></option>
<% } %>