Allow JSONWriter and JSONValueSerializer to ignore binary values when instructed to do so.

Design discussion is available here: http://groups.google.com/a/chromium.org/group/chromium-dev/browse_thread/thread/967eb64325c24f9c

BUG=None
TEST=base_unittests


Review URL: http://codereview.chromium.org/8505033

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@110021 0039d316-1c4b-4281-b951-d872f2087c98
parent 16d57d91
......@@ -17,10 +17,24 @@ const char* JSONFileValueSerializer::kNoSuchFile = "File doesn't exist.";
JSONStringValueSerializer::~JSONStringValueSerializer() {}
bool JSONStringValueSerializer::Serialize(const Value& root) {
return SerializeInternal(root, false);
}
bool JSONStringValueSerializer::SerializeAndOmitBinaryValues(
const Value& root) {
return SerializeInternal(root, true);
}
bool JSONStringValueSerializer::SerializeInternal(const Value& root,
bool omit_binary_values) {
if (!json_string_ || initialized_with_const_string_)
return false;
base::JSONWriter::Write(&root, pretty_print_, json_string_);
base::JSONWriter::WriteWithOptions(
&root,
pretty_print_,
omit_binary_values ? base::JSONWriter::OPTIONS_OMIT_BINARY_VALUES : 0,
json_string_);
return true;
}
......@@ -38,10 +52,21 @@ Value* JSONStringValueSerializer::Deserialize(int* error_code,
/******* File Serializer *******/
bool JSONFileValueSerializer::Serialize(const Value& root) {
return SerializeInternal(root, false);
}
bool JSONFileValueSerializer::SerializeAndOmitBinaryValues(const Value& root) {
return SerializeInternal(root, true);
}
bool JSONFileValueSerializer::SerializeInternal(const Value& root,
bool omit_binary_values) {
std::string json_string;
JSONStringValueSerializer serializer(&json_string);
serializer.set_pretty_print(true);
bool result = serializer.Serialize(root);
bool result = omit_binary_values ?
serializer.SerializeAndOmitBinaryValues(root) :
serializer.Serialize(root);
if (!result)
return false;
......
......@@ -39,7 +39,11 @@ class BASE_EXPORT JSONStringValueSerializer : public base::ValueSerializer {
// Attempt to serialize the data structure represented by Value into
// JSON. If the return value is true, the result will have been written
// into the string passed into the constructor.
virtual bool Serialize(const Value& root);
virtual bool Serialize(const Value& root) OVERRIDE;
// Equivalent to Serialize(root) except binary values are omitted from the
// output.
bool SerializeAndOmitBinaryValues(const Value& root);
// Attempt to deserialize the data structure encoded in the string passed
// in to the constructor into a structure of Value objects. If the return
......@@ -48,7 +52,8 @@ class BASE_EXPORT JSONStringValueSerializer : public base::ValueSerializer {
// If |error_message| is non-null, it will be filled in with a formatted
// error message including the location of the error if appropriate.
// The caller takes ownership of the returned value.
virtual Value* Deserialize(int* error_code, std::string* error_message);
virtual Value* Deserialize(int* error_code, std::string* error_message)
OVERRIDE;
void set_pretty_print(bool new_value) { pretty_print_ = new_value; }
bool pretty_print() { return pretty_print_; }
......@@ -58,6 +63,8 @@ class BASE_EXPORT JSONStringValueSerializer : public base::ValueSerializer {
}
private:
bool SerializeInternal(const Value& root, bool omit_binary_values);
std::string* json_string_;
bool initialized_with_const_string_;
bool pretty_print_; // If true, serialization will span multiple lines.
......@@ -86,7 +93,11 @@ class BASE_EXPORT JSONFileValueSerializer : public base::ValueSerializer {
// Attempt to serialize the data structure represented by Value into
// JSON. If the return value is true, the result will have been written
// into the file whose name was passed into the constructor.
virtual bool Serialize(const Value& root);
virtual bool Serialize(const Value& root) OVERRIDE;
// Equivalent to Serialize(root) except binary values are omitted from the
// output.
bool SerializeAndOmitBinaryValues(const Value& root);
// Attempt to deserialize the data structure encoded in the file passed
// in to the constructor into a structure of Value objects. If the return
......@@ -95,7 +106,8 @@ class BASE_EXPORT JSONFileValueSerializer : public base::ValueSerializer {
// If |error_message| is non-null, it will be filled in with a formatted
// error message including the location of the error if appropriate.
// The caller takes ownership of the returned value.
virtual Value* Deserialize(int* error_code, std::string* error_message);
virtual Value* Deserialize(int* error_code, std::string* error_message)
OVERRIDE;
// This enum is designed to safely overlap with JSONReader::JsonParseError.
enum JsonFileError {
......@@ -117,6 +129,8 @@ class BASE_EXPORT JSONFileValueSerializer : public base::ValueSerializer {
static const char* GetErrorMessageForCode(int error_code);
private:
bool SerializeInternal(const Value& root, bool omit_binary_values);
FilePath json_file_path_;
// A wrapper for file_util::ReadFileToString which returns a non-zero
......
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Copyright (c) 2011 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.
......@@ -26,19 +26,21 @@ const char* JSONWriter::kEmptyArray = "[]";
void JSONWriter::Write(const Value* const node,
bool pretty_print,
std::string* json) {
WriteWithOptionalEscape(node, pretty_print, true, json);
WriteWithOptions(node, pretty_print, 0, json);
}
/* static */
void JSONWriter::WriteWithOptionalEscape(const Value* const node,
bool pretty_print,
bool escape,
std::string* json) {
void JSONWriter::WriteWithOptions(const Value* const node,
bool pretty_print,
int options,
std::string* json) {
json->clear();
// Is there a better way to estimate the size of the output?
json->reserve(1024);
JSONWriter writer(pretty_print, json);
writer.BuildJSONString(node, 0, escape);
bool escape = !(options & OPTIONS_DO_NOT_ESCAPE);
bool omit_binary_values = !!(options & OPTIONS_OMIT_BINARY_VALUES);
writer.BuildJSONString(node, 0, escape, omit_binary_values);
if (pretty_print)
json->append(kPrettyPrintLineEnding);
}
......@@ -51,7 +53,8 @@ JSONWriter::JSONWriter(bool pretty_print, std::string* json)
void JSONWriter::BuildJSONString(const Value* const node,
int depth,
bool escape) {
bool escape,
bool omit_binary_values) {
switch (node->GetType()) {
case Value::TYPE_NULL:
json_string_->append("null");
......@@ -122,16 +125,21 @@ void JSONWriter::BuildJSONString(const Value* const node,
const ListValue* list = static_cast<const ListValue*>(node);
for (size_t i = 0; i < list->GetSize(); ++i) {
Value* value = NULL;
bool result = list->Get(i, &value);
DCHECK(result);
if (omit_binary_values && value->GetType() == Value::TYPE_BINARY) {
continue;
}
if (i != 0) {
json_string_->append(",");
if (pretty_print_)
json_string_->append(" ");
}
Value* value = NULL;
bool result = list->Get(i, &value);
DCHECK(result);
BuildJSONString(value, depth, escape);
BuildJSONString(value, depth, escape, omit_binary_values);
}
if (pretty_print_)
......@@ -151,16 +159,20 @@ void JSONWriter::BuildJSONString(const Value* const node,
for (DictionaryValue::key_iterator key_itr = dict->begin_keys();
key_itr != dict->end_keys();
++key_itr) {
Value* value = NULL;
bool result = dict->GetWithoutPathExpansion(*key_itr, &value);
DCHECK(result);
if (omit_binary_values && value->GetType() == Value::TYPE_BINARY) {
continue;
}
if (key_itr != dict->begin_keys()) {
json_string_->append(",");
if (pretty_print_)
json_string_->append(kPrettyPrintLineEnding);
}
Value* value = NULL;
bool result = dict->GetWithoutPathExpansion(*key_itr, &value);
DCHECK(result);
if (pretty_print_)
IndentLine(depth + 1);
AppendQuotedString(*key_itr);
......@@ -169,7 +181,7 @@ void JSONWriter::BuildJSONString(const Value* const node,
} else {
json_string_->append(":");
}
BuildJSONString(value, depth + 1, escape);
BuildJSONString(value, depth + 1, escape, omit_binary_values);
}
if (pretty_print_) {
......@@ -182,8 +194,15 @@ void JSONWriter::BuildJSONString(const Value* const node,
break;
}
case Value::TYPE_BINARY:
{
if (!omit_binary_values) {
NOTREACHED() << "Cannot serialize binary value.";
}
break;
}
default:
// TODO(jhughes): handle TYPE_BINARY
NOTREACHED() << "unknown json type";
}
}
......
......@@ -17,6 +17,17 @@ class Value;
class BASE_EXPORT JSONWriter {
public:
enum Options {
// Do not escape the string, preserving its UTF8 characters. It is useful
// if you can pass the resulting string to the JSON parser in binary form
// (as UTF8).
OPTIONS_DO_NOT_ESCAPE = 1 << 0,
// For values of binary type, the value (and key if within a dictionary)
// will be omitted from the output.
OPTIONS_OMIT_BINARY_VALUES = 1 << 1
};
// Given a root node, generates a JSON string and puts it into |json|.
// If |pretty_print| is true, return a slightly nicer formated json string
// (pads with whitespace to help readability). If |pretty_print| is false,
......@@ -27,13 +38,10 @@ class BASE_EXPORT JSONWriter {
static void Write(const Value* const node, bool pretty_print,
std::string* json);
// Same as above, but has an option to not escape the string, preserving its
// UTF8 characters. It is useful if you can pass resulting string to the
// JSON parser in binary form (as UTF8).
static void WriteWithOptionalEscape(const Value* const node,
bool pretty_print,
bool escape,
std::string* json);
// Same as above but with |options| which is a bunch of JSONWriter::Options
// bitwise ORed together.
static void WriteWithOptions(const Value* const node, bool pretty_print,
int options, std::string* json);
// A static, constant JSON string representing an empty array. Useful
// for empty JSON argument passing.
......@@ -44,7 +52,8 @@ class BASE_EXPORT JSONWriter {
// Called recursively to build the JSON string. Whe completed, value is
// json_string_ will contain the JSON.
void BuildJSONString(const Value* const node, int depth, bool escape);
void BuildJSONString(const Value* const node, int depth, bool escape,
bool ignore_binary_values);
// Appends a quoted, escaped, version of (UTF-8) str to json_string_.
void AppendQuotedString(const std::string& str);
......
// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Copyright (c) 2011 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.
......@@ -93,6 +93,32 @@ TEST(JSONWriterTest, Writing) {
period_dict3.SetWithoutPathExpansion("a.b", Value::CreateIntegerValue(1));
JSONWriter::Write(&period_dict3, false, &output_js);
ASSERT_EQ("{\"a\":{\"b\":2},\"a.b\":1}", output_js);
// Test ignoring binary values.
root = BinaryValue::CreateWithCopiedBuffer("asdf", 4);
JSONWriter::WriteWithOptions(root, false,
JSONWriter::OPTIONS_OMIT_BINARY_VALUES,
&output_js);
ASSERT_TRUE(output_js.empty());
delete root;
ListValue binary_list;
binary_list.Append(Value::CreateIntegerValue(5));
binary_list.Append(BinaryValue::CreateWithCopiedBuffer("asdf", 4));
binary_list.Append(Value::CreateIntegerValue(2));
JSONWriter::WriteWithOptions(&binary_list, false,
JSONWriter::OPTIONS_OMIT_BINARY_VALUES,
&output_js);
ASSERT_EQ("[5,2]", output_js);
DictionaryValue binary_dict;
binary_dict.Set("a", Value::CreateIntegerValue(5));
binary_dict.Set("b", BinaryValue::CreateWithCopiedBuffer("asdf", 4));
binary_dict.Set("c", Value::CreateIntegerValue(2));
JSONWriter::WriteWithOptions(&binary_dict, false,
JSONWriter::OPTIONS_OMIT_BINARY_VALUES,
&output_js);
ASSERT_EQ("{\"a\":5,\"c\":2}", output_js);
}
} // namespace base
......@@ -1006,7 +1006,8 @@ std::string AboutStats(const std::string& query) {
std::string data;
if (query == "json" || query == kStringsJsPath) {
base::JSONWriter::WriteWithOptionalEscape(&root, true, false, &data);
base::JSONWriter::WriteWithOptions(
&root, true, base::JSONWriter::OPTIONS_DO_NOT_ESCAPE, &data);
if (query == kStringsJsPath)
data = "var templateData = " + data + ";";
} else if (query == "raw") {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment