Add JSON output support to Emboss text format.
diff --git a/compiler/back_end/cpp/generated_code_templates b/compiler/back_end/cpp/generated_code_templates
index e8f7c46..1810573 100644
--- a/compiler/back_end/cpp/generated_code_templates
+++ b/compiler/back_end/cpp/generated_code_templates
@@ -1,17 +1,3 @@
-// Copyright 2019 Google LLC
-//
-// Licensed under the Apache License, Version 2.0 (the "License");
-// you may not use this file except in compliance with the License.
-// You may obtain a copy of the License at
-//
-//     https://www.apache.org/licenses/LICENSE-2.0
-//
-// Unless required by applicable law or agreed to in writing, software
-// distributed under the License is distributed on an "AS IS" BASIS,
-// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-// See the License for the specific language governing permissions and
-// limitations under the License.
-
 // -*- mode: C++ -*-
 // vim: set filetype=cpp:
 
@@ -29,14 +15,14 @@
  */
 #ifndef ${header_guard}
 #define ${header_guard}
-#include <stdint.h>
-#include <string.h>
+// #include <stdint.h>
+// #include <string.h>
 
-#include <algorithm>
-#include <type_traits>
-#include <utility>
+// #include <algorithm>
+// #include <type_traits>
+// #include <utility>
 
-#include "runtime/cpp/emboss_cpp_util.h"
+#include "third_party/emboss/runtime/cpp/emboss_cpp_util.h"
 
 ${includes}
 
