OLD | NEW |
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 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 <cmath> | 7 #include <cmath> |
8 | 8 |
9 #include "base/json/string_escape.h" | 9 #include "base/json/string_escape.h" |
10 #include "base/logging.h" | 10 #include "base/logging.h" |
11 #include "base/strings/string_number_conversions.h" | 11 #include "base/strings/string_number_conversions.h" |
12 #include "base/strings/stringprintf.h" | 12 #include "base/strings/stringprintf.h" |
13 #include "base/strings/utf_string_conversions.h" | 13 #include "base/strings/utf_string_conversions.h" |
14 #include "base/values.h" | 14 #include "base/values.h" |
15 | 15 |
16 namespace base { | 16 namespace base { |
17 | 17 |
18 #if defined(OS_WIN) | 18 #if defined(OS_WIN) |
19 static const char kPrettyPrintLineEnding[] = "\r\n"; | 19 static const char kPrettyPrintLineEnding[] = "\r\n"; |
20 #else | 20 #else |
21 static const char kPrettyPrintLineEnding[] = "\n"; | 21 static const char kPrettyPrintLineEnding[] = "\n"; |
22 #endif | 22 #endif |
23 | 23 |
24 // static | 24 /* static */ |
| 25 const char* JSONWriter::kEmptyArray = "[]"; |
| 26 |
| 27 /* static */ |
25 void JSONWriter::Write(const Value* const node, std::string* json) { | 28 void JSONWriter::Write(const Value* const node, std::string* json) { |
26 WriteWithOptions(node, 0, json); | 29 WriteWithOptions(node, 0, json); |
27 } | 30 } |
28 | 31 |
29 // static | 32 /* static */ |
30 void JSONWriter::WriteWithOptions(const Value* const node, int options, | 33 void JSONWriter::WriteWithOptions(const Value* const node, int options, |
31 std::string* json) { | 34 std::string* json) { |
32 json->clear(); | 35 json->clear(); |
33 // Is there a better way to estimate the size of the output? | 36 // Is there a better way to estimate the size of the output? |
34 json->reserve(1024); | 37 json->reserve(1024); |
35 | 38 |
| 39 bool escape = !(options & OPTIONS_DO_NOT_ESCAPE); |
36 bool omit_binary_values = !!(options & OPTIONS_OMIT_BINARY_VALUES); | 40 bool omit_binary_values = !!(options & OPTIONS_OMIT_BINARY_VALUES); |
37 bool omit_double_type_preservation = | 41 bool omit_double_type_preservation = |
38 !!(options & OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION); | 42 !!(options & OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION); |
39 bool pretty_print = !!(options & OPTIONS_PRETTY_PRINT); | 43 bool pretty_print = !!(options & OPTIONS_PRETTY_PRINT); |
40 | 44 |
41 JSONWriter writer(omit_binary_values, omit_double_type_preservation, | 45 JSONWriter writer(escape, omit_binary_values, omit_double_type_preservation, |
42 pretty_print, json); | 46 pretty_print, json); |
43 writer.BuildJSONString(node, 0); | 47 writer.BuildJSONString(node, 0); |
44 | 48 |
45 if (pretty_print) | 49 if (pretty_print) |
46 json->append(kPrettyPrintLineEnding); | 50 json->append(kPrettyPrintLineEnding); |
47 } | 51 } |
48 | 52 |
49 JSONWriter::JSONWriter(bool omit_binary_values, | 53 JSONWriter::JSONWriter(bool escape, bool omit_binary_values, |
50 bool omit_double_type_preservation, bool pretty_print, | 54 bool omit_double_type_preservation, bool pretty_print, |
51 std::string* json) | 55 std::string* json) |
52 : omit_binary_values_(omit_binary_values), | 56 : escape_(escape), |
| 57 omit_binary_values_(omit_binary_values), |
53 omit_double_type_preservation_(omit_double_type_preservation), | 58 omit_double_type_preservation_(omit_double_type_preservation), |
54 pretty_print_(pretty_print), | 59 pretty_print_(pretty_print), |
55 json_string_(json) { | 60 json_string_(json) { |
56 DCHECK(json); | 61 DCHECK(json); |
57 } | 62 } |
58 | 63 |
59 void JSONWriter::BuildJSONString(const Value* const node, int depth) { | 64 void JSONWriter::BuildJSONString(const Value* const node, int depth) { |
60 switch (node->GetType()) { | 65 switch (node->GetType()) { |
61 case Value::TYPE_NULL: | 66 case Value::TYPE_NULL: |
62 json_string_->append("null"); | 67 json_string_->append("null"); |
(...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
111 } | 116 } |
112 json_string_->append(real); | 117 json_string_->append(real); |
113 break; | 118 break; |
114 } | 119 } |
115 | 120 |
116 case Value::TYPE_STRING: | 121 case Value::TYPE_STRING: |
117 { | 122 { |
118 std::string value; | 123 std::string value; |
119 bool result = node->GetAsString(&value); | 124 bool result = node->GetAsString(&value); |
120 DCHECK(result); | 125 DCHECK(result); |
121 EscapeJSONString(value, true, json_string_); | 126 if (escape_) { |
| 127 JsonDoubleQuote(UTF8ToUTF16(value), true, json_string_); |
| 128 } else { |
| 129 JsonDoubleQuote(value, true, json_string_); |
| 130 } |
122 break; | 131 break; |
123 } | 132 } |
124 | 133 |
125 case Value::TYPE_LIST: | 134 case Value::TYPE_LIST: |
126 { | 135 { |
127 json_string_->append("["); | 136 json_string_->append("["); |
128 if (pretty_print_) | 137 if (pretty_print_) |
129 json_string_->append(" "); | 138 json_string_->append(" "); |
130 | 139 |
131 const ListValue* list = static_cast<const ListValue*>(node); | 140 const ListValue* list = static_cast<const ListValue*>(node); |
(...skipping 21 matching lines...) Expand all Loading... |
153 break; | 162 break; |
154 } | 163 } |
155 | 164 |
156 case Value::TYPE_DICTIONARY: | 165 case Value::TYPE_DICTIONARY: |
157 { | 166 { |
158 json_string_->append("{"); | 167 json_string_->append("{"); |
159 if (pretty_print_) | 168 if (pretty_print_) |
160 json_string_->append(kPrettyPrintLineEnding); | 169 json_string_->append(kPrettyPrintLineEnding); |
161 | 170 |
162 const DictionaryValue* dict = | 171 const DictionaryValue* dict = |
163 static_cast<const DictionaryValue*>(node); | 172 static_cast<const DictionaryValue*>(node); |
164 bool first_entry = true; | 173 bool first_entry = true; |
165 for (DictionaryValue::Iterator itr(*dict); !itr.IsAtEnd(); | 174 for (DictionaryValue::Iterator itr(*dict); !itr.IsAtEnd(); |
166 itr.Advance(), first_entry = false) { | 175 itr.Advance(), first_entry = false) { |
167 if (omit_binary_values_ && | 176 if (omit_binary_values_ && |
168 itr.value().GetType() == Value::TYPE_BINARY) { | 177 itr.value().GetType() == Value::TYPE_BINARY) { |
169 continue; | 178 continue; |
170 } | 179 } |
171 | 180 |
172 if (!first_entry) { | 181 if (!first_entry) { |
173 json_string_->append(","); | 182 json_string_->append(","); |
174 if (pretty_print_) | 183 if (pretty_print_) |
175 json_string_->append(kPrettyPrintLineEnding); | 184 json_string_->append(kPrettyPrintLineEnding); |
176 } | 185 } |
177 | 186 |
178 if (pretty_print_) | 187 if (pretty_print_) |
179 IndentLine(depth + 1); | 188 IndentLine(depth + 1); |
180 | 189 AppendQuotedString(itr.key()); |
181 EscapeJSONString(itr.key(), true, json_string_); | |
182 if (pretty_print_) { | 190 if (pretty_print_) { |
183 json_string_->append(": "); | 191 json_string_->append(": "); |
184 } else { | 192 } else { |
185 json_string_->append(":"); | 193 json_string_->append(":"); |
186 } | 194 } |
187 BuildJSONString(&itr.value(), depth + 1); | 195 BuildJSONString(&itr.value(), depth + 1); |
188 } | 196 } |
189 | 197 |
190 if (pretty_print_) { | 198 if (pretty_print_) { |
191 json_string_->append(kPrettyPrintLineEnding); | 199 json_string_->append(kPrettyPrintLineEnding); |
(...skipping 11 matching lines...) Expand all Loading... |
203 NOTREACHED() << "Cannot serialize binary value."; | 211 NOTREACHED() << "Cannot serialize binary value."; |
204 } | 212 } |
205 break; | 213 break; |
206 } | 214 } |
207 | 215 |
208 default: | 216 default: |
209 NOTREACHED() << "unknown json type"; | 217 NOTREACHED() << "unknown json type"; |
210 } | 218 } |
211 } | 219 } |
212 | 220 |
| 221 void JSONWriter::AppendQuotedString(const std::string& str) { |
| 222 // TODO(viettrungluu): |str| is UTF-8, not ASCII, so to properly escape it we |
| 223 // have to convert it to UTF-16. This round-trip is suboptimal. |
| 224 JsonDoubleQuote(UTF8ToUTF16(str), true, json_string_); |
| 225 } |
| 226 |
213 void JSONWriter::IndentLine(int depth) { | 227 void JSONWriter::IndentLine(int depth) { |
214 // It may be faster to keep an indent string so we don't have to keep | 228 // It may be faster to keep an indent string so we don't have to keep |
215 // reallocating. | 229 // reallocating. |
216 json_string_->append(std::string(depth * 3, ' ')); | 230 json_string_->append(std::string(depth * 3, ' ')); |
217 } | 231 } |
218 | 232 |
219 } // namespace base | 233 } // namespace base |
OLD | NEW |