What hook can I use to modify Views Datasource JSON output? I'm using Views and Views Datasource to generate a JSON feed for my site. I've got a Video field which has both a video and a thumbnail image.

I want to include the url of the thumbnail image in my json feed. I add the Video field to my list of fields in the View and I choose the "Video thumbnail" format instead of the "Video Player" format so that it will show the thumbnail instead of the video. When I do this in a normal View it works perfectly. However, when I do it with a JSON document view, it doesn't work properly. It renders the url to the video instead of rendering the url to the thumbnail image. 

I'm going to create another question which talks about how to get this to work properly, but THIS question is my backup solution. 

I can rewrite the field so that it includes the fid of the thumbnail image, so my current idea is implementing a hook that will allow me to post process the rendered json or manipulate the data structure before it gets converted to json so that I can just lookup the image by its fid and then replace that piece of data in the array with the proper image url.

I have tried MANY hooks so far, but none of them provide data which represents the json data. 


hook_views_pre_view 
hook_views_pre_render 
hook_views_post_render
hook_views_post_execute


My guess is that Views Datasource is processing the data after I've seen it in my hook implementations.

What hook can I use so manipulate the data structure before it gets converted to json or alternatively, what hook can I use to manipulate the json string after it has been converted to json?
I find my 1st answer informative regarding auxillery information regarding views and views_datasource. So here's 1 way I think you get the url you want.

You said:


  My guess is that Views Datasource is processing the data after I've
  seen it in my hook implementations.


It is, look at what views_json_view_pre_render() is doing:

function views_json_views_pre_render(&amp;$view) {
  if(isset($view-&gt;plugin_name) &amp;&amp; $view-&gt;plugin_name == 'views_json') {
    // Support for Video field.
    if(!empty($view-&gt;result)) {
      // Process each View result.
      foreach($view-&gt;result as $row =&gt; $result) {
        // Only process the entity fields defined by the View.
        foreach($view-&gt;field as $field_name =&gt; $field) {
          if($field instanceof views_handler_field_field) {
            if($field-&gt;field_info['type'] == 'video') {

              // Get the Video URL.
              $video = $field-&gt;get_value($view-&gt;result[$row]);
              // -- See this line !!
              $url = file_create_url($video[0]['uri']);
              $render_array = array(
                '#type' =&gt; 'markup',
                '#markup' =&gt; filter_xss($url),
              );
              // Substitute embed code with URL. @todo Add support for escaped embed codes.
              // See this line !!
              $view-&gt;result[$row]-&gt;{'field_'. $field_name}[0]['rendered'] = $render_array;
            }


If its a video field views_json is taking each of the results and replacing the embed code with the URL of the video. This is what  you're seeing.

So how do you fix this. You write your own hook_views_pre_render() that runs before views_json's pre render. In your pre render function you change $video[0]['uri'] to whatever url you want -- ultimately thats the value views_json will use. If you can get the FID or the full url to the image here you should be able to easily set that value.

So in your own module you'd write 2 functions:

// File: mymodule.install
function MYMODULE_install() {
// Set the weight of the mymodule.module to a value lower than views_datasource's views_json module.
  db_update('system')
   -&gt;fields(array('weight' =&gt; -1))
   -&gt;condition('name', 'mymodule')
   -&gt;execute();
}


// File: mymodule.module
/**
 * Implements hook_views_pre_render().
 */
function mymodule_views_pre_render(&amp;$view) {
  if(isset($view-&gt;plugin_name) &amp;&amp; $view-&gt;plugin_name == 'views_json' &amp;&amp; $view-&gt;name == 'YOUR_SPECIFIC_VIEW') {
    // Support for Video field.
    if(!empty($view-&gt;result)) {
      // Process each View result.
      foreach($view-&gt;result as $row =&gt; $result) {
        // Only process the entity fields defined by the View.
        foreach($view-&gt;field as $field_name =&gt; $field) {
          if($field instanceof views_handler_field_field) {
            if($field-&gt;field_info['type'] == 'video') {
              // Change the video uri to the image you want ...
              $view-&gt;result[$row][0]['uri'] = /* some logic here */;
            }
          }
        }
      }
    }
  }
}


Your pre render hook will run before views_datasource's. It simply alters the url to whatever you want. Then views_datasource's views_json hook runs and just uses it as its supposed to -- you just slipped in the correct value. This should work. Code is untested.