<p>I just threw together a add-on that will provide a Twig filter called <code>prune</code> to allow you to more easily do what you're asking here.</p>

<p><a href="https://github.com/mattstauffer/craftcms-prune">https://github.com/mattstauffer/craftcms-prune</a></p>

<p>With <code>prune</code> you can now just do the following:</p>

<pre><code>{{ craft.entries.section('news').find() | prune(['title', 'body']) | json_encode() | raw }}
</code></pre>

<p>Just pass in an array of the fields you want to pluck out. It's pretty new and could use some love, but it'll get the basics done for sure.</p>

CC BY-SA 3.0
2014-06-12T13:33:38.503Z
Beautiful. This will give me something to work off of.
Bill Criswell
CC BY-SA 3.0
2014-06-12T15:21:37.007Z
That's just an awesome little plugin, gj!
André Elvan
CC BY-SA 3.0
2014-06-12T13:18:48.580Z
2014-06-12T13:18:48.580Z
Matt Stauffer
<p>You could also loop through all fields and output it depending on the field-type.</p>

<p><strong>Example:</strong></p>

<pre><code>{% spaceless %}

[
    {% for entry in craft.entries.section('news').limit(1) %}
    {
        {# General Fields #}
        'slug': {{ entry.slug | json_encode() | raw }},
        'postDate': {{ entry.postDate | json_encode() | raw }},
        'title': {{ entry.title | json_encode() | raw }},
        'author': {{ entry.author.name | json_encode() | raw }},


        {# Your Fields #}
        {% for field in entry.getType().getFieldLayout().getFields() %}
            {% set field_attr = attribute(entry, field.field.handle) %}

            {% switch field.field.type %}
                {% case 'Assets' %}
                    "{{ field.field.handle | escape('js') }}": { {% for asset in field_attr %} { 'title': {{ asset.title | json_encode() | raw }}, 'url': {{ asset.url | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% case 'Categories' %}
                    "{{ field.field.handle | escape('js') }}": { {% for category in field_attr %} { 'title': {{ category.title | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% case 'Checkboxes' %}
                    "{{ field.field.handle | escape('js') }}": { {% for option in field_attr %} { 'label': {{ option.label | json_encode() | raw }}, 'value': {{ option.value | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% case 'Date' %}
                    "{{ field.field.handle | escape('js') }}": {{ field_attr | json_encode() | raw }},

                {% case 'DropDown' %}
                    "{{ field.field.handle | escape('js') }}": { 'label': {{ field_attr.label | json_encode() | raw }}, 'value': {{ field_attr.value | json_encode() | raw }} },

                {% case 'Entries' %}
                    "{{ field.field.handle | escape('js') }}": { {% for field_entry in field_attr %} { 'title': {{ field_entry.title | json_encode() | raw }}, 'slug': {{ field_entry.slug | json_encode() | raw }}, 'url': {{ field_entry.url | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% case 'Matrix' %}
                    "{{ field.field.handle | escape('js') }}": {{ 'This is a matrix-field' | json_encode() | raw }},

                {% case 'MultiSelect' %}
                    "{{ field.field.handle | escape('js') }}": { {% for option in field_attr %} { 'label': {{ option.label | json_encode() | raw }}, 'value': {{ option.value | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% case 'Radiobutton' %}
                    "{{ field.field.handle | escape('js') }}": { 'label': {{ field_attr.label | json_encode() | raw }}, 'value': {{ field_attr.value | json_encode() | raw }} },

                {% case 'Tags' %}
                    "{{ field.field.handle | escape('js') }}": { {% for tag in field_attr %} { 'name': {{ tag.name | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% case 'Users' %}
                    "{{ field.field.handle | escape('js') }}": { {% for user in field_attr %} { 'name': {{ user.name | json_encode() | raw }}, 'id': {{ user.id | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% default %}
                    "{{ field.field.handle | escape('js') }}": {{ field_attr | json_encode() | raw }},
            {% endswitch %}
        {% endfor %}
    }
    {% endfor %}
]

{% endspaceless %}
</code></pre>

<p><strong>You might need to customize it, depending on what attributes you need</strong></p>

<p>To make it work with Matrix you'd need to create a Matrix case and copy the whole loop inside that case and set it to use the block var.</p>

CC BY-SA 3.0
2014-06-12T13:45:16.623Z
Thanks! I was hoping to get a little bit of Matt's answer with a little bit of this answer. I'm going to try and combine them both with a "json" route maybe as see how that all goes.
Bill Criswell
CC BY-SA 3.0
2014-06-12T13:54:16.743Z
@BillCriswell I think there may be space for us to make `prune` smart enough (or add an additional filter) to do special handling for any other types. I thought about building it all out, but figured it would be better to start with just the pruning part. :)
Matt Stauffer
CC BY-SA 3.0
2014-06-12T14:15:12.580Z
@Matt Would love to see a plugin which handles all the json stuff :)
Victor
CC BY-SA 3.0
2014-06-12T14:18:32.450Z
@victorIn Ha, I was actually going to add a second filter that was pruneToJson that was Prune + json_encode + raw, but I ran out of time. I'll do that soon, but the tougher part is making sure it handles all the other fields correctly like you mentioned here. I'll try to dig in on some lunch break soon and will post back here.
Matt Stauffer
CC BY-SA 3.0
2014-06-12T13:36:29.027Z
2014-06-12T13:36:29.027Z
Victor
<p>You could also do what Victor In has suggested, but deal with everything in arrays and hashes instead of building a big string. That way you only have to encode once at the end, and it's easier (for me) to debug.</p>

<pre><code>{% spaceless %}
  {% set entries = [] %}

  {% for entry in craft.entries.section('people') %}
    {% set thisEntry = {} %}

    {% for fieldModel in entry.getType().getFieldLayout().getFields() %}
      {% set fieldHandle = fieldModel.field.handle %}
      {% set fieldAttr = attribute(entry, fieldHandle) %}

      {% switch fieldModel.field.type %}

        {% case 'Assets' %}
          {% set enumerable = [] %}
          {% for asset in fieldAttr %}
            {% set enumerable = enumerable|merge([{
              'title': asset.title,
              'url': asset.url
            }]) %}
          {% endfor %}
          {% set fieldValue = enumerable %}

        {% default %}
          {% set fieldValue = fieldAttr %}
      {% endswitch %}

      {% set thisEntry = thisEntry|merge({(fieldHandle): fieldValue}) %}
    {% endfor %}

    {% set entries = entries|merge([thisEntry]) %}
  {% endfor %}
  {{ entries | json_encode() | raw }}
{% endspaceless %}
</code></pre>

CC BY-SA 3.0
2014-09-16T19:21:26.327Z
However, I think expanding on Prune's functionality is the way to go!
Tim Kelty
CC BY-SA 3.0
2014-09-16T19:20:58.947Z
2014-09-16T19:20:58.947Z
Tim Kelty
<p>I found another plugin that returns JSON format.</p>

<p>Reference Link: <a href="https://github.com/wesrice/rest-easy" rel="nofollow">https://github.com/wesrice/rest-easy</a></p>

<p>I tested it out. It allows you to configure the parameters you need in the URL. </p>

CC BY-SA 3.0
2017-01-17T00:01:39.163Z
Unfortunately this plugin is now deprecated. The [Element API plugin](https://github.com/pixelandtonic/ElementAPI) is now the best bet.
Simon East
CC BY-SA 3.0
2015-09-10T18:01:08.970Z
2015-09-10T18:01:08.970Z
Sandy D.
<p>Twig is great for outputting HTML/XML markup, but it’s not exactly the best option when you just want to output some data as JSON.</p>

<p>The <a href="https://github.com/pixelandtonic/ElementAPI" rel="noreferrer">Element API</a> plugin aims to make outputting entries (and other element types) as JSON as easy as possible, and it’s completely customizable from its PHP-based API configuration file.</p>

<p>To achieve your desired JSON output, you would set your craft/config/elementapi.php file to this:</p>

<pre class="lang-php prettyprint-override"><code>&lt;?php
namespace Craft;

return [
    'endpoints' =&gt; [

        'entries.json' =&gt; [
            'elementType' =&gt; 'Entry',
            'criteria' =&gt; ['section' =&gt; 'news'],
            'transformer' =&gt; function(EntryModel $entry) {
                return [
                    'title' =&gt; $entry-&gt;title,
                    'body' =&gt; (string) $entry-&gt;body
                ];
            }
        ],

    ]
];
</code></pre>

CC BY-SA 4.0
2020-02-18T06:34:10.907Z
That is the ultimate best answer.
Gfra54
CC BY-SA 3.0
2015-08-19T18:15:58.280Z
2018-02-12T21:32:33.113Z
2018-02-12T21:32:33.113Z
Brandon Kelly
<p>I've played around with a few implementations but I still don't feel like either is right. </p>

<p>I first came across building the JSON itself. This would be in a file at "craft/templates/entries.json".</p>

<pre><code>[
  {% for entry in craft.entries.section('news').find() %}
    {
      "title": "{{ entry.title | e('js') }}",
      "body": "{{ entry.body | e('js') }}"
    } {% if not loop.last %},{% endif %}
  {% endfor %}
]
</code></pre>

<p>This worked but I didn't feel right about writing my own JSON so I came up with this approach instead.</p>

<pre><code>{% set results = [] %}
{% for entry in craft.entries.section('news').find() %}
{%
  set results = results | merge([{
    'title': entry.title,
    'body': entry.body
  }])
%}
{% endfor %}
{{ results | json_encode() | raw }}
</code></pre>

<p>This works, the JSON will definitely end up valid and as a bonus it'll be condensed but it's not very reusable and when I add fields I need to adjust it.</p>

<p>What approach should I take to make a reliable way to query data from Craft and return json?</p>

CC BY-SA 3.0
2014-06-12T01:24:34.713Z
Haven't tried this, but could you just output the array returned by craft.entries? {{ craft.entries.section('news').find() | json_encode() | raw }}
Jeremy Gimbel
CC BY-SA 3.0
2014-06-12T01:27:23.540Z
I gave that a shot at the start but it just returned two empty objects.
Bill Criswell
<entries><json>
How can I retrieve channel data in json format?
# How can I retrieve channel data in json format?

(Asked by: username_0 on 2014-06-12)

I've played around with a few implementations but I still don't feel like either is right. 
I first came across building the JSON itself. This would be in a file at "craft/templates/entries.json".
[
  {% for entry in craft.entries.section('news').find() %}
    {
      "title": "{{ entry.title | e('js') }}",
      "body": "{{ entry.body | e('js') }}"
    } {% if not loop.last %},{% endif %}
  {% endfor %}
]

This worked but I didn't feel right about writing my own JSON so I came up with this approach instead.
{% set results = [] %}
{% for entry in craft.entries.section('news').find() %}
{%
  set results = results | merge([{
    'title': entry.title,
    'body': entry.body
  }])
%}
{% endfor %}
{{ results | json_encode() | raw }}

This works, the JSON will definitely end up valid and as a bonus it'll be condensed but it's not very reusable and when I add fields I need to adjust it.
What approach should I take to make a reliable way to query data from Craft and return json?

**Tags:** entries, json
> **Comments:**
> **username_1**: Haven't tried this, but could you just output the array returned by craft.entries? {{ craft.entries.section('news').find() | json_encode() | raw }}  
> **username_0**: I gave that a shot at the start but it just returned two empty objects.  

---

## 5 answers

### Answer by username_8 on 2015-08-19. Score: 27 | Accepted answer

Twig is great for outputting HTML/XML markup, but it’s not exactly the best option when you just want to output some data as JSON.
The Element API plugin aims to make outputting entries (and other element types) as JSON as easy as possible, and it’s completely customizable from its PHP-based API configuration file.
To achieve your desired JSON output, you would set your craft/config/elementapi.php file to this:
 [

        'entries.json' => [
            'elementType' => 'Entry',
            'criteria' => ['section' => 'news'],
            'transformer' => function(EntryModel $entry) {
                return [
                    'title' => $entry->title,
                    'body' => (string) $entry->body
                ];
            }
        ],

    ]
];

> **Comments:**
> **username_9**: That is the ultimate best answer.  

---

### Answer by username_2 on 2014-06-12. Score: 28

I just threw together a add-on that will provide a Twig filter called prune to allow you to more easily do what you're asking here.
https://github.com/mattstauffer/craftcms-prune
With prune you can now just do the following:
{{ craft.entries.section('news').find() | prune(['title', 'body']) | json_encode() | raw }}

Just pass in an array of the fields you want to pluck out. It's pretty new and could use some love, but it'll get the basics done for sure.

> **Comments:**
> **username_0**: Beautiful. This will give me something to work off of.  
> **username_3**: That's just an awesome little plugin, gj!  

---

### Answer by username_4 on 2014-06-12. Score: 12

You could also loop through all fields and output it depending on the field-type.
Example:
{% spaceless %}

[
    {% for entry in craft.entries.section('news').limit(1) %}
    {
        {# General Fields #}
        'slug': {{ entry.slug | json_encode() | raw }},
        'postDate': {{ entry.postDate | json_encode() | raw }},
        'title': {{ entry.title | json_encode() | raw }},
        'author': {{ entry.author.name | json_encode() | raw }},


        {# Your Fields #}
        {% for field in entry.getType().getFieldLayout().getFields() %}
            {% set field_attr = attribute(entry, field.field.handle) %}

            {% switch field.field.type %}
                {% case 'Assets' %}
                    "{{ field.field.handle | escape('js') }}": { {% for asset in field_attr %} { 'title': {{ asset.title | json_encode() | raw }}, 'url': {{ asset.url | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% case 'Categories' %}
                    "{{ field.field.handle | escape('js') }}": { {% for category in field_attr %} { 'title': {{ category.title | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% case 'Checkboxes' %}
                    "{{ field.field.handle | escape('js') }}": { {% for option in field_attr %} { 'label': {{ option.label | json_encode() | raw }}, 'value': {{ option.value | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% case 'Date' %}
                    "{{ field.field.handle | escape('js') }}": {{ field_attr | json_encode() | raw }},

                {% case 'DropDown' %}
                    "{{ field.field.handle | escape('js') }}": { 'label': {{ field_attr.label | json_encode() | raw }}, 'value': {{ field_attr.value | json_encode() | raw }} },

                {% case 'Entries' %}
                    "{{ field.field.handle | escape('js') }}": { {% for field_entry in field_attr %} { 'title': {{ field_entry.title | json_encode() | raw }}, 'slug': {{ field_entry.slug | json_encode() | raw }}, 'url': {{ field_entry.url | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% case 'Matrix' %}
                    "{{ field.field.handle | escape('js') }}": {{ 'This is a matrix-field' | json_encode() | raw }},

                {% case 'MultiSelect' %}
                    "{{ field.field.handle | escape('js') }}": { {% for option in field_attr %} { 'label': {{ option.label | json_encode() | raw }}, 'value': {{ option.value | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% case 'Radiobutton' %}
                    "{{ field.field.handle | escape('js') }}": { 'label': {{ field_attr.label | json_encode() | raw }}, 'value': {{ field_attr.value | json_encode() | raw }} },

                {% case 'Tags' %}
                    "{{ field.field.handle | escape('js') }}": { {% for tag in field_attr %} { 'name': {{ tag.name | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% case 'Users' %}
                    "{{ field.field.handle | escape('js') }}": { {% for user in field_attr %} { 'name': {{ user.name | json_encode() | raw }}, 'id': {{ user.id | json_encode() | raw }} }, {% else %}null{% endfor %} },

                {% default %}
                    "{{ field.field.handle | escape('js') }}": {{ field_attr | json_encode() | raw }},
            {% endswitch %}
        {% endfor %}
    }
    {% endfor %}
]

{% endspaceless %}

You might need to customize it, depending on what attributes you need
To make it work with Matrix you'd need to create a Matrix case and copy the whole loop inside that case and set it to use the block var.

> **Comments:**
> **username_0**: Thanks! I was hoping to get a little bit of Matt's answer with a little bit of this answer. I'm going to try and combine them both with a "json" route maybe as see how that all goes.  
> **username_2**: @BillCriswell I think there may be space for us to make `prune` smart enough (or add an additional filter) to do special handling for any other types. I thought about building it all out, but figured it would be better to start with just the pruning part. :)  
> **username_4**: @Matt Would love to see a plugin which handles all the json stuff :)  
> **username_2**: @victorIn Ha, I was actually going to add a second filter that was pruneToJson that was Prune + json_encode + raw, but I ran out of time. I'll do that soon, but the tougher part is making sure it handles all the other fields correctly like you mentioned here. I'll try to dig in on some lunch break soon and will post back here.  

---

### Answer by username_5 on 2014-09-16. Score: 5

You could also do what Victor In has suggested, but deal with everything in arrays and hashes instead of building a big string. That way you only have to encode once at the end, and it's easier (for me) to debug.
{% spaceless %}
  {% set entries = [] %}

  {% for entry in craft.entries.section('people') %}
    {% set thisEntry = {} %}

    {% for fieldModel in entry.getType().getFieldLayout().getFields() %}
      {% set fieldHandle = fieldModel.field.handle %}
      {% set fieldAttr = attribute(entry, fieldHandle) %}

      {% switch fieldModel.field.type %}

        {% case 'Assets' %}
          {% set enumerable = [] %}
          {% for asset in fieldAttr %}
            {% set enumerable = enumerable|merge([{
              'title': asset.title,
              'url': asset.url
            }]) %}
          {% endfor %}
          {% set fieldValue = enumerable %}

        {% default %}
          {% set fieldValue = fieldAttr %}
      {% endswitch %}

      {% set thisEntry = thisEntry|merge({(fieldHandle): fieldValue}) %}
    {% endfor %}

    {% set entries = entries|merge([thisEntry]) %}
  {% endfor %}
  {{ entries | json_encode() | raw }}
{% endspaceless %}

> **Comments:**
> **username_5**: However, I think expanding on Prune's functionality is the way to go!  

---

### Answer by username_6 on 2015-09-10. Score: 1

I found another plugin that returns JSON format.

Reference Link: <https://github.com/wesrice/rest-easy>

I tested it out. It allows you to configure the parameters you need in the URL.

> **Comments:**
> **username_7**: Unfortunately this plugin is now deprecated. The [Element API plugin](https://github.com/pixelandtonic/ElementAPI) is now the best bet.  

---

