OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "base/json/json_writer.h" | 5 #include "base/json/json_writer.h" |
6 | 6 |
7 #include "base/json/string_escape.h" | 7 #include "base/json/string_escape.h" |
8 #include "base/logging.h" | 8 #include "base/logging.h" |
9 #include "base/stringprintf.h" | 9 #include "base/stringprintf.h" |
10 #include "base/string_number_conversions.h" | 10 #include "base/string_number_conversions.h" |
11 #include "base/values.h" | 11 #include "base/values.h" |
12 #include "base/utf_string_conversions.h" | 12 #include "base/utf_string_conversions.h" |
13 | 13 |
14 namespace base { | 14 namespace base { |
15 | 15 |
16 #if defined(OS_WIN) | 16 #if defined(OS_WIN) |
17 static const char kPrettyPrintLineEnding[] = "\r\n"; | 17 static const char kPrettyPrintLineEnding[] = "\r\n"; |
18 #else | 18 #else |
19 static const char kPrettyPrintLineEnding[] = "\n"; | 19 static const char kPrettyPrintLineEnding[] = "\n"; |
20 #endif | 20 #endif |
21 | 21 |
22 /* static */ | 22 /* static */ |
23 const char* JSONWriter::kEmptyArray = "[]"; | 23 const char* JSONWriter::kEmptyArray = "[]"; |
24 | 24 |
25 /* static */ | 25 /* static */ |
26 void JSONWriter::Write(const Value* const node, | 26 void JSONWriter::Write(const Value* const node, |
27 bool pretty_print, | 27 bool pretty_print, |
28 std::string* json) { | 28 std::string* json) { |
29 WriteWithOptions(node, pretty_print, 0, json); | 29 WriteWithOptionalEscape(node, pretty_print, true, json); |
30 } | 30 } |
31 | 31 |
32 /* static */ | 32 /* static */ |
33 void JSONWriter::WriteWithOptions(const Value* const node, | 33 void JSONWriter::WriteWithOptionalEscape(const Value* const node, |
34 bool pretty_print, | 34 bool pretty_print, |
35 int options, | 35 bool escape, |
36 std::string* json) { | 36 std::string* json) { |
37 json->clear(); | 37 json->clear(); |
38 // Is there a better way to estimate the size of the output? | 38 // Is there a better way to estimate the size of the output? |
39 json->reserve(1024); | 39 json->reserve(1024); |
40 JSONWriter writer(pretty_print, json); | 40 JSONWriter writer(pretty_print, json); |
41 bool escape = !(options & OPTIONS_DO_NOT_ESCAPE); | 41 writer.BuildJSONString(node, 0, escape); |
42 bool omit_binary_values = !!(options & OPTIONS_OMIT_BINARY_VALUES); | |
43 writer.BuildJSONString(node, 0, escape, omit_binary_values); | |
44 if (pretty_print) | 42 if (pretty_print) |
45 json->append(kPrettyPrintLineEnding); | 43 json->append(kPrettyPrintLineEnding); |
46 } | 44 } |
47 | 45 |
48 JSONWriter::JSONWriter(bool pretty_print, std::string* json) | 46 JSONWriter::JSONWriter(bool pretty_print, std::string* json) |
49 : json_string_(json), | 47 : json_string_(json), |
50 pretty_print_(pretty_print) { | 48 pretty_print_(pretty_print) { |
51 DCHECK(json); | 49 DCHECK(json); |
52 } | 50 } |
53 | 51 |
54 void JSONWriter::BuildJSONString(const Value* const node, | 52 void JSONWriter::BuildJSONString(const Value* const node, |
55 int depth, | 53 int depth, |
56 bool escape, | 54 bool escape) { |
57 bool omit_binary_values) { | |
58 switch (node->GetType()) { | 55 switch (node->GetType()) { |
59 case Value::TYPE_NULL: | 56 case Value::TYPE_NULL: |
60 json_string_->append("null"); | 57 json_string_->append("null"); |
61 break; | 58 break; |
62 | 59 |
63 case Value::TYPE_BOOLEAN: | 60 case Value::TYPE_BOOLEAN: |
64 { | 61 { |
65 bool value; | 62 bool value; |
66 bool result = node->GetAsBoolean(&value); | 63 bool result = node->GetAsBoolean(&value); |
67 DCHECK(result); | 64 DCHECK(result); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
118 } | 115 } |
119 | 116 |
120 case Value::TYPE_LIST: | 117 case Value::TYPE_LIST: |
121 { | 118 { |
122 json_string_->append("["); | 119 json_string_->append("["); |
123 if (pretty_print_) | 120 if (pretty_print_) |
124 json_string_->append(" "); | 121 json_string_->append(" "); |
125 | 122 |
126 const ListValue* list = static_cast<const ListValue*>(node); | 123 const ListValue* list = static_cast<const ListValue*>(node); |
127 for (size_t i = 0; i < list->GetSize(); ++i) { | 124 for (size_t i = 0; i < list->GetSize(); ++i) { |
128 Value* value = NULL; | |
129 bool result = list->Get(i, &value); | |
130 DCHECK(result); | |
131 | |
132 if (omit_binary_values && value->GetType() == Value::TYPE_BINARY) { | |
133 continue; | |
134 } | |
135 | |
136 if (i != 0) { | 125 if (i != 0) { |
137 json_string_->append(","); | 126 json_string_->append(","); |
138 if (pretty_print_) | 127 if (pretty_print_) |
139 json_string_->append(" "); | 128 json_string_->append(" "); |
140 } | 129 } |
141 | 130 |
142 BuildJSONString(value, depth, escape, omit_binary_values); | 131 Value* value = NULL; |
| 132 bool result = list->Get(i, &value); |
| 133 DCHECK(result); |
| 134 BuildJSONString(value, depth, escape); |
143 } | 135 } |
144 | 136 |
145 if (pretty_print_) | 137 if (pretty_print_) |
146 json_string_->append(" "); | 138 json_string_->append(" "); |
147 json_string_->append("]"); | 139 json_string_->append("]"); |
148 break; | 140 break; |
149 } | 141 } |
150 | 142 |
151 case Value::TYPE_DICTIONARY: | 143 case Value::TYPE_DICTIONARY: |
152 { | 144 { |
153 json_string_->append("{"); | 145 json_string_->append("{"); |
154 if (pretty_print_) | 146 if (pretty_print_) |
155 json_string_->append(kPrettyPrintLineEnding); | 147 json_string_->append(kPrettyPrintLineEnding); |
156 | 148 |
157 const DictionaryValue* dict = | 149 const DictionaryValue* dict = |
158 static_cast<const DictionaryValue*>(node); | 150 static_cast<const DictionaryValue*>(node); |
159 for (DictionaryValue::key_iterator key_itr = dict->begin_keys(); | 151 for (DictionaryValue::key_iterator key_itr = dict->begin_keys(); |
160 key_itr != dict->end_keys(); | 152 key_itr != dict->end_keys(); |
161 ++key_itr) { | 153 ++key_itr) { |
162 Value* value = NULL; | |
163 bool result = dict->GetWithoutPathExpansion(*key_itr, &value); | |
164 DCHECK(result); | |
165 | |
166 if (omit_binary_values && value->GetType() == Value::TYPE_BINARY) { | |
167 continue; | |
168 } | |
169 | |
170 if (key_itr != dict->begin_keys()) { | 154 if (key_itr != dict->begin_keys()) { |
171 json_string_->append(","); | 155 json_string_->append(","); |
172 if (pretty_print_) | 156 if (pretty_print_) |
173 json_string_->append(kPrettyPrintLineEnding); | 157 json_string_->append(kPrettyPrintLineEnding); |
174 } | 158 } |
175 | 159 |
| 160 Value* value = NULL; |
| 161 bool result = dict->GetWithoutPathExpansion(*key_itr, &value); |
| 162 DCHECK(result); |
| 163 |
176 if (pretty_print_) | 164 if (pretty_print_) |
177 IndentLine(depth + 1); | 165 IndentLine(depth + 1); |
178 AppendQuotedString(*key_itr); | 166 AppendQuotedString(*key_itr); |
179 if (pretty_print_) { | 167 if (pretty_print_) { |
180 json_string_->append(": "); | 168 json_string_->append(": "); |
181 } else { | 169 } else { |
182 json_string_->append(":"); | 170 json_string_->append(":"); |
183 } | 171 } |
184 BuildJSONString(value, depth + 1, escape, omit_binary_values); | 172 BuildJSONString(value, depth + 1, escape); |
185 } | 173 } |
186 | 174 |
187 if (pretty_print_) { | 175 if (pretty_print_) { |
188 json_string_->append(kPrettyPrintLineEnding); | 176 json_string_->append(kPrettyPrintLineEnding); |
189 IndentLine(depth); | 177 IndentLine(depth); |
190 json_string_->append("}"); | 178 json_string_->append("}"); |
191 } else { | 179 } else { |
192 json_string_->append("}"); | 180 json_string_->append("}"); |
193 } | 181 } |
194 break; | 182 break; |
195 } | 183 } |
196 | 184 |
197 case Value::TYPE_BINARY: | |
198 { | |
199 if (!omit_binary_values) { | |
200 NOTREACHED() << "Cannot serialize binary value."; | |
201 } | |
202 break; | |
203 } | |
204 | |
205 default: | 185 default: |
| 186 // TODO(jhughes): handle TYPE_BINARY |
206 NOTREACHED() << "unknown json type"; | 187 NOTREACHED() << "unknown json type"; |
207 } | 188 } |
208 } | 189 } |
209 | 190 |
210 void JSONWriter::AppendQuotedString(const std::string& str) { | 191 void JSONWriter::AppendQuotedString(const std::string& str) { |
211 // TODO(viettrungluu): |str| is UTF-8, not ASCII, so to properly escape it we | 192 // TODO(viettrungluu): |str| is UTF-8, not ASCII, so to properly escape it we |
212 // have to convert it to UTF-16. This round-trip is suboptimal. | 193 // have to convert it to UTF-16. This round-trip is suboptimal. |
213 JsonDoubleQuote(UTF8ToUTF16(str), true, json_string_); | 194 JsonDoubleQuote(UTF8ToUTF16(str), true, json_string_); |
214 } | 195 } |
215 | 196 |
216 void JSONWriter::IndentLine(int depth) { | 197 void JSONWriter::IndentLine(int depth) { |
217 // It may be faster to keep an indent string so we don't have to keep | 198 // It may be faster to keep an indent string so we don't have to keep |
218 // reallocating. | 199 // reallocating. |
219 json_string_->append(std::string(depth * 3, ' ')); | 200 json_string_->append(std::string(depth * 3, ' ')); |
220 } | 201 } |
221 | 202 |
222 } // namespace base | 203 } // namespace base |
OLD | NEW |