Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Output a server generated json object in jade without json parse

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>
like image 885
zmanc Avatar asked Aug 15 '15 03:08

zmanc


2 Answers

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.

like image 200
36 revs, 21 users 73% Avatar answered Nov 03 '22 03:11

36 revs, 21 users 73%


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>
like image 41
manji Avatar answered Nov 03 '22 02:11

manji