Addressing comments.
diff --git a/Makefile b/Makefile
index 03e0058..77935bc 100644
--- a/Makefile
+++ b/Makefile
@@ -1406,7 +1406,9 @@
     src/core/iomgr/tcp_server_posix.c \
     src/core/iomgr/time_averaged_stats.c \
     src/core/json/json.c \
-    src/core/json/json-string.c \
+    src/core/json/json_reader.c \
+    src/core/json/json_string.c \
+    src/core/json/json_writer.c \
     src/core/statistics/census_init.c \
     src/core/statistics/census_log.c \
     src/core/statistics/census_rpc_stats.c \
@@ -1526,7 +1528,9 @@
 src/core/iomgr/tcp_server_posix.c: $(OPENSSL_DEP)
 src/core/iomgr/time_averaged_stats.c: $(OPENSSL_DEP)
 src/core/json/json.c: $(OPENSSL_DEP)
-src/core/json/json-string.c: $(OPENSSL_DEP)
+src/core/json/json_reader.c: $(OPENSSL_DEP)
+src/core/json/json_string.c: $(OPENSSL_DEP)
+src/core/json/json_writer.c: $(OPENSSL_DEP)
 src/core/statistics/census_init.c: $(OPENSSL_DEP)
 src/core/statistics/census_log.c: $(OPENSSL_DEP)
 src/core/statistics/census_rpc_stats.c: $(OPENSSL_DEP)
@@ -1667,7 +1671,9 @@
 objs/$(CONFIG)/src/core/iomgr/tcp_server_posix.o: 
 objs/$(CONFIG)/src/core/iomgr/time_averaged_stats.o: 
 objs/$(CONFIG)/src/core/json/json.o: 
-objs/$(CONFIG)/src/core/json/json-string.o: 
+objs/$(CONFIG)/src/core/json/json_reader.o: 
+objs/$(CONFIG)/src/core/json/json_string.o: 
+objs/$(CONFIG)/src/core/json/json_writer.o: 
 objs/$(CONFIG)/src/core/statistics/census_init.o: 
 objs/$(CONFIG)/src/core/statistics/census_log.o: 
 objs/$(CONFIG)/src/core/statistics/census_rpc_stats.o: 
@@ -1828,7 +1834,9 @@
     src/core/iomgr/tcp_server_posix.c \
     src/core/iomgr/time_averaged_stats.c \
     src/core/json/json.c \
-    src/core/json/json-string.c \
+    src/core/json/json_reader.c \
+    src/core/json/json_string.c \
+    src/core/json/json_writer.c \
     src/core/statistics/census_init.c \
     src/core/statistics/census_log.c \
     src/core/statistics/census_rpc_stats.c \
@@ -1952,7 +1960,9 @@
 objs/$(CONFIG)/src/core/iomgr/tcp_server_posix.o: 
 objs/$(CONFIG)/src/core/iomgr/time_averaged_stats.o: 
 objs/$(CONFIG)/src/core/json/json.o: 
-objs/$(CONFIG)/src/core/json/json-string.o: 
+objs/$(CONFIG)/src/core/json/json_reader.o: 
+objs/$(CONFIG)/src/core/json/json_string.o: 
+objs/$(CONFIG)/src/core/json/json_writer.o: 
 objs/$(CONFIG)/src/core/statistics/census_init.o: 
 objs/$(CONFIG)/src/core/statistics/census_log.o: 
 objs/$(CONFIG)/src/core/statistics/census_rpc_stats.o: 
diff --git a/build.json b/build.json
index 18c6b2e..c2f44ef 100644
--- a/build.json
+++ b/build.json
@@ -61,6 +61,10 @@
         "src/core/iomgr/tcp_posix.h",
         "src/core/iomgr/tcp_server.h",
         "src/core/iomgr/time_averaged_stats.h",
+        "src/core/json/json.h",
+        "src/core/json/json_common.h",
+        "src/core/json/json_reader.h",
+        "src/core/json/json_writer.h",
         "src/core/statistics/census_interface.h",
         "src/core/statistics/census_log.h",
         "src/core/statistics/census_rpc_stats.h",
@@ -139,7 +143,9 @@
         "src/core/iomgr/tcp_server_posix.c",
         "src/core/iomgr/time_averaged_stats.c",
         "src/core/json/json.c",
-        "src/core/json/json-string.c",
+        "src/core/json/json_reader.c",
+        "src/core/json/json_string.c",
+        "src/core/json/json_writer.c",
         "src/core/statistics/census_init.c",
         "src/core/statistics/census_log.c",
         "src/core/statistics/census_rpc_stats.c",
