Tweak/Wontfix a few tests that we could care less about.
[chromium-blink-merge.git] / base / json / json_writer.cc
blobffdad767a4627939877ba18a117d9ed22abf8d5c
1 // Copyright (c) 2009 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "base/json/json_writer.h"
7 #include "base/json/string_escape.h"
8 #include "base/logging.h"
9 #include "base/string_util.h"
10 #include "base/values.h"
11 #include "base/utf_string_conversions.h"
13 namespace base {
15 #if defined(OS_WIN)
16 static const char kPrettyPrintLineEnding[] = "\r\n";
17 #else
18 static const char kPrettyPrintLineEnding[] = "\n";
19 #endif
21 /* static */
22 const char* JSONWriter::kEmptyArray = "[]";
24 /* static */
25 void JSONWriter::Write(const Value* const node,
26 bool pretty_print,
27 std::string* json) {
28 WriteWithOptionalEscape(node, pretty_print, true, json);
31 /* static */
32 void JSONWriter::WriteWithOptionalEscape(const Value* const node,
33 bool pretty_print,
34 bool escape,
35 std::string* json) {
36 json->clear();
37 // Is there a better way to estimate the size of the output?
38 json->reserve(1024);
39 JSONWriter writer(pretty_print, json);
40 writer.BuildJSONString(node, 0, escape);
41 if (pretty_print)
42 json->append(kPrettyPrintLineEnding);
45 JSONWriter::JSONWriter(bool pretty_print, std::string* json)
46 : json_string_(json),
47 pretty_print_(pretty_print) {
48 DCHECK(json);
51 void JSONWriter::BuildJSONString(const Value* const node,
52 int depth,
53 bool escape) {
54 switch (node->GetType()) {
55 case Value::TYPE_NULL:
56 json_string_->append("null");
57 break;
59 case Value::TYPE_BOOLEAN:
61 bool value;
62 bool result = node->GetAsBoolean(&value);
63 DCHECK(result);
64 json_string_->append(value ? "true" : "false");
65 break;
68 case Value::TYPE_INTEGER:
70 int value;
71 bool result = node->GetAsInteger(&value);
72 DCHECK(result);
73 StringAppendF(json_string_, "%d", value);
74 break;
77 case Value::TYPE_REAL:
79 double value;
80 bool result = node->GetAsReal(&value);
81 DCHECK(result);
82 std::string real = DoubleToString(value);
83 // Ensure that the number has a .0 if there's no decimal or 'e'. This
84 // makes sure that when we read the JSON back, it's interpreted as a
85 // real rather than an int.
86 if (real.find('.') == std::string::npos &&
87 real.find('e') == std::string::npos &&
88 real.find('E') == std::string::npos) {
89 real.append(".0");
91 // The JSON spec requires that non-integer values in the range (-1,1)
92 // have a zero before the decimal point - ".52" is not valid, "0.52" is.
93 if (real[0] == '.') {
94 real.insert(0, "0");
95 } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') {
96 // "-.1" bad "-0.1" good
97 real.insert(1, "0");
99 json_string_->append(real);
100 break;
103 case Value::TYPE_STRING:
105 std::string value;
106 bool result = node->GetAsString(&value);
107 DCHECK(result);
108 if (escape) {
109 JsonDoubleQuote(UTF8ToUTF16(value), true, json_string_);
110 } else {
111 JsonDoubleQuote(value, true, json_string_);
113 break;
116 case Value::TYPE_LIST:
118 json_string_->append("[");
119 if (pretty_print_)
120 json_string_->append(" ");
122 const ListValue* list = static_cast<const ListValue*>(node);
123 for (size_t i = 0; i < list->GetSize(); ++i) {
124 if (i != 0) {
125 json_string_->append(",");
126 if (pretty_print_)
127 json_string_->append(" ");
130 Value* value = NULL;
131 bool result = list->Get(i, &value);
132 DCHECK(result);
133 BuildJSONString(value, depth, escape);
136 if (pretty_print_)
137 json_string_->append(" ");
138 json_string_->append("]");
139 break;
142 case Value::TYPE_DICTIONARY:
144 json_string_->append("{");
145 if (pretty_print_)
146 json_string_->append(kPrettyPrintLineEnding);
148 const DictionaryValue* dict =
149 static_cast<const DictionaryValue*>(node);
150 for (DictionaryValue::key_iterator key_itr = dict->begin_keys();
151 key_itr != dict->end_keys();
152 ++key_itr) {
153 if (key_itr != dict->begin_keys()) {
154 json_string_->append(",");
155 if (pretty_print_)
156 json_string_->append(kPrettyPrintLineEnding);
159 Value* value = NULL;
160 bool result = dict->GetWithoutPathExpansion(*key_itr, &value);
161 DCHECK(result);
163 if (pretty_print_)
164 IndentLine(depth + 1);
165 AppendQuotedString(*key_itr);
166 if (pretty_print_) {
167 json_string_->append(": ");
168 } else {
169 json_string_->append(":");
171 BuildJSONString(value, depth + 1, escape);
174 if (pretty_print_) {
175 json_string_->append(kPrettyPrintLineEnding);
176 IndentLine(depth);
177 json_string_->append("}");
178 } else {
179 json_string_->append("}");
181 break;
184 default:
185 // TODO(jhughes): handle TYPE_BINARY
186 NOTREACHED() << "unknown json type";
190 void JSONWriter::AppendQuotedString(const std::wstring& str) {
191 JsonDoubleQuote(WideToUTF16Hack(str), true, json_string_);
194 void JSONWriter::IndentLine(int depth) {
195 // It may be faster to keep an indent string so we don't have to keep
196 // reallocating.
197 json_string_->append(std::string(depth * 3, ' '));
200 } // namespace base