I have a JSON object that does not conform to JSON standards, and I cannot change the structure of the object to make it adhere to JSON standards.
I need to make this object render in the middle of a javascript block in a Jade template. The object is actually a configuration object that is going in a function block in the template.
Here is the object.
{
services: [],
version: "1438276796258",
country: "default",
role: "User",
Zack_Init: function () {
},
Zack_Global: function (event) {
},
Zack_PostRender: function () {
},
renderers: ['Renderer', 'NONE']
}
UPDATE Here is how I am getting that object from a JS file.
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);
}
});
}
When JSON.stringify processes the object it drops the three functions in the conversion process.
I am adding a plunker to show the progress of the current solution. Which outputs the below. The only thing left is to remove the formatting characters.
{"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>
If I'm understanding your request correctly (that you want to take the contents of a file that's loaded externally and then load it in a <script>
block), I think the solutions that have been explored so far are largely over-engineered.
Here's what I have:
// 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;
And then in your Jade file:
block content
h1= title
script!= jsObj
You can see the output from the jsObj
variable if you swap script
for pre
, but script
will do what you're asking.
In order to remove new line characters safely, 'comments' should be removed first:
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>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With