Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-06-12T13:33:38.503Z
Answers.Text: Beautiful. This will give me something to work off of.
Answers.UserDisplayName: Bill Criswell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-06-12T15:21:37.007Z
Answers.Text: That's just an awesome little plugin, gj!
Answers.UserDisplayName: André Elvan
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-06-12T13:18:48.580Z
Answers.LastActivityDate: 2014-06-12T13:18:48.580Z
Answers.UserDisplayName: Matt Stauffer
Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-06-12T13:45:16.623Z
Answers.Text: 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.
Answers.UserDisplayName: Bill Criswell
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-06-12T13:54:16.743Z
Answers.Text: @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. :)
Answers.UserDisplayName: Matt Stauffer
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-06-12T14:15:12.580Z
Answers.Text: @Matt Would love to see a plugin which handles all the json stuff :)
Answers.UserDisplayName: Victor
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-06-12T14:18:32.450Z
Answers.Text: @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.
Answers.UserDisplayName: Matt Stauffer
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-06-12T13:36:29.027Z
Answers.LastActivityDate: 2014-06-12T13:36:29.027Z
Answers.UserDisplayName: Victor
Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-09-16T19:21:26.327Z
Answers.Text: However, I think expanding on Prune's functionality is the way to go!
Answers.UserDisplayName: Tim Kelty
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2014-09-16T19:20:58.947Z
Answers.LastActivityDate: 2014-09-16T19:20:58.947Z
Answers.UserDisplayName: Tim Kelty
Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2017-01-17T00:01:39.163Z
Answers.Text: Unfortunately this plugin is now deprecated. The [Element API plugin](https://github.com/pixelandtonic/ElementAPI) is now the best bet.
Answers.UserDisplayName: Simon East
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-09-10T18:01:08.970Z
Answers.LastActivityDate: 2015-09-10T18:01:08.970Z
Answers.UserDisplayName: Sandy D.
Answers.Body: <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>
  
Answers.ContentLicense: CC BY-SA 4.0
Answers.CreationDate: 2020-02-18T06:34:10.907Z
Answers.Text: That is the ultimate best answer.
Answers.UserDisplayName: Gfra54
Answers.ContentLicense: CC BY-SA 3.0
Answers.CreationDate: 2015-08-19T18:15:58.280Z
Answers.LastActivityDate: 2018-02-12T21:32:33.113Z
Answers.LastEditDate: 2018-02-12T21:32:33.113Z
Answers.UserDisplayName: Brandon Kelly
Body: <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>
  
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2014-06-12T01:24:34.713Z
Comments.Text: Haven't tried this, but could you just output the array returned by craft.entries? {{ craft.entries.section('news').find() | json_encode() | raw }}
Comments.UserDisplayName: Jeremy Gimbel
Comments.ContentLicense: CC BY-SA 3.0
Comments.CreationDate: 2014-06-12T01:27:23.540Z
Comments.Text: I gave that a shot at the start but it just returned two empty objects.
Comments.UserDisplayName: Bill Criswell
Tags: <entries><json>
Title: How can I retrieve channel data in json format?
ThreadText: # 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](https://github.com/pixelandtonic/ElementAPI) 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:
  
  ```php
  <?php
  namespace Craft;
  
  return [
      'endpoints' => [
  
          '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/username_2/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 username_2'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**: @username_0 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**: @username_2 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 username_4 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.  
  
  ---
  
  