OLD | NEW |
1 // Copyright (c) 2010 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 WriteWithOptionalEscape(node, pretty_print, true, json); | 29 WriteWithOptions(node, pretty_print, 0, json); |
30 } | 30 } |
31 | 31 |
32 /* static */ | 32 /* static */ |
33 void JSONWriter::WriteWithOptionalEscape(const Value* const node, | 33 void JSONWriter::WriteWithOptions(const Value* const node, |
34 bool pretty_print, | 34 bool pretty_print, |
35 bool escape, | 35 int options, |
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 writer.BuildJSONString(node, 0, escape); | 41 bool escape = !(options & OPTIONS_DO_NOT_ESCAPE); |
| 42 bool omit_binary_values = !!(options & OPTIONS_OMIT_BINARY_VALUES); |
| 43 writer.BuildJSONString(node, 0, escape, omit_binary_values); |
42 if (pretty_print) | 44 if (pretty_print) |
43 json->append(kPrettyPrintLineEnding); | 45 json->append(kPrettyPrintLineEnding); |
44 } | 46 } |
45 | 47 |
46 JSONWriter::JSONWriter(bool pretty_print, std::string* json) | 48 JSONWriter::JSONWriter(bool pretty_print, std::string* json) |
47 : json_string_(json), | 49 : json_string_(json), |
48 pretty_print_(pretty_print) { | 50 pretty_print_(pretty_print) { |
49 DCHECK(json); | 51 DCHECK(json); |
50 } | 52 } |
51 | 53 |
52 void JSONWriter::BuildJSONString(const Value* const node, | 54 void JSONWriter::BuildJSONString(const Value* const node, |
53 int depth, | 55 int depth, |
54 bool escape) { | 56 bool escape, |
| 57 bool omit_binary_values) { |
55 switch (node->GetType()) { | 58 switch (node->GetType()) { |
56 case Value::TYPE_NULL: | 59 case Value::TYPE_NULL: |
57 json_string_->append("null"); | 60 json_string_->append("null"); |
58 break; | 61 break; |
59 | 62 |
60 case Value::TYPE_BOOLEAN: | 63 case Value::TYPE_BOOLEAN: |
61 { | 64 { |
62 bool value; | 65 bool value; |
63 bool result = node->GetAsBoolean(&value); | 66 bool result = node->GetAsBoolean(&value); |
64 DCHECK(result); | 67 DCHECK(result); |
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
115 } | 118 } |
116 | 119 |
117 case Value::TYPE_LIST: | 120 case Value::TYPE_LIST: |
118 { | 121 { |
119 json_string_->append("["); | 122 json_string_->append("["); |
120 if (pretty_print_) | 123 if (pretty_print_) |
121 json_string_->append(" "); | 124 json_string_->append(" "); |
122 | 125 |
123 const ListValue* list = static_cast<const ListValue*>(node); | 126 const ListValue* list = static_cast<const ListValue*>(node); |
124 for (size_t i = 0; i < list->GetSize(); ++i) { | 127 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 |
125 if (i != 0) { | 136 if (i != 0) { |
126 json_string_->append(","); | 137 json_string_->append(","); |
127 if (pretty_print_) | 138 if (pretty_print_) |
128 json_string_->append(" "); | 139 json_string_->append(" "); |
129 } | 140 } |
130 | 141 |
131 Value* value = NULL; | 142 BuildJSONString(value, depth, escape, omit_binary_values); |
132 bool result = list->Get(i, &value); | |
133 DCHECK(result); | |
134 BuildJSONString(value, depth, escape); | |
135 } | 143 } |
136 | 144 |
137 if (pretty_print_) | 145 if (pretty_print_) |
138 json_string_->append(" "); | 146 json_string_->append(" "); |
139 json_string_->append("]"); | 147 json_string_->append("]"); |
140 break; | 148 break; |
141 } | 149 } |
142 | 150 |
143 case Value::TYPE_DICTIONARY: | 151 case Value::TYPE_DICTIONARY: |
144 { | 152 { |
145 json_string_->append("{"); | 153 json_string_->append("{"); |
146 if (pretty_print_) | 154 if (pretty_print_) |
147 json_string_->append(kPrettyPrintLineEnding); | 155 json_string_->append(kPrettyPrintLineEnding); |
148 | 156 |
149 const DictionaryValue* dict = | 157 const DictionaryValue* dict = |
150 static_cast<const DictionaryValue*>(node); | 158 static_cast<const DictionaryValue*>(node); |
151 for (DictionaryValue::key_iterator key_itr = dict->begin_keys(); | 159 for (DictionaryValue::key_iterator key_itr = dict->begin_keys(); |
152 key_itr != dict->end_keys(); | 160 key_itr != dict->end_keys(); |
153 ++key_itr) { | 161 ++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 |
154 if (key_itr != dict->begin_keys()) { | 170 if (key_itr != dict->begin_keys()) { |
155 json_string_->append(","); | 171 json_string_->append(","); |
156 if (pretty_print_) | 172 if (pretty_print_) |
157 json_string_->append(kPrettyPrintLineEnding); | 173 json_string_->append(kPrettyPrintLineEnding); |
158 } | 174 } |
159 | 175 |
160 Value* value = NULL; | |
161 bool result = dict->GetWithoutPathExpansion(*key_itr, &value); | |
162 DCHECK(result); | |
163 | |
164 if (pretty_print_) | 176 if (pretty_print_) |
165 IndentLine(depth + 1); | 177 IndentLine(depth + 1); |
166 AppendQuotedString(*key_itr); | 178 AppendQuotedString(*key_itr); |
167 if (pretty_print_) { | 179 if (pretty_print_) { |
168 json_string_->append(": "); | 180 json_string_->append(": "); |
169 } else { | 181 } else { |
170 json_string_->append(":"); | 182 json_string_->append(":"); |
171 } | 183 } |
172 BuildJSONString(value, depth + 1, escape); | 184 BuildJSONString(value, depth + 1, escape, omit_binary_values); |
173 } | 185 } |
174 | 186 |
175 if (pretty_print_) { | 187 if (pretty_print_) { |
176 json_string_->append(kPrettyPrintLineEnding); | 188 json_string_->append(kPrettyPrintLineEnding); |
177 IndentLine(depth); | 189 IndentLine(depth); |
178 json_string_->append("}"); | 190 json_string_->append("}"); |
179 } else { | 191 } else { |
180 json_string_->append("}"); | 192 json_string_->append("}"); |
181 } | 193 } |
182 break; | 194 break; |
183 } | 195 } |
184 | 196 |
| 197 case Value::TYPE_BINARY: |
| 198 { |
| 199 if (!omit_binary_values) { |
| 200 NOTREACHED() << "Cannot serialize binary value."; |
| 201 } |
| 202 break; |
| 203 } |
| 204 |
185 default: | 205 default: |
186 // TODO(jhughes): handle TYPE_BINARY | |
187 NOTREACHED() << "unknown json type"; | 206 NOTREACHED() << "unknown json type"; |
188 } | 207 } |
189 } | 208 } |
190 | 209 |
191 void JSONWriter::AppendQuotedString(const std::string& str) { | 210 void JSONWriter::AppendQuotedString(const std::string& str) { |
192 // TODO(viettrungluu): |str| is UTF-8, not ASCII, so to properly escape it we | 211 // TODO(viettrungluu): |str| is UTF-8, not ASCII, so to properly escape it we |
193 // have to convert it to UTF-16. This round-trip is suboptimal. | 212 // have to convert it to UTF-16. This round-trip is suboptimal. |
194 JsonDoubleQuote(UTF8ToUTF16(str), true, json_string_); | 213 JsonDoubleQuote(UTF8ToUTF16(str), true, json_string_); |
195 } | 214 } |
196 | 215 |
197 void JSONWriter::IndentLine(int depth) { | 216 void JSONWriter::IndentLine(int depth) { |
198 // It may be faster to keep an indent string so we don't have to keep | 217 // It may be faster to keep an indent string so we don't have to keep |
199 // reallocating. | 218 // reallocating. |
200 json_string_->append(std::string(depth * 3, ' ')); | 219 json_string_->append(std::string(depth * 3, ' ')); |
201 } | 220 } |
202 | 221 |
203 } // namespace base | 222 } // namespace base |
OLD | NEW |