Properly Iterating Through JSON Data in EJS Templates: Avoiding Common Pitfalls and Best Practices

Dec 02, 2025 · Programming · 11 views · 7.8

Keywords: EJS Templates | JSON Iteration | Node.js | Template Engine | JavaScript Data Processing

Abstract: This article provides an in-depth exploration of common error patterns when handling JSON data in EJS templates, particularly issues arising from the misuse of JSON.stringify(). Through analysis of a typical example, it explains why directly iterating over stringified data yields unexpected results and presents correct solutions. The article also discusses the characteristics of JavaScript execution context in EJS templates, explaining why certain client-side code (like alert) doesn't work properly in EJS. Finally, by comparing the advantages and disadvantages of different approaches, it proposes best practices for efficiently processing JSON data in EJS.

Introduction: Common Misconceptions in JSON Processing with EJS Templates

When using the EJS (Embedded JavaScript) templating engine, developers frequently need to handle JSON data passed from the server to the client. A common requirement is to iterate through this data within templates to dynamically generate HTML content. However, due to insufficient understanding of EJS execution context and JavaScript data type conversion, many developers fall into typical traps.

Problem Analysis: Why JSON.stringify() Causes Iteration Errors

Consider this typical erroneous code example:

<% for(var i=0; i<JSON.stringify(data).length; i++) { %>
   <tr>
     <td>
       <%= JSON.stringify(data)[i].id %>
     </td>
   </tr>
<% } %>

The root cause of this problem lies in misunderstanding the JSON.stringify() method. JSON.stringify() converts JavaScript objects to JSON strings, rather than returning the original array. For example, with the following data:

var data = [
    { id: 1, name: "bob" },
    { id: 2, name: "john" },
    { id: 3, name: "jake" }
];

JSON.stringify(data) actually returns:

"[{\"id\":1,\"name\":\"bob\"},{\"id\":2,\"name\":\"john\"},{\"id\":3,\"name\":\"jake\"}]"

This is a string whose length is the character count (approximately 70 characters in this example), not the element count of the original array (3 elements). Therefore, when using JSON.stringify(data).length as the loop condition, the loop executes approximately 70 times instead of the expected 3 times.

Correct Solution: Using Raw Data Directly

The correct approach is to use the raw JavaScript array passed from the server directly, rather than converting it to a string. Here's the corrected code:

<table>
<% for(var i=0; i < data.length; i++) { %>
   <tr>
     <td><%= data[i].id %></td>
     <td><%= data[i].name %></td>
   </tr>
<% } %>
</table>

How this code works:

  1. data is the raw JavaScript array object passed from the server
  2. data.length correctly returns the element count of the array (3)
  3. data[i].id and data[i].name directly access the properties of array elements
  4. EJS's <%= %> tags automatically convert values to strings for output

Execution Context Analysis: Why alert() Doesn't Work in EJS

Another common issue is attempting to use client-side JavaScript functions like alert() in EJS templates:

<% alert('t'); %> or <% window.alert('t'); %>

This causes a "not defined" error because JavaScript code within EJS templates executes on the server side, not in the browser. The EJS templating engine runs on the Node.js server, converting templates to HTML strings before sending them to the client. In the server-side execution environment:

If you need to display an alert box on the client side, the correct approach is:

<script>
    alert('t');
</script>

Advanced Techniques: Safely Passing JSON Data

In some scenarios, you genuinely need to pass JSON data to client-side JavaScript. In such cases, security considerations are important:

<script>
    var row = <%- JSON.stringify(data) %>;
    // Now row is a JavaScript array available on the client side
    console.log(row);
    // Can be further processed in client-side JavaScript
    row.forEach(function(item) {
        console.log(item.id, item.name);
    });
</script>

Here, EJS's <%- %> tag (unescaped output) is used because JSON.stringify() already generates valid JSON strings. However, note:

Performance Optimization Recommendations

When handling large amounts of data, performance considerations become important:

  1. Avoid Repeated Calls: Don't repeatedly call JSON.stringify(data) within loops, as this causes unnecessary performance overhead
  2. Cache References: For frequently accessed data, cache it in local variables
  3. Use EJS Local Variables: EJS supports local variable passing, which can reduce global lookups

Best Practices Summary

Based on the above analysis, best practices for handling JSON data in EJS include:

  1. Using raw JavaScript objects directly in template logic, rather than stringified versions
  2. Clearly distinguishing between server-side execution (<% %>) and client-side execution (<script>) code
  3. When data needs to be passed to the client, using <%- JSON.stringify(data) %> to safely output JSON
  4. Always properly escaping and validating user input data
  5. Avoiding repeated calculations in loops and caching frequently used values to improve performance

By following these principles, developers can avoid common pitfalls and write secure, efficient EJS template code.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.