diff -urp views-view-json.tpl.php views-view-json.tpl.php.patched
--- views-view-json.tpl.php	2009-11-01 18:53:41.000000000 -0500
+++ views-view-json.tpl.php.patched	2009-11-09 01:46:53.000000000 -0500
@@ -1,5 +1,5 @@
 <?php
-// $Id: views-view-json.tpl.php,v 1.1.2.8 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
@@ -15,180 +15,177 @@
  */
 
 
-switch ($options['format']) {
-  // Simple (Coder)
-  case 'simple-coder':
-    json_simple_render($view, TRUE);
-    break;
-
-  // MIT Simile/Exhibit
-  case 'exhibit':
-    json_exhibit_render($view);
-    break;
-
-  // MIT Simile/Exhibit (Coder)
-  case 'exhibit-coder':
-    json_exhibit_render($view, TRUE);
-    break;
-
-  // Simple
-  default:
-    json_simple_render($view);
-}
-
+$options['displaying_output'] = $view->override_path;
 
-function json_simple_render($view, $coder_mode = FALSE) {
-  define('EXHIBIT_DATE_FORMAT', '%Y-%m-%d %H:%M:%S');
+json_render($view->result, $options);
 
-  $eol      = '';
-  $spaces1  = '';
-  $spaces2  = '';
-  $spaces4  = '';
-
-  if ($view->override_path) {
-    // inside a live preview so use HTML line breaks and space accordingly
-    $eol      = '<br />';
-    $spaces1  = ' ';
-    $spaces2  = str_repeat('&nbsp;', 2);
-    $spaces4  = str_repeat('&nbsp;', 4);
-  }
-
-  $json = '{' . $spaces1 .'"nodes"'. $spaces1 .':'. $spaces1 .'['. $eol;
-
-  $more_view_results = FALSE;
-  foreach ($view->result as $node) {
-    $json .= ($more_view_results ? ','. $eol : '') . $spaces2 .'{'. $eol;
-
-    $more_fields = FALSE;
-    foreach ($node as $field_label => $field_value) {
-      $label = trim(views_json_strip_illegal_chars(views_json_encode_special_chars($field_label)));
-      $value = views_json_encode_special_chars(trim(views_json_is_date($field_value)));
-      if ((is_null($value)) || ($value == '')) continue;
-
-//    if (preg_match('/\d/', $value)) {
-//      if (strtotime($value)) {
-//        $value = gmstrftime(EXHIBIT_DATE_FORMAT, strtotime($value));
-//      }
-//    }
 
-      // strip out Profile: from profile fields
-      $label = str_replace('_value', '', str_replace('profile_values_profile_', '', $label));
+/**
+ * Render JSON.
+ *
+ * The function will directly output a JSON string instead of returning it.
+ *
+ * @param $items
+ *   The collection of items to encode into JSON.
+ * @param $options
+ *   Render options.
+ */
+function json_render($items, $options) {
+  $obj = new stdClass();
 
-      if ($view->override_path) {
-        $value = check_plain($value);
-      }
+  // do some preprocessing if necessary
 
-      $json .= ($more_fields ? ','. $eol : '') . $spaces4 .'"'. $label .'"'. $spaces1 .':'. $spaces1 .'"'. $value .'"';
+  if ($options['format'] === 'exhibit') {
+    // we'll be rendering MIT Simile/Exhibit JSON
 
-      $more_fields = TRUE;
+    // add required fields
+    $num_items = count($items);
+    for ($i = 0; $i < $num_items; ++$i) {
+      if (!isset($items[$i]->type)) {
+        $items[$i]->type = (isset($node->type) ? $node->type : 'Item');
+      }
+      if (!isset($items[$i]->label)) {
+        $items[$i]->label = (isset($node->type) ? $node->title : 'none');
+      }
     }
 
-    $json .= $eol . $spaces2 .'}';
-
-    $more_view_results = TRUE;
+    $obj->items = _json_exhibit_preprocess($items);
   }
-
-  $json .= ']'. $spaces1 .'}';
-
-  if ($view->override_path) {
-    // we're inside a live preview so pretty-print the JSON
-    print '<code>'. $json .'</code>';
+  else {
+    // we'll be rendering regular JSON
+    $obj->nodes = $items;
   }
-  elseif ($coder_mode) {
-    // we're in "coder" mode so just output the JSON
-    print $json;
+
+  // render the output
+  if ($options['displaying_output']) {
+    // we're inside a live preview where the JSON is pretty-printed
+    print '<code>'. _json_preview_render($obj) .'</code>';
   }
   else {
-    // we're in callback mode so switch the content type and stop further processing of the page
-    drupal_set_header('Content-Type: text/javascript');
-    print $json;
-    module_invoke_all('exit');
-    exit;
+    if (function_exists('json_encode')) {
+      $json = json_encode($obj);
+    }
+    else {
+      $json = _json_render($obj);
+    }
+
+    if ($options['using_coder']) {
+      // we're in "coder" mode
+      print $json;
+    }
+    else {
+      // we want to send the JSON as a server response so switch the content type
+      // and stop further processing of the page.
+      drupal_set_header('Content-Type: application/json');
+      print $json;
+      module_invoke_all('exit');
+      exit;
+    }
   }
 }
 
 
-function json_exhibit_render($view, $coder_mode = FALSE) {
-  define('EXHIBIT_DATE_FORMAT', '%Y-%m-%d %H:%M:%S');
+/**
+ * Helper function that builds the JSON.
+ */
+function _json_render($var) {
+//  define('EXHIBIT_DATE_FORMAT', '%Y-%m-%d %H:%M:%S');
 
-  $eol      = '';
-  $spaces1  = '';
-  $spaces2  = '';
-  $spaces4  = '';
-
-  if ($view->override_path) {
-    // inside a live preview so use HTML line breaks and space accordingly
-    $eol      = '<br />';
-    $spaces1  = ' ';
-    $spaces2  = str_repeat('&nbsp;', 2);
-    $spaces4  = str_repeat('&nbsp;', 4);
-  }
-
-  $json = '{' . $spaces1 .'"items"'. $spaces1 .':'. $spaces1 .'['. $eol;
-
-  $more_view_results = FALSE;
-  foreach ($view->result as $node) {
-    $json .= ($more_view_results ? ','. $eol : '') . $spaces2 .'{'. $eol;
-    $json .= $spaces4 .'"type"'. $spaces1 .':'. $spaces1 .'"'.'##type##'.'",'. $eol;
-    $json .= $spaces4 .'"label"'. $spaces1 .':'. $spaces1 .'"'.'##label##'.'",'. $eol;
-
-    $more_fields = FALSE;
-    foreach ($node as $field_label => $field_value) {
-      $label = trim(views_json_strip_illegal_chars(views_json_encode_special_chars($field_label)));
-      $value = views_json_encode_special_chars(trim(views_json_is_date($field_value)));
-      if ((is_null($value)) || ($value == '')) continue;
-
-//    if (preg_match('/\d/', $value)) {
-//      if (strtotime($value)) {
-//        $value = gmstrftime(EXHIBIT_DATE_FORMAT, strtotime($value));
+  // hack of the elegant drupal_to_js() function
+  switch (gettype($var)) {
+    case 'boolean':
+      // lowercase is necessary!
+      return $var ? 'true' : 'false';
+    case 'integer':
+    case 'double':
+      return $var;
+    case 'resource':
+    case 'string':
+//      if (preg_match('/\d/', $var)) {
+//        if (strtotime($var)) {
+//          $var = gmstrftime(EXHIBIT_DATE_FORMAT, strtotime($value));
+//        }
 //      }
-//    }
-
-      // strip out Profile: from profile fields
-      $label = str_replace('_value', '', str_replace('profile_values_profile_', '', $label));
 
-      if ($view->override_path) {
-        $value = check_plain($value);
-      }
-
-      if ($label == 'type') {
-        $json = str_replace('##type##', $value, $json);
-      }
-      elseif ($label == 'label') {
-        $json = str_replace('##label##', $value, $json);
+      $value = views_json_encode_special_chars(trim(views_json_is_date($var)));
+//      $value = str_replace(array("\r", "\n", "<", ">", "&"),
+//                           array('\r', '\n', '\x3c', '\x3e', '\x26'),
+//                           addslashes($value));
+      return '"'. $value .'"';
+    case 'array':
+      // Arrays in JSON can't be associative.  If the array is empty or if it
+      // has sequential whole number keys starting with 0, it's not associative
+      // so we can go ahead and convert it as an array.
+      if (empty($var) || array_keys($var) === range(0, sizeof($var) - 1)) {
+        $output = array();
+        foreach ($var as $v) {
+          $output[] = _json_render($v);
+        }
+        return '['. implode(',', $output) .']';
       }
-      else {
-        $json .= ($more_fields ? ','. $eol : '') . $spaces4 .'"'. $label .'"'. $spaces1 .':'. $spaces1 .'"'. $value .'"';
+      // Otherwise, fall through to convert the array as an object.
+    case 'object':
+      $output = array();
+      foreach ($var as $k => $v) {
+        $output[] = _json_render(strval($k)) .':'. _json_render($v);
       }
-    }
-
-    if (strpos($json, '##type##') !== FALSE) {
-      $json = str_replace('##type##', (isset($node->type) ? $node->type : 'Item'), $json);
-    }
-    if (strpos($json, '##label##') !== FALSE) {
-      $json = str_replace('##label##', (isset($node->title) ? $node->title : 'none'), $json);
-    }
+      return '{'. implode(',', $output) .'}';
+    default:
+      return 'null';
+  }
+}
 
-    $json .= $eol . $spaces2 .'}';
 
-    $more_view_results = TRUE;
-  }
+/**
+ * Helper function that builds pretty-printed JSON.
+ */
+function _json_preview_render($var, $depth = 0) {
+//  define('EXHIBIT_DATE_FORMAT', '%Y-%m-%d %H:%M:%S');
 
-  $json .= ']'. $spaces1 .'}';
+  $base_indent  = '&nbsp;&nbsp;';
+  $eol          = '<br />';
+  $indent       = str_repeat($base_indent, $depth);
+
+  // hack of the elegant drupal_to_js() function
+  switch (gettype($var)) {
+    case 'boolean':
+      // lowercase is necessary!
+      return $var ? 'true' : 'false';
+    case 'integer':
+    case 'double':
+      return $var;
+    case 'resource':
+    case 'string':
+//      if (preg_match('/\d/', $var)) {
+//        if (strtotime($var)) {
+//          $var = gmstrftime(EXHIBIT_DATE_FORMAT, strtotime($value));
+//        }
+//      }
 
-  if ($view->override_path) {
-    // we're inside a live preview so pretty-print the JSON
-    print '<code>'. $json .'</code>';
-  }
-  elseif ($coder_mode) {
-    // we're in "coder" mode so just output the JSON
-    print $json;
-  }
-  else {
-    // we're in callback mode so switch the content type and stop further processing of the page
-    drupal_set_header('Content-Type: text/javascript');
-    print $json;
-    module_invoke_all('exit');
-    exit;
+      $value = views_json_encode_special_chars(trim(views_json_is_date($var)));
+//      $value = str_replace(array("\r", "\n", "<", ">", "&"),
+//                           array('\r', '\n', '\x3c', '\x3e', '\x26'),
+//                           addslashes($value));
+      return '"'. check_plain($value) .'"';
+    case 'array':
+      // Arrays in JSON can't be associative.  If the array is empty or if it
+      // has sequential whole number keys starting with 0, it's not associative
+      // so we can go ahead and convert it as an array.
+      if (empty($var) || array_keys($var) === range(0, sizeof($var) - 1)) {
+        $output = array();
+        foreach ($var as $v) {
+          $output[] = $indent . $base_indent . _json_preview_render($v, $depth + 1);
+        }
+        return '['. (!empty($output) ? $eol . implode(','. $eol, $output) . $eol . $indent : '') .']';
+      }
+      // Otherwise, fall through to convert the array as an object.
+    case 'object':
+      $output = array();
+      foreach ($var as $k => $v) {
+        $output[] = $indent . $base_indent . _json_preview_render(strval($k)) .' : '. _json_preview_render($v, $depth + 1);
+      }
+      return '{'. (!empty($output) ? $eol . implode(','. $eol, $output) . $eol . $indent : '') .'}';
+    default:
+      return 'null';
   }
 }
diff -urp views-view-rdf.tpl.php views-view-rdf.tpl.php.patched
--- views-view-rdf.tpl.php	2009-11-01 18:53:41.000000000 -0500
+++ views-view-rdf.tpl.php.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views-view-rdf.tpl.php,v 1.1.2.9 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 /**
  * @file
  * View template to render views as RDF. Supports FOAF and SIOC vocabulary.
diff -urp views-view-row-unformatted.tpl.php views-view-row-unformatted.tpl.php.patched
--- views-view-row-unformatted.tpl.php	2009-11-01 18:53:41.000000000 -0500
+++ views-view-row-unformatted.tpl.php.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views-view-row-unformatted.tpl.php,v 1.1.2.2 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
diff -urp views-view-xhtml.tpl.php views-view-xhtml.tpl.php.patched
--- views-view-xhtml.tpl.php	2009-11-01 18:53:41.000000000 -0500
+++ views-view-xhtml.tpl.php.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views-view-xhtml.tpl.php,v 1.1.2.9 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 /**
  * @file
  * View template to render views as XHTML microformats.
diff -urp views-view-xml.tpl.php views-view-xml.tpl.php.patched
--- views-view-xml.tpl.php	2009-11-01 18:53:41.000000000 -0500
+++ views-view-xml.tpl.php.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views-view-xml.tpl.php,v 1.1.2.11 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
diff -urp views_json.module views_json.module.patched
--- views_json.module	2009-11-01 18:53:41.000000000 -0500
+++ views_json.module.patched	2009-11-08 11:34:47.000000000 -0500
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_json.module,v 1.1.2.4 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
@@ -46,16 +46,9 @@ function views_json_strip_illegal_chars(
  *   String with special JSON characters encoded.
  */
 function views_json_encode_special_chars($input) {
-  $output = str_replace(chr(92), '\\', $input);
-  $output = str_replace(chr(47), '\/', $output);
-  $output = str_replace('"', '\"', $output);
-  $output = str_replace(chr(8), '\b', $output);
-  $output = str_replace(chr(12), '\f', $output);
-  $output = str_replace(chr(13) . chr(10), '\n', $output);
-  $output = str_replace(chr(10), '\n', $output);
-  $output = str_replace(chr(13), '\r', $output);
-  $output = str_replace(chr(9), '\t', $output);
-  return $output;
+  $search   = array(chr(92), chr(47), '"', chr(8), chr(12), chr(13) . chr(10), chr(10), chr(13), chr(9));
+  $replace  = array('\\', '\/', '\"', '\b', '\f', '\n', '\n', '\r', '\t');
+  return str_replace($search, $replace, $input);
 }
 
 
@@ -68,13 +61,13 @@ function views_json_encode_special_chars
  *   Either the original input or a date string.
  */
 function views_json_is_date($input) {
-  if (strpos($input, 'a:3:{s:5:"month"') !== 0) {
-    return $input;
-  }
-  else {        // serialized date array
+  if (is_string($input) && strpos($input, 'a:3:{s:5:"month"') === 0) {
+    // serialized date array
     $date = unserialize($input);
     return format_date(mktime(0, 0, 0, $date['month'], $date['day'], $date['year']), 'custom', DATE_ISO8601);
   }
+
+  return $input;
 }
 
 
@@ -89,10 +82,12 @@ function views_json_is_date($input) {
  *   The display of the view to use.
  * @param $args
  *   The arguments to pass to the view.
+ * @param $raw
+ *   If TRUE, the JSON data is returned as a string.  Otherwise, an object representation is returned.
  * @return
- *   The JSON object in associative array form or NULL otherwise.
+ *   The JSON data in the form of an object or a string or NULL otherwise.
  */
-function views_json_get_json($name, $display_id = 'default', $args = array()) {
+function views_json_get($name, $display_id = 'default', $args = array(), $raw = FALSE) {
   $view = views_get_view($name);
   if (!is_object($view)) return NULL;
 
@@ -102,5 +97,9 @@ function views_json_get_json($name, $dis
   $length     = $finish_pos - $start_pos + 1;
   $json       = trim(substr($preview, $start_pos, $length));
 
-  return json_decode($json, TRUE);
+  if ($raw) {
+    return $json;
+  }
+
+  return json_decode($json);
 }
diff -urp views_json.views.inc views_json.views.inc.patched
--- views_json.views.inc	2009-11-01 18:53:41.000000000 -0500
+++ views_json.views.inc.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_json.views.inc,v 1.1.2.4 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
diff -urp views_plugin_style_json.inc views_plugin_style_json.inc.patched
--- views_plugin_style_json.inc	2009-11-01 18:53:41.000000000 -0500
+++ views_plugin_style_json.inc.patched	2009-11-07 14:11:43.000000000 -0500
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_plugin_style_json.inc,v 1.1.2.3 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
@@ -29,12 +29,16 @@ class views_plugin_style_json extends vi
       '#type'           => 'radios',
       '#title'          => t('JSON data format'),
       '#options'        => array(
-        'simple'        => t('Simple'),
-        'simple-coder'  => t('Simple (Coder)'),
-        'exhibit'       => t('MIT Simile/Exhibit'),
-        'exhibit-coder' => t('MIT Simile/Exhibit (Coder)'),
+        'simple'  => t('Simple'),
+        'exhibit' => t('MIT Simile/Exhibit'),
       ),
       '#default_value'  => $this->options['format'],
     );
+    $form['using_coder'] = array(
+      '#type'           => 'checkbox',
+      '#title'          => t('Use coder mode'),
+      '#default_value'  => $this->options['using_coder'],
+      '#description'    => t('Not using coder mode means the JSON gets output directly and the server ceases normal page processing.  Using coder mode means the server does not cease processing after outputting the JSON.  This allows for the Views API to be used with the view without having to prematurely terminate page processing.'),
+    );
   }
 }
diff -urp views_plugin_style_rdf.inc views_plugin_style_rdf.inc.patched
--- views_plugin_style_rdf.inc	2009-11-01 18:53:41.000000000 -0500
+++ views_plugin_style_rdf.inc.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_plugin_style_rdf.inc,v 1.1.2.4 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
diff -urp views_plugin_style_xhtml.inc views_plugin_style_xhtml.inc.patched
--- views_plugin_style_xhtml.inc	2009-11-01 18:53:41.000000000 -0500
+++ views_plugin_style_xhtml.inc.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_plugin_style_xhtml.inc,v 1.1.2.3 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
diff -urp views_plugin_style_xml.inc views_plugin_style_xml.inc.patched
--- views_plugin_style_xml.inc	2009-11-01 18:53:41.000000000 -0500
+++ views_plugin_style_xml.inc.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_plugin_style_xml.inc,v 1.1.2.3 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
diff -urp views_rdf.module views_rdf.module.patched
--- views_rdf.module	2009-11-01 18:53:41.000000000 -0500
+++ views_rdf.module.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_rdf.module,v 1.1.4.6 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
diff -urp views_rdf.views.inc views_rdf.views.inc.patched
--- views_rdf.views.inc	2009-11-01 18:53:41.000000000 -0500
+++ views_rdf.views.inc.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_rdf.views.inc,v 1.1.2.4 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
diff -urp views_xhtml.module views_xhtml.module.patched
--- views_xhtml.module	2009-11-01 18:53:41.000000000 -0500
+++ views_xhtml.module.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_xhtml.module,v 1.1.4.6 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
diff -urp views_xhtml.views.inc views_xhtml.views.inc.patched
--- views_xhtml.views.inc	2009-11-01 18:53:41.000000000 -0500
+++ views_xhtml.views.inc.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_xhtml.views.inc,v 1.1.2.4 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
diff -urp views_xml.module views_xml.module.patched
--- views_xml.module	2009-11-01 18:53:41.000000000 -0500
+++ views_xml.module.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_xml.module,v 1.1.4.7 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
diff -urp views_xml.views.inc views_xml.views.inc.patched
--- views_xml.views.inc	2009-11-01 18:53:41.000000000 -0500
+++ views_xml.views.inc.patched	2009-10-15 19:10:51.000000000 -0400
@@ -1,5 +1,5 @@
 <?php
-// $Id: views_xml.views.inc,v 1.1.2.4 2009/11/01 23:53:41 allisterbeharry Exp $
+// $Id$
 
 /**
  * @file
