diff --git a/drupalorg_drush.drush.inc b/drupalorg_drush.drush.inc
index 1e64302..77200f6 100644
--- a/drupalorg_drush.drush.inc
+++ b/drupalorg_drush.drush.inc
@@ -22,8 +22,11 @@ define('DRUPALORG_DRUSH_DOCUMENTATION_LINK', 'http://drupal.org/node/642116');
 define('DRUPALORG_DRUSH_PACKAGING_LIBRARY_WHITELIST', 'http://drupal.org/packaging-whitelist');
 // URL of allowed patches on drupal.org.
 define('DRUPALORG_DRUSH_ALLOWED_PATCH_URL', 'http://drupal.org/files');
-// Name of the package contents file used by the packaging script.
+// TODO: Rip this out after JSON format is deployed.
+// Name of the package contents .txt file used by the packaging script.
 define('DRUPALORG_DRUSH_PACKAGE_CONTENTS_FILE', 'package_contents.txt');
+// Name of the package contents JSON file used by the packaging script.
+define('DRUPALORG_DRUSH_PACKAGE_CONTENTS_JSON_FILE', 'package_contents.json');
 // Name of the build errors file used by the packaging script.
 define('DRUPALORG_DRUSH_BUILD_ERRORS_FILE', 'build_errors.txt');
 
