【问题标题】:Output a server generated json object in jade without json parse在没有json解析的jade中输出服务器生成的json对象
【发布时间】:2015-11-08 08:44:18
【问题描述】:

我有一个不符合 JSON 标准的 JSON 对象,我无法更改对象的结构以使其符合 JSON 标准。

我需要在 Jade 模板中的 javascript 块中间渲染这个对象。该对象实际上是一个配置对象,它位于模板中的功能块中。

这里是对象。

{
  services: [],
  version: "1438276796258",
  country: "default",
  role: "User",
  Zack_Init: function () {

  },
  Zack_Global: function (event) {

  },
  Zack_PostRender: function () {

  }, 
  renderers: ['Renderer', 'NONE']
}

更新 这是我从 JS 文件中获取该对象的方法。

function readJSFile(url, filename, callback) {
  fs.readFile(url, "utf-8", function (err, data) {
    if (err) {
      callback(err);
      return;
    }
    try {
      callback(filename, data);
    } catch (exception) {
      callback(exception);
    }
  });
}

当 JSON.stringify 处理对象时,它会在转换过程中删除三个函数。

我正在添加一个 plunker 来显示当前解决方案的进度。输出以下内容。唯一剩下的就是删除格式化字符。

{"services":[],"version":"1438276796258","country":"default","role":"User","Zack_Init":function () {\n\n },"Zack_Global":function (event) {\n\n },"Zack_PostRender":function () {\n\n },"renderers":["Renderer","NONE"]}

function convertToString(obj) {
  return JSON.stringify(obj, function(k, v) {
    return (typeof v === 'function' ? ['@@beginFunction@@', v.toString(), '@@endFunction@@'].join('') : v);
  }).replace(/"@@beginFunction@@|@@endFunction@@"/g, '');
}

obj = {
  services: [],
  version: "1438276796258",
  country: "default",
  role: "User",
  Zack_Init: function() {

  },
  Zack_Global: function(event) {

  },
  Zack_PostRender: function() {

  },
  renderers: ['Renderer', 'NONE']
};

$('#test').text(convertToString(obj));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="test"></div>

【问题讨论】:

  • 具体问题是什么?你试过什么没用?你只是显示一个字符串吗?
  • 已更新以给出实际问题。

标签: javascript json node.js pug


【解决方案1】:

编辑:配置对象是否需要动态选择或修改?你可以使用包含吗?如果不是,那么未转义的缓冲区代码 (http://jade-lang.com/reference/code/) 似乎是使用 readFile 传回的字符串的方法。


字符串化解决方案:

编辑:比我原来的建议更好的解决方案:

function funcyStringify(obj) {
    var funcMap = {};
    var sections = JSON.stringify(obj, function(k, v) {
        if (typeof v === 'function') {
            funcMap[k] = v;
            return ['@@function@@', k, '@@function@@'].join('');
        }
        return v;
    }).split(/"?@@function@@"?/g);
    for (var i = 1; i < sections.length-1; i+=2) {
        sections[i] = funcMap[sections[i]];
    }
    return sections.join('');
}

如果您需要在引用不同函数的嵌套对象中具有相同的属性名称,则需要做更多的工作。


原文如下:

对 Jade 不够熟悉,无法在其中输入此内容,但使用 EJS,您可以执行以下操作:

<script>
var configObject = {
<% for (var key in configObject) {
     if (configObject.hasOwnProperty(key)) { %>
       <%- key %>:
       <% if (typeof configObject[key] === 'function') { %>
           <%- configObject[key].toString() %>
       <% } else { %>
           <%- JSON.stringify(configObject[key]) %>
       <% } %>
<% } } %>
};
</script>

如果您的函数低于顶层,则会变得更加复杂。

【讨论】:

  • 更好的解决方案让我非常接近,但是.toString() 方法正在添加格式字符,如\n\t。我怎样才能将它们也删除?
  • 编辑去掉\n和\t。还将替换字符串从空字符串更改为单个空格,以防万一。如果您在函数中使用双引号或使用转义字符,则需要进行更多修改(您可以摆弄替换正则表达式——可能需要多次替换调用)。
  • 让它删除字符确实有效,但我发现它会干扰代码 // 中的 cmets,然后 cmets 会删除整个 javascript 块。我正在为此添加赏金。希望我们能弄清楚最后一部分,我会把赏金扔给你。谢谢:)
  • @zmanc,已编辑;希望它对你有用:) - 一个限制是目前不处理具有相同属性名称的嵌套对象引用不同的函数。
【解决方案2】:

为了安全地删除换行符,应该先删除'cmets':

function convertToString(obj) {
  return JSON.stringify(obj, function(k, v) {
    return (
      typeof v !== 'function' ? 
        v :
        v.toString().replace(/\/\/.*?$/mg, '')        // removes single line comments
                    .replace(/\/\*[\s\S]*?\*\//g, '') // removes multi-line comments
                    .replace(/[\r\n]/g, '')           // removes new line
    );
  }, 2).replace(/"(function.+)",?$/gm, '$1');         // removes quotes around functions
}

obj = {
  services: [],
  version: "1438276796258",
  country: "default",
  role: "User",
  Zack_Init: function() {
    // comment
    var a = 1;// comment //
    if(a === /*comment */ 3) {//comment
      /* comment
      comment*/
    }
    /*end*/
  },
  Zack_Global: function(event) {
  },
  Zack_PostRender: function() {
  },
  renderers: ['Renderer', 'NONE']
};

$('#result').text(convertToString(obj));
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<pre id="result"></pre>

【讨论】:

  • 这让我大部分时间到达那里,是我需要照顾的一小部分,但这是解决方案的基础。谢谢。
  • 对于那些好奇的人,这是我不得不改变的两件事:.replace(/[\r\n\t]/g, '').replace(/\u007d$/, '},')
【解决方案3】:

如果我正确理解了您的请求(您希望获取从外部加载的文件的内容,然后将其加载到 &lt;script&gt; 块中),我认为到目前为止已探索的解决方案已基本结束- 设计。

这是我所拥有的:

// index.js
var express = require('express');
var router = express.Router();
var fs = require('fs');

router.get('/', function(req, res, next) {
  readJSFile('./whacky_obj.js', 'whacky_json_obj.js', render); // used .js because OP implies that as the file source in the extraction method
  function render(fname, obj) {
    res.render('index', { jsObj: obj });
  }
});

// OP's readJSFile method
function readJSFile(url, filename, callback) {
  fs.readFile(url, "utf-8", function (err, data) {
    if (err) {
      callback(err);
      return;
    }
    try {
      callback(filename, data);
    } catch (exception) {
      callback(exception);
    }
  });
}

module.exports = router;

然后在你的 Jade 文件中:

block content
  h1= title
  script!= jsObj

如果您将script 换成pre,您可以看到jsObj 变量的输出,但script 会按照您的要求执行。

【讨论】:

    猜你喜欢
    • 2017-02-26
    • 2016-08-28
    • 1970-01-01
    • 1970-01-01
    • 2023-03-25
    • 2021-03-19
    • 1970-01-01
    • 1970-01-01
    • 2023-03-03
    相关资源
    最近更新 更多