diff options
author | mgiuca <mgiuca@chromium.org> | 2015-02-04 19:02:42 -0800 |
---|---|---|
committer | Commit bot <commit-bot@chromium.org> | 2015-02-05 03:03:51 +0000 |
commit | a82ce4efc2cfa3812b96e22b5d3a68f915c7fbfb (patch) | |
tree | b5bee172001bad87df4b018e33b8b64cccd8baea /base/json | |
parent | 607b369291eb47c87582a0f9af2b5f0b4d031dfa (diff) | |
download | chromium_src-a82ce4efc2cfa3812b96e22b5d3a68f915c7fbfb.zip chromium_src-a82ce4efc2cfa3812b96e22b5d3a68f915c7fbfb.tar.gz chromium_src-a82ce4efc2cfa3812b96e22b5d3a68f915c7fbfb.tar.bz2 |
JSONStringValueSerializer takes a StringPiece instead of std::string&.
This allows callers to pass a char* (string literal) or StringPiece
(lightweight substring) without having to explicitly construct a string
object.
Refactored the implementation to avoid an ugly const_cast and Boolean to
avoid mutating a const pointer. Updated tests to use char* literals, and
added some new tests to test the new edge cases.
BUG=455068
Review URL: https://codereview.chromium.org/895913004
Cr-Commit-Position: refs/heads/master@{#314728}
Diffstat (limited to 'base/json')
-rw-r--r-- | base/json/json_string_value_serializer.cc | 13 | ||||
-rw-r--r-- | base/json/json_string_value_serializer.h | 17 | ||||
-rw-r--r-- | base/json/json_value_serializer_unittest.cc | 84 |
3 files changed, 84 insertions, 30 deletions
diff --git a/base/json/json_string_value_serializer.cc b/base/json/json_string_value_serializer.cc index b48f73c..b626640 100644 --- a/base/json/json_string_value_serializer.cc +++ b/base/json/json_string_value_serializer.cc @@ -12,16 +12,15 @@ using base::Value; JSONStringValueSerializer::JSONStringValueSerializer(std::string* json_string) : json_string_(json_string), - initialized_with_const_string_(false), + json_string_readonly_(*json_string), pretty_print_(false), allow_trailing_comma_(false) { - DCHECK(json_string); } JSONStringValueSerializer::JSONStringValueSerializer( - const std::string& json_string) - : json_string_(&const_cast<std::string&>(json_string)), - initialized_with_const_string_(true), + const base::StringPiece& json_string) + : json_string_(nullptr), + json_string_readonly_(json_string), pretty_print_(false), allow_trailing_comma_(false) { } @@ -39,7 +38,7 @@ bool JSONStringValueSerializer::SerializeAndOmitBinaryValues( bool JSONStringValueSerializer::SerializeInternal(const Value& root, bool omit_binary_values) { - if (initialized_with_const_string_) + if (!json_string_) return false; int options = 0; @@ -53,7 +52,7 @@ bool JSONStringValueSerializer::SerializeInternal(const Value& root, Value* JSONStringValueSerializer::Deserialize(int* error_code, std::string* error_str) { - return base::JSONReader::ReadAndReturnError(*json_string_, + return base::JSONReader::ReadAndReturnError(json_string_readonly_, allow_trailing_comma_ ? base::JSON_ALLOW_TRAILING_COMMAS : base::JSON_PARSE_RFC, error_code, error_str); diff --git a/base/json/json_string_value_serializer.h b/base/json/json_string_value_serializer.h index 3e0cb00..7f99bc9 100644 --- a/base/json/json_string_value_serializer.h +++ b/base/json/json_string_value_serializer.h @@ -10,6 +10,7 @@ #include "base/base_export.h" #include "base/basictypes.h" #include "base/files/file_path.h" +#include "base/strings/string_piece.h" #include "base/values.h" class BASE_EXPORT JSONStringValueSerializer : public base::ValueSerializer { @@ -19,10 +20,10 @@ class BASE_EXPORT JSONStringValueSerializer : public base::ValueSerializer { // retains ownership of the string. |json_string| must not be null. explicit JSONStringValueSerializer(std::string* json_string); - // This version allows initialization with a const string reference for - // deserialization only. Retains a reference to |json_string|, so the string - // argument must outlive the JSONStringValueSerializer. - explicit JSONStringValueSerializer(const std::string& json_string); + // This version allows initialization with a StringPiece for deserialization + // only. Retains a reference to the contents of |json_string|, so the data + // must outlive the JSONStringValueSerializer. + explicit JSONStringValueSerializer(const base::StringPiece& json_string); ~JSONStringValueSerializer() override; @@ -55,8 +56,12 @@ class BASE_EXPORT JSONStringValueSerializer : public base::ValueSerializer { private: bool SerializeInternal(const base::Value& root, bool omit_binary_values); - std::string* json_string_; // Not null. - bool initialized_with_const_string_; + // String for writing. Owned by the caller of the constructor. Will be null if + // the serializer was initialized with a const string. + std::string* json_string_; + // String for reading. Data is owned by the caller of the constructor. If + // |json_string_| is non-null, this is a view onto |json_string_|. + base::StringPiece json_string_readonly_; bool pretty_print_; // If true, serialization will span multiple lines. // If true, deserialization will allow trailing commas. bool allow_trailing_comma_; diff --git a/base/json/json_value_serializer_unittest.cc b/base/json/json_value_serializer_unittest.cc index e3c349c..d2a84de 100644 --- a/base/json/json_value_serializer_unittest.cc +++ b/base/json/json_value_serializer_unittest.cc @@ -12,6 +12,7 @@ #include "base/json/json_writer.h" #include "base/memory/scoped_ptr.h" #include "base/path_service.h" +#include "base/strings/string_piece.h" #include "base/strings/string_util.h" #include "base/strings/utf_string_conversions.h" #include "base/values.h" @@ -42,6 +43,20 @@ const char kProperJSONWithCommas[] = "\t\"compound\": { \"a\": 1, \"b\": 2, },\n" "}\n"; +// kProperJSON with a few misc characters at the begin and end. +const char kProperJSONPadded[] = + ")]}'\n" + "{\n" + " \"compound\": {\n" + " \"a\": 1,\n" + " \"b\": 2\n" + " },\n" + " \"some_String\": \"1337\",\n" + " \"some_int\": 42,\n" + " \"the_list\": [ \"val1\", \"val2\" ]\n" + "}\n" + "?!ab\n"; + const char kWinLineEnds[] = "\r\n"; const char kLinuxLineEnds[] = "\n"; @@ -74,7 +89,43 @@ void ValidateJsonList(const std::string& json) { // Test proper JSON [de]serialization from string is working. TEST(JSONValueSerializerTest, ReadProperJSONFromString) { // Try to deserialize it through the serializer. + JSONStringValueSerializer str_deserializer(kProperJSON); + + int error_code = 0; + std::string error_message; + scoped_ptr<Value> value( + str_deserializer.Deserialize(&error_code, &error_message)); + ASSERT_TRUE(value.get()); + ASSERT_EQ(0, error_code); + ASSERT_TRUE(error_message.empty()); + // Verify if the same JSON is still there. + CheckJSONIsStillTheSame(*value); +} + +// Test proper JSON deserialization from a string pointer is working. +TEST(JSONValueSerializerTest, ReadProperJSONFromStringPointer) { + // Try to deserialize a string pointer through the serializer. (This exercises + // a separate code path to passing a StringPiece.) std::string proper_json(kProperJSON); + JSONStringValueSerializer str_deserializer(&proper_json); + + int error_code = 0; + std::string error_message; + scoped_ptr<Value> value( + str_deserializer.Deserialize(&error_code, &error_message)); + ASSERT_TRUE(value.get()); + ASSERT_EQ(0, error_code); + ASSERT_TRUE(error_message.empty()); + // Verify if the same JSON is still there. + CheckJSONIsStillTheSame(*value); +} + +// Test proper JSON deserialization from a StringPiece substring. +TEST(JSONValueSerializerTest, ReadProperJSONFromStringPiece) { + // Create a StringPiece for the substring of kProperJSONPadded that matches + // kProperJSON. + base::StringPiece proper_json(kProperJSONPadded); + proper_json = proper_json.substr(5, proper_json.length() - 10); JSONStringValueSerializer str_deserializer(proper_json); int error_code = 0; @@ -92,8 +143,7 @@ TEST(JSONValueSerializerTest, ReadProperJSONFromString) { // the proper flag for that is set. TEST(JSONValueSerializerTest, ReadJSONWithTrailingCommasFromString) { // Try to deserialize it through the serializer. - std::string proper_json(kProperJSONWithCommas); - JSONStringValueSerializer str_deserializer(proper_json); + JSONStringValueSerializer str_deserializer(kProperJSONWithCommas); int error_code = 0; std::string error_message; @@ -165,9 +215,9 @@ TEST(JSONValueSerializerTest, ReadJSONWithCommasFromFile) { } TEST(JSONValueSerializerTest, Roundtrip) { - const std::string original_serialization = + static const char kOriginalSerialization[] = "{\"bool\":true,\"double\":3.14,\"int\":42,\"list\":[1,2],\"null\":null}"; - JSONStringValueSerializer serializer(original_serialization); + JSONStringValueSerializer serializer(kOriginalSerialization); scoped_ptr<Value> root(serializer.Deserialize(NULL, NULL)); ASSERT_TRUE(root.get()); ASSERT_TRUE(root->IsType(Value::TYPE_DICTIONARY)); @@ -198,7 +248,7 @@ TEST(JSONValueSerializerTest, Roundtrip) { std::string test_serialization; JSONStringValueSerializer mutable_serializer(&test_serialization); ASSERT_TRUE(mutable_serializer.Serialize(*root_dict)); - ASSERT_EQ(original_serialization, test_serialization); + ASSERT_EQ(kOriginalSerialization, test_serialization); mutable_serializer.set_pretty_print(true); ASSERT_TRUE(mutable_serializer.Serialize(*root_dict)); @@ -273,15 +323,15 @@ TEST(JSONValueSerializerTest, UnicodeStrings) { string16 test(WideToUTF16(L"\x7F51\x9875")); root.SetString("web", test); - std::string expected = "{\"web\":\"\xE7\xBD\x91\xE9\xA1\xB5\"}"; + static const char kExpected[] = "{\"web\":\"\xE7\xBD\x91\xE9\xA1\xB5\"}"; std::string actual; JSONStringValueSerializer serializer(&actual); ASSERT_TRUE(serializer.Serialize(root)); - ASSERT_EQ(expected, actual); + ASSERT_EQ(kExpected, actual); // escaped ascii text -> json - JSONStringValueSerializer deserializer(expected); + JSONStringValueSerializer deserializer(kExpected); scoped_ptr<Value> deserial_root(deserializer.Deserialize(NULL, NULL)); ASSERT_TRUE(deserial_root.get()); DictionaryValue* dict_root = @@ -297,15 +347,15 @@ TEST(JSONValueSerializerTest, HexStrings) { string16 test(WideToUTF16(L"\x01\x02")); root.SetString("test", test); - std::string expected = "{\"test\":\"\\u0001\\u0002\"}"; + static const char kExpected[] = "{\"test\":\"\\u0001\\u0002\"}"; std::string actual; JSONStringValueSerializer serializer(&actual); ASSERT_TRUE(serializer.Serialize(root)); - ASSERT_EQ(expected, actual); + ASSERT_EQ(kExpected, actual); // escaped ascii text -> json - JSONStringValueSerializer deserializer(expected); + JSONStringValueSerializer deserializer(kExpected); scoped_ptr<Value> deserial_root(deserializer.Deserialize(NULL, NULL)); ASSERT_TRUE(deserial_root.get()); DictionaryValue* dict_root = @@ -315,8 +365,8 @@ TEST(JSONValueSerializerTest, HexStrings) { ASSERT_EQ(test, test_value); // Test converting escaped regular chars - std::string escaped_chars = "{\"test\":\"\\u0067\\u006f\"}"; - JSONStringValueSerializer deserializer2(escaped_chars); + static const char kEscapedChars[] = "{\"test\":\"\\u0067\\u006f\"}"; + JSONStringValueSerializer deserializer2(kEscapedChars); deserial_root.reset(deserializer2.Deserialize(NULL, NULL)); ASSERT_TRUE(deserial_root.get()); dict_root = static_cast<DictionaryValue*>(deserial_root.get()); @@ -327,12 +377,12 @@ TEST(JSONValueSerializerTest, HexStrings) { TEST(JSONValueSerializerTest, AllowTrailingComma) { scoped_ptr<Value> root; scoped_ptr<Value> root_expected; - std::string test_with_commas("{\"key\": [true,],}"); - std::string test_no_commas("{\"key\": [true]}"); + static const char kTestWithCommas[] = "{\"key\": [true,],}"; + static const char kTestNoCommas[] = "{\"key\": [true]}"; - JSONStringValueSerializer serializer(test_with_commas); + JSONStringValueSerializer serializer(kTestWithCommas); serializer.set_allow_trailing_comma(true); - JSONStringValueSerializer serializer_expected(test_no_commas); + JSONStringValueSerializer serializer_expected(kTestNoCommas); root.reset(serializer.Deserialize(NULL, NULL)); ASSERT_TRUE(root.get()); root_expected.reset(serializer_expected.Deserialize(NULL, NULL)); |