在没有 json 解析的情况下在 jade 中输出服务器生成的 json 对象
Output a server generated json object in jade without json parse
我有一个 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 处理对象时,它会在转换过程中删除三个函数。
我正在添加一个插件来显示当前解决方案的进度。输出如下。唯一剩下的就是删除格式字符。
{"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>
编辑:配置对象是您需要 select 还是动态修改的东西?你可以使用包含吗?如果不是,那么未转义的缓冲区代码 (http://jade-lang.com/reference/code/) 似乎是处理 readFile 传回的字符串的方法。
Stringify 解决方案:
编辑:比我原来的建议更好的解决方案:
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>
如果你有低于顶层的函数,会变得更复杂。
为了安全地删除换行符,应该先删除'comments':
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, ''); // 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>
如果我正确理解了您的请求(您想要获取外部加载的文件的内容,然后将其加载到 <script>
块中),我认为已经探索过的解决方案far 在很大程度上是过度设计的。
这是我拥有的:
// 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
会按照您的要求执行。
我有一个 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 处理对象时,它会在转换过程中删除三个函数。
我正在添加一个插件来显示当前解决方案的进度。输出如下。唯一剩下的就是删除格式字符。
{"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>
编辑:配置对象是您需要 select 还是动态修改的东西?你可以使用包含吗?如果不是,那么未转义的缓冲区代码 (http://jade-lang.com/reference/code/) 似乎是处理 readFile 传回的字符串的方法。
Stringify 解决方案:
编辑:比我原来的建议更好的解决方案:
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>
如果你有低于顶层的函数,会变得更复杂。
为了安全地删除换行符,应该先删除'comments':
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, ''); // 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>
如果我正确理解了您的请求(您想要获取外部加载的文件的内容,然后将其加载到 <script>
块中),我认为已经探索过的解决方案far 在很大程度上是过度设计的。
这是我拥有的:
// 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
会按照您的要求执行。