16d528ed9Sopenharmony_ci// Copyright (c) 2012 The Chromium Authors. All rights reserved. 26d528ed9Sopenharmony_ci// Use of this source code is governed by a BSD-style license that can be 36d528ed9Sopenharmony_ci// found in the LICENSE file. 46d528ed9Sopenharmony_ci 56d528ed9Sopenharmony_ci#include "base/json/json_writer.h" 66d528ed9Sopenharmony_ci 76d528ed9Sopenharmony_ci#include <stdint.h> 86d528ed9Sopenharmony_ci 96d528ed9Sopenharmony_ci#include <cmath> 106d528ed9Sopenharmony_ci#include <limits> 116d528ed9Sopenharmony_ci 126d528ed9Sopenharmony_ci#include "base/json/string_escape.h" 136d528ed9Sopenharmony_ci#include "base/logging.h" 146d528ed9Sopenharmony_ci#include "base/strings/string_number_conversions.h" 156d528ed9Sopenharmony_ci#include "base/strings/utf_string_conversions.h" 166d528ed9Sopenharmony_ci#include "base/values.h" 176d528ed9Sopenharmony_ci#include "util/build_config.h" 186d528ed9Sopenharmony_ci 196d528ed9Sopenharmony_cinamespace base { 206d528ed9Sopenharmony_ci 216d528ed9Sopenharmony_ci#if defined(OS_WIN) 226d528ed9Sopenharmony_ciconst char kPrettyPrintLineEnding[] = "\r\n"; 236d528ed9Sopenharmony_ci#else 246d528ed9Sopenharmony_ciconst char kPrettyPrintLineEnding[] = "\n"; 256d528ed9Sopenharmony_ci#endif 266d528ed9Sopenharmony_ci 276d528ed9Sopenharmony_ci// static 286d528ed9Sopenharmony_cibool JSONWriter::Write(const Value& node, std::string* json) { 296d528ed9Sopenharmony_ci return WriteWithOptions(node, 0, json); 306d528ed9Sopenharmony_ci} 316d528ed9Sopenharmony_ci 326d528ed9Sopenharmony_ci// static 336d528ed9Sopenharmony_cibool JSONWriter::WriteWithOptions(const Value& node, 346d528ed9Sopenharmony_ci int options, 356d528ed9Sopenharmony_ci std::string* json) { 366d528ed9Sopenharmony_ci json->clear(); 376d528ed9Sopenharmony_ci // Is there a better way to estimate the size of the output? 386d528ed9Sopenharmony_ci json->reserve(1024); 396d528ed9Sopenharmony_ci 406d528ed9Sopenharmony_ci JSONWriter writer(options, json); 416d528ed9Sopenharmony_ci bool result = writer.BuildJSONString(node, 0U); 426d528ed9Sopenharmony_ci 436d528ed9Sopenharmony_ci if (options & OPTIONS_PRETTY_PRINT) 446d528ed9Sopenharmony_ci json->append(kPrettyPrintLineEnding); 456d528ed9Sopenharmony_ci 466d528ed9Sopenharmony_ci return result; 476d528ed9Sopenharmony_ci} 486d528ed9Sopenharmony_ci 496d528ed9Sopenharmony_ciJSONWriter::JSONWriter(int options, std::string* json) 506d528ed9Sopenharmony_ci : omit_binary_values_((options & OPTIONS_OMIT_BINARY_VALUES) != 0), 516d528ed9Sopenharmony_ci pretty_print_((options & OPTIONS_PRETTY_PRINT) != 0), 526d528ed9Sopenharmony_ci json_string_(json) { 536d528ed9Sopenharmony_ci DCHECK(json); 546d528ed9Sopenharmony_ci} 556d528ed9Sopenharmony_ci 566d528ed9Sopenharmony_cibool JSONWriter::BuildJSONString(const Value& node, size_t depth) { 576d528ed9Sopenharmony_ci switch (node.type()) { 586d528ed9Sopenharmony_ci case Value::Type::NONE: { 596d528ed9Sopenharmony_ci json_string_->append("null"); 606d528ed9Sopenharmony_ci return true; 616d528ed9Sopenharmony_ci } 626d528ed9Sopenharmony_ci 636d528ed9Sopenharmony_ci case Value::Type::BOOLEAN: { 646d528ed9Sopenharmony_ci bool value; 656d528ed9Sopenharmony_ci bool result = node.GetAsBoolean(&value); 666d528ed9Sopenharmony_ci DCHECK(result); 676d528ed9Sopenharmony_ci json_string_->append(value ? "true" : "false"); 686d528ed9Sopenharmony_ci return result; 696d528ed9Sopenharmony_ci } 706d528ed9Sopenharmony_ci 716d528ed9Sopenharmony_ci case Value::Type::INTEGER: { 726d528ed9Sopenharmony_ci int value; 736d528ed9Sopenharmony_ci bool result = node.GetAsInteger(&value); 746d528ed9Sopenharmony_ci DCHECK(result); 756d528ed9Sopenharmony_ci json_string_->append(IntToString(value)); 766d528ed9Sopenharmony_ci return result; 776d528ed9Sopenharmony_ci } 786d528ed9Sopenharmony_ci 796d528ed9Sopenharmony_ci case Value::Type::STRING: { 806d528ed9Sopenharmony_ci std::string value; 816d528ed9Sopenharmony_ci bool result = node.GetAsString(&value); 826d528ed9Sopenharmony_ci DCHECK(result); 836d528ed9Sopenharmony_ci EscapeJSONString(value, true, json_string_); 846d528ed9Sopenharmony_ci return result; 856d528ed9Sopenharmony_ci } 866d528ed9Sopenharmony_ci 876d528ed9Sopenharmony_ci case Value::Type::LIST: { 886d528ed9Sopenharmony_ci json_string_->push_back('['); 896d528ed9Sopenharmony_ci if (pretty_print_) 906d528ed9Sopenharmony_ci json_string_->push_back(' '); 916d528ed9Sopenharmony_ci 926d528ed9Sopenharmony_ci const ListValue* list = nullptr; 936d528ed9Sopenharmony_ci bool first_value_has_been_output = false; 946d528ed9Sopenharmony_ci bool result = node.GetAsList(&list); 956d528ed9Sopenharmony_ci DCHECK(result); 966d528ed9Sopenharmony_ci for (const auto& value : *list) { 976d528ed9Sopenharmony_ci if (omit_binary_values_ && value.type() == Value::Type::BINARY) 986d528ed9Sopenharmony_ci continue; 996d528ed9Sopenharmony_ci 1006d528ed9Sopenharmony_ci if (first_value_has_been_output) { 1016d528ed9Sopenharmony_ci json_string_->push_back(','); 1026d528ed9Sopenharmony_ci if (pretty_print_) 1036d528ed9Sopenharmony_ci json_string_->push_back(' '); 1046d528ed9Sopenharmony_ci } 1056d528ed9Sopenharmony_ci 1066d528ed9Sopenharmony_ci if (!BuildJSONString(value, depth)) 1076d528ed9Sopenharmony_ci result = false; 1086d528ed9Sopenharmony_ci 1096d528ed9Sopenharmony_ci first_value_has_been_output = true; 1106d528ed9Sopenharmony_ci } 1116d528ed9Sopenharmony_ci 1126d528ed9Sopenharmony_ci if (pretty_print_) 1136d528ed9Sopenharmony_ci json_string_->push_back(' '); 1146d528ed9Sopenharmony_ci json_string_->push_back(']'); 1156d528ed9Sopenharmony_ci return result; 1166d528ed9Sopenharmony_ci } 1176d528ed9Sopenharmony_ci 1186d528ed9Sopenharmony_ci case Value::Type::DICTIONARY: { 1196d528ed9Sopenharmony_ci json_string_->push_back('{'); 1206d528ed9Sopenharmony_ci if (pretty_print_) 1216d528ed9Sopenharmony_ci json_string_->append(kPrettyPrintLineEnding); 1226d528ed9Sopenharmony_ci 1236d528ed9Sopenharmony_ci const DictionaryValue* dict = nullptr; 1246d528ed9Sopenharmony_ci bool first_value_has_been_output = false; 1256d528ed9Sopenharmony_ci bool result = node.GetAsDictionary(&dict); 1266d528ed9Sopenharmony_ci DCHECK(result); 1276d528ed9Sopenharmony_ci for (DictionaryValue::Iterator itr(*dict); !itr.IsAtEnd(); 1286d528ed9Sopenharmony_ci itr.Advance()) { 1296d528ed9Sopenharmony_ci if (omit_binary_values_ && itr.value().type() == Value::Type::BINARY) { 1306d528ed9Sopenharmony_ci continue; 1316d528ed9Sopenharmony_ci } 1326d528ed9Sopenharmony_ci 1336d528ed9Sopenharmony_ci if (first_value_has_been_output) { 1346d528ed9Sopenharmony_ci json_string_->push_back(','); 1356d528ed9Sopenharmony_ci if (pretty_print_) 1366d528ed9Sopenharmony_ci json_string_->append(kPrettyPrintLineEnding); 1376d528ed9Sopenharmony_ci } 1386d528ed9Sopenharmony_ci 1396d528ed9Sopenharmony_ci if (pretty_print_) 1406d528ed9Sopenharmony_ci IndentLine(depth + 1U); 1416d528ed9Sopenharmony_ci 1426d528ed9Sopenharmony_ci EscapeJSONString(itr.key(), true, json_string_); 1436d528ed9Sopenharmony_ci json_string_->push_back(':'); 1446d528ed9Sopenharmony_ci if (pretty_print_) 1456d528ed9Sopenharmony_ci json_string_->push_back(' '); 1466d528ed9Sopenharmony_ci 1476d528ed9Sopenharmony_ci if (!BuildJSONString(itr.value(), depth + 1U)) 1486d528ed9Sopenharmony_ci result = false; 1496d528ed9Sopenharmony_ci 1506d528ed9Sopenharmony_ci first_value_has_been_output = true; 1516d528ed9Sopenharmony_ci } 1526d528ed9Sopenharmony_ci 1536d528ed9Sopenharmony_ci if (pretty_print_) { 1546d528ed9Sopenharmony_ci json_string_->append(kPrettyPrintLineEnding); 1556d528ed9Sopenharmony_ci IndentLine(depth); 1566d528ed9Sopenharmony_ci } 1576d528ed9Sopenharmony_ci 1586d528ed9Sopenharmony_ci json_string_->push_back('}'); 1596d528ed9Sopenharmony_ci return result; 1606d528ed9Sopenharmony_ci } 1616d528ed9Sopenharmony_ci 1626d528ed9Sopenharmony_ci case Value::Type::BINARY: 1636d528ed9Sopenharmony_ci // Successful only if we're allowed to omit it. 1646d528ed9Sopenharmony_ci DLOG_IF(ERROR, !omit_binary_values_) << "Cannot serialize binary value."; 1656d528ed9Sopenharmony_ci return omit_binary_values_; 1666d528ed9Sopenharmony_ci } 1676d528ed9Sopenharmony_ci NOTREACHED(); 1686d528ed9Sopenharmony_ci return false; 1696d528ed9Sopenharmony_ci} 1706d528ed9Sopenharmony_ci 1716d528ed9Sopenharmony_civoid JSONWriter::IndentLine(size_t depth) { 1726d528ed9Sopenharmony_ci json_string_->append(depth * 3U, ' '); 1736d528ed9Sopenharmony_ci} 1746d528ed9Sopenharmony_ci 1756d528ed9Sopenharmony_ci} // namespace base 176