@@ -71,7 +74,9 @@ function drupalorg_drush_make_options() {
   return array(
     'drupal-org' => 'Use Drupal.org validation',
     'drupal-org-log-errors-to-file' => 'Log make errors to a file',
+    // TODO: Rip this out after JSON format is deployed.
     'drupal-org-log-package-items-to-file' => 'Log package items to a file',
+    'drupal-org-log-package-contents-to-json-file' => 'Log package item metadata to a JSON file',
     'drupal-org-build-root' => 'Location to place custom build files',
     'drupal-org-whitelist-url' => 'URL of the human-readable packaging library whitelist',
     'drupal-org-allowed-patch-url' => 'URL of allowed patches in .make files',
@@ -139,6 +144,13 @@ function drupalorg_drush_drush_init() {
     // Optionally set up the package contents file. The packaging script
     // expects it, so it's created as an empty file here to ensure it
     // exists.
+    if (drupalorg_drush_log_json()) {
+      $drupal_org_build_root = drush_get_option('drupal-org-build-root');
+      if (!touch($drupal_org_build_root . '/' . DRUPALORG_DRUSH_PACKAGE_CONTENTS_JSON_FILE)) {
+        make_error('FILE_ERROR', dt('Unable to write package contents file to %build_root', array('%build_root' => $drupal_org_build_root)));
+      }
+    }
+    // TODO: Rip this out after JSON format is deployed.
     if (drush_get_option('drupal-org-log-package-items-to-file')) {
       $drupal_org_build_root = drush_get_option('drupal-org-build-root');
       if (!touch($drupal_org_build_root . '/' . DRUPALORG_DRUSH_PACKAGE_CONTENTS_FILE)) {
@@ -165,7 +177,8 @@ function drupalorg_drush_make_validate_info($info) {
         'DrushMakeDo_DownloadGit',
         'DrushMakeDo_DownloadURL',
         'DrushMakeDo_ProjectPatch',
-        'DrushMakeDo_SetReleaseMetadata',
+        // NOTE: This must be the last transformer!
+        'DrushMakeDo_RecordProjectMetadata',
       ),
     );
     $pass = TRUE;
@@ -195,7 +208,12 @@ function drupalorg_drush_make_validate_info($info) {
       if ($library_transformer->whitelist_loaded()) {
         foreach ($info['libraries'] as $library => $library_data) {
           drush_log(dt("Running transformer DrushMakeDo_LibraryWhitelist on .make file for library !library", array('!library' => $library)), 'debug');
-          if (!$library_transformer->verify($library_data, $library)) {
+          if ($library_transformer->verify($library_data, $library)) {
+            if (drupalorg_drush_log_json()) {
+              drupalorg_drush_json($library, drupalorg_drush_get_library_json_data($library_data));
+            }
+          }
+          else {
             $pass = FALSE;
           }
           $info['libraries'][$library] = $library_data;
@@ -211,6 +229,9 @@ function drupalorg_drush_make_validate_info($info) {
       make_error('BUILD_ERROR', dt('The drupal.org validation check failed -- see @doc_link for more information.', array('@doc_link' => DRUPALORG_DRUSH_DOCUMENTATION_LINK)));
       return FALSE;
     }
+    elseif (drupalorg_drush_log_json() && !drupalorg_drush_write_package_contents_to_json_file()) {
+      return FALSE;
+    }
   }
   return $info;
 }
@@ -538,8 +559,26 @@ class DrushMakeDo_ProjectPatch extends DrushMakeDo_Transformer {
   }
   */
 }
-class DrushMakeDo_SetReleaseMetadata extends DrushMakeDo_Transformer {
+class DrushMakeDo_RecordProjectMetadata extends DrushMakeDo_Transformer {
   function verify(&$project_data, $project, $core) {
+    if (drupalorg_drush_log_json()) {
+      $project_data += array(
+        'name' => $project,
+        'core' => $core,
+        'location' => drush_get_option('make-update-default-url', RELEASE_INFO_DEFAULT_URL),
+      );
+      if ($release = drupalorg_drush_set_release_metadata($project_data)) {
+        $release_nid = basename($release['release_link']);
+        $item_data = array(
+          'nid' => $release_nid,
+        );
+      }
+      else {
+        $item_data = drupalorg_drush_get_project_json_data($project_data);
+      }
+      drupalorg_drush_json($project, $item_data);
+    }
+    // TODO: Rip this out after JSON format is deployed.
     if (drush_get_option('drupal-org-log-package-items-to-file')) {
       $project_data += array(
         'name' => $project,
@@ -561,7 +600,8 @@ class DrushMakeDo_SetReleaseMetadata extends DrushMakeDo_Transformer {
  * Find and store release node information about a project.
  *
  * If a valid release node is found for the project configuration, metadata
- * is stored in the file specified by DRUPALORG_DRUSH_PACKAGE_CONTENTS_FILE.
+ * is stored in the file specified by
+ * DRUPALORG_DRUSH_PACKAGE_CONTENTS_JSON_FILE.
  *
  * TODO: In the future, output the metadata as JSON?
  */
@@ -573,21 +613,43 @@ function drupalorg_drush_set_release_metadata(&$project) {
     $request['project_type'] = $project['type'] = updatexml_determine_project_type($xml);
     // Try to identify the most appropriate release.
     if ($release = updatexml_parse_release($request, $xml, 'version')) {
-      drupalorg_drush_write_package_item_nid($release);
+      // TODO: Rip this out after JSON format is deployed.
+      if (drush_get_option('drupal-org-log-package-items-to-file')) {
+        drupalorg_drush_write_package_contents($release);
+      }
+      else {
+        return $release;
+      }
     }
   }
 }
 
 /**
  * Store a package item in a package summary file.
+ *
+ * TODO: Rip this out after JSON format is deployed.
  */
-function drupalorg_drush_write_package_item_nid($release) {
+function drupalorg_drush_write_package_contents($release) {
   // Write the item's nid to the package contents file.
   $item_nid = basename($release['release_link']);
   return $item_nid && file_put_contents(drush_get_option('drupal-org-build-root') . '/' . DRUPALORG_DRUSH_PACKAGE_CONTENTS_FILE, "$item_nid\n", FILE_APPEND);
 }
 
 /**
+ * Store a package item in a package summary file in JSON format.
+ */
+function drupalorg_drush_write_package_contents_to_json_file() {
+  $json = json_encode(drupalorg_drush_json());
+  $filepath = drush_get_option('drupal-org-build-root') . '/' . DRUPALORG_DRUSH_PACKAGE_CONTENTS_JSON_FILE;
+  if (file_put_contents($filepath, $json, FILE_APPEND)) {
+    return TRUE;
+  }
+  else {
+    make_error('BUILD_ERROR', dt("Failed to write '%file'", array('%file' => $filepath)));
+  }
+}
+
+/**
  * Custom logging function for packaging errors.
  *
  * Logs all error messages to a build_errors.txt file in the root of the
@@ -676,3 +738,67 @@ function drupalorg_drush_get_remote_file($url) {
   return array($result, $data);
 }
 
+function drupalorg_drush_log_json() {
+  return drush_get_option('drupal-org-log-package-contents-to-json-file');
+}
+
+function drupalorg_drush_get_project_json_data($project) {
+  $data = array();
+  $top_attributes = array(
+    'version',
+  );
+  foreach ($top_attributes as $attribute) {
+    if (isset($project[$attribute])) {
+      $data[$attribute] = $project[$attribute];
+    }
+  }
+  if (isset($project['download'])) {
+    $download_attributes = array(
+      'branch',
+      'revision',
+      'tag',
+    );
+    foreach ($download_attributes as $attribute) {
+      if (isset($project['download'][$attribute])) {
+        $data[$attribute] = $project['download'][$attribute];
+      }
+    }
+  }
+  if (isset($project['patch'])) {
+    $data['patch'] = array();
+    foreach ($project['patch'] as $patch) {
+      $data['patch'][] = $patch;
+    }
+  }
+  return $data;
+}
+
+function drupalorg_drush_get_library_json_data($library) {
+  $data = array();
+  $top_attributes = array(
+    'url',
+  );
+  foreach ($top_attributes as $attribute) {
+    if (isset($library[$attribute])) {
+      $data[$attribute] = $library[$attribute];
+    }
+  }
+  if (isset($library['patch'])) {
+    $data['patch'] = array();
+    foreach ($library['patch'] as $patch) {
+      $data['patch'][] = $patch;
+    }
+  }
+  return $data;
+}
+
+function drupaalorg_drush_json($item = NULL, $item_data = array()) {
+  static $json = array();
+  if (isset($item)) {
+    $json[$item] = $item_data;
+  }
+  else {
+    return $json;
+  }
+}
+
