Formatting Channel Entries as JSON in ExpressionEngine

If you are working with javascript a lot in ExpressionEngine, you will probably at some point need to use AJAX. Libraries such as jQuery make this easy, and out of the box it’s possible to create simple ExpressionEngine templates which can return HTML to be consumed by your javascript code. However, it is sometimes more convenient to return JSON data which can then be formatted client-side using javascript.

Producing JSON with ExpressionEngine is not so straightforward. There is a plugin for ExpressionEngine which produce JSON formatted output but this offers no customisation over the output, which is especially important if using complex custom fields (such as Channel Files or Channel Images).

Basic JSON

The solution is to create the formatted JSON yourself using standard ExpressionEngine templates. Below is a simple example of a channel entry formatted as JSON. The basic form of JSON is that each object should consist of a series of name-value pairs, with each pair separated by a comma, with the whole object surrounded by braces.

  {
    "Title": "Test Blog Post",
    "Link": "http://www.mysite.com/blog/view/test-blog-post/",
    "Summary": "This is the summary of my blog post",
    "Category": "Test Posts",
    "Image": "<img width=\"100\" height=\"100\" alt=\"Image Description\" title=\"Image Title\" src=\"http://www.mysite.com/images/test-blog-post-image.png\">"
  }

Notice that any double-quotes in the values have to be escaped with a forward-slash to ensure they can be interpreted correctly in javascript.

If you have multiple objects (i.e. an array), each object should be separated by a comma and the whole array should be enclosed in square brackets.

[
  {
    "Title": "Test Blog Post",
    "Link": "http://www.mysite.com/blog/view/test-blog-post/",
    "Summary": "This is the summary of my blog post",
    "Category": "Test Posts",
    "Image": "<img width=\"100\" height=\"100\" alt=\"Image Description\" title=\"Image Title\" src=\"http://www.mysite.com/images/test-blog-post-image.png\">"
  },
  {
    "Title": "Test Blog Post 2",
    "Link": "http://www.mysite.com/blog/view/test-blog-post2/",
    "Summary": "This is the summary of my blog post 2",
    "Category": "Test Posts",
    "Image": "<img width=\"100\" height=\"100\" alt=\"Image Description\" title=\"Image Title\" src=\"http://www.mysite.com/images/test-blog-post2-image.png\">"
  }
]

Producing JSON with ExpressionEngine

So, that’s the basic form of JSON, how can we produce this in ExpressionEngine using templates? Here is an example which does just that.

[
    {exp:channel:entries channel="blog" limit="100" backspace="6"}
    {
        "Title": "{title}",
        "Link": "{title_permalink="blog/view"}",
        "Summary": "{if summary}{summary}{/if}",
        "Category": "{categories limit="1"}{category_name}{/categories}",
        "Image": "{exp:channel_images:images entry_id="{entry_id}" limit="1"}<img width=\"{image:width}\" height=\"{image:height}\" alt=\"{image:description}\" title=\"{image:title}\" src=\"{image:url}\">{/exp:channel_images:images}"
    },
    {/exp:channel:entries}
]

All we are doing here is injecting into a simple JSON template the channel tags to produce the output required. As you can see, we can format the channel tags however we want, including using conditionals, nest tags etc.

Producing JSON with ExpressionEngine Correctly

There’s just one problem with the template above. We’ve already stated above that any double-quotes in the JSON object values need to be escaped to ensure that we don’t break the formatting of the output. However, we cannot be sure what values will be within the individual channel entries. We therefore need to act defensively and remove/escape any characters which might cause problems. Luckily for us, that nice man Low has provided the excellent Low Replace plugin which allows us to perform find and replace operations on any tag prior to display.

In this case, we want to prefix double-quotes with a backslash, and also also remove any linebreaks as then can also destroy the formatting.

[
    {exp:channel:entries channel="blog" limit="100" backspace="6"}
    {
        "Title": "{exp:low_replace find="QUOTE|NEWLINE" replace="\QUOTE|SPACE" multiple="yes"}{title}{/exp:low_replace}",
        "Link": "{title_permalink="blog/view"}",
        "Summary": "{if summary}{exp:low_replace find="QUOTE|NEWLINE" replace="\QUOTE|SPACE" multiple="yes"}{summary}{/exp:low_replace}{/if}",
        "Category": "{categories limit="1"}{exp:low_replace find="QUOTE|NEWLINE" replace="\QUOTE|SPACE" multiple="yes"}{category_name}{/exp:low_replace}{/categories}",
        "Image": "{exp:channel_images:images entry_id="{entry_id}" limit="1"}<img width=\"{image:width}\" height=\"{image:height}\" alt=\"{image:description}\" title=\"{image:title}\" src=\"{image:url}\">{/exp:channel_images:images}"
    },
    {/exp:channel:entries}
]

And you’re done. >Once you’ve completed your JSON, you might want to check that the JSON produced is valid (because if it isn’t valid your jQuery will typically fail silently). For this, I use the excellent JSLint online validator.

05
Jan 2012
POSTED BY
POSTED IN ExpressionEngine
DISCUSSION 7 Comments
TAGS