@@ -283,8 +269,14 @@
   void WriteToTextStream(
       Stream *emboss_reserved_local_stream,
       ::emboss::TextOutputOptions emboss_reserved_local_options) const {
-    ::emboss::TextOutputOptions emboss_reserved_local_field_options =
+    auto emboss_reserved_local_field_options =
         emboss_reserved_local_options.PlusOneIndent();
+    if (emboss_reserved_local_options.json()) {
+      emboss_reserved_local_field_options =
+          emboss_reserved_local_field_options.WithComments(false)
+                                             .WithDigitGrouping(false)
+                                             .WithNumericBase(10);
+    }
     if (emboss_reserved_local_options.multiline()) {
       emboss_reserved_local_stream->Write("{\n");
     } else {
@@ -295,11 +287,18 @@
     // Avoid unused variable warnings for empty structures:
     (void)emboss_reserved_local_wrote_field;
     if (emboss_reserved_local_options.multiline()) {
+      if (emboss_reserved_local_wrote_field &&
+          emboss_reserved_local_options.json()) {
+        emboss_reserved_local_stream->Write("\n");
+      }
       emboss_reserved_local_stream->Write(
           emboss_reserved_local_options.current_indent());
       emboss_reserved_local_stream->Write("}");
     } else {
-      emboss_reserved_local_stream->Write(" }");
+      if (!emboss_reserved_local_options.json()) {
+        emboss_reserved_local_stream->Write(" ");
+      }
+      emboss_reserved_local_stream->Write("}");
     }
   }
 
@@ -323,20 +322,31 @@
       // they are not `Ok()` overall, since submembers may still be `Ok()`.
       if (!emboss_reserved_local_field_options.allow_partial_output() ||
           ${field_name}().IsAggregate() || ${field_name}().Ok()) {
+        if (emboss_reserved_local_wrote_field) {
+          if (emboss_reserved_local_field_options.json() ||
+              !emboss_reserved_local_field_options.multiline()) {
+            emboss_reserved_local_stream->Write(",");
+          }
+        }
         if (emboss_reserved_local_field_options.multiline()) {
           emboss_reserved_local_stream->Write(
               emboss_reserved_local_field_options.current_indent());
         } else {
-          if (emboss_reserved_local_wrote_field) {
-            emboss_reserved_local_stream->Write(",");
+          if (!emboss_reserved_local_field_options.json() ||
+              emboss_reserved_local_wrote_field) {
+            emboss_reserved_local_stream->Write(" ");
           }
-          emboss_reserved_local_stream->Write(" ");
         }
-        emboss_reserved_local_stream->Write("${field_name}: ");
+        if (emboss_reserved_local_field_options.json()) {
+          emboss_reserved_local_stream->Write("\"${field_name}\": ");
+        } else {
+          emboss_reserved_local_stream->Write("${field_name}: ");
+        }
         ${field_name}().WriteToTextStream(emboss_reserved_local_stream,
                                            emboss_reserved_local_field_options);
         emboss_reserved_local_wrote_field = true;
-        if (emboss_reserved_local_field_options.multiline()) {
+        if (emboss_reserved_local_field_options.multiline() &&
+            !emboss_reserved_local_field_options.json()) {
           emboss_reserved_local_stream->Write("\n");
         }
       } else if (emboss_reserved_local_field_options.allow_partial_output() &&
diff --git a/compiler/back_end/cpp/testcode/text_format_test.cc b/compiler/back_end/cpp/testcode/text_format_test.cc
index 82559cd..19f7ebd 100644
--- a/compiler/back_end/cpp/testcode/text_format_test.cc
+++ b/compiler/back_end/cpp/testcode/text_format_test.cc
@@ -15,12 +15,12 @@
 // Tests of generated code for text format.
 #include <stdint.h>
 
-#include <type_traits>
-#include <utility>
-#include <vector>
+#include <array>
+#include <numeric>
 
-#include "gtest/gtest.h"
-#include "testdata/text_format.emb.h"
+#include "testing/base/public/gunit.h"
+#include "third_party/emboss/runtime/cpp/emboss_text_util.h"
+#include "third_party/emboss/testdata/text_format.emb.h"
 
 namespace emboss {
 namespace test {
@@ -93,6 +93,89 @@
   EXPECT_EQ(view.b().Read(), 4);
 }
 
+TEST(TextFormat, JsonOutput) {
+  ::std::array<char, 57> values = {};
+  ::std::iota(values.begin(), values.end(), 0);
+
+  const auto view = MakeJsonTestStructView(&values);
+  EXPECT_EQ(
+      "{\"one_byte_enum\": \"ZERO\", \"seven_bit_uint\": 1, \"one_bit_flag\": "
+      "false, \"one_byte_uint\": 2, \"two_byte_uint\": 1027, "
+      "\"four_byte_uint\": 134678021, \"eight_byte_uint\": "
+      "1157159078456920585, \"uint8_array\": [17, 18, 19, 20, 21, 22, 23, 24, "
+      "25, 26], \"uint16_array\": [7195, 7709, 8223, 8737, 9251, 9765, 10279, "
+      "10793, 11307, 11821], \"struct_array\": [{\"element_one\": 47, "
+      "\"element_two\": 48, \"element_three\": 49, \"element_four\": 50}, "
+      "{\"element_one\": 51, \"element_two\": 52, \"element_three\": 53, "
+      "\"element_four\": 54}]}",
+      ::emboss::WriteToString(view, TextOutputOptions().Json(true)));
+}
+
+TEST(TextFormat, JsonOutputRobustness) {
+  ::std::array<char, 57> values = {};
+  ::std::iota(values.begin(), values.end(), 0);
+
+  const auto view = MakeJsonTestStructView(&values);
+  auto options = ::emboss::TextOutputOptions()
+                     .Json(true)
+                     .WithComments(true)
+                     .WithDigitGrouping(true)
+                     .WithNumericBase(16);
+  EXPECT_EQ(
+      "{\"one_byte_enum\": \"ZERO\", \"seven_bit_uint\": 1, \"one_bit_flag\": "
+      "false, \"one_byte_uint\": 2, \"two_byte_uint\": 1027, "
+      "\"four_byte_uint\": 134678021, \"eight_byte_uint\": "
+      "1157159078456920585, \"uint8_array\": [17, 18, 19, 20, 21, 22, 23, 24, "
+      "25, 26], \"uint16_array\": [7195, 7709, 8223, 8737, 9251, 9765, 10279, "
+      "10793, 11307, 11821], \"struct_array\": [{\"element_one\": 47, "
+      "\"element_two\": 48, \"element_three\": 49, \"element_four\": 50}, "
+      "{\"element_one\": 51, \"element_two\": 52, \"element_three\": 53, "
+      "\"element_four\": 54}]}",
+      ::emboss::WriteToString(view, options));
+}
+
+TEST(TextFormat, DigitGroupingAndNumericBase) {
+  ::std::array<char, 57> values = {};
+  ::std::iota(values.begin(), values.end(), 0);
+
+  const auto view = MakeJsonTestStructView(&values);
+  auto options =
+      ::emboss::TextOutputOptions().WithDigitGrouping(true).WithNumericBase(16);
+  EXPECT_EQ(
+      "{ one_byte_enum: ZERO, seven_bit_uint: 0x1, one_bit_flag: false, "
+      "one_byte_uint: 0x2, two_byte_uint: 0x403, four_byte_uint: 0x807_0605, "
+      "eight_byte_uint: 0x100f_0e0d_0c0b_0a09, uint8_array: { [0x0]: 0x11, "
+      "0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, [0x8]: 0x19, 0x1a }, "
+      "uint16_array: { [0x0]: 0x1c1b, 0x1e1d, 0x201f, 0x2221, 0x2423, 0x2625, "
+      "0x2827, 0x2a29, [0x8]: 0x2c2b, 0x2e2d }, struct_array: { [0x0]: { "
+      "element_one: 0x2f, element_two: 0x30, element_three: 0x31, "
+      "element_four: 0x32 }, { element_one: 0x33, element_two: 0x34, "
+      "element_three: 0x35, element_four: 0x36 } } }",
+      ::emboss::WriteToString(view, options));
+}
+
+TEST(TextFormat, MultilineAndPartial) {
+  ::std::array<char, 1> values = {10};
+  // MakeVanillaView expects a pointer to an array of size 2, so we have to
+  // construct the view manually.
+  auto view = VanillaWriter(values.data(), values.size());
+  auto options =
+      ::emboss::TextOutputOptions().Multiline(true).WithAllowPartialOutput(
+          true);
+  EXPECT_EQ(
+      "{\n"
+      "a: 10\n"
+      "}",
+      ::emboss::WriteToString(view, options));
+}
+
+TEST(TextFormat, JsonSkippedFieldOutput) {
+  ::std::array<char, 3> values = {1, 2, 3};
+  const auto view = MakeStructWithSkippedFieldsView(&values);
+  EXPECT_EQ("{\"a\": 1, \"c\": 3}",
+            ::emboss::WriteToString(view, TextOutputOptions().Json(true)));
+}
+
 }  // namespace
 }  // namespace test
 }  // namespace emboss
diff --git a/compiler/util/parser_types.py b/compiler/util/parser_types.py
index a3ef34d..89cb186 100644
--- a/compiler/util/parser_types.py
+++ b/compiler/util/parser_types.py
@@ -15,7 +15,7 @@
 """Types related to the LR(1) parser.
 
 This module contains types used by the LR(1) parser, which are also used in
-other parts of the compiler: 
+other parts of the compiler:
 
     SourcePosition: a position (zero-width) within a source file.
     SourceLocation: a span within a source file.
diff --git a/runtime/cpp/emboss_text_util.h b/runtime/cpp/emboss_text_util.h
index 9cfe03d..30f5dfd 100644
--- a/runtime/cpp/emboss_text_util.h
+++ b/runtime/cpp/emboss_text_util.h
@@ -13,10 +13,11 @@
 // limitations under the License.
 
 // This header contains functionality related to Emboss text output.
-#ifndef EMBOSS_RUNTIME_CPP_EMBOSS_TEXT_UTIL_H_
-#define EMBOSS_RUNTIME_CPP_EMBOSS_TEXT_UTIL_H_
+#ifndef THIRD_PARTY_EMBOSS_RUNTIME_CPP_EMBOSS_TEXT_UTIL_H_
+#define THIRD_PARTY_EMBOSS_RUNTIME_CPP_EMBOSS_TEXT_UTIL_H_
 
 #include <array>
+#include <cctype>
 #include <climits>
 #include <cmath>
 #include <cstdint>
@@ -25,9 +26,11 @@
 #include <limits>
 #include <sstream>
 #include <string>
+#include <type_traits>
+#include <utility>
 #include <vector>
 
-#include "runtime/cpp/emboss_defines.h"
+#include "third_party/emboss/runtime/cpp/emboss_defines.h"
 
 namespace emboss {
 
@@ -80,12 +83,19 @@
     return result;
   }
 
+  TextOutputOptions Json(bool new_value) const {
+    TextOutputOptions result = *this;
+    result.json_ = new_value;
+    return result;
+  }
+
   ::std::string current_indent() const { return current_indent_; }
   ::std::string indent() const { return indent_; }
   bool multiline() const { return multiline_; }
   bool digit_grouping() const { return digit_grouping_; }
   bool comments() const { return comments_; }
   ::std::uint8_t numeric_base() const { return numeric_base_; }
+  bool json() const { return json_; }
   bool allow_partial_output() const { return allow_partial_output_; }
 
  private:
@@ -95,6 +105,7 @@
   bool multiline_ = false;
   bool digit_grouping_ = false;
   bool allow_partial_output_ = false;
+  bool json_ = false;
   ::std::uint8_t numeric_base_ = 10;
 };
 
@@ -337,13 +348,17 @@
 template <class Stream, class View>
 void WriteIntegerViewToTextStream(View *view, Stream *stream,
                                   const TextOutputOptions &options) {
-  WriteIntegerToTextStream(view->Read(), stream, options.numeric_base(),
-                           options.digit_grouping());
-  if (options.comments()) {
-    stream->Write("  # ");
-    WriteIntegerToTextStream(view->Read(), stream,
-                             options.numeric_base() == 10 ? 16 : 10,
+  if (options.json()) {
+    WriteIntegerToTextStream(view->Read(), stream, 10, false);
+  } else {
+    WriteIntegerToTextStream(view->Read(), stream, options.numeric_base(),
                              options.digit_grouping());
+    if (options.comments()) {
+      stream->Write("  # ");
+      WriteIntegerToTextStream(view->Read(), stream,
+                               options.numeric_base() == 10 ? 16 : 10,
+                               options.digit_grouping());
+    }
   }
 }
 
@@ -562,6 +577,10 @@
   // currently available.
 
   if (::std::isnan(n)) {
+    if (options.json()) {
+      stream->Write("\"NaN\"");
+      return;
+    }
     // The printf format for NaN is just "NaN".  In the interests of keeping
     // things bit-exact, Emboss prints the exact NaN.
     typename FloatConstants<Float>::MatchingIntegerType bits;
@@ -585,6 +604,14 @@
   }
 
   if (::std::isinf(n)) {
+    if (options.json()) {
+      if (n < 0.0) {
+        stream->Write("\"-Infinity\"");
+      } else {
+        stream->Write("\"Infinity\"");
+      }
+      return;
+    }
     if (n < 0.0) {
       stream->Write("-Inf");
     } else {
@@ -636,18 +663,23 @@
                                const TextOutputOptions &options) {
   const char *name = TryToGetNameFromEnum(view->Read());
   if (name != nullptr) {
+    if (options.json()) stream->Write("\"");
     stream->Write(name);
+    if (options.json()) stream->Write("\"");
   }
   // If the enum value has no known name, then write its numeric value
   // instead.  If it does have a known name, and comments are enabled on the
   // output, then write the numeric value as a comment.
-  if (name == nullptr || options.comments()) {
-    if (name != nullptr) stream->Write("  # ");
+  if (name == nullptr || (options.comments() && !options.json())) {
+    if (name != nullptr) {
+      stream->Write("  # ");
+    }
     WriteIntegerToTextStream(
         static_cast<
             typename ::std::underlying_type<typename View::ValueType>::type>(
             view->Read()),
-        stream, options.numeric_base(), options.digit_grouping());
+        stream, options.json() ? 10 : options.numeric_base(),
+        options.json() ? false : options.digit_grouping());
   }
 }
 
@@ -756,7 +788,34 @@
 void WriteArrayToTextStream(Array *array, Stream *stream,
                             const TextOutputOptions &options) {
   TextOutputOptions element_options = options.PlusOneIndent();
-  if (options.multiline()) {
+  if (options.json()) {
+    element_options = element_options.WithComments(false)
+                          .WithDigitGrouping(false)
+                          .WithNumericBase(10);
+    stream->Write("[");
+    bool first = true;
+    for (::std::size_t i = 0; i < array->ElementCount(); ++i) {
+      if (!options.allow_partial_output() || (*array)[i].IsAggregate() ||
+          (*array)[i].Ok()) {
+        if (!first) {
+          stream->Write(",");
+        }
+        if (options.multiline()) {
+          stream->Write("\n");
+          stream->Write(element_options.current_indent());
+        } else if (!first) {
+          stream->Write(" ");
+        }
+        (*array)[i].WriteToTextStream(stream, element_options);
+        first = false;
+      }
+    }
+    if (options.multiline()) {
+      stream->Write("\n");
+      stream->Write(options.current_indent());
+    }
+    stream->Write("]");
+  } else if (options.multiline()) {
     stream->Write("{");
     WriteShorthandArrayCommentToTextStream(array, stream, element_options);
     for (::std::size_t i = 0; i < array->ElementCount(); ++i) {
@@ -896,4 +955,4 @@
 
 }  // namespace emboss
 
-#endif  // EMBOSS_RUNTIME_CPP_EMBOSS_TEXT_UTIL_H_
+#endif  // THIRD_PARTY_EMBOSS_RUNTIME_CPP_EMBOSS_TEXT_UTIL_H_
diff --git a/runtime/cpp/test/emboss_array_view_test.cc b/runtime/cpp/test/emboss_array_view_test.cc
index 1f632e8..15cb9eb 100644
--- a/runtime/cpp/test/emboss_array_view_test.cc
+++ b/runtime/cpp/test/emboss_array_view_test.cc
@@ -12,15 +12,18 @@
 // See the License for the specific language governing permissions and
 // limitations under the License.
 
-#include "runtime/cpp/emboss_array_view.h"
+#include "third_party/emboss/runtime/cpp/emboss_array_view.h"
 
+#include <cstddef>
+#include <cstdint>
 #include <string>
-#include <type_traits>
 
-#include "absl/strings/str_format.h"
-#include "gtest/gtest.h"
-#include "runtime/cpp/emboss_prelude.h"
-#include "runtime/cpp/emboss_text_util.h"
+#include "testing/base/public/gunit.h"
+#include "third_party/absl/strings/str_format.h"
+#include "third_party/emboss/runtime/cpp/emboss_memory_util.h"
+#include "third_party/emboss/runtime/cpp/emboss_prelude.h"
+#include "third_party/emboss/runtime/cpp/emboss_text_util.h"
+#include "third_party/emboss/runtime/cpp/emboss_view_parameters.h"
 
 namespace emboss {
 namespace support {
@@ -215,6 +218,18 @@
       "0x8, 0xd, 0x15, 0x22, 0x37, 0x59 }");
 }
 
+TEST(ArrayView, TextFormatOutput_AsJson) {
+  signed char bytes[16] = {-3, 2, -1, 1,  0,  1,  1,  2,
+                           3,  5, 8,  13, 21, 34, 55, 89};
+  auto buffer = ReadWriteContiguousBuffer{
+      reinterpret_cast</**/ ::std::uint8_t*>(bytes), sizeof bytes};
+  auto byte_array =
+      ArrayView<FixedIntView<8>, ReadWriteContiguousBuffer, 1>{buffer};
+
+  EXPECT_EQ("[-3, 2, -1, 1, 0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]",
+            WriteToString(byte_array, TextOutputOptions().Json(true)));
+}
+
 TEST(ArrayView, TextFormatOutput_8BitIntElementTypes) {
   ::std::uint8_t bytes[1] = {65};
   auto buffer = ReadWriteContiguousBuffer{bytes, sizeof bytes};
diff --git a/testdata/text_format.emb b/testdata/text_format.emb
index 7458170..a8fb026 100644
--- a/testdata/text_format.emb
+++ b/testdata/text_format.emb
@@ -14,6 +14,7 @@
 
 -- Structures used specifically to test text format input and output.
 
+[$default byte_order: "LittleEndian"]
 [(cpp) namespace: "emboss::test"]
 
 
@@ -34,3 +35,31 @@
   2 [+2]  Vanilla  b
     [text_output: "Skip"]
   4 [+2]  Vanilla  c
+
+enum JsonTestEnum:
+  ZERO  = 0
+  ONE   = 1
+  TWO   = 2
+  THREE = 3
+  FOUR  = 4
+
+struct JsonTestArrayStruct:
+  0 [+1]  UInt  element_one
+  1 [+1]  UInt  element_two
+  2 [+1]  UInt  element_three
+  3 [+1]  UInt  element_four
+
+
+struct JsonTestStruct:
+  0  [+1]         JsonTestEnum           one_byte_enum
+  1  [+1]  bits:
+    0  [+7]       UInt                   seven_bit_uint
+    7  [+1]       Flag                   one_bit_flag
+
+  2  [+1]         UInt                   one_byte_uint
+  3  [+2]         UInt                   two_byte_uint
+  5  [+4]         UInt                   four_byte_uint
+  9  [+8]         UInt                   eight_byte_uint
+  17 [+10]        UInt:8[]               uint8_array
+  27 [+20]        UInt:16[]              uint16_array
+  47 [+40]        JsonTestArrayStruct[]  struct_array