Thanks to visit codestin.com
Credit goes to chromium.googlesource.com

blob: c55719e5b52559329fa5f3967cc73cf4413a3803 [file] [log] [blame]
Avi Drissmane4622aa2022-09-08 20:36:061// Copyright 2012 The Chromium Authors
license.botbf09a502008-08-24 00:55:552// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
initial.commitd7cae122008-07-26 21:49:384
[email protected]93d49d72009-10-23 20:00:205#include "base/json/json_writer.h"
initial.commitd7cae122008-07-26 21:49:386
avi7e3976a2015-12-03 16:46:547#include <stdint.h>
8
[email protected]ba4fb5a2012-03-08 22:55:299#include <cmath>
avi7e3976a2015-12-03 16:46:5410#include <limits>
Helmut Januschka4e477ef42024-02-27 19:26:4511#include <string_view>
Victor Hugo Vianna Silvaab2c6ac2025-03-18 19:52:3412#include <variant>
[email protected]ba4fb5a2012-03-08 22:55:2913
[email protected]93d49d72009-10-23 20:00:2014#include "base/json/string_escape.h"
initial.commitd7cae122008-07-26 21:49:3815#include "base/logging.h"
Peter Kastingfbb9e562021-06-27 02:57:3716#include "base/numerics/safe_conversions.h"
[email protected]dfa049e2013-02-07 02:57:2217#include "base/strings/string_number_conversions.h"
Devon Loehraebcaea42025-03-05 22:12:3218#include "base/strings/to_string.h"
[email protected]cf0e6222013-03-20 16:50:3219#include "base/values.h"
avi9b6f42932015-12-26 22:15:1420#include "build/build_config.h"
initial.commitd7cae122008-07-26 21:49:3821
[email protected]93d49d72009-10-23 20:00:2022namespace base {
23
Xiaohan Wang01bac022022-01-15 14:45:0124#if BUILDFLAG(IS_WIN)
[email protected]44ea5312014-01-29 22:50:2825const char kPrettyPrintLineEnding[] = "\r\n";
[email protected]b81637c32009-06-26 21:17:2426#else
[email protected]44ea5312014-01-29 22:50:2827const char kPrettyPrintLineEnding[] = "\n";
[email protected]b81637c32009-06-26 21:17:2428#endif
initial.commitd7cae122008-07-26 21:49:3829
[email protected]bbe15712013-12-11 22:10:4530// static
Daniel Cheng8ac305b2022-02-17 00:05:1131bool JSONWriter::Write(ValueView node, std::string* json, size_t max_depth) {
Chris Davis3dece342019-10-09 00:42:1332 return WriteWithOptions(node, 0, json, max_depth);
[email protected]3388d4c2009-05-15 10:13:2833}
34
[email protected]bbe15712013-12-11 22:10:4535// static
Daniel Cheng8ac305b2022-02-17 00:05:1136bool JSONWriter::WriteWithOptions(ValueView node,
estade8d046462015-05-16 01:02:3437 int options,
Chris Davis3dece342019-10-09 00:42:1338 std::string* json,
39 size_t max_depth) {
initial.commitd7cae122008-07-26 21:49:3840 json->clear();
41 // Is there a better way to estimate the size of the output?
Jeroen Dhollander7088e1532023-03-28 10:15:3642 if (json->capacity() < 1024) {
Dominic Battrec75c5852021-02-12 23:14:4643 json->reserve(1024);
Jeroen Dhollander7088e1532023-03-28 10:15:3644 }
[email protected]4abb4602012-03-16 01:59:5545
Chris Davis3dece342019-10-09 00:42:1346 JSONWriter writer(options, json, max_depth);
Daniel Cheng8ac305b2022-02-17 00:05:1147 bool result = node.Visit([&writer](const auto& member) {
48 return writer.BuildJSONString(member, 0);
49 });
Daniel Chenga367fe52022-02-15 18:08:4850
Jeroen Dhollander7088e1532023-03-28 10:15:3651 if (options & OPTIONS_PRETTY_PRINT) {
Daniel Chenga367fe52022-02-15 18:08:4852 json->append(kPrettyPrintLineEnding);
Jeroen Dhollander7088e1532023-03-28 10:15:3653 }
Daniel Chenga367fe52022-02-15 18:08:4854
55 return result;
56}
57
Chris Davis3dece342019-10-09 00:42:1358JSONWriter::JSONWriter(int options, std::string* json, size_t max_depth)
[email protected]44ea5312014-01-29 22:50:2859 : omit_binary_values_((options & OPTIONS_OMIT_BINARY_VALUES) != 0),
60 omit_double_type_preservation_(
61 (options & OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION) != 0),
62 pretty_print_((options & OPTIONS_PRETTY_PRINT) != 0),
Chris Davis3dece342019-10-09 00:42:1363 json_string_(json),
64 max_depth_(max_depth),
65 stack_depth_(0) {
initial.commitd7cae122008-07-26 21:49:3866 DCHECK(json);
Chris Davis3dece342019-10-09 00:42:1367 CHECK_LE(max_depth, internal::kAbsoluteMaxDepth);
initial.commitd7cae122008-07-26 21:49:3868}
69
Victor Hugo Vianna Silvaab2c6ac2025-03-18 19:52:3470bool JSONWriter::BuildJSONString(std::monostate node, size_t depth) {
Daniel Cheng8ac305b2022-02-17 00:05:1171 json_string_->append("null");
72 return true;
73}
initial.commitd7cae122008-07-26 21:49:3874
Daniel Cheng8ac305b2022-02-17 00:05:1175bool JSONWriter::BuildJSONString(bool node, size_t depth) {
Devon Loehraebcaea42025-03-05 22:12:3276 json_string_->append(base::ToString(node));
Daniel Cheng8ac305b2022-02-17 00:05:1177 return true;
78}
[email protected]e959b8dc2014-02-06 09:24:4879
Daniel Cheng8ac305b2022-02-17 00:05:1180bool JSONWriter::BuildJSONString(int node, size_t depth) {
81 json_string_->append(NumberToString(node));
82 return true;
83}
[email protected]e959b8dc2014-02-06 09:24:4884
Daniel Cheng8ac305b2022-02-17 00:05:1185bool JSONWriter::BuildJSONString(double node, size_t depth) {
86 if (omit_double_type_preservation_ &&
87 IsValueInRangeForNumericType<int64_t>(node) && std::floor(node) == node) {
88 json_string_->append(NumberToString(static_cast<int64_t>(node)));
89 return true;
initial.commitd7cae122008-07-26 21:49:3890 }
jdoerriefdea8be2018-10-30 22:15:3091
Daniel Cheng8ac305b2022-02-17 00:05:1192 std::string real = NumberToString(node);
93 // Ensure that the number has a .0 if there's no decimal or 'e'. This
94 // makes sure that when we read the JSON back, it's interpreted as a
95 // real rather than an int.
Jeroen Dhollander7088e1532023-03-28 10:15:3696 if (real.find_first_of(".eE") == std::string::npos) {
Daniel Cheng8ac305b2022-02-17 00:05:1197 real.append(".0");
Jeroen Dhollander7088e1532023-03-28 10:15:3698 }
Daniel Cheng8ac305b2022-02-17 00:05:1199
100 // The JSON spec requires that non-integer values in the range (-1,1)
101 // have a zero before the decimal point - ".52" is not valid, "0.52" is.
102 if (real[0] == '.') {
103 real.insert(0, 1, '0');
104 } else if (real.length() > 1 && real[0] == '-' && real[1] == '.') {
105 // "-.1" bad "-0.1" good
106 real.insert(1, 1, '0');
107 }
108 json_string_->append(real);
109 return true;
110}
111
Helmut Januschka4e477ef42024-02-27 19:26:45112bool JSONWriter::BuildJSONString(std::string_view node, size_t depth) {
Daniel Cheng8ac305b2022-02-17 00:05:11113 EscapeJSONString(node, true, json_string_);
114 return true;
115}
116
117bool JSONWriter::BuildJSONString(const Value::BlobStorage& node, size_t depth) {
118 // Successful only if we're allowed to omit it.
119 DLOG_IF(ERROR, !omit_binary_values_) << "Cannot serialize binary value.";
120 return omit_binary_values_;
initial.commitd7cae122008-07-26 21:49:38121}
122
Daniel Chenga367fe52022-02-15 18:08:48123bool JSONWriter::BuildJSONString(const Value::Dict& node, size_t depth) {
124 internal::StackMarker depth_check(max_depth_, &stack_depth_);
125
Jeroen Dhollander7088e1532023-03-28 10:15:36126 if (depth_check.IsTooDeep()) {
Daniel Chenga367fe52022-02-15 18:08:48127 return false;
Jeroen Dhollander7088e1532023-03-28 10:15:36128 }
Daniel Chenga367fe52022-02-15 18:08:48129
130 json_string_->push_back('{');
Jeroen Dhollander7088e1532023-03-28 10:15:36131 if (pretty_print_) {
Daniel Chenga367fe52022-02-15 18:08:48132 json_string_->append(kPrettyPrintLineEnding);
Jeroen Dhollander7088e1532023-03-28 10:15:36133 }
Daniel Chenga367fe52022-02-15 18:08:48134
135 bool first_value_has_been_output = false;
136 bool result = true;
137 for (const auto [key, value] : node) {
Jeroen Dhollander7088e1532023-03-28 10:15:36138 if (omit_binary_values_ && value.type() == Value::Type::BINARY) {
Daniel Chenga367fe52022-02-15 18:08:48139 continue;
Jeroen Dhollander7088e1532023-03-28 10:15:36140 }
Daniel Chenga367fe52022-02-15 18:08:48141
142 if (first_value_has_been_output) {
143 json_string_->push_back(',');
Jeroen Dhollander7088e1532023-03-28 10:15:36144 if (pretty_print_) {
Daniel Chenga367fe52022-02-15 18:08:48145 json_string_->append(kPrettyPrintLineEnding);
Jeroen Dhollander7088e1532023-03-28 10:15:36146 }
Daniel Chenga367fe52022-02-15 18:08:48147 }
148
Jeroen Dhollander7088e1532023-03-28 10:15:36149 if (pretty_print_) {
Daniel Chenga367fe52022-02-15 18:08:48150 IndentLine(depth + 1U);
Jeroen Dhollander7088e1532023-03-28 10:15:36151 }
Daniel Chenga367fe52022-02-15 18:08:48152
153 EscapeJSONString(key, true, json_string_);
154 json_string_->push_back(':');
Jeroen Dhollander7088e1532023-03-28 10:15:36155 if (pretty_print_) {
Daniel Chenga367fe52022-02-15 18:08:48156 json_string_->push_back(' ');
Jeroen Dhollander7088e1532023-03-28 10:15:36157 }
Daniel Chenga367fe52022-02-15 18:08:48158
Daniel Cheng8ac305b2022-02-17 00:05:11159 result &= value.Visit([this, depth = depth + 1](const auto& member) {
160 return BuildJSONString(member, depth);
161 });
Daniel Chenga367fe52022-02-15 18:08:48162
163 first_value_has_been_output = true;
164 }
165
166 if (pretty_print_) {
Jeroen Dhollander7088e1532023-03-28 10:15:36167 if (first_value_has_been_output) {
Xiaohan Wang01d84c362022-04-15 15:00:08168 json_string_->append(kPrettyPrintLineEnding);
Jeroen Dhollander7088e1532023-03-28 10:15:36169 }
Daniel Chenga367fe52022-02-15 18:08:48170 IndentLine(depth);
171 }
172
173 json_string_->push_back('}');
174 return result;
175}
176
177bool JSONWriter::BuildJSONString(const Value::List& node, size_t depth) {
178 internal::StackMarker depth_check(max_depth_, &stack_depth_);
179
Jeroen Dhollander7088e1532023-03-28 10:15:36180 if (depth_check.IsTooDeep()) {
Daniel Chenga367fe52022-02-15 18:08:48181 return false;
Jeroen Dhollander7088e1532023-03-28 10:15:36182 }
Daniel Chenga367fe52022-02-15 18:08:48183
184 json_string_->push_back('[');
Jeroen Dhollander7088e1532023-03-28 10:15:36185 if (pretty_print_) {
Daniel Chenga367fe52022-02-15 18:08:48186 json_string_->push_back(' ');
Jeroen Dhollander7088e1532023-03-28 10:15:36187 }
Daniel Chenga367fe52022-02-15 18:08:48188
189 bool first_value_has_been_output = false;
190 bool result = true;
191 for (const auto& value : node) {
Jeroen Dhollander7088e1532023-03-28 10:15:36192 if (omit_binary_values_ && value.type() == Value::Type::BINARY) {
Daniel Chenga367fe52022-02-15 18:08:48193 continue;
Jeroen Dhollander7088e1532023-03-28 10:15:36194 }
Daniel Chenga367fe52022-02-15 18:08:48195
196 if (first_value_has_been_output) {
197 json_string_->push_back(',');
Jeroen Dhollander7088e1532023-03-28 10:15:36198 if (pretty_print_) {
Daniel Chenga367fe52022-02-15 18:08:48199 json_string_->push_back(' ');
Jeroen Dhollander7088e1532023-03-28 10:15:36200 }
Daniel Chenga367fe52022-02-15 18:08:48201 }
202
Daniel Cheng8ac305b2022-02-17 00:05:11203 result &= value.Visit([this, depth](const auto& member) {
204 return BuildJSONString(member, depth);
205 });
Daniel Chenga367fe52022-02-15 18:08:48206
207 first_value_has_been_output = true;
208 }
209
Jeroen Dhollander7088e1532023-03-28 10:15:36210 if (pretty_print_) {
Daniel Chenga367fe52022-02-15 18:08:48211 json_string_->push_back(' ');
Jeroen Dhollander7088e1532023-03-28 10:15:36212 }
Daniel Chenga367fe52022-02-15 18:08:48213 json_string_->push_back(']');
214 return result;
215}
216
[email protected]44ea5312014-01-29 22:50:28217void JSONWriter::IndentLine(size_t depth) {
218 json_string_->append(depth * 3U, ' ');
initial.commitd7cae122008-07-26 21:49:38219}
[email protected]93d49d72009-10-23 20:00:20220
Arthur Sonzognie5fff99c2024-02-21 15:58:24221std::optional<std::string> WriteJson(ValueView node, size_t max_depth) {
Jeroen Dhollander7088e1532023-03-28 10:15:36222 std::string result;
223 if (!JSONWriter::Write(node, &result, max_depth)) {
Arthur Sonzognie5fff99c2024-02-21 15:58:24224 return std::nullopt;
Jeroen Dhollander7088e1532023-03-28 10:15:36225 }
226 return result;
227}
228
Arthur Sonzognie5fff99c2024-02-21 15:58:24229std::optional<std::string> WriteJsonWithOptions(ValueView node,
230 uint32_t options,
231 size_t max_depth) {
Jeroen Dhollander7088e1532023-03-28 10:15:36232 std::string result;
233 if (!JSONWriter::WriteWithOptions(node, static_cast<int>(options), &result,
234 max_depth)) {
Arthur Sonzognie5fff99c2024-02-21 15:58:24235 return std::nullopt;
Jeroen Dhollander7088e1532023-03-28 10:15:36236 }
237 return result;
238}
239
[email protected]93d49d72009-10-23 20:00:20240} // namespace base