103

I'm using Handlebars templates and JSON data is already represented in [Object object], how do I parse this data outside of the Handlebars? For example, I'm trying to populate a JavaScript variable on the page through a handlebars tag, but this doesn't work.

Any suggestions? Thank you!

EDIT:

To clarify, I'm using ExpressJS w/ Handlebars for templating. In my route, I have this:

var user = {}
user = {'id' : 123, 'name' : 'First Name'}

res.render('index', {user : user});

Then in my index.hbs template, I now have a {{user}} object. I can use {{#each}} to iterate through the object just fine. However, I'm also using Backbonejs and I want to pass this data to a View, such as this:

myView = new myView({
   user : {{user}}
});

The problem is that {{user}} simply shows [Object object] in the source. If I put it in console.log I get an error that says 'Unexpected Identifier'.

2
  • You'll have to elaborate on "doesn't work." Can you provide a relevant snippet of code and a description of what you're expecting instead of [Object object]? If you're simply trying to see the object's keys/values, you'll want to use console.log with a debugger or JSON.stringify. Commented Apr 19, 2012 at 16:53
  • Console.log shows [Object object] also. I'll update post to explain better. Commented Apr 19, 2012 at 16:57

10 Answers 10

202

When outputting {{user}}, Handlebars will first retrieve the user's .toString() value. For plain Objects, the default result of this is the "[object Object]" you're seeing.

To get something more useful, you'll either want to display a specific property of the object:

{{user.id}}
{{user.name}}

Or, you can use/define a helper to format the object differently:

Handlebars.registerHelper('json', function(context) {
    return JSON.stringify(context);
});
myView = new myView({
    user : {{{json user}}} // note triple brackets to disable HTML encoding
});
Sign up to request clarification or add additional context in comments.

9 Comments

it should be: {{{json user}}}, otherwise the json string will be encoded.
Thank you, this is perfect. For Express users: app.set('view engine', 'hbs'); var Handlebars = require('hbs');
Works great. Also for express-handlebars users: var exphbs = require('express-handlebars'); app.engine('handlebars', exphbs({ helpers: { json: function (context) { return JSON.stringify(context); } } }));
Or just include the helpers when you render. res.render('index', { var1: 'some value', helpers: { json: function (context) { return JSON.stringify(context); } });
@acmoune Going over the network, from server to client, the object has to be serialized into a data format. So sending it as it is in memory isn't strictly possible. Though, you may be able to share the definition of the User type and reconstruct the instance for the client – user : new User({{{json user}}}).
|
16

You can simple stringify the JSON:

var user = {}
user = {'id' : 123, 'name' : 'First Name'};
// for print
user.stringify = JSON.stringify(user);

Then in template print by:

{{{user.stringify}}};

1 Comment

The answers above are splendid. I actually encountered an issue when rendering the JSON string in the view because i had an unescaped quote, This answer solved that stackoverflow.com/a/22105906/7998284
7

I'm using server-side templating in node-js, but this may apply client-side as well. I register Jonathan's json helper in node. In my handler, I add context (such as addressBook) via res.locals. Then I can store the context variable client-side as follows:

<script>
  {{#if addressBook}}
  console.log("addressBook:", {{{json addressBook}}});
  window.addressBook = {{{json addressBook}}};
  {{/if}}
</script>

Note the triple curlies (as pointed out by Jim Liu).

Comments

7

You can render the keys/values of a list or object in a Handlebars template like this:

{{#each the_object}}
  {{@key}}: {{this}}
{{/each}}

1 Comment

Note that this will print [object Object] for nested objects
4

Just improving the answer from @sajjad.

Adding a 'pre' tag will make it look a lot nicer.

<pre>
  {{#each the_object}}
    {{@key}}: {{this}}
  {{/each}}
</pre>

1 Comment

This is actually a good answer if you don't want to register a helper.
2

In the Node Router - Stringify the response object. See below line.

 response.render("view", {responseObject:JSON.stringify(object)});

In HTML Script tag - user Template literals (Template strings) and use JSON.parse.

const json= `{{{responseObject}}}`;
const str = JSON.parse(json);

Worked like a charm!

1 Comment

What if you dont want to use a script tag.
1

You are trying to pass templating syntax {{ }} inside a JSON object which is not valid.

You may need to do this instead:

myView = new myView({ user : user });

Comments

1

To condense (what I found to be) the most helpful answers...

JSON helper for handlebars (credit):

Handlebars.registerHelper("json", function (context) {
    return JSON.stringify(context);
});

JSON helper for express-handlebars (credit and I updated to newest conventions):

app.engine(
    "handlebars",
    exphbs.engine({
        defaultLayout: "main",
        helpers: {
            json: function (context) { 
                return JSON.stringify(context);
            }
        }
    })
);

And then on the templating side: {{json example}}

Comments

0

If you want more control over the output formatting you can write your own helper. This one has a recursive function to traverse nested objects.

  Handlebars.registerHelper('objToList', function(context) {
    function toList(obj, indent) {
      var res=""
      for (var k in obj) { 
          if (obj[k] instanceof Object) {
              res=res+k+"\n"+toList(obj[k], ("   " + indent)) ;
          }
          else{
              res=res+indent+k+" : "+obj[k]+"\n";
          }
      }
      return res;
    }    
    return toList(context,"");
  });

We used handlebars for email templates and this proved useful for a user like the following

{
  "user": {
    "id": 123,
    "name": "First Name",
    "account": {
      "bank": "Wells Fargo",
      "sort code": " 123-456"
    }
  }
}

Comments

0

You can do this:

 <div>
   {{toJSON this}}   
</div>

Define toJSON() in helper.js:

var helper = {};
module.exports = helper;
    helper.toJSON = function (context) {
        return JSON.stringify(context);
    };

In App.js:

const helper = require('./helper/helper');
app.engine('hbs', handlebars({
  layoutsDir: __dirname + '/views/layouts',
  extname: 'hbs',
  helpers: helper
}));

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.