1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors 2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be 3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file. 4*6777b538SAndroid Build Coastguard Worker 5*6777b538SAndroid Build Coastguard Worker #ifndef BASE_JSON_JSON_WRITER_H_ 6*6777b538SAndroid Build Coastguard Worker #define BASE_JSON_JSON_WRITER_H_ 7*6777b538SAndroid Build Coastguard Worker 8*6777b538SAndroid Build Coastguard Worker #include <stddef.h> 9*6777b538SAndroid Build Coastguard Worker 10*6777b538SAndroid Build Coastguard Worker #include <cstdint> 11*6777b538SAndroid Build Coastguard Worker #include <optional> 12*6777b538SAndroid Build Coastguard Worker #include <string> 13*6777b538SAndroid Build Coastguard Worker #include <string_view> 14*6777b538SAndroid Build Coastguard Worker 15*6777b538SAndroid Build Coastguard Worker #include "base/base_export.h" 16*6777b538SAndroid Build Coastguard Worker #include "base/json/json_common.h" 17*6777b538SAndroid Build Coastguard Worker #include "base/memory/raw_ptr.h" 18*6777b538SAndroid Build Coastguard Worker #include "base/values.h" 19*6777b538SAndroid Build Coastguard Worker 20*6777b538SAndroid Build Coastguard Worker namespace base { 21*6777b538SAndroid Build Coastguard Worker 22*6777b538SAndroid Build Coastguard Worker enum JsonOptions { 23*6777b538SAndroid Build Coastguard Worker // This option instructs the writer that if a Binary value is encountered, 24*6777b538SAndroid Build Coastguard Worker // the value (and key if within a dictionary) will be omitted from the 25*6777b538SAndroid Build Coastguard Worker // output, and success will be returned. Otherwise, if a binary value is 26*6777b538SAndroid Build Coastguard Worker // encountered, failure will be returned. 27*6777b538SAndroid Build Coastguard Worker OPTIONS_OMIT_BINARY_VALUES = 1 << 0, 28*6777b538SAndroid Build Coastguard Worker 29*6777b538SAndroid Build Coastguard Worker // This option instructs the writer to write doubles that have no fractional 30*6777b538SAndroid Build Coastguard Worker // part as a normal integer (i.e., without using exponential notation 31*6777b538SAndroid Build Coastguard Worker // or appending a '.0') as long as the value is within the range of a 32*6777b538SAndroid Build Coastguard Worker // 64-bit int. 33*6777b538SAndroid Build Coastguard Worker OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION = 1 << 1, 34*6777b538SAndroid Build Coastguard Worker 35*6777b538SAndroid Build Coastguard Worker // Return a slightly nicer formatted json string (pads with whitespace to 36*6777b538SAndroid Build Coastguard Worker // help with readability). 37*6777b538SAndroid Build Coastguard Worker OPTIONS_PRETTY_PRINT = 1 << 2, 38*6777b538SAndroid Build Coastguard Worker }; 39*6777b538SAndroid Build Coastguard Worker 40*6777b538SAndroid Build Coastguard Worker // Given a root node, generates and returns a JSON string. 41*6777b538SAndroid Build Coastguard Worker // 42*6777b538SAndroid Build Coastguard Worker // Returns `std::nullopt` if 43*6777b538SAndroid Build Coastguard Worker // * the nesting depth exceeds `max_depth`, or 44*6777b538SAndroid Build Coastguard Worker // * the JSON contains binary values. 45*6777b538SAndroid Build Coastguard Worker BASE_EXPORT std::optional<std::string> WriteJson( 46*6777b538SAndroid Build Coastguard Worker ValueView node, 47*6777b538SAndroid Build Coastguard Worker size_t max_depth = internal::kAbsoluteMaxDepth); 48*6777b538SAndroid Build Coastguard Worker 49*6777b538SAndroid Build Coastguard Worker // Given a root node, generates and returns a JSON string. 50*6777b538SAndroid Build Coastguard Worker // The string is formatted according to `options` which is a bitmask of 51*6777b538SAndroid Build Coastguard Worker // `JsonOptions`. 52*6777b538SAndroid Build Coastguard Worker // 53*6777b538SAndroid Build Coastguard Worker // Returns `std::nullopt` if 54*6777b538SAndroid Build Coastguard Worker // * the nesting depth exceeds `max_depth,` or 55*6777b538SAndroid Build Coastguard Worker // * the JSON contains binary values 56*6777b538SAndroid Build Coastguard Worker // (unless `JsonOptions::OPTIONS_OMIT_BINARY_VALUES` is passed). 57*6777b538SAndroid Build Coastguard Worker BASE_EXPORT std::optional<std::string> WriteJsonWithOptions( 58*6777b538SAndroid Build Coastguard Worker ValueView node, 59*6777b538SAndroid Build Coastguard Worker uint32_t options, 60*6777b538SAndroid Build Coastguard Worker size_t max_depth = internal::kAbsoluteMaxDepth); 61*6777b538SAndroid Build Coastguard Worker 62*6777b538SAndroid Build Coastguard Worker class BASE_EXPORT JSONWriter { 63*6777b538SAndroid Build Coastguard Worker public: 64*6777b538SAndroid Build Coastguard Worker using Options = JsonOptions; 65*6777b538SAndroid Build Coastguard Worker // TODO: Once we support c++20 we replace these with 66*6777b538SAndroid Build Coastguard Worker // `using enum ::JsonOptions`. 67*6777b538SAndroid Build Coastguard Worker static constexpr auto OPTIONS_OMIT_BINARY_VALUES = 68*6777b538SAndroid Build Coastguard Worker JsonOptions::OPTIONS_OMIT_BINARY_VALUES; 69*6777b538SAndroid Build Coastguard Worker static constexpr auto OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION = 70*6777b538SAndroid Build Coastguard Worker JsonOptions::OPTIONS_OMIT_DOUBLE_TYPE_PRESERVATION; 71*6777b538SAndroid Build Coastguard Worker static constexpr auto OPTIONS_PRETTY_PRINT = 72*6777b538SAndroid Build Coastguard Worker JsonOptions::OPTIONS_PRETTY_PRINT; 73*6777b538SAndroid Build Coastguard Worker 74*6777b538SAndroid Build Coastguard Worker JSONWriter(const JSONWriter&) = delete; 75*6777b538SAndroid Build Coastguard Worker JSONWriter& operator=(const JSONWriter&) = delete; 76*6777b538SAndroid Build Coastguard Worker 77*6777b538SAndroid Build Coastguard Worker // Given a root node, generates a JSON string and puts it into |json|. 78*6777b538SAndroid Build Coastguard Worker // The output string is overwritten and not appended. 79*6777b538SAndroid Build Coastguard Worker // 80*6777b538SAndroid Build Coastguard Worker // TODO(tc): Should we generate json if it would be invalid json (e.g., 81*6777b538SAndroid Build Coastguard Worker // |node| is not a dictionary/list Value or if there are inf/-inf float 82*6777b538SAndroid Build Coastguard Worker // values)? Return true on success and false on failure. 83*6777b538SAndroid Build Coastguard Worker // 84*6777b538SAndroid Build Coastguard Worker // Deprecated: use the standalone method `WriteJson()` instead. 85*6777b538SAndroid Build Coastguard Worker static bool Write(ValueView node, 86*6777b538SAndroid Build Coastguard Worker std::string* json, 87*6777b538SAndroid Build Coastguard Worker size_t max_depth = internal::kAbsoluteMaxDepth); 88*6777b538SAndroid Build Coastguard Worker 89*6777b538SAndroid Build Coastguard Worker // Same as above but with |options| which is a bunch of JSONWriter::Options 90*6777b538SAndroid Build Coastguard Worker // bitwise ORed together. Return true on success and false on failure. 91*6777b538SAndroid Build Coastguard Worker // 92*6777b538SAndroid Build Coastguard Worker // Deprecated: use the standalone method `WriteJsonWithOptions()` instead. 93*6777b538SAndroid Build Coastguard Worker static bool WriteWithOptions(ValueView node, 94*6777b538SAndroid Build Coastguard Worker int options, 95*6777b538SAndroid Build Coastguard Worker std::string* json, 96*6777b538SAndroid Build Coastguard Worker size_t max_depth = internal::kAbsoluteMaxDepth); 97*6777b538SAndroid Build Coastguard Worker 98*6777b538SAndroid Build Coastguard Worker private: 99*6777b538SAndroid Build Coastguard Worker JSONWriter(int options, 100*6777b538SAndroid Build Coastguard Worker std::string* json, 101*6777b538SAndroid Build Coastguard Worker size_t max_depth = internal::kAbsoluteMaxDepth); 102*6777b538SAndroid Build Coastguard Worker 103*6777b538SAndroid Build Coastguard Worker // Called recursively to build the JSON string. When completed, 104*6777b538SAndroid Build Coastguard Worker // |json_string_| will contain the JSON. 105*6777b538SAndroid Build Coastguard Worker bool BuildJSONString(absl::monostate node, size_t depth); 106*6777b538SAndroid Build Coastguard Worker bool BuildJSONString(bool node, size_t depth); 107*6777b538SAndroid Build Coastguard Worker bool BuildJSONString(int node, size_t depth); 108*6777b538SAndroid Build Coastguard Worker bool BuildJSONString(double node, size_t depth); 109*6777b538SAndroid Build Coastguard Worker bool BuildJSONString(std::string_view node, size_t depth); 110*6777b538SAndroid Build Coastguard Worker bool BuildJSONString(const Value::BlobStorage& node, size_t depth); 111*6777b538SAndroid Build Coastguard Worker bool BuildJSONString(const Value::Dict& node, size_t depth); 112*6777b538SAndroid Build Coastguard Worker bool BuildJSONString(const Value::List& node, size_t depth); 113*6777b538SAndroid Build Coastguard Worker 114*6777b538SAndroid Build Coastguard Worker // Adds space to json_string_ for the indent level. 115*6777b538SAndroid Build Coastguard Worker void IndentLine(size_t depth); 116*6777b538SAndroid Build Coastguard Worker 117*6777b538SAndroid Build Coastguard Worker bool omit_binary_values_; 118*6777b538SAndroid Build Coastguard Worker bool omit_double_type_preservation_; 119*6777b538SAndroid Build Coastguard Worker bool pretty_print_; 120*6777b538SAndroid Build Coastguard Worker 121*6777b538SAndroid Build Coastguard Worker // Where we write JSON data as we generate it. 122*6777b538SAndroid Build Coastguard Worker raw_ptr<std::string> json_string_; 123*6777b538SAndroid Build Coastguard Worker 124*6777b538SAndroid Build Coastguard Worker // Maximum depth to write. 125*6777b538SAndroid Build Coastguard Worker const size_t max_depth_; 126*6777b538SAndroid Build Coastguard Worker 127*6777b538SAndroid Build Coastguard Worker // The number of times the writer has recursed (current stack depth). 128*6777b538SAndroid Build Coastguard Worker size_t stack_depth_; 129*6777b538SAndroid Build Coastguard Worker }; 130*6777b538SAndroid Build Coastguard Worker 131*6777b538SAndroid Build Coastguard Worker } // namespace base 132*6777b538SAndroid Build Coastguard Worker 133*6777b538SAndroid Build Coastguard Worker #endif // BASE_JSON_JSON_WRITER_H_ 134