OLD | NEW |
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 // | 4 // |
5 // A JSON parser. Converts strings of JSON into a Value object (see | 5 // A JSON parser. Converts strings of JSON into a Value object (see |
6 // base/values.h). | 6 // base/values.h). |
7 // http://www.ietf.org/rfc/rfc4627.txt?number=4627 | 7 // http://www.ietf.org/rfc/rfc4627.txt?number=4627 |
8 // | 8 // |
9 // Known limitations/deviations from the RFC: | 9 // Known limitations/deviations from the RFC: |
10 // - Only knows how to parse ints within the range of a signed 32 bit int and | 10 // - Only knows how to parse ints within the range of a signed 32 bit int and |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
75 | 75 |
76 // End should be one char past the end of the token. | 76 // End should be one char past the end of the token. |
77 int length; | 77 int length; |
78 | 78 |
79 // Get the character that's one past the end of this token. | 79 // Get the character that's one past the end of this token. |
80 wchar_t NextChar() { | 80 wchar_t NextChar() { |
81 return *(begin + length); | 81 return *(begin + length); |
82 } | 82 } |
83 }; | 83 }; |
84 | 84 |
85 // Error messages that can be returned. | 85 // Error codes during parsing. |
| 86 enum JsonParseError { |
| 87 JSON_NO_ERROR = 0, |
| 88 JSON_BAD_ROOT_ELEMENT_TYPE, |
| 89 JSON_INVALID_ESCAPE, |
| 90 JSON_SYNTAX_ERROR, |
| 91 JSON_TRAILING_COMMA, |
| 92 JSON_TOO_MUCH_NESTING, |
| 93 JSON_UNEXPECTED_DATA_AFTER_ROOT, |
| 94 JSON_UNSUPPORTED_ENCODING, |
| 95 JSON_UNQUOTED_DICTIONARY_KEY, |
| 96 }; |
| 97 |
| 98 // String versions of parse error codes. |
86 static const char* kBadRootElementType; | 99 static const char* kBadRootElementType; |
87 static const char* kInvalidEscape; | 100 static const char* kInvalidEscape; |
88 static const char* kSyntaxError; | 101 static const char* kSyntaxError; |
89 static const char* kTrailingComma; | 102 static const char* kTrailingComma; |
90 static const char* kTooMuchNesting; | 103 static const char* kTooMuchNesting; |
91 static const char* kUnexpectedDataAfterRoot; | 104 static const char* kUnexpectedDataAfterRoot; |
92 static const char* kUnsupportedEncoding; | 105 static const char* kUnsupportedEncoding; |
93 static const char* kUnquotedDictionaryKey; | 106 static const char* kUnquotedDictionaryKey; |
94 | 107 |
95 JSONReader(); | 108 JSONReader(); |
96 | 109 |
97 // Reads and parses |json|, returning a Value. The caller owns the returned | 110 // Reads and parses |json|, returning a Value. The caller owns the returned |
98 // instance. If |json| is not a properly formed JSON string, returns NULL. | 111 // instance. If |json| is not a properly formed JSON string, returns NULL. |
99 // If |allow_trailing_comma| is true, we will ignore trailing commas in | 112 // If |allow_trailing_comma| is true, we will ignore trailing commas in |
100 // objects and arrays even though this goes against the RFC. | 113 // objects and arrays even though this goes against the RFC. |
101 static Value* Read(const std::string& json, bool allow_trailing_comma); | 114 static Value* Read(const std::string& json, bool allow_trailing_comma); |
102 | 115 |
103 // Reads and parses |json| like Read(). |error_message_out| is optional. If | 116 // Reads and parses |json| like Read(). |error_code_out| and |error_msg_out| |
104 // specified and NULL is returned, |error_message_out| will be populated with | 117 // are optional. If specified and NULL is returned, they will be populated |
105 // a string describing the error. Otherwise, |error_message_out| is | 118 // an error code and a formatted error message (including error location if |
106 // unmodified. | 119 // appropriate). Otherwise, they will be unmodified. |
107 static Value* ReadAndReturnError(const std::string& json, | 120 static Value* ReadAndReturnError(const std::string& json, |
108 bool allow_trailing_comma, | 121 bool allow_trailing_comma, |
109 std::string* error_message_out); | 122 int* error_code_out, |
| 123 std::string* error_msg_out); |
110 | 124 |
111 // Returns the error message if the last call to JsonToValue() failed. If the | 125 // Converts a JSON parse error code into a human readable message. |
112 // last call did not fail, returns a valid empty string. | 126 // Returns an empty string if error_code is JSON_NO_ERROR. |
113 std::string error_message() { return error_message_; } | 127 static std::string ErrorCodeToString(JsonParseError error_code); |
| 128 |
| 129 // Returns the error code if the last call to JsonToValue() failed. |
| 130 // Returns JSON_NO_ERROR otherwise. |
| 131 JsonParseError error_code() const { return error_code_; } |
| 132 |
| 133 // Converts error_code_ to a human-readable string, including line and column |
| 134 // numbers if appropriate. |
| 135 std::string GetErrorMessage() const; |
114 | 136 |
115 // Reads and parses |json|, returning a Value. The caller owns the returned | 137 // Reads and parses |json|, returning a Value. The caller owns the returned |
116 // instance. If |json| is not a properly formed JSON string, returns NULL and | 138 // instance. If |json| is not a properly formed JSON string, returns NULL and |
117 // a detailed error can be retrieved from |error_message()|. | 139 // a detailed error can be retrieved from |error_message()|. |
118 // If |check_root| is true, we require that the root object be an object or | 140 // If |check_root| is true, we require that the root object be an object or |
119 // array. Otherwise, it can be any valid JSON type. | 141 // array. Otherwise, it can be any valid JSON type. |
120 // If |allow_trailing_comma| is true, we will ignore trailing commas in | 142 // If |allow_trailing_comma| is true, we will ignore trailing commas in |
121 // objects and arrays even though this goes against the RFC. | 143 // objects and arrays even though this goes against the RFC. |
122 Value* JsonToValue(const std::string& json, bool check_root, | 144 Value* JsonToValue(const std::string& json, bool check_root, |
123 bool allow_trailing_comma); | 145 bool allow_trailing_comma); |
124 | 146 |
125 private: | 147 private: |
126 static std::string FormatErrorMessage(int line, int column, | 148 static std::string FormatErrorMessage(int line, int column, |
127 const char* description); | 149 const std::string& description); |
128 | 150 |
129 DISALLOW_COPY_AND_ASSIGN(JSONReader); | 151 DISALLOW_COPY_AND_ASSIGN(JSONReader); |
130 | 152 |
131 FRIEND_TEST(JSONReaderTest, Reading); | 153 FRIEND_TEST(JSONReaderTest, Reading); |
132 FRIEND_TEST(JSONReaderTest, ErrorMessages); | 154 FRIEND_TEST(JSONReaderTest, ErrorMessages); |
133 | 155 |
134 // Recursively build Value. Returns NULL if we don't have a valid JSON | 156 // Recursively build Value. Returns NULL if we don't have a valid JSON |
135 // string. If |is_root| is true, we verify that the root element is either | 157 // string. If |is_root| is true, we verify that the root element is either |
136 // an object or an array. | 158 // an object or an array. |
137 Value* BuildValue(bool is_root); | 159 Value* BuildValue(bool is_root); |
(...skipping 25 matching lines...) Expand all Loading... |
163 // Increments |json_pos_| past leading whitespace and comments. | 185 // Increments |json_pos_| past leading whitespace and comments. |
164 void EatWhitespaceAndComments(); | 186 void EatWhitespaceAndComments(); |
165 | 187 |
166 // If |json_pos_| is at the start of a comment, eat it, otherwise, returns | 188 // If |json_pos_| is at the start of a comment, eat it, otherwise, returns |
167 // false. | 189 // false. |
168 bool EatComment(); | 190 bool EatComment(); |
169 | 191 |
170 // Checks if |json_pos_| matches str. | 192 // Checks if |json_pos_| matches str. |
171 bool NextStringMatch(const std::wstring& str); | 193 bool NextStringMatch(const std::wstring& str); |
172 | 194 |
173 // Creates the error message that will be returned to the caller. The current | 195 // Sets the error code that will be returned to the caller. The current |
174 // line and column are determined and added into the final message. | 196 // line and column are determined and added into the final message. |
175 void SetErrorMessage(const char* description, const wchar_t* error_pos); | 197 void SetErrorCode(const JsonParseError error, const wchar_t* error_pos); |
176 | 198 |
177 // Pointer to the starting position in the input string. | 199 // Pointer to the starting position in the input string. |
178 const wchar_t* start_pos_; | 200 const wchar_t* start_pos_; |
179 | 201 |
180 // Pointer to the current position in the input string. | 202 // Pointer to the current position in the input string. |
181 const wchar_t* json_pos_; | 203 const wchar_t* json_pos_; |
182 | 204 |
183 // Used to keep track of how many nested lists/dicts there are. | 205 // Used to keep track of how many nested lists/dicts there are. |
184 int stack_depth_; | 206 int stack_depth_; |
185 | 207 |
186 // A parser flag that allows trailing commas in objects and arrays. | 208 // A parser flag that allows trailing commas in objects and arrays. |
187 bool allow_trailing_comma_; | 209 bool allow_trailing_comma_; |
188 | 210 |
189 // Contains the error message for the last call to JsonToValue(), if any. | 211 // Contains the error code for the last call to JsonToValue(), if any. |
190 std::string error_message_; | 212 JsonParseError error_code_; |
| 213 int error_line_; |
| 214 int error_col_; |
191 }; | 215 }; |
192 | 216 |
193 } // namespace base | 217 } // namespace base |
194 | 218 |
195 #endif // BASE_JSON_JSON_READER_H_ | 219 #endif // BASE_JSON_JSON_READER_H_ |
OLD | NEW |