| // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style license that can be |
| // found in the LICENSE file. |
| |
| // A JSON parser, converting from a base::StringPiece to a base::Value. |
| // |
| // The JSON spec is: |
| // https://tools.ietf.org/rfc/rfc8259.txt |
| // which obsoletes the earlier RFCs 4627, 7158 and 7159. |
| // |
| // This RFC should be equivalent to the informal spec: |
| // https://www.json.org/json-en.html |
| // |
| // Implementation choices permitted by the RFC: |
| // - Nesting is limited (to a configurable depth, 200 by default). |
| // - Numbers are limited to those representable by a finite double. The |
| // conversion from a JSON number (in the base::StringPiece input) to a |
| // double-flavored base::Value may also be lossy. |
| // - The input (which must be UTF-8) may begin with a BOM (Byte Order Mark). |
| // - Duplicate object keys (strings) are silently allowed. Last key-value pair |
| // wins. Previous pairs are discarded. |
| // |
| // Configurable (see the JSONParserOptions type) deviations from the RFC: |
| // - Allow trailing commas: "[1,2,]". |
| // - Replace invalid Unicode with U+FFFD REPLACEMENT CHARACTER. |
| // - Allow "// etc\n" and "/* etc */" C-style comments. |
| // - Allow ASCII control characters, including literal (not escaped) NUL bytes |
| // and new lines, within a JSON string. |
| // - Allow "\\v" escapes within a JSON string, producing a vertical tab. |
| // - Allow "\\x23" escapes within a JSON string. Subtly, the 2-digit hex value |
| // is a Unicode code point, not a UTF-8 byte. For example, "\\xFF" in the |
| // JSON source decodes to a base::Value whose string contains "\xC3\xBF", the |
| // UTF-8 encoding of U+00FF LATIN SMALL LETTER Y WITH DIAERESIS. Converting |
| // from UTF-8 to UTF-16, e.g. via UTF8ToWide, will recover a 16-bit 0x00FF. |
| |
| #ifndef BASE_JSON_JSON_READER_H_ |
| #define BASE_JSON_JSON_READER_H_ |
| |
| #include <memory> |
| #include <string> |
| |
| #include "base/base_export.h" |
| #include "base/json/json_common.h" |
| #include "base/strings/string_piece.h" |
| #include "base/values.h" |
| #include "third_party/abseil-cpp/absl/types/optional.h" |
| |
| namespace base { |
| |
| enum JSONParserOptions { |
| // Parses the input strictly according to RFC 8259. |
| JSON_PARSE_RFC = 0, |
| |
| // Allows commas to exist after the last element in structures. |
| JSON_ALLOW_TRAILING_COMMAS = 1 << 0, |
| |
| // If set the parser replaces invalid code points (i.e. lone |
| // surrogates) with the Unicode replacement character (U+FFFD). If |
| // not set, invalid code points trigger a hard error and parsing |
| // fails. |
| JSON_REPLACE_INVALID_CHARACTERS = 1 << 1, |
| |
| // Allows both C (/* */) and C++ (//) style comments. |
| JSON_ALLOW_COMMENTS = 1 << 2, |
| |
| // Permits unescaped ASCII control characters (such as unescaped \r and \n) |
| // in the range [0x00,0x1F]. |
| JSON_ALLOW_CONTROL_CHARS = 1 << 3, |
| |
| // Permits \\v vertical tab escapes. |
| JSON_ALLOW_VERT_TAB = 1 << 4, |
| |
| // Permits \\xNN escapes as described above. |
| JSON_ALLOW_X_ESCAPES = 1 << 5, |
| |
| // This parser historically accepted, without configuration flags, |
| // non-standard JSON extensions. This flag enables that traditional parsing |
| // behavior. |
| // |
| // This set of options is mirrored in Rust |
| // base::JsonOptions::with_chromium_extensions(). |
| JSON_PARSE_CHROMIUM_EXTENSIONS = JSON_ALLOW_COMMENTS | |
| JSON_ALLOW_CONTROL_CHARS | |
| JSON_ALLOW_VERT_TAB | JSON_ALLOW_X_ESCAPES, |
| }; |
| |
| class BASE_EXPORT JSONReader { |
| public: |
| struct BASE_EXPORT ValueWithError { |
| ValueWithError(); |
| ValueWithError(ValueWithError&& other); |
| ValueWithError& operator=(ValueWithError&& other); |
| |
| ValueWithError(const ValueWithError&) = delete; |
| ValueWithError& operator=(const ValueWithError&) = delete; |
| |
| ~ValueWithError(); |
| |
| absl::optional<Value> value; |
| |
| // Contains default values if |value| exists, or the error status if |value| |
| // is absl::nullopt. |
| std::string error_message; |
| int error_line = 0; |
| int error_column = 0; |
| }; |
| |
| // This class contains only static methods. |
| JSONReader() = delete; |
| JSONReader(const JSONReader&) = delete; |
| JSONReader& operator=(const JSONReader&) = delete; |
| |
| // Reads and parses |json|, returning a Value. |
| // If |json| is not a properly formed JSON string, returns absl::nullopt. |
| static absl::optional<Value> Read( |
| StringPiece json, |
| int options = JSON_PARSE_CHROMIUM_EXTENSIONS, |
| size_t max_depth = internal::kAbsoluteMaxDepth); |
| |
| // Deprecated. Use the Read() method above. |
| // Reads and parses |json|, returning a Value. |
| // If |json| is not a properly formed JSON string, returns nullptr. |
| // Wrap this in base::FooValue::From() to check the Value is of type Foo and |
| // convert to a FooValue at the same time. |
| static std::unique_ptr<Value> ReadDeprecated( |
| StringPiece json, |
| int options = JSON_PARSE_CHROMIUM_EXTENSIONS, |
| size_t max_depth = internal::kAbsoluteMaxDepth); |
| |
| // Reads and parses |json| like Read(). Returns a ValueWithError, which on |
| // error, will be populated with a formatted error message, an error code, and |
| // the error location if appropriate. |
| static ValueWithError ReadAndReturnValueWithError( |
| StringPiece json, |
| int options = JSON_PARSE_CHROMIUM_EXTENSIONS); |
| }; |
| |
| } // namespace base |
| |
| #endif // BASE_JSON_JSON_READER_H_ |