// 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. Converts strings of JSON into a Value object (see // base/values.h). // http://www.ietf.org/rfc/rfc4627.txt?number=4627 // // Known limitations/deviations from the RFC: // - Only knows how to parse ints within the range of a signed 32 bit int and // decimal numbers within a double. // - Assumes input is encoded as UTF8. The spec says we should allow UTF-16 // (BE or LE) and UTF-32 (BE or LE) as well. // - We limit nesting to 100 levels to prevent stack overflow (this is allowed // by the RFC). // - A Unicode FAQ ("http://unicode.org/faq/utf_bom.html") writes a data // stream may start with a Unicode Byte-Order-Mark (U+FEFF), i.e. the input // UTF-8 string for the JSONReader::JsonToValue() function may start with a // UTF-8 BOM (0xEF, 0xBB, 0xBF). // To avoid the function from mis-treating a UTF-8 BOM as an invalid // character, the function skips a Unicode BOM at the beginning of the // Unicode string (converted from the input UTF-8 string) before parsing it. // // TODO(tc): Add a parsing option to to relax object keys being wrapped in // double quotes // TODO(tc): Add an option to disable comment stripping #ifndef BASE_JSON_JSON_READER_H_ #define BASE_JSON_JSON_READER_H_ #include <string> #include "base/base_export.h" #include "base/basictypes.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_piece.h" namespace base { class Value; namespace internal { class JSONParser; } } namespace base { enum JSONParserOptions { // Parses the input strictly according to RFC 4627, except for where noted // above. JSON_PARSE_RFC = 0, // Allows commas to exist after the last element in structures. JSON_ALLOW_TRAILING_COMMAS = 1 << 0, // The parser can perform optimizations by placing hidden data in the root of // the JSON object, which speeds up certain operations on children. However, // if the child is Remove()d from root, it would result in use-after-free // unless it is DeepCopy()ed or this option is used. JSON_DETACHABLE_CHILDREN = 1 << 1, }; class BASE_EXPORT JSONReader { public: // Error codes during parsing. enum JsonParseError { JSON_NO_ERROR = 0, JSON_INVALID_ESCAPE, JSON_SYNTAX_ERROR, JSON_UNEXPECTED_TOKEN, JSON_TRAILING_COMMA, JSON_TOO_MUCH_NESTING, JSON_UNEXPECTED_DATA_AFTER_ROOT, JSON_UNSUPPORTED_ENCODING, JSON_UNQUOTED_DICTIONARY_KEY, JSON_PARSE_ERROR_COUNT }; // String versions of parse error codes. static const char* kInvalidEscape; static const char* kSyntaxError; static const char* kUnexpectedToken; static const char* kTrailingComma; static const char* kTooMuchNesting; static const char* kUnexpectedDataAfterRoot; static const char* kUnsupportedEncoding; static const char* kUnquotedDictionaryKey; // Constructs a reader with the default options, JSON_PARSE_RFC. JSONReader(); // Constructs a reader with custom options. explicit JSONReader(int options); ~JSONReader(); // Reads and parses |json|, returning a Value. The caller owns the returned // instance. If |json| is not a properly formed JSON string, returns NULL. static Value* Read(const StringPiece& json); // Reads and parses |json|, returning a Value owned by the caller. The // parser respects the given |options|. If the input is not properly formed, // returns NULL. static Value* Read(const StringPiece& json, int options); // Reads and parses |json| like Read(). |error_code_out| and |error_msg_out| // are optional. If specified and NULL is returned, they will be populated // an error code and a formatted error message (including error location if // appropriate). Otherwise, they will be unmodified. static Value* ReadAndReturnError(const StringPiece& json, int options, // JSONParserOptions int* error_code_out, std::string* error_msg_out); // Converts a JSON parse error code into a human readable message. // Returns an empty string if error_code is JSON_NO_ERROR. static std::string ErrorCodeToString(JsonParseError error_code); // Parses an input string into a Value that is owned by the caller. Value* ReadToValue(const std::string& json); // Returns the error code if the last call to ReadToValue() failed. // Returns JSON_NO_ERROR otherwise. JsonParseError error_code() const; // Converts error_code_ to a human-readable string, including line and column // numbers if appropriate. std::string GetErrorMessage() const; private: scoped_ptr<internal::JSONParser> parser_; }; } // namespace base #endif // BASE_JSON_JSON_READER_H_