diff --git a/src/core/json/json-reader-defs.h b/src/core/json/json-reader-defs.h
deleted file mode 100644
index 10c8473..0000000
--- a/src/core/json/json-reader-defs.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/*
- *
- * Copyright 2014, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* the following need to be pre-defined:
- *    grpc_json_reader_opaque_t  // A type you can use to keep track of your
- *                               // own stuff.
- *    grpc_json_wchar_t          // A type that can hold a unicode character
- *                               // unsigned is good enough.
- *    grpc_json_string_t         // A type that can hold a growable string.
- */
-
-enum grpc_json_reader_state_t {
-  GRPC_JSON_STATE_OBJECT_KEY_BEGIN,
-  GRPC_JSON_STATE_OBJECT_KEY_STRING,
-  GRPC_JSON_STATE_OBJECT_KEY_END,
-  GRPC_JSON_STATE_VALUE_BEGIN,
-  GRPC_JSON_STATE_VALUE_STRING,
-  GRPC_JSON_STATE_STRING_ESCAPE,
-  GRPC_JSON_STATE_STRING_ESCAPE_U1,
-  GRPC_JSON_STATE_STRING_ESCAPE_U2,
-  GRPC_JSON_STATE_STRING_ESCAPE_U3,
-  GRPC_JSON_STATE_STRING_ESCAPE_U4,
-  GRPC_JSON_STATE_VALUE_NUMBER,
-  GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL,
-  GRPC_JSON_STATE_VALUE_NUMBER_ZERO,
-  GRPC_JSON_STATE_VALUE_NUMBER_DOT,
-  GRPC_JSON_STATE_VALUE_NUMBER_E,
-  GRPC_JSON_STATE_VALUE_NUMBER_EPM,
-  GRPC_JSON_STATE_VALUE_TRUE_R,
-  GRPC_JSON_STATE_VALUE_TRUE_U,
-  GRPC_JSON_STATE_VALUE_TRUE_E,
-  GRPC_JSON_STATE_VALUE_FALSE_A,
-  GRPC_JSON_STATE_VALUE_FALSE_L,
-  GRPC_JSON_STATE_VALUE_FALSE_S,
-  GRPC_JSON_STATE_VALUE_FALSE_E,
-  GRPC_JSON_STATE_VALUE_NULL_U,
-  GRPC_JSON_STATE_VALUE_NULL_L1,
-  GRPC_JSON_STATE_VALUE_NULL_L2,
-  GRPC_JSON_STATE_VALUE_END,
-  GRPC_JSON_STATE_END
-};
-
-struct grpc_json_reader_t {
-  /* You are responsible for the initialization of the following. */
-  grpc_json_reader_opaque_t opaque;
-
-  /* Everything down here is private,
-     and initialized by grpc_json_reader_init. */
-  int depth;
-  int in_object;
-  int in_array;
-  int escaped_string_was_key;
-  int container_just_begun;
-  grpc_json_wchar_t unicode;
-  enum grpc_json_reader_state_t state;
-};
-
-/* The return type of the parser. */
-typedef enum {
-  GRPC_JSON_DONE,          /* The parser finished successfully. */
-  GRPC_JSON_EAGAIN,        /* The parser yields to get more data. */
-  GRPC_JSON_READ_ERROR,    /* The parser passes through a read error. */
-  GRPC_JSON_PARSE_ERROR,   /* The parser found an error in the json stream. */
-  GRPC_JSON_INTERNAL_ERROR /* The parser got an internal error. */
-} grpc_json_reader_ret_t;
diff --git a/src/core/json/json-string.c b/src/core/json/json-string.c
deleted file mode 100644
index 771c2cc..0000000
--- a/src/core/json/json-string.c
+++ /dev/null
@@ -1,378 +0,0 @@
-/*
- *
- * Copyright 2014, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-#include <string.h>
-
-#include <grpc/support/alloc.h>
-#include <grpc/support/log.h>
-
-#include "src/core/json/json.h"
-
-/* This json-writer will put everything in a big string.
- * The point is that we allocate that string in chunks of 256 bytes.
- */
-typedef struct {
-  char *output;
-  size_t free_space, string_len, allocated;
-} grpc_json_writer_opaque_t;
-
-#include "src/core/json/json-writer-defs.h"
-
-/* The json-reader will construct a bunch of grpc_json objects and
- * link them all up together in a tree-like structure that will represent
- * the json data in memory.
- *
- * It also uses its own input as a scratchpad to store all of the decoded,
- * unescaped strings. So we need to keep track of all these pointers in
- * that opaque structure the reader will carry for us.
- *
- * Note that this works because the act of parsing json always reduces its
- * input size, and never expands it.
- */
-typedef struct {
-  grpc_json *top;
-  grpc_json *current_container;
-  grpc_json *current_value;
-  char *input;
-  char *key;
-  char *string;
-  char *string_ptr;
-  size_t remaining_input;
-} grpc_json_reader_opaque_t;
-
-typedef unsigned grpc_json_wchar_t;
-
-#include "src/core/json/json-reader-defs.h"
-
-/* Next up, the definitions needed for the implementation. */
-#define grpc_json_static_inline static
-#define grpc_json_eof -1
-#define grpc_json_eagain -2
-#define grpc_json_error -3
-
-/* This functions checks if there's enough space left in the output buffer,
- * and will enlarge it if necessary. We're only allocating chunks of 256
- * bytes at a time (or multiples thereof).
- */
-static void grpc_json_writer_output_check(struct grpc_json_writer_t *writer,
-                                          size_t needed) {
-  if (writer->opaque.free_space >= needed) return;
-  needed = (needed - writer->opaque.free_space + 0xff) & ~0xff;
-  writer->opaque.output = (char *)gpr_realloc(
-      writer->opaque.output, writer->opaque.allocated + needed);
-  writer->opaque.free_space += needed;
-  writer->opaque.allocated += needed;
-}
-
-/* These are needed by the writer's implementation. */
-static void grpc_json_writer_output_char(struct grpc_json_writer_t *writer,
-                                         char c) {
-  grpc_json_writer_output_check(writer, 1);
-  writer->opaque.output[writer->opaque.string_len++] = c;
-  writer->opaque.free_space--;
-}
-
-static void grpc_json_writer_output_string_with_len(
-    struct grpc_json_writer_t *writer, const char *str, size_t len) {
-  grpc_json_writer_output_check(writer, len);
-  memcpy(writer->opaque.output + writer->opaque.string_len, str, len);
-  writer->opaque.string_len += len;
-  writer->opaque.free_space -= len;
-}
-
-static void grpc_json_writer_output_string(struct grpc_json_writer_t *writer,
-                                           const char *str) {
-  size_t len = strlen(str);
-  grpc_json_writer_output_string_with_len(writer, str, len);
-}
-
-#include "src/core/json/json-writer-impl.h"
-
-/* The reader asks us to clear our scratchpad. In our case, we'll simply mark
- * the end of the current string, and advance our output pointer.
- */
-static void grpc_json_reader_string_clear(struct grpc_json_reader_t *reader) {
-  if (reader->opaque.string) {
-    GPR_ASSERT(reader->opaque.string_ptr < reader->opaque.input);
-    *reader->opaque.string_ptr++ = 0;
-  }
-  reader->opaque.string = reader->opaque.string_ptr;
-}
-
-static void grpc_json_reader_string_add_char(struct grpc_json_reader_t *reader,
-                                             int c) {
-  GPR_ASSERT(reader->opaque.string_ptr < reader->opaque.input);
-  *reader->opaque.string_ptr++ = (char)c;
-}
-
-/* We are converting a unicode character into utf-8 here. */
-/* The unicode escape encoding of json can only hold 16-bits values.
- * So the the 4th case, as well as the last test aren't techically
- * necessary, but I wrote them anyway for completion.
- */
-static void grpc_json_reader_string_add_wchar(struct grpc_json_reader_t *reader,
-                                              unsigned int c) {
-  if (c <= 0x7f) {
-    grpc_json_reader_string_add_char(reader, c);
-  } else if (c <= 0x7ff) {
-    int b1 = 0xc0 | ((c >> 6) & 0x1f);
-    int b2 = 0x80 | (c & 0x3f);
-    grpc_json_reader_string_add_char(reader, b1);
-    grpc_json_reader_string_add_char(reader, b2);
-  } else if (c <= 0xffff) {
-    int b1 = 0xe0 | ((c >> 12) & 0x0f);
-    int b2 = 0x80 | ((c >> 6) & 0x3f);
-    int b3 = 0x80 | (c & 0x3f);
-    grpc_json_reader_string_add_char(reader, b1);
-    grpc_json_reader_string_add_char(reader, b2);
-    grpc_json_reader_string_add_char(reader, b3);
-  } else if (c <= 0x1fffff) {
-    int b1 = 0xf0 | ((c >> 18) & 0x07);
-    int b2 = 0x80 | ((c >> 12) & 0x3f);
-    int b3 = 0x80 | ((c >> 6) & 0x3f);
-    int b4 = 0x80 | (c & 0x3f);
-    grpc_json_reader_string_add_char(reader, b1);
-    grpc_json_reader_string_add_char(reader, b2);
-    grpc_json_reader_string_add_char(reader, b3);
-    grpc_json_reader_string_add_char(reader, b4);
-  }
-}
-
-/* We consider that the input may be a zero-terminated string. So we
- * can end up hitting eof before the end of the alleged string length.
- */
-static int grpc_json_reader_read_char(struct grpc_json_reader_t *reader) {
-  int r;
-
-  if (reader->opaque.remaining_input == 0) {
-    return grpc_json_eof;
-  }
-
-  r = *reader->opaque.input++;
-  reader->opaque.remaining_input--;
-
-  if (r == 0) {
-    reader->opaque.remaining_input = 0;
-    return grpc_json_eof;
-  }
-
-  return r;
-}
-
-/* Helper function to create a new grpc_json object and link it into
- * our tree-in-progress inside our opaque structure.
- */
-static grpc_json *grpc_json_new_and_link(struct grpc_json_reader_t *reader,
-                                         enum grpc_json_type_t type) {
-  grpc_json *json = grpc_json_new(type);
-
-  json->parent = reader->opaque.current_container;
-  json->prev = reader->opaque.current_value;
-  reader->opaque.current_value = json;
-
-  if (json->prev) {
-    json->prev->next = json;
-  }
-  if (json->parent) {
-    if (!json->parent->child) {
-      json->parent->child = json;
-    }
-    if (json->parent->type == GRPC_JSON_OBJECT) {
-      json->key = reader->opaque.key;
-    }
-  }
-  if (!reader->opaque.top) {
-    reader->opaque.top = json;
-  }
-
-  return json;
-}
-
-static void grpc_json_reader_container_begins(struct grpc_json_reader_t *reader,
-                                              enum grpc_json_type_t type) {
-  grpc_json *container;
-
-  GPR_ASSERT(type == GRPC_JSON_ARRAY || type == GRPC_JSON_OBJECT);
-
-  container = grpc_json_new_and_link(reader, type);
-  reader->opaque.current_container = container;
-  reader->opaque.current_value = NULL;
-}
-
-/* It's important to remember that the reader is mostly state-less, so it
- * isn't trying to remember what was the container prior the one that just
- * ends. Since we're keeping track of these for our own purpose, we are
- * able to return that information back, which is useful for it to validate
- * the input json stream.
- *
- * Also note that if we're at the top of the tree, and the last container
- * ends, we have to return GRPC_JSON_NONE.
- */
-static enum grpc_json_type_t grpc_json_reader_container_ends(
-    struct grpc_json_reader_t *reader) {
-  enum grpc_json_type_t container_type = GRPC_JSON_NONE;
-
-  GPR_ASSERT(reader->opaque.current_container);
-
-  reader->opaque.current_value = reader->opaque.current_container;
-  reader->opaque.current_container = reader->opaque.current_container->parent;
-
-  if (reader->opaque.current_container) {
-    container_type = reader->opaque.current_container->type;
-  }
-
-  return container_type;
-}
-
-/* The next 3 functions basically are the reader asking us to use our string
- * scratchpad for one of these 3 purposes.
- *
- * Note that in the set_number case, we're not going to try interpreting it.
- * We'll keep it as a string, and leave it to the caller to evaluate it.
- */
-static void grpc_json_reader_object_set_key(struct grpc_json_reader_t *reader) {
-  reader->opaque.key = reader->opaque.string;
-}
-
-static void grpc_json_reader_container_set_string(
-    struct grpc_json_reader_t *reader) {
-  grpc_json *json = grpc_json_new_and_link(reader, GRPC_JSON_STRING);
-  json->value = reader->opaque.string;
-}
-
-static int grpc_json_reader_container_set_number(
-    struct grpc_json_reader_t *reader) {
-  grpc_json *json = grpc_json_new_and_link(reader, GRPC_JSON_NUMBER);
-  json->value = reader->opaque.string;
-  return 1;
-}
-
-/* The object types true, false and null are self-sufficient, and don't need
- * any more information beside their type.
- */
-static void grpc_json_reader_container_set_true(
-    struct grpc_json_reader_t *reader) {
-  grpc_json_new_and_link(reader, GRPC_JSON_TRUE);
-}
-
-static void grpc_json_reader_container_set_false(
-    struct grpc_json_reader_t *reader) {
-  grpc_json_new_and_link(reader, GRPC_JSON_FALSE);
-}
-
-static void grpc_json_reader_container_set_null(
-    struct grpc_json_reader_t *reader) {
-  grpc_json_new_and_link(reader, GRPC_JSON_NULL);
-}
-
-/* Now that we've defined all that's needed for the parser's implementation,
- * let's include its file. */
-#include "json-reader-impl.h"
-
-/* And finally, let's define our public API. */
-grpc_json *grpc_json_parse_string_with_len(char *input, size_t size) {
-  struct grpc_json_reader_t reader;
-  grpc_json *json = NULL;
-  grpc_json_reader_ret_t status;
-
-  if (!input) return NULL;
-
-  reader.opaque.top = reader.opaque.current_container =
-      reader.opaque.current_value = NULL;
-  reader.opaque.string = reader.opaque.key = NULL;
-  reader.opaque.string_ptr = reader.opaque.input = input;
-  reader.opaque.remaining_input = size;
-  grpc_json_reader_init(&reader);
-
-  status = grpc_json_reader_run(&reader);
-  json = reader.opaque.top;
-
-  if ((status != GRPC_JSON_DONE) && json) {
-    grpc_json_delete(json);
-    json = NULL;
-  }
-
-  return json;
-}
-
-grpc_json *grpc_json_parse_string(char *input) {
-  return grpc_json_parse_string_with_len(input, 0x7fffffff);
-}
-
-static void grpc_json_dump_recursive(struct grpc_json_writer_t *writer,
-                                     grpc_json *json, int in_object) {
-  while (json) {
-    if (in_object) grpc_json_writer_object_key(writer, json->key);
-
-    switch (json->type) {
-      case GRPC_JSON_OBJECT:
-      case GRPC_JSON_ARRAY:
-        grpc_json_writer_container_begins(writer, json->type);
-        if (json->child)
-          grpc_json_dump_recursive(writer, json->child,
-                                   json->type == GRPC_JSON_OBJECT);
-        grpc_json_writer_container_ends(writer, json->type);
-        break;
-      case GRPC_JSON_STRING:
-        grpc_json_writer_value_string(writer, json->value);
-        break;
-      case GRPC_JSON_NUMBER:
-        grpc_json_writer_value_raw(writer, json->value);
-        break;
-      case GRPC_JSON_TRUE:
-        grpc_json_writer_value_raw_with_len(writer, "true", 4);
-        break;
-      case GRPC_JSON_FALSE:
-        grpc_json_writer_value_raw_with_len(writer, "false", 5);
-        break;
-      case GRPC_JSON_NULL:
-        grpc_json_writer_value_raw_with_len(writer, "null", 4);
-        break;
-      default:
-        abort();
-    }
-    json = json->next;
-  }
-}
-
-char *grpc_json_dump_to_string(grpc_json *json, int indent) {
-  struct grpc_json_writer_t writer;
-  writer.opaque.output = NULL;
-  writer.opaque.free_space = writer.opaque.string_len =
-      writer.opaque.allocated = 0;
-  grpc_json_writer_init(&writer, indent);
-  grpc_json_dump_recursive(&writer, json, 0);
-  grpc_json_writer_output_char(&writer, 0);
-
-  return writer.opaque.output;
-}
diff --git a/src/core/json/json-writer-defs.h b/src/core/json/json-writer-defs.h
deleted file mode 100644
index f8ab988..0000000
--- a/src/core/json/json-writer-defs.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- *
- * Copyright 2014, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-/* the following need to be pre-defined:
- *    grpc_json_writer_opaque_t  // A type you can use to keep track of your
- *                               // own stuff.
- */
-
-struct grpc_json_writer_t {
-  grpc_json_writer_opaque_t opaque;
-
-  int indent;
-  int depth;
-  int container_empty;
-  int got_key;
-};
diff --git a/src/core/json/json-writer-impl.h b/src/core/json/json-writer-impl.h
deleted file mode 100644
index f3ef968..0000000
--- a/src/core/json/json-writer-impl.h
+++ /dev/null
@@ -1,233 +0,0 @@
-/*
- *
- * Copyright 2014, Google Inc.
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are
- * met:
- *
- *     * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *     * Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following disclaimer
- * in the documentation and/or other materials provided with the
- * distribution.
- *     * Neither the name of Google Inc. nor the names of its
- * contributors may be used to endorse or promote products derived from
- * this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
- * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
- * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
- * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
- * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
- * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
- * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
- * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- *
- */
-
-
-/* The idea of the writer is basically symmetrical of the reader. While the
- * reader emits various calls to your code, the writer takes basically the
- * same calls and emit json out of it. It doesn't try to make any check on
- * the order of the calls you do on it.
- *
- * Also, unlike the reader, the writer expects UTF-8 encoded input strings.
- *
- * The following need to be defined:
- *
- * // Adds a character to the output stream.
- * void grpc_json_writer_output_char(struct grpc_json_writer_t *, char);
- * // Adds a zero-terminated string to the output stream.
- * void grpc_json_writer_output_string(
- *   struct grpc_json_writer_t *writer, const char *str);
- * // Adds a fixed-length string to the output stream.
- * void grpc_json_writer_output_string_with_len(
- *   struct grpc_json_writer_t *writer, const char *str, size_t len);
-
- */
-
-/* Call this function to initialize the writer structure. */
-grpc_json_static_inline void grpc_json_writer_init(
-    struct grpc_json_writer_t* writer, int indent) {
-  writer->depth = 0;
-  writer->container_empty = 1;
-  writer->got_key = 0;
-  writer->indent = indent;
-}
-
-/* This function is fully private. */
-grpc_json_static_inline void grpc_json_writer_output_indent(
-    struct grpc_json_writer_t* writer) {
-  static const char spacesstr[] =
-      "                "
-      "                "
-      "                "
-      "                ";
-
-  int spaces = writer->depth * writer->indent;
-
-  if (writer->got_key) {
-    grpc_json_writer_output_char(writer, ' ');
-    return;
-  }
-
-  while (spaces >= (sizeof(spacesstr) - 1)) {
-    grpc_json_writer_output_string_with_len(writer, spacesstr,
-                                            sizeof(spacesstr) - 1);
-    spaces -= (sizeof(spacesstr) - 1);
-  }
-
-  if (!spaces) return;
-
-  grpc_json_writer_output_string_with_len(
-      writer, spacesstr + sizeof(spacesstr) - 1 - spaces, spaces);
-}
-
-/* This function is fully private. */
-grpc_json_static_inline void grpc_json_writer_value_end(
-    struct grpc_json_writer_t* writer) {
-  if (writer->container_empty) {
-    writer->container_empty = 0;
-    if (!writer->indent || !writer->depth) return;
-    grpc_json_writer_output_char(writer, '\n');
-  } else {
-    grpc_json_writer_output_char(writer, ',');
-    if (!writer->indent) return;
-    grpc_json_writer_output_char(writer, '\n');
-  }
-}
-
-/* This function is fully private. */
-grpc_json_static_inline void grpc_json_writer_escape_string(
-    struct grpc_json_writer_t* writer, const char* string) {
-  static const char hex[] = "0123456789abcdef";
-  grpc_json_writer_output_char(writer, '"');
-
-  for (;;) {
-    unsigned char c = (unsigned char)*string++;
-    if (!c) {
-      break;
-    } else if ((c >= 32) && (c <= 127)) {
-      if ((c == '\\') || (c == '"')) grpc_json_writer_output_char(writer, '\\');
-      grpc_json_writer_output_char(writer, c);
-    } else if (c < 32) {
-      grpc_json_writer_output_char(writer, '\\');
-      switch (c) {
-        case '\b':
-          grpc_json_writer_output_char(writer, 'b');
-          break;
-        case '\f':
-          grpc_json_writer_output_char(writer, 'f');
-          break;
-        case '\n':
-          grpc_json_writer_output_char(writer, 'n');
-          break;
-        case '\r':
-          grpc_json_writer_output_char(writer, 'r');
-          break;
-        case '\t':
-          grpc_json_writer_output_char(writer, 't');
-          break;
-        default:
-          grpc_json_writer_output_string_with_len(writer, "u00", 3);
-          grpc_json_writer_output_char(writer, c >= 16 ? '1' : '0');
-          grpc_json_writer_output_char(writer, hex[c & 15]);
-          break;
-      }
-    } else {
-      unsigned unicode = 0;
-      if ((c & 0xe0) == 0xc0) {
-        unicode = c & 0x1f;
-        unicode <<= 6;
-        c = *string++;
-        if ((c & 0xc0) != 0x80) break;
-        unicode |= c & 0x3f;
-      } else if ((c & 0xf0) == 0xe0) {
-        unicode = c & 0x0f;
-        unicode <<= 6;
-        c = *string++;
-        if ((c & 0xc0) != 0x80) break;
-        unicode |= c & 0x3f;
-        unicode <<= 6;
-        c = *string++;
-        if ((c & 0xc0) != 0x80) break;
-        unicode |= c & 0x3f;
-      } else {
-        break;
-      }
-      grpc_json_writer_output_string_with_len(writer, "\\u", 2);
-      grpc_json_writer_output_char(writer, hex[(unicode >> 12) & 0x0f]);
-      grpc_json_writer_output_char(writer, hex[(unicode >> 8) & 0x0f]);
-      grpc_json_writer_output_char(writer, hex[(unicode >> 4) & 0x0f]);
-      grpc_json_writer_output_char(writer, hex[(unicode) & 0x0f]);
-    }
-  }
-
-  grpc_json_writer_output_char(writer, '"');
-}
-
-/* Call that function to start a new json container. */
-grpc_json_static_inline void grpc_json_writer_container_begins(
-    struct grpc_json_writer_t* writer, enum grpc_json_type_t type) {
-  if (!writer->got_key) grpc_json_writer_value_end(writer);
-  grpc_json_writer_output_indent(writer);
-  grpc_json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '{' : '[');
-  writer->container_empty = 1;
-  writer->got_key = 0;
-  writer->depth++;
-}
-
-/* Call that function to end the current json container. */
-grpc_json_static_inline void grpc_json_writer_container_ends(
-    struct grpc_json_writer_t* writer, enum grpc_json_type_t type) {
-  if (writer->indent && !writer->container_empty)
-    grpc_json_writer_output_char(writer, '\n');
-  writer->depth--;
-  if (!writer->container_empty) grpc_json_writer_output_indent(writer);
-  grpc_json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '}' : ']');
-  writer->container_empty = 0;
-  writer->got_key = 0;
-}
-
-/* If you are in a GRPC_JSON_OBJECT container, call this to set up a key. */
-grpc_json_static_inline void grpc_json_writer_object_key(
-    struct grpc_json_writer_t* writer, const char* string) {
-  grpc_json_writer_value_end(writer);
-  grpc_json_writer_output_indent(writer);
-  grpc_json_writer_escape_string(writer, string);
-  grpc_json_writer_output_char(writer, ':');
-  writer->got_key = 1;
-}
-
-/* Sets a raw value - use it for numbers. */
-grpc_json_static_inline void grpc_json_writer_value_raw(
-    struct grpc_json_writer_t* writer, const char* string) {
-  if (!writer->got_key) grpc_json_writer_value_end(writer);
-  grpc_json_writer_output_indent(writer);
-  grpc_json_writer_output_string(writer, string);
-  writer->got_key = 0;
-}
-
-/* Sets a raw value with a known length - use it for true, false and null. */
-grpc_json_static_inline void grpc_json_writer_value_raw_with_len(
-    struct grpc_json_writer_t* writer, const char* string, unsigned len) {
-  if (!writer->got_key) grpc_json_writer_value_end(writer);
-  grpc_json_writer_output_indent(writer);
-  grpc_json_writer_output_string_with_len(writer, string, len);
-  writer->got_key = 0;
-}
-
-/* Outputs a string value. This will add double quotes, and escape it. */
-grpc_json_static_inline void grpc_json_writer_value_string(
-    struct grpc_json_writer_t* writer, const char* string) {
-  if (!writer->got_key) grpc_json_writer_value_end(writer);
-  grpc_json_writer_output_indent(writer);
-  grpc_json_writer_escape_string(writer, string);
-  writer->got_key = 0;
-}
diff --git a/src/core/json/json.c b/src/core/json/json.c
index 2905aba..e7fcec3 100644
--- a/src/core/json/json.c
+++ b/src/core/json/json.c
@@ -35,8 +35,8 @@
 
 #include "src/core/json/json.h"
 
-grpc_json *grpc_json_new(enum grpc_json_type_t type) {
-  grpc_json *json = (grpc_json *)gpr_malloc(sizeof(grpc_json));
+grpc_json *grpc_json_new(grpc_json_type type) {
+  grpc_json *json = gpr_malloc(sizeof(grpc_json));
   json->parent = json->child = json->next = json->prev = NULL;
   json->type = type;
 
diff --git a/src/core/json/json.h b/src/core/json/json.h
index a0bc4df..433ba22 100644
--- a/src/core/json/json.h
+++ b/src/core/json/json.h
@@ -36,12 +36,18 @@
 
 #include <stdlib.h>
 
-#include "src/core/json/json-defs.h"
+#include "src/core/json/json_common.h"
 
-typedef struct grpc_json_t {
-  struct grpc_json_t* next, *prev, *child, *parent;
-  enum grpc_json_type_t type;
+/* A tree-like structure to hold json values. The key and value pointers
+ * are not owned by it.
+ */
+typedef struct grpc_json {
+  struct grpc_json* next;
+  struct grpc_json* prev;
+  struct grpc_json* child;
+  struct grpc_json* parent;
 
+  grpc_json_type type;
   const char* key;
   const char* value;
 } grpc_json;
@@ -51,7 +57,11 @@
  * all of the keys and values for the returned object tree.
  *
  * They assume UTF-8 input stream, and will output UTF-8 encoded
- * strings in the tree.
+ * strings in the tree. The input stream's UTF-8 isn't validated,
+ * as in, what you input is what you get as an output.
+ *
+ * All the keys and values in the grpc_json_t objects will be strings
+ * pointing at your input buffer.
  *
  * Delete the allocated tree afterward using grpc_json_delete().
  */
@@ -72,7 +82,7 @@
  * Deletion is recursive. We will not attempt to free any of the strings
  * in any of the objects of that tree.
  */
-grpc_json* grpc_json_new(enum grpc_json_type_t type);
+grpc_json* grpc_json_new(grpc_json_type type);
 void grpc_json_delete(grpc_json* json);
 
 #endif /* __GRPC_SRC_CORE_JSON_JSON_H__ */
diff --git a/src/core/json/json-defs.h b/src/core/json/json_common.h
similarity index 87%
rename from src/core/json/json-defs.h
rename to src/core/json/json_common.h
index decf35e..88a8155 100644
--- a/src/core/json/json-defs.h
+++ b/src/core/json/json_common.h
@@ -31,8 +31,11 @@
  *
  */
 
-/* The various json types. "NONE" may only used on top-level. */
-enum grpc_json_type_t {
+#ifndef __GRPC_SRC_CORE_JSON_JSON_COMMON_H__
+#define __GRPC_SRC_CORE_JSON_JSON_COMMON_H__
+
+/* The various json types. */
+typedef enum {
   GRPC_JSON_OBJECT,
   GRPC_JSON_ARRAY,
   GRPC_JSON_STRING,
@@ -40,5 +43,7 @@
   GRPC_JSON_TRUE,
   GRPC_JSON_FALSE,
   GRPC_JSON_NULL,
-  GRPC_JSON_NONE
-};
+  GRPC_JSON_TOP_LEVEL
+} grpc_json_type;
+
+#endif /* __GRPC_SRC_CORE_JSON_JSON_COMMON_H__ */
diff --git a/src/core/json/json-reader-impl.h b/src/core/json/json_reader.c
similarity index 75%
rename from src/core/json/json-reader-impl.h
rename to src/core/json/json_reader.c
index 2fe5695..c387796 100644
--- a/src/core/json/json-reader-impl.h
+++ b/src/core/json/json_reader.c
@@ -31,113 +31,93 @@
  *
  */
 
-/* the following need to be pre-defined:
- *    grpc_json_static_inline      // A macro to declare a static inline
- *                                 // function
- *    grpc_json_eof                // A macro that can be used in a switch
- *                                 // statement, that grpc_json_read_char
- *                                 // can return
- *    grpc_json_eagain             // A macro that can be used in a switch
- *                                 // statement, that grpc_json_read_char
- *                                 // can return
- *    grpc_json_error              // A macro that can be used in a switch
- *                                 // statement, that grpc_json_read_char
- *                                 // can return
- *
- *    // A macro or a function that clears your internal scratchpad.
- *    grpc_json_reader_string_clear(struct grpc_json_reader_t*);
- *    // A macro or a function that adds a character to your internal
- *    // scratchpad.
- *    grpc_json_reader_string_add_char(struct grpc_json_reader_t*, int);
- *    // A macro or a function that adds a unicode character to your internal
- *    // scratchpad.
- *    grpc_json_reader_string_add_wchar(struct grpc_json_reader_t*,
- *                                      grpc_json_wchar_t);
- *
- *    // A macro or a function that returns the next character from the input.
- *    // It can return:
- *    //  . an actual character into an int - unicode, wchar_t, whatever, as
- *    //    long as it's going to work in a switch statement, and can be tested
- *    //    against typical json tokens, such as '{', '[', ',', '}', ']', digits
- *    //    and whitespaces.
- *    //  . grpc_json_eof, which means the end of the input has been reached.
- *    //  . grpc_json_eagain, which means the parser needs to yield before
- *    //    getting more input.
- *    //  . grpc_json_error, which means the parser needs to exit with an error.
- *    int grpc_json_reader_read_char(struct grpc_json_reader_t*);
- *
- *    // A macro or a function that will be called to signal the beginning of a
- *    // container.
- *    // The argument "type" can be either GRPC_JSON_OBJECT, or GRPC_JSON_ARRAY.
- *    void grpc_json_reader_container_begins(struct grpc_json_reader_t*,
- *                                           enum *grpc_json_type_t type)
- *    // A macro or a function that will be called to signal the end of the
- *    // current container. It must return GRPC_JSON_OBJECT or GRPC_JSON_ARRAY
- *    // to signal what is the new current container, or GRPC_JSON_NONE if the
- *    // stack of containers is now empty.
- *    enum grpc_json_type_t
- *      grpc_json_reader_container_ends(struct grpc_json_reader_t*);
- *
- *    // A macro or a function that will be called to signal that json->string
- *    // contains the string of a object's key that is being added.
- *    void grpc_json_reader_object_set_key(struct grpc_json_reader_t*);
- *
- *    // A set of macro or functions that will be called to signal that the
- *    // current container is getting a new value. set_string and set_number
- *    // are reading their value from your internal scratchpad. set_number
- *    // must return a boolean to signal if the number parsing succeeded or
- *    // not. There is little reason for it not to.
- *    void grpc_json_reader_container_set_string(struct grpc_json_reader_t*);
- *    int grpc_json_reader_container_set_number(struct grpc_json_reader_t*);
- *    void grpc_json_reader_container_set_true(struct grpc_json_reader_t*);
- *    void grpc_json_reader_container_set_false(struct grpc_json_reader_t*);
- *    void grpc_json_reader_container_set_null(struct grpc_json_reader_t*);
- */
+#include <grpc/support/port_platform.h>
+#include "src/core/json/json_reader.h"
+
+static void grpc_json_reader_string_clear(grpc_json_reader* reader) {
+  reader->string_clear(reader);
+}
+
+static void grpc_json_reader_string_add_char(grpc_json_reader* reader,
+                                             gpr_uint32 c) {
+  reader->string_add_char(reader, c);
+}
+
+static void grpc_json_reader_string_add_utf32(grpc_json_reader* reader,
+                                              gpr_uint32 utf32) {
+  reader->string_add_utf32(reader, utf32);
+}
+
+static gpr_uint32
+    grpc_json_reader_read_char(grpc_json_reader* reader) {
+  return reader->read_char(reader);
+}
+
+static void grpc_json_reader_container_begins(grpc_json_reader* reader,
+                                              grpc_json_type type) {
+  reader->container_begins(reader, type);
+}
+
+static grpc_json_type
+    grpc_json_reader_container_ends(grpc_json_reader* reader) {
+  return reader->container_ends(reader);
+}
+
+static void grpc_json_reader_set_key(grpc_json_reader* reader) {
+  reader->set_key(reader);
+}
+
+static void grpc_json_reader_set_string(grpc_json_reader* reader) {
+  reader->set_string(reader);
+}
+
+static int grpc_json_reader_set_number(grpc_json_reader* reader) {
+  return reader->set_number(reader);
+}
+
+static void grpc_json_reader_set_true(grpc_json_reader* reader) {
+  reader->set_true(reader);
+}
+
+static void grpc_json_reader_set_false(grpc_json_reader* reader) {
+  reader->set_false(reader);
+}
+
+static void grpc_json_reader_set_null(grpc_json_reader* reader) {
+  reader->set_null(reader);
+}
 
 /* Call this function to initialize the reader structure. */
-grpc_json_static_inline void grpc_json_reader_init(
-    struct grpc_json_reader_t* reader) {
+void grpc_json_reader_init(grpc_json_reader* reader) {
   reader->depth = 0;
   reader->in_object = 0;
   reader->in_array = 0;
+  reader->unicode_high_surrogate = 0;
   grpc_json_reader_string_clear(reader);
   reader->state = GRPC_JSON_STATE_VALUE_BEGIN;
 }
 
-/* Call this function to start parsing the input. It will return the following:
- *    . GRPC_JSON_DONE if the input got eof, and the parsing finished
- *      successfully.
- *    . GRPC_JSON_EAGAIN if the read_char function returned again. Call the
- *      parser again as needed. It is okay to call the parser in polling mode,
- *      although a bit dull.
- *    . GRPC_JSON_READ_ERROR if the read_char function returned an error. The
- *      state isn't broken however, and the function can be called again if the
- *      error has been corrected. But please use the EAGAIN feature instead for
- *      consistency.
- *    . GRPC_JSON_PARSE_ERROR if the input was somehow invalid.
- *    . GRPC_JSON_INTERNAL_ERROR if the parser somehow ended into an invalid
- *      internal state.
- */
+int grpc_json_reader_is_complete(grpc_json_reader* reader) {
+  return ((reader->depth == 0) && ((reader->state == GRPC_JSON_STATE_END) ||
+          (reader->state == GRPC_JSON_STATE_VALUE_END)));
+}
 
-grpc_json_static_inline grpc_json_reader_ret_t
-grpc_json_reader_run(struct grpc_json_reader_t* reader) {
+grpc_json_reader_ret grpc_json_reader_run(grpc_json_reader* reader) {
   int c, success;
 
-  /* This state-machine is a strict implementation of http://json.org/ */
+  /* This state-machine is a strict implementation of ECMA-404 */
   for (;;) {
     c = grpc_json_reader_read_char(reader);
     switch (c) {
       /* Let's process the error cases first. */
-      case grpc_json_error:
+      case GRPC_JSON_READ_CHAR_ERROR:
         return GRPC_JSON_READ_ERROR;
 
-      case grpc_json_eagain:
+      case GRPC_JSON_READ_CHAR_EAGAIN:
         return GRPC_JSON_EAGAIN;
 
-      case grpc_json_eof:
-        if ((reader->depth == 0) &&
-            ((reader->state == GRPC_JSON_STATE_END) ||
-             (reader->state == GRPC_JSON_STATE_VALUE_END))) {
+      case GRPC_JSON_READ_CHAR_EOF:
+        if (grpc_json_reader_is_complete(reader)) {
           return GRPC_JSON_DONE;
         } else {
           return GRPC_JSON_PARSE_ERROR;
@@ -159,6 +139,8 @@
 
           case GRPC_JSON_STATE_OBJECT_KEY_STRING:
           case GRPC_JSON_STATE_VALUE_STRING:
+            if (c != ' ') return GRPC_JSON_PARSE_ERROR;
+            if (reader->unicode_high_surrogate) return GRPC_JSON_PARSE_ERROR;
             grpc_json_reader_string_add_char(reader, c);
             break;
 
@@ -166,7 +148,7 @@
           case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
           case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
           case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
-            success = grpc_json_reader_container_set_number(reader);
+            success = grpc_json_reader_set_number(reader);
             if (!success) return GRPC_JSON_PARSE_ERROR;
             grpc_json_reader_string_clear(reader);
             reader->state = GRPC_JSON_STATE_VALUE_END;
@@ -184,6 +166,7 @@
         switch (reader->state) {
           case GRPC_JSON_STATE_OBJECT_KEY_STRING:
           case GRPC_JSON_STATE_VALUE_STRING:
+            if (reader->unicode_high_surrogate) return GRPC_JSON_PARSE_ERROR;
             grpc_json_reader_string_add_char(reader, c);
             break;
 
@@ -191,7 +174,7 @@
           case GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL:
           case GRPC_JSON_STATE_VALUE_NUMBER_ZERO:
           case GRPC_JSON_STATE_VALUE_NUMBER_EPM:
-            success = grpc_json_reader_container_set_number(reader);
+            success = grpc_json_reader_set_number(reader);
             if (!success) return GRPC_JSON_PARSE_ERROR;
             grpc_json_reader_string_clear(reader);
             reader->state = GRPC_JSON_STATE_VALUE_END;
@@ -235,7 +218,7 @@
                   reader->in_object = 0;
                   reader->in_array = 1;
                   break;
-                case GRPC_JSON_NONE:
+                case GRPC_JSON_TOP_LEVEL:
                   if (reader->depth != 0) return GRPC_JSON_INTERNAL_ERROR;
                   reader->in_object = 0;
                   reader->in_array = 0;
@@ -267,6 +250,7 @@
 
           /* This is the \\ case. */
           case GRPC_JSON_STATE_STRING_ESCAPE:
+            if (reader->unicode_high_surrogate) return GRPC_JSON_PARSE_ERROR;
             grpc_json_reader_string_add_char(reader, '\\');
             if (reader->escaped_string_was_key) {
               reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
@@ -289,21 +273,25 @@
             break;
 
           case GRPC_JSON_STATE_OBJECT_KEY_STRING:
+            if (reader->unicode_high_surrogate) return GRPC_JSON_PARSE_ERROR;
             if (c == '"') {
               reader->state = GRPC_JSON_STATE_OBJECT_KEY_END;
-              grpc_json_reader_object_set_key(reader);
+              grpc_json_reader_set_key(reader);
               grpc_json_reader_string_clear(reader);
             } else {
+              if (c < 32) return GRPC_JSON_PARSE_ERROR;
               grpc_json_reader_string_add_char(reader, c);
             }
             break;
 
           case GRPC_JSON_STATE_VALUE_STRING:
+            if (reader->unicode_high_surrogate) return GRPC_JSON_PARSE_ERROR;
             if (c == '"') {
               reader->state = GRPC_JSON_STATE_VALUE_END;
-              grpc_json_reader_container_set_string(reader);
+              grpc_json_reader_set_string(reader);
               grpc_json_reader_string_clear(reader);
             } else {
+              if (c < 32) return GRPC_JSON_PARSE_ERROR;
               grpc_json_reader_string_add_char(reader, c);
             }
             break;
@@ -374,6 +362,8 @@
             } else {
               reader->state = GRPC_JSON_STATE_VALUE_STRING;
             }
+            if (reader->unicode_high_surrogate && c != 'u')
+              return GRPC_JSON_PARSE_ERROR;
             switch (c) {
               case '"':
               case '/':
@@ -396,7 +386,7 @@
                 break;
               case 'u':
                 reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U1;
-                reader->unicode = 0;
+                reader->unicode_char = 0;
                 break;
               default:
                 return GRPC_JSON_PARSE_ERROR;
@@ -416,8 +406,8 @@
             } else {
               return GRPC_JSON_PARSE_ERROR;
             }
-            reader->unicode <<= 4;
-            reader->unicode |= c;
+            reader->unicode_char <<= 4;
+            reader->unicode_char |= c;
 
             switch (reader->state) {
               case GRPC_JSON_STATE_STRING_ESCAPE_U1:
@@ -430,7 +420,27 @@
                 reader->state = GRPC_JSON_STATE_STRING_ESCAPE_U4;
                 break;
               case GRPC_JSON_STATE_STRING_ESCAPE_U4:
-                grpc_json_reader_string_add_wchar(reader, reader->unicode);
+                if ((reader->unicode_char & 0xfc00) == 0xd800) {
+                  /* high surrogate utf-16 */
+                  if (reader->unicode_high_surrogate)
+                    return GRPC_JSON_PARSE_ERROR;
+                  reader->unicode_high_surrogate = reader->unicode_char;
+                } else if ((reader->unicode_char & 0xfc00) == 0xdc00) {
+                  /* low surrogate utf-16 */
+                  gpr_uint32 utf32;
+                  if (!reader->unicode_high_surrogate)
+                    return GRPC_JSON_PARSE_ERROR;
+                  utf32 = 0x10000;
+                  utf32 += (reader->unicode_high_surrogate - 0xd800) * 0x400;
+                  utf32 += reader->unicode_char - 0xdc00;
+                  grpc_json_reader_string_add_utf32(reader, utf32);
+                  reader->unicode_high_surrogate = 0;
+                } else {
+                  /* anything else */
+                  if (reader->unicode_high_surrogate)
+                    return GRPC_JSON_PARSE_ERROR;
+                  grpc_json_reader_string_add_utf32(reader, reader->unicode_char);
+                }
                 if (reader->escaped_string_was_key) {
                   reader->state = GRPC_JSON_STATE_OBJECT_KEY_STRING;
                 } else {
@@ -564,7 +574,7 @@
 
           case GRPC_JSON_STATE_VALUE_TRUE_E:
             if (c != 'e') return GRPC_JSON_PARSE_ERROR;
-            grpc_json_reader_container_set_true(reader);
+            grpc_json_reader_set_true(reader);
             reader->state = GRPC_JSON_STATE_VALUE_END;
             break;
 
@@ -585,7 +595,7 @@
 
           case GRPC_JSON_STATE_VALUE_FALSE_E:
             if (c != 'e') return GRPC_JSON_PARSE_ERROR;
-            grpc_json_reader_container_set_false(reader);
+            grpc_json_reader_set_false(reader);
             reader->state = GRPC_JSON_STATE_VALUE_END;
             break;
 
@@ -601,7 +611,7 @@
 
           case GRPC_JSON_STATE_VALUE_NULL_L2:
             if (c != 'l') return GRPC_JSON_PARSE_ERROR;
-            grpc_json_reader_container_set_null(reader);
+            grpc_json_reader_set_null(reader);
             reader->state = GRPC_JSON_STATE_VALUE_END;
             break;
 
diff --git a/src/core/json/json_reader.h b/src/core/json/json_reader.h
new file mode 100644
index 0000000..d71f0b8
--- /dev/null
+++ b/src/core/json/json_reader.h
@@ -0,0 +1,158 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#ifndef __GRPC_SRC_CORE_JSON_JSON_READER_H__
+#define __GRPC_SRC_CORE_JSON_JSON_READER_H__
+
+#include <grpc/support/port_platform.h>
+#include "src/core/json/json_common.h"
+
+typedef enum {
+  GRPC_JSON_STATE_OBJECT_KEY_BEGIN,
+  GRPC_JSON_STATE_OBJECT_KEY_STRING,
+  GRPC_JSON_STATE_OBJECT_KEY_END,
+  GRPC_JSON_STATE_VALUE_BEGIN,
+  GRPC_JSON_STATE_VALUE_STRING,
+  GRPC_JSON_STATE_STRING_ESCAPE,
+  GRPC_JSON_STATE_STRING_ESCAPE_U1,
+  GRPC_JSON_STATE_STRING_ESCAPE_U2,
+  GRPC_JSON_STATE_STRING_ESCAPE_U3,
+  GRPC_JSON_STATE_STRING_ESCAPE_U4,
+  GRPC_JSON_STATE_VALUE_NUMBER,
+  GRPC_JSON_STATE_VALUE_NUMBER_WITH_DECIMAL,
+  GRPC_JSON_STATE_VALUE_NUMBER_ZERO,
+  GRPC_JSON_STATE_VALUE_NUMBER_DOT,
+  GRPC_JSON_STATE_VALUE_NUMBER_E,
+  GRPC_JSON_STATE_VALUE_NUMBER_EPM,
+  GRPC_JSON_STATE_VALUE_TRUE_R,
+  GRPC_JSON_STATE_VALUE_TRUE_U,
+  GRPC_JSON_STATE_VALUE_TRUE_E,
+  GRPC_JSON_STATE_VALUE_FALSE_A,
+  GRPC_JSON_STATE_VALUE_FALSE_L,
+  GRPC_JSON_STATE_VALUE_FALSE_S,
+  GRPC_JSON_STATE_VALUE_FALSE_E,
+  GRPC_JSON_STATE_VALUE_NULL_U,
+  GRPC_JSON_STATE_VALUE_NULL_L1,
+  GRPC_JSON_STATE_VALUE_NULL_L2,
+  GRPC_JSON_STATE_VALUE_END,
+  GRPC_JSON_STATE_END
+} grpc_json_reader_state;
+
+enum {
+  /* The first non-unicode value is 0x110000. But let's pick
+   * a value high enough to start our error codes from. These
+   * values are safe to return from the read_char function.
+   */
+  GRPC_JSON_READ_CHAR_EOF = 0x7ffffff0,
+  GRPC_JSON_READ_CHAR_EAGAIN,
+  GRPC_JSON_READ_CHAR_ERROR
+};
+
+typedef struct grpc_json_reader {
+  /* You are responsible for your own opaque userdata.
+   * Among other things, it needs to hold a string scratchpad.
+   */
+  void* userdata;
+
+  /* You also need to set up these callbacks. */
+
+  /* Clears your internal string scratchpad. */
+  void (*string_clear)(struct grpc_json_reader*);
+  /* Adds a char to the string scratchpad. */
+  void (*string_add_char)(struct grpc_json_reader*, gpr_uint32 c);
+  /* Adds a utf32 char to the string scratchpad. */
+  void (*string_add_utf32)(struct grpc_json_reader*, gpr_uint32 c);
+  /* Reads a character from your input. May be utf-8, 16 or 32. */
+  gpr_uint32 (*read_char)(struct grpc_json_reader*);
+  /* Starts a container of type GRPC_JSON_ARRAY or GRPC_JSON_OBJECT. */
+  void (*container_begins)(struct grpc_json_reader*, grpc_json_type type);
+  /* Ends the current container. Must return the type of its parent. */
+  grpc_json_type (*container_ends)(struct grpc_json_reader*);
+  /* Your internal string scratchpad is an object's key. */
+  void (*set_key)(struct grpc_json_reader*);
+  /* Your internal string scratchpad is a string value. */
+  void (*set_string)(struct grpc_json_reader*);
+  /* Your internal string scratchpad is a numerical value. Return 1 if valid. */
+  int (*set_number)(struct grpc_json_reader*);
+  /* Sets the values true, false or null. */
+  void (*set_true)(struct grpc_json_reader*);
+  void (*set_false)(struct grpc_json_reader*);
+  void (*set_null)(struct grpc_json_reader*);
+
+  /* Everything down here is private,
+     and initialized by grpc_json_reader_init. */
+  int depth;
+  int in_object;
+  int in_array;
+  int escaped_string_was_key;
+  int container_just_begun;
+  gpr_uint16 unicode_char, unicode_high_surrogate;
+  grpc_json_reader_state state;
+} grpc_json_reader;
+
+/* The return type of the parser. */
+typedef enum {
+  GRPC_JSON_DONE,          /* The parser finished successfully. */
+  GRPC_JSON_EAGAIN,        /* The parser yields to get more data. */
+  GRPC_JSON_READ_ERROR,    /* The parser passes through a read error. */
+  GRPC_JSON_PARSE_ERROR,   /* The parser found an error in the json stream. */
+  GRPC_JSON_INTERNAL_ERROR /* The parser got an internal error. */
+} grpc_json_reader_ret;
+
+/* Call this function to start parsing the input. It will return the following:
+ *    . GRPC_JSON_DONE if the input got eof, and the parsing finished
+ *      successfully.
+ *    . GRPC_JSON_EAGAIN if the read_char function returned again. Call the
+ *      parser again as needed. It is okay to call the parser in polling mode,
+ *      although a bit dull.
+ *    . GRPC_JSON_READ_ERROR if the read_char function returned an error. The
+ *      state isn't broken however, and the function can be called again if the
+ *      error has been corrected. But please use the EAGAIN feature instead for
+ *      consistency.
+ *    . GRPC_JSON_PARSE_ERROR if the input was somehow invalid.
+ *    . GRPC_JSON_INTERNAL_ERROR if the parser somehow ended into an invalid
+ *      internal state.
+ */
+grpc_json_reader_ret grpc_json_reader_run(grpc_json_reader* reader);
+
+/* Call this function to initialize the reader structure. */
+void grpc_json_reader_init(grpc_json_reader* reader);
+
+/* You may call this from the read_char callback if you don't know where is the
+ * end of your input stream, and you'd like the json reader to hint you that it
+ * has completed reading its input, so you can return an EOF to it. Note that
+ * there might still be trailing whitespaces after that point.
+ */
+int grpc_json_reader_is_complete(grpc_json_reader* reader);
+
+#endif /* __GRPC_SRC_CORE_JSON_JSON_READER_H__ */
diff --git a/src/core/json/json_string.c b/src/core/json/json_string.c
new file mode 100644
index 0000000..12309c4
--- /dev/null
+++ b/src/core/json/json_string.c
@@ -0,0 +1,391 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <string.h>
+#include <stdlib.h>
+
+#include <grpc/support/alloc.h>
+#include <grpc/support/log.h>
+
+#include "src/core/json/json.h"
+#include "src/core/json/json_reader.h"
+#include "src/core/json/json_writer.h"
+
+/* The json reader will construct a bunch of grpc_json objects and
+ * link them all up together in a tree-like structure that will represent
+ * the json data in memory.
+ *
+ * It also uses its own input as a scratchpad to store all of the decoded,
+ * unescaped strings. So we need to keep track of all these pointers in
+ * that opaque structure the reader will carry for us.
+ *
+ * Note that this works because the act of parsing json always reduces its
+ * input size, and never expands it.
+ */
+typedef struct {
+  grpc_json* top;
+  grpc_json* current_container;
+  grpc_json* current_value;
+  char* input;
+  char* key;
+  char* string;
+  char* string_ptr;
+  size_t remaining_input;
+} grpc_json_reader_opaque;
+
+/* This json writer will put everything in a big string.
+ * The point is that we allocate that string in chunks of 256 bytes.
+ */
+typedef struct {
+  char* output;
+  size_t free_space, string_len, allocated;
+} grpc_json_writer_opaque;
+
+
+/* This function checks if there's enough space left in the output buffer,
+ * and will enlarge it if necessary. We're only allocating chunks of 256
+ * bytes at a time (or multiples thereof).
+ */
+static void grpc_json_writer_output_check(grpc_json_writer* writer,
+                                          size_t needed) {
+  grpc_json_writer_opaque* state = writer->userdata;
+  if (state->free_space >= needed) return;
+  needed -= state->free_space;
+  /* Round up by 256 bytes. */
+  needed = (needed + 0xff) & ~0xff;
+  state->output = gpr_realloc(state->output, state->allocated + needed);
+  state->free_space += needed;
+  state->allocated += needed;
+}
+
+/* These are needed by the writer's implementation. */
+static void grpc_json_writer_output_char(grpc_json_writer* writer,
+                                         char c) {
+  grpc_json_writer_opaque* state = writer->userdata;
+  grpc_json_writer_output_check(writer, 1);
+  state->output[state->string_len++] = c;
+  state->free_space--;
+}
+
+static void grpc_json_writer_output_string_with_len(
+    grpc_json_writer* writer, const char* str, size_t len) {
+  grpc_json_writer_opaque* state = writer->userdata;
+  grpc_json_writer_output_check(writer, len);
+  memcpy(state->output + state->string_len, str, len);
+  state->string_len += len;
+  state->free_space -= len;
+}
+
+static void grpc_json_writer_output_string(grpc_json_writer* writer,
+                                           const char* str) {
+  size_t len = strlen(str);
+  grpc_json_writer_output_string_with_len(writer, str, len);
+}
+
+/* The reader asks us to clear our scratchpad. In our case, we'll simply mark
+ * the end of the current string, and advance our output pointer.
+ */
+static void grpc_json_reader_string_clear(grpc_json_reader* reader) {
+  grpc_json_reader_opaque* state = reader->userdata;
+  if (state->string) {
+    GPR_ASSERT(state->string_ptr < state->input);
+    *state->string_ptr++ = 0;
+  }
+  state->string = state->string_ptr;
+}
+
+static void grpc_json_reader_string_add_char(grpc_json_reader* reader, gpr_uint32 c) {
+  grpc_json_reader_opaque* state = reader->userdata;
+  GPR_ASSERT(state->string_ptr < state->input);
+  GPR_ASSERT(c <= 0xff);
+  *state->string_ptr++ = (char)c;
+}
+
+/* We are converting a UTF-32 character into UTF-8 here. */
+static void grpc_json_reader_string_add_utf32(grpc_json_reader* reader, gpr_uint32 c) {
+  if (c <= 0x7f) {
+    grpc_json_reader_string_add_char(reader, c);
+  } else if (c <= 0x7ff) {
+    int b1 = 0xc0 | ((c >> 6) & 0x1f);
+    int b2 = 0x80 | (c & 0x3f);
+    grpc_json_reader_string_add_char(reader, b1);
+    grpc_json_reader_string_add_char(reader, b2);
+  } else if (c <= 0xffff) {
+    int b1 = 0xe0 | ((c >> 12) & 0x0f);
+    int b2 = 0x80 | ((c >> 6) & 0x3f);
+    int b3 = 0x80 | (c & 0x3f);
+    grpc_json_reader_string_add_char(reader, b1);
+    grpc_json_reader_string_add_char(reader, b2);
+    grpc_json_reader_string_add_char(reader, b3);
+  } else if (c <= 0x1fffff) {
+    int b1 = 0xf0 | ((c >> 18) & 0x07);
+    int b2 = 0x80 | ((c >> 12) & 0x3f);
+    int b3 = 0x80 | ((c >> 6) & 0x3f);
+    int b4 = 0x80 | (c & 0x3f);
+    grpc_json_reader_string_add_char(reader, b1);
+    grpc_json_reader_string_add_char(reader, b2);
+    grpc_json_reader_string_add_char(reader, b3);
+    grpc_json_reader_string_add_char(reader, b4);
+  }
+}
+
+/* We consider that the input may be a zero-terminated string. So we
+ * can end up hitting eof before the end of the alleged string length.
+ */
+static gpr_uint32 grpc_json_reader_read_char(grpc_json_reader* reader) {
+  gpr_uint32 r;
+  grpc_json_reader_opaque* state = reader->userdata;
+
+  if (state->remaining_input == 0) return GRPC_JSON_READ_CHAR_EOF;
+
+  r = *state->input++;
+  state->remaining_input--;
+
+  if (r == 0) {
+    state->remaining_input = 0;
+    return GRPC_JSON_READ_CHAR_EOF;
+  }
+
+  return r;
+}
+
+/* Helper function to create a new grpc_json object and link it into
+ * our tree-in-progress inside our opaque structure.
+ */
+static grpc_json* grpc_json_new_and_link(grpc_json_reader* reader,
+                                         grpc_json_type type) {
+  grpc_json_reader_opaque* state = reader->userdata;
+  grpc_json* json = grpc_json_new(type);
+
+  json->parent = state->current_container;
+  json->prev = state->current_value;
+  state->current_value = json;
+
+  if (json->prev) {
+    json->prev->next = json;
+  }
+  if (json->parent) {
+    if (!json->parent->child) {
+      json->parent->child = json;
+    }
+    if (json->parent->type == GRPC_JSON_OBJECT) {
+      json->key = state->key;
+    }
+  }
+  if (!state->top) {
+    state->top = json;
+  }
+
+  return json;
+}
+
+static void grpc_json_reader_container_begins(grpc_json_reader* reader,
+                                              grpc_json_type type) {
+  grpc_json_reader_opaque* state = reader->userdata;
+  grpc_json* container;
+
+  GPR_ASSERT(type == GRPC_JSON_ARRAY || type == GRPC_JSON_OBJECT);
+
+  container = grpc_json_new_and_link(reader, type);
+  state->current_container = container;
+  state->current_value = NULL;
+}
+
+/* It's important to remember that the reader is mostly stateless, so it
+ * isn't trying to remember what the container was prior the one that just
+ * ends. Since we're keeping track of these for our own purpose, we are
+ * able to return that information back, which is useful for it to validate
+ * the input json stream.
+ *
+ * Also note that if we're at the top of the tree, and the last container
+ * ends, we have to return GRPC_JSON_TOP_LEVEL.
+ */
+static grpc_json_type grpc_json_reader_container_ends(
+    grpc_json_reader* reader) {
+  grpc_json_type container_type = GRPC_JSON_TOP_LEVEL;
+  grpc_json_reader_opaque* state = reader->userdata;
+
+  GPR_ASSERT(state->current_container);
+
+  state->current_value = state->current_container;
+  state->current_container = state->current_container->parent;
+
+  if (state->current_container) {
+    container_type = state->current_container->type;
+  }
+
+  return container_type;
+}
+
+/* The next 3 functions basically are the reader asking us to use our string
+ * scratchpad for one of these 3 purposes.
+ *
+ * Note that in the set_number case, we're not going to try interpreting it.
+ * We'll keep it as a string, and leave it to the caller to evaluate it.
+ */
+static void grpc_json_reader_set_key(grpc_json_reader* reader) {
+  grpc_json_reader_opaque* state = reader->userdata;
+  state->key = state->string;
+}
+
+static void grpc_json_reader_set_string(
+    grpc_json_reader* reader) {
+  grpc_json_reader_opaque* state = reader->userdata;
+  grpc_json* json = grpc_json_new_and_link(reader, GRPC_JSON_STRING);
+  json->value = state->string;
+}
+
+static int grpc_json_reader_set_number(
+    grpc_json_reader* reader) {
+  grpc_json_reader_opaque* state = reader->userdata;
+  grpc_json* json = grpc_json_new_and_link(reader, GRPC_JSON_NUMBER);
+  json->value = state->string;
+  return 1;
+}
+
+/* The object types true, false and null are self-sufficient, and don't need
+ * any more information beside their type.
+ */
+static void grpc_json_reader_set_true(
+    grpc_json_reader *reader) {
+  grpc_json_new_and_link(reader, GRPC_JSON_TRUE);
+}
+
+static void grpc_json_reader_set_false(
+    grpc_json_reader *reader) {
+  grpc_json_new_and_link(reader, GRPC_JSON_FALSE);
+}
+
+static void grpc_json_reader_set_null(
+    grpc_json_reader *reader) {
+  grpc_json_new_and_link(reader, GRPC_JSON_NULL);
+}
+
+/* And finally, let's define our public API. */
+grpc_json* grpc_json_parse_string_with_len(char* input, size_t size) {
+  grpc_json_reader reader;
+  grpc_json_reader_opaque state;
+  grpc_json *json = NULL;
+  grpc_json_reader_ret status;
+
+  if (!input) return NULL;
+
+  state.top = state.current_container = state.current_value = NULL;
+  state.string = state.key = NULL;
+  state.string_ptr = state.input = input;
+  state.remaining_input = size;
+  reader.userdata = &state;
+  reader.string_clear = grpc_json_reader_string_clear;
+  reader.string_add_char = grpc_json_reader_string_add_char;
+  reader.string_add_utf32 = grpc_json_reader_string_add_utf32;
+  reader.read_char = grpc_json_reader_read_char;
+  reader.container_begins = grpc_json_reader_container_begins;
+  reader.container_ends = grpc_json_reader_container_ends;
+  reader.set_key = grpc_json_reader_set_key;
+  reader.set_string = grpc_json_reader_set_string;
+  reader.set_number = grpc_json_reader_set_number;
+  reader.set_true = grpc_json_reader_set_true;
+  reader.set_false = grpc_json_reader_set_false;
+  reader.set_null = grpc_json_reader_set_null;
+  grpc_json_reader_init(&reader);
+
+  status = grpc_json_reader_run(&reader);
+  json = state.top;
+
+  if ((status != GRPC_JSON_DONE) && json) {
+    grpc_json_delete(json);
+    json = NULL;
+  }
+
+  return json;
+}
+
+#define UNBOUND_JSON_STRING_LENGTH 0x7fffffff
+
+grpc_json* grpc_json_parse_string(char* input) {
+  return grpc_json_parse_string_with_len(input, UNBOUND_JSON_STRING_LENGTH);
+}
+
+static void grpc_json_dump_recursive(grpc_json_writer* writer,
+                                     grpc_json* json, int in_object) {
+  while (json) {
+    if (in_object) grpc_json_writer_object_key(writer, json->key);
+
+    switch (json->type) {
+      case GRPC_JSON_OBJECT:
+      case GRPC_JSON_ARRAY:
+        grpc_json_writer_container_begins(writer, json->type);
+        if (json->child)
+          grpc_json_dump_recursive(writer, json->child,
+                                   json->type == GRPC_JSON_OBJECT);
+        grpc_json_writer_container_ends(writer, json->type);
+        break;
+      case GRPC_JSON_STRING:
+        grpc_json_writer_value_string(writer, json->value);
+        break;
+      case GRPC_JSON_NUMBER:
+        grpc_json_writer_value_raw(writer, json->value);
+        break;
+      case GRPC_JSON_TRUE:
+        grpc_json_writer_value_raw_with_len(writer, "true", 4);
+        break;
+      case GRPC_JSON_FALSE:
+        grpc_json_writer_value_raw_with_len(writer, "false", 5);
+        break;
+      case GRPC_JSON_NULL:
+        grpc_json_writer_value_raw_with_len(writer, "null", 4);
+        break;
+      default:
+        abort();
+    }
+    json = json->next;
+  }
+}
+
+char* grpc_json_dump_to_string(grpc_json* json, int indent) {
+  grpc_json_writer writer;
+  grpc_json_writer_opaque state;
+  state.output = NULL;
+  state.free_space = state.string_len = state.allocated = 0;
+  writer.userdata = &state;
+  writer.output_char = grpc_json_writer_output_char;
+  writer.output_string = grpc_json_writer_output_string;
+  writer.output_string_with_len = grpc_json_writer_output_string_with_len;
+  grpc_json_writer_init(&writer, indent);
+
+  grpc_json_dump_recursive(&writer, json, 0);
+
+  grpc_json_writer_output_char(&writer, 0);
+
+  return state.output;
+}
diff --git a/src/core/json/json_writer.c b/src/core/json/json_writer.c
new file mode 100644
index 0000000..9fc65aa
--- /dev/null
+++ b/src/core/json/json_writer.c
@@ -0,0 +1,248 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+#include <grpc/support/port_platform.h>
+#include "src/core/json/json_writer.h"
+
+static void grpc_json_writer_output_char(grpc_json_writer* writer, char c) {
+  writer->output_char(writer, c);
+}
+
+static void grpc_json_writer_output_string(grpc_json_writer* writer, const char* str) {
+  writer->output_string(writer, str);
+}
+
+static void grpc_json_writer_output_string_with_len(grpc_json_writer* writer, const char* str, size_t len) {
+  writer->output_string_with_len(writer, str, len);
+}
+
+/* Call this function to initialize the writer structure. */
+void grpc_json_writer_init(grpc_json_writer* writer, int indent) {
+  writer->depth = 0;
+  writer->container_empty = 1;
+  writer->got_key = 0;
+  writer->indent = indent;
+}
+
+static void grpc_json_writer_output_indent(
+    grpc_json_writer* writer) {
+  static const char spacesstr[] =
+      "                "
+      "                "
+      "                "
+      "                ";
+
+  int spaces = writer->depth * writer->indent;
+
+  if (writer->got_key) {
+    grpc_json_writer_output_char(writer, ' ');
+    return;
+  }
+
+  while (spaces >= (sizeof(spacesstr) - 1)) {
+    grpc_json_writer_output_string_with_len(writer, spacesstr,
+                                            sizeof(spacesstr) - 1);
+    spaces -= (sizeof(spacesstr) - 1);
+  }
+
+  if (!spaces) return;
+
+  grpc_json_writer_output_string_with_len(
+      writer, spacesstr + sizeof(spacesstr) - 1 - spaces, spaces);
+}
+
+static void grpc_json_writer_value_end(
+    grpc_json_writer* writer) {
+  if (writer->container_empty) {
+    writer->container_empty = 0;
+    if (!writer->indent || !writer->depth) return;
+    grpc_json_writer_output_char(writer, '\n');
+  } else {
+    grpc_json_writer_output_char(writer, ',');
+    if (!writer->indent) return;
+    grpc_json_writer_output_char(writer, '\n');
+  }
+}
+
+static void grpc_json_writer_escape_utf16(grpc_json_writer* writer, gpr_uint16 utf16) {
+  static const char hex[] = "0123456789abcdef";
+
+  grpc_json_writer_output_string_with_len(writer, "\\u", 2);
+  grpc_json_writer_output_char(writer, hex[(utf16 >> 12) & 0x0f]);
+  grpc_json_writer_output_char(writer, hex[(utf16 >> 8) & 0x0f]);
+  grpc_json_writer_output_char(writer, hex[(utf16 >> 4) & 0x0f]);
+  grpc_json_writer_output_char(writer, hex[(utf16) & 0x0f]);
+}
+
+static void grpc_json_writer_escape_string(
+    grpc_json_writer* writer, const char* string) {
+  grpc_json_writer_output_char(writer, '"');
+
+  for (;;) {
+    unsigned char c = (unsigned char)*string++;
+    if (!c) {
+      break;
+    } else if ((c >= 32) && (c <= 127)) {
+      if ((c == '\\') || (c == '"')) grpc_json_writer_output_char(writer, '\\');
+      grpc_json_writer_output_char(writer, c);
+    } else if (c < 32) {
+      grpc_json_writer_output_char(writer, '\\');
+      switch (c) {
+        case '\b':
+          grpc_json_writer_output_char(writer, 'b');
+          break;
+        case '\f':
+          grpc_json_writer_output_char(writer, 'f');
+          break;
+        case '\n':
+          grpc_json_writer_output_char(writer, 'n');
+          break;
+        case '\r':
+          grpc_json_writer_output_char(writer, 'r');
+          break;
+        case '\t':
+          grpc_json_writer_output_char(writer, 't');
+          break;
+        default:
+          grpc_json_writer_escape_utf16(writer, c);
+          break;
+      }
+    } else {
+      gpr_uint32 utf32 = 0;
+      int extra = 0;
+      int i;
+      int valid = 1;
+      if ((c & 0xe0) == 0xc0) {
+        utf32 = c & 0x1f;
+        extra = 1;
+      } else if ((c & 0xf0) == 0xe0) {
+        utf32 = c & 0x0f;
+        extra = 2;
+      } else if ((c & 0xf8) == 0xf0) {
+        utf32 = c & 0x07;
+        extra = 3;
+      } else {
+        break;
+      }
+      for (i = 0; i < extra; i++) {
+        utf32 <<= 6;
+        c = *string++;
+        if ((c & 0xc0) != 0x80) {
+          valid = 0;
+          break;
+        }
+        utf32 |= c & 0x3f;
+      }
+      if (!valid) break;
+      /* The range 0xd800 - 0xdfff is reserved by the surrogates ad vitam.
+       * Any other range is technically reserved for future usage, so if we
+       * don't want the software to break in the future, we have to allow
+       * anything else. The first non-unicode character is 0x110000. */
+      if (((utf32 >= 0xd800) && (utf32 <= 0xdfff)) ||
+          (utf32 >= 0x110000)) break;
+      if (utf32 >= 0x10000) {
+        /* If utf32 contains a character that is above 0xffff, it needs to be
+         * broken down into a utf-16 surrogate pair. A surrogate pair is first
+         * a high surrogate, followed by a low surrogate. Each surrogate holds
+         * 10 bits of usable data, thus allowing a total of 20 bits of data.
+         * The high surrogate marker is 0xd800, while the low surrogate marker
+         * is 0xdc00. The low 10 bits of each will be the usable data.
+         *
+         * After re-combining the 20 bits of data, one has to add 0x10000 to
+         * the resulting value, in order to obtain the original character.
+         * This is obviously because the range 0x0000 - 0xffff can be written
+         * without any special trick.
+         *
+         * Since 0x10ffff is the highest allowed character, we're working in
+         * the range 0x00000 - 0xfffff after we decrement it by 0x10000.
+         * That range is exactly 20 bits.
+         */
+        utf32 -= 0x10000;
+        grpc_json_writer_escape_utf16(writer, 0xd800 | (utf32 >> 10));
+        grpc_json_writer_escape_utf16(writer, 0xdc00 | (utf32 && 0x3ff));
+      } else {
+        grpc_json_writer_escape_utf16(writer, utf32);
+      }
+    }
+  }
+
+  grpc_json_writer_output_char(writer, '"');
+}
+
+void grpc_json_writer_container_begins(grpc_json_writer* writer, grpc_json_type type) {
+  if (!writer->got_key) grpc_json_writer_value_end(writer);
+  grpc_json_writer_output_indent(writer);
+  grpc_json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '{' : '[');
+  writer->container_empty = 1;
+  writer->got_key = 0;
+  writer->depth++;
+}
+
+void grpc_json_writer_container_ends(grpc_json_writer* writer, grpc_json_type type) {
+  if (writer->indent && !writer->container_empty)
+    grpc_json_writer_output_char(writer, '\n');
+  writer->depth--;
+  if (!writer->container_empty) grpc_json_writer_output_indent(writer);
+  grpc_json_writer_output_char(writer, type == GRPC_JSON_OBJECT ? '}' : ']');
+  writer->container_empty = 0;
+  writer->got_key = 0;
+}
+
+void grpc_json_writer_object_key(grpc_json_writer* writer, const char* string) {
+  grpc_json_writer_value_end(writer);
+  grpc_json_writer_output_indent(writer);
+  grpc_json_writer_escape_string(writer, string);
+  grpc_json_writer_output_char(writer, ':');
+  writer->got_key = 1;
+}
+
+void grpc_json_writer_value_raw(grpc_json_writer* writer, const char* string) {
+  if (!writer->got_key) grpc_json_writer_value_end(writer);
+  grpc_json_writer_output_indent(writer);
+  grpc_json_writer_output_string(writer, string);
+  writer->got_key = 0;
+}
+
+void grpc_json_writer_value_raw_with_len(grpc_json_writer* writer, const char* string, size_t len) {
+  if (!writer->got_key) grpc_json_writer_value_end(writer);
+  grpc_json_writer_output_indent(writer);
+  grpc_json_writer_output_string_with_len(writer, string, len);
+  writer->got_key = 0;
+}
+
+void grpc_json_writer_value_string(grpc_json_writer* writer, const char* string) {
+  if (!writer->got_key) grpc_json_writer_value_end(writer);
+  grpc_json_writer_output_indent(writer);
+  grpc_json_writer_escape_string(writer, string);
+  writer->got_key = 0;
+}
diff --git a/src/core/json/json_writer.h b/src/core/json/json_writer.h
new file mode 100644
index 0000000..f0baa1e
--- /dev/null
+++ b/src/core/json/json_writer.h
@@ -0,0 +1,92 @@
+/*
+ *
+ * Copyright 2014, Google Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *
+ *     * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ * copyright notice, this list of conditions and the following disclaimer
+ * in the documentation and/or other materials provided with the
+ * distribution.
+ *     * Neither the name of Google Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from
+ * this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
+ * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
+ * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ */
+
+/* The idea of the writer is basically symmetrical of the reader. While the
+ * reader emits various calls to your code, the writer takes basically the
+ * same calls and emit json out of it. It doesn't try to make any check on
+ * the order of the calls you do on it. Meaning you can theorically force
+ * it to generate invalid json.
+ *
+ * Also, unlike the reader, the writer expects UTF-8 encoded input strings.
+ * These strings will be UTF-8 validated, and any invalid character will
+ * cut the conversion short, before any invalid UTF-8 sequence, thus forming
+ * a valid UTF-8 string overall.
+ */
+
+#ifndef __GRPC_SRC_CORE_JSON_JSON_WRITER_H__
+#define __GRPC_SRC_CORE_JSON_JSON_WRITER_H__
+
+#include <stdlib.h>
+
+#include "src/core/json/json_common.h"
+
+typedef struct grpc_json_writer {
+  /* You are responsible for your own opaque userdata. */
+  void* userdata;
+
+  /* The rest are your own callbacks. Define them. */
+
+  /* Adds a character to the output stream. */
+  void (*output_char)(struct grpc_json_writer*, char);
+  /* Adds a zero-terminated string to the output stream. */
+  void (*output_string)(struct grpc_json_writer*, const char* str);
+  /* Adds a fixed-length string to the output stream. */
+  void (*output_string_with_len)(struct grpc_json_writer*, const char* str, size_t len);
+
+  int indent;
+  int depth;
+  int container_empty;
+  int got_key;
+} grpc_json_writer;
+
+/* Call this to initialize your writer structure. The indent parameter is
+ * specifying the number of spaces to use for indenting the output. If you
+ * use indent=0, then the output will not have any newlines either, thus
+ * emitting a condensed json output.
+ */
+void grpc_json_writer_init(grpc_json_writer* writer, int indent);
+
+/* Signals the beginning of a container. */
+void grpc_json_writer_container_begins(grpc_json_writer* writer, grpc_json_type type);
+/* Signals the end of a container. */
+void grpc_json_writer_container_ends(grpc_json_writer* writer, grpc_json_type type);
+/* Writes down an object key for the next value. */
+void grpc_json_writer_object_key(grpc_json_writer* writer, const char* string);
+/* Sets a raw value. Useful for numbers. */
+void grpc_json_writer_value_raw(grpc_json_writer* writer, const char* string);
+/* Sets a raw value with its length. Useful for values like true or false. */
+void grpc_json_writer_value_raw_with_len(grpc_json_writer* writer, const char* string, size_t len);
+/* Sets a string value. It'll be escaped, and utf-8 validated. */
+void grpc_json_writer_value_string(grpc_json_writer* writer, const char* string);
+
+#endif /* __GRPC_SRC_CORE_JSON_JSON_WRITER_H__ */
diff --git a/src/core/security/credentials.c b/src/core/security/credentials.c
index 78937c1..28adf1e 100644
--- a/src/core/security/credentials.c
+++ b/src/core/security/credentials.c
@@ -392,7 +392,7 @@
     }
     gpr_asprintf(&new_access_token, "%s %s", token_type->value,
                  access_token->value);
-    token_lifetime->tv_sec = expires_in->valueint;
+    token_lifetime->tv_sec = strtol(expires_in->value, NULL, 10);
     token_lifetime->tv_nsec = 0;
     if (*token_elem != NULL) grpc_mdelem_unref(*token_elem);
     *token_elem = grpc_mdelem_from_strings(ctx, GRPC_AUTHORIZATION_METADATA_KEY,
diff --git a/src/core/security/json_token.c b/src/core/security/json_token.c
index 2da30f4..9aeeb89 100644
--- a/src/core/security/json_token.c
+++ b/src/core/security/json_token.c
@@ -169,26 +169,26 @@
 
 /* --- jwt encoding and signature. --- */
 
-static void create_child(grpc_json **brother, grpc_json *parent,
+static grpc_json *create_child(grpc_json *brother, grpc_json *parent,
                          const char *key, const char *value,
-                         enum grpc_json_type_t type) {
+                         grpc_json_type type) {
   grpc_json *child = grpc_json_new(type);
-  if (*brother) (*brother)->next = child;
+  if (brother) (brother)->next = child;
   if (!parent->child) parent->child = child;
   child->parent = parent;
   child->value = value;
   child->key = key;
-  *brother = child;
+  return child;
 }
 
 static char *encoded_jwt_header(const char *algorithm) {
   grpc_json *json = grpc_json_new(GRPC_JSON_OBJECT);
-  grpc_json *brother = NULL;
+  grpc_json *child = NULL;
   char *json_str = NULL;
   char *result = NULL;
 
-  create_child(&brother, json, "alg", algorithm, GRPC_JSON_STRING);
-  create_child(&brother, json, "typ", GRPC_JWT_TYPE, GRPC_JSON_STRING);
+  child = create_child(NULL, json, "alg", algorithm, GRPC_JSON_STRING);
+  create_child(child, json, "typ", GRPC_JWT_TYPE, GRPC_JSON_STRING);
 
   json_str = grpc_json_dump_to_string(json, 0);
   result = grpc_base64_encode(json_str, strlen(json_str), 1, 0);
@@ -200,7 +200,7 @@
 static char *encoded_jwt_claim(const grpc_auth_json_key *json_key,
                                const char *scope, gpr_timespec token_lifetime) {
   grpc_json *json = grpc_json_new(GRPC_JSON_OBJECT);
-  grpc_json *brother = NULL;
+  grpc_json *child = NULL;
   char *json_str = NULL;
   char *result = NULL;
   gpr_timespec now = gpr_now();
@@ -215,11 +215,12 @@
   sprintf(now_str, "%ld", now.tv_sec);
   sprintf(expiration_str, "%ld", expiration.tv_sec);
 
-  create_child(&brother, json, "iss", json_key->client_email, GRPC_JSON_STRING);
-  create_child(&brother, json, "scope", scope, GRPC_JSON_STRING);
-  create_child(&brother, json, "aud", GRPC_JWT_AUDIENCE, GRPC_JSON_STRING);
-  create_child(&brother, json, "iat", now_str, GRPC_JSON_NUMBER);
-  create_child(&brother, json, "exp", expiration_str, GRPC_JSON_NUMBER);
+  child = create_child(NULL, json, "iss", json_key->client_email,
+                       GRPC_JSON_STRING);
+  child = create_child(child, json, "scope", scope, GRPC_JSON_STRING);
+  child = create_child(child, json, "aud", GRPC_JWT_AUDIENCE, GRPC_JSON_STRING);
+  child = create_child(child, json, "iat", now_str, GRPC_JSON_NUMBER);
+  create_child(child, json, "exp", expiration_str, GRPC_JSON_NUMBER);
 
   json_str = grpc_json_dump_to_string(json, 0);
   result = grpc_base64_encode(json_str, strlen(json_str), 1, 0);
diff --git a/test/core/security/credentials_test.c b/test/core/security/credentials_test.c
index ec21e0d..fbad52d 100644
--- a/test/core/security/credentials_test.c
+++ b/test/core/security/credentials_test.c
@@ -55,23 +55,23 @@
    Maximum size for a string literal is 509 chars in C89, yay!  */
 static const char test_json_key_str_part1[] =
     "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----"
-    "\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\n7mJEqg"
-    "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\nyjSeg/"
+    "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJEqg"
+    "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/"
     "rWBQvS4hle4LfijkP3J5BG+"
-    "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\nOnVF6N7dL3nTYZg+"
-    "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\nDZgSE6Bu/"
-    "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\n/"
+    "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+"
+    "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/"
+    "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/"
     "8HpCqFYM9V8f34SBWfD4fRFT+n/"
-    "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\ngqXjDvpkypEusgXAykECQQD+";
+    "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+";
 static const char test_json_key_str_part2[] =
-    "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\nCslxoHQM8s+"
-    "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\nEkoy2L/"
-    "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\nAARh2QJBAMKeDAG"
-    "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\n8FZi5c8idxiwC36kbAL6HzA"
-    "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\n6z8RJm0+"
+    "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+"
+    "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/"
+    "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDAG"
+    "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6HzA"
+    "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+"
     "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/"
-    "5nZ68ECQQDvYuI3\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZY"
-    "Ap6LI9W\nIqv4vr6y38N79TTC\n-----END PRIVATE KEY-----\n\", ";
+    "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZY"
+    "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", ";
 static const char test_json_key_str_part3[] =
     "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
     "\"client_email\": "
diff --git a/test/core/security/json_token_test.c b/test/core/security/json_token_test.c
index 2f9f6dd..1eddfc1 100644
--- a/test/core/security/json_token_test.c
+++ b/test/core/security/json_token_test.c
@@ -49,23 +49,23 @@
    Maximum size for a string literal is 509 chars in C89, yay!  */
 static const char test_json_key_str_part1[] =
     "{ \"private_key\": \"-----BEGIN PRIVATE KEY-----"
-    "\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\n7mJEqg"
-    "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\nyjSeg/"
+    "\\nMIICeAIBADANBgkqhkiG9w0BAQEFAASCAmIwggJeAgEAAoGBAOEvJsnoHnyHkXcp\\n7mJEqg"
+    "WGjiw71NfXByguekSKho65FxaGbsnSM9SMQAqVk7Q2rG+I0OpsT0LrWQtZ\\nyjSeg/"
     "rWBQvS4hle4LfijkP3J5BG+"
-    "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\nOnVF6N7dL3nTYZg+"
-    "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\nDZgSE6Bu/"
-    "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\n/"
+    "IXDMP8RfziNRQsenAXDNPkY4kJCvKux2xdD\\nOnVF6N7dL3nTYZg+"
+    "uQrNsMTz9UxVAgMBAAECgYEAzbLewe1xe9vy+2GoSsfib+28\\nDZgSE6Bu/"
+    "zuFoPrRc6qL9p2SsnV7txrunTyJkkOnPLND9ABAXybRTlcVKP/sGgza\\n/"
     "8HpCqFYM9V8f34SBWfD4fRFT+n/"
-    "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\ngqXjDvpkypEusgXAykECQQD+";
+    "73cfRUtGXdXpseva2lh8RilIQfPhNZAncenU\\ngqXjDvpkypEusgXAykECQQD+";
 static const char test_json_key_str_part2[] =
-    "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\nCslxoHQM8s+"
-    "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\nEkoy2L/"
-    "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\nAARh2QJBAMKeDAG"
-    "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\n8FZi5c8idxiwC36kbAL6HzA"
-    "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\n6z8RJm0+"
+    "53XxNVnxBHsYb+AYEfklR96yVi8HywjVHP34+OQZ\\nCslxoHQM8s+"
+    "dBnjfScLu22JqkPv04xyxmt0QAKm9+vTdAkEA4ib7YvEAn2jXzcCI\\nEkoy2L/"
+    "XydR1GCHoacdfdAwiL2npOdnbvi4ZmdYRPY1LSTO058tQHKVXV7NLeCa3\\nAARh2QJBAMKeDAG"
+    "W303SQv2cZTdbeaLKJbB5drz3eo3j7dDKjrTD9JupixFbzcGw\\n8FZi5c8idxiwC36kbAL6HzA"
+    "ZoX+ofI0CQE6KCzPJTtYNqyShgKAZdJ8hwOcvCZtf\\n6z8RJm0+"
     "6YBd38lfh5j8mZd7aHFf6I17j5AQY7oPEc47TjJj/"
-    "5nZ68ECQQDvYuI3\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZY"
-    "Ap6LI9W\nIqv4vr6y38N79TTC\n-----END PRIVATE KEY-----\n\", ";
+    "5nZ68ECQQDvYuI3\\nLyK5fS8g0SYbmPOL9TlcHDOqwG0mrX9qpg5DC2fniXNSrrZ64GTDKdzZY"
+    "Ap6LI9W\\nIqv4vr6y38N79TTC\\n-----END PRIVATE KEY-----\\n\", ";
 static const char test_json_key_str_part3[] =
     "\"private_key_id\": \"e6b5137873db8d2ef81e06a47289e6434ec8a165\", "
     "\"client_email\": "
diff --git a/vsprojects/vs2013/grpc.vcxproj b/vsprojects/vs2013/grpc.vcxproj
index 28ea603..d325121 100644
--- a/vsprojects/vs2013/grpc.vcxproj
+++ b/vsprojects/vs2013/grpc.vcxproj
@@ -134,6 +134,10 @@
     <ClInclude Include="..\..\src\core\iomgr\tcp_posix.h" />
     <ClInclude Include="..\..\src\core\iomgr\tcp_server.h" />
     <ClInclude Include="..\..\src\core\iomgr\time_averaged_stats.h" />
+    <ClInclude Include="..\..\src\core\json\json.h" />
+    <ClInclude Include="..\..\src\core\json\json_common.h" />
+    <ClInclude Include="..\..\src\core\json\json_reader.h" />
+    <ClInclude Include="..\..\src\core\json\json_writer.h" />
     <ClInclude Include="..\..\src\core\statistics\census_interface.h" />
     <ClInclude Include="..\..\src\core\statistics\census_log.h" />
     <ClInclude Include="..\..\src\core\statistics\census_rpc_stats.h" />
@@ -278,7 +282,11 @@
     </ClCompile>
     <ClCompile Include="..\..\src\core\json\json.c">
     </ClCompile>
-    <ClCompile Include="..\..\src\core\json\json-string.c">
+    <ClCompile Include="..\..\src\core\json\json_reader.c">
+    </ClCompile>
+    <ClCompile Include="..\..\src\core\json\json_string.c">
+    </ClCompile>
+    <ClCompile Include="..\..\src\core\json\json_writer.c">
     </ClCompile>
     <ClCompile Include="..\..\src\core\statistics\census_init.c">
     </ClCompile>
diff --git a/vsprojects/vs2013/grpc.vcxproj.filters b/vsprojects/vs2013/grpc.vcxproj.filters
index 4f03c14..6b7e63e 100644
--- a/vsprojects/vs2013/grpc.vcxproj.filters
+++ b/vsprojects/vs2013/grpc.vcxproj.filters
@@ -157,6 +157,18 @@
     <ClCompile Include="..\..\src\core\iomgr\time_averaged_stats.c">
       <Filter>src\core\iomgr</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\core\json\json.c">
+      <Filter>src\core\json</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\core\json\json_reader.c">
+      <Filter>src\core\json</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\core\json\json_string.c">
+      <Filter>src\core\json</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\core\json\json_writer.c">
+      <Filter>src\core\json</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\src\core\statistics\census_init.c">
       <Filter>src\core\statistics</Filter>
     </ClCompile>
@@ -280,9 +292,6 @@
     <ClCompile Include="..\..\src\core\transport\transport.c">
       <Filter>src\core\transport</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\third_party\cJSON\cJSON.c">
-      <Filter>third_party\cJSON</Filter>
-    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\include\grpc\grpc_security.h">
@@ -464,6 +473,18 @@
     <ClInclude Include="..\..\src\core\iomgr\time_averaged_stats.h">
       <Filter>src\core\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\core\json\json.h">
+      <Filter>src\core\json</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\core\json\json_common.h">
+      <Filter>src\core\json</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\core\json\json_reader.h">
+      <Filter>src\core\json</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\core\json\json_writer.h">
+      <Filter>src\core\json</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\src\core\statistics\census_interface.h">
       <Filter>src\core\statistics</Filter>
     </ClInclude>
@@ -599,6 +620,9 @@
     <Filter Include="src\core\iomgr">
       <UniqueIdentifier>{1baf3894-af37-e647-bdbc-95dc17ed0073}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core\json">
+      <UniqueIdentifier>{e665cc0e-b994-d7c5-cc18-2007392019f0}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\core\security">
       <UniqueIdentifier>{1d850ac6-e639-4eab-5338-4ba40272fcc9}</UniqueIdentifier>
     </Filter>
@@ -617,12 +641,6 @@
     <Filter Include="src\core\tsi">
       <UniqueIdentifier>{0b0f9ab1-efa4-7f03-e446-6fb9b5227e84}</UniqueIdentifier>
     </Filter>
-    <Filter Include="third_party">
-      <UniqueIdentifier>{aaab30a4-2a15-732e-c141-3fbc0f0f5a7a}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="third_party\cJSON">
-      <UniqueIdentifier>{332d0840-2c7a-bb09-8e58-585a6fb3959f}</UniqueIdentifier>
-    </Filter>
   </ItemGroup>
 </Project>
 
diff --git a/vsprojects/vs2013/grpc_unsecure.vcxproj b/vsprojects/vs2013/grpc_unsecure.vcxproj
index 28ea603..d325121 100644
--- a/vsprojects/vs2013/grpc_unsecure.vcxproj
+++ b/vsprojects/vs2013/grpc_unsecure.vcxproj
@@ -134,6 +134,10 @@
     <ClInclude Include="..\..\src\core\iomgr\tcp_posix.h" />
     <ClInclude Include="..\..\src\core\iomgr\tcp_server.h" />
     <ClInclude Include="..\..\src\core\iomgr\time_averaged_stats.h" />
+    <ClInclude Include="..\..\src\core\json\json.h" />
+    <ClInclude Include="..\..\src\core\json\json_common.h" />
+    <ClInclude Include="..\..\src\core\json\json_reader.h" />
+    <ClInclude Include="..\..\src\core\json\json_writer.h" />
     <ClInclude Include="..\..\src\core\statistics\census_interface.h" />
     <ClInclude Include="..\..\src\core\statistics\census_log.h" />
     <ClInclude Include="..\..\src\core\statistics\census_rpc_stats.h" />
@@ -278,7 +282,11 @@
     </ClCompile>
     <ClCompile Include="..\..\src\core\json\json.c">
     </ClCompile>
-    <ClCompile Include="..\..\src\core\json\json-string.c">
+    <ClCompile Include="..\..\src\core\json\json_reader.c">
+    </ClCompile>
+    <ClCompile Include="..\..\src\core\json\json_string.c">
+    </ClCompile>
+    <ClCompile Include="..\..\src\core\json\json_writer.c">
     </ClCompile>
     <ClCompile Include="..\..\src\core\statistics\census_init.c">
     </ClCompile>
diff --git a/vsprojects/vs2013/grpc_unsecure.vcxproj.filters b/vsprojects/vs2013/grpc_unsecure.vcxproj.filters
index a7ba173..b9f6525 100644
--- a/vsprojects/vs2013/grpc_unsecure.vcxproj.filters
+++ b/vsprojects/vs2013/grpc_unsecure.vcxproj.filters
@@ -118,6 +118,18 @@
     <ClCompile Include="..\..\src\core\iomgr\time_averaged_stats.c">
       <Filter>src\core\iomgr</Filter>
     </ClCompile>
+    <ClCompile Include="..\..\src\core\json\json.c">
+      <Filter>src\core\json</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\core\json\json_reader.c">
+      <Filter>src\core\json</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\core\json\json_string.c">
+      <Filter>src\core\json</Filter>
+    </ClCompile>
+    <ClCompile Include="..\..\src\core\json\json_writer.c">
+      <Filter>src\core\json</Filter>
+    </ClCompile>
     <ClCompile Include="..\..\src\core\statistics\census_init.c">
       <Filter>src\core\statistics</Filter>
     </ClCompile>
@@ -241,9 +253,6 @@
     <ClCompile Include="..\..\src\core\transport\transport.c">
       <Filter>src\core\transport</Filter>
     </ClCompile>
-    <ClCompile Include="..\..\third_party\cJSON\cJSON.c">
-      <Filter>third_party\cJSON</Filter>
-    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\..\include\grpc\byte_buffer.h">
@@ -389,6 +398,18 @@
     <ClInclude Include="..\..\src\core\iomgr\time_averaged_stats.h">
       <Filter>src\core\iomgr</Filter>
     </ClInclude>
+    <ClInclude Include="..\..\src\core\json\json.h">
+      <Filter>src\core\json</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\core\json\json_common.h">
+      <Filter>src\core\json</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\core\json\json_reader.h">
+      <Filter>src\core\json</Filter>
+    </ClInclude>
+    <ClInclude Include="..\..\src\core\json\json_writer.h">
+      <Filter>src\core\json</Filter>
+    </ClInclude>
     <ClInclude Include="..\..\src\core\statistics\census_interface.h">
       <Filter>src\core\statistics</Filter>
     </ClInclude>
@@ -524,6 +545,9 @@
     <Filter Include="src\core\iomgr">
       <UniqueIdentifier>{a9df8b24-ecea-ff6d-8999-d8fa54cd70bf}</UniqueIdentifier>
     </Filter>
+    <Filter Include="src\core\json">
+      <UniqueIdentifier>{443ffc61-1bea-2477-6e54-1ddf8c139264}</UniqueIdentifier>
+    </Filter>
     <Filter Include="src\core\statistics">
       <UniqueIdentifier>{e084164c-a069-00e3-db35-4e0b1cd6f0b7}</UniqueIdentifier>
     </Filter>
@@ -536,12 +560,6 @@
     <Filter Include="src\core\transport\chttp2">
       <UniqueIdentifier>{5fcd6206-f774-9ae6-4b85-305d6a723843}</UniqueIdentifier>
     </Filter>
-    <Filter Include="third_party">
-      <UniqueIdentifier>{025c051e-8eba-125b-67f9-173f95176eb2}</UniqueIdentifier>
-    </Filter>
-    <Filter Include="third_party\cJSON">
-      <UniqueIdentifier>{7d75397e-988a-baac-897e-2ea7b43d5dd9}</UniqueIdentifier>
-    </Filter>
   </ItemGroup>
 </Project>