| 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 |