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