(*this)(p.second);
}
+ template <typename Iterator>
+ void printKVPairs(Iterator begin, Iterator end) const {
+ printKV(*begin);
+ for (++begin; begin != end; ++begin) {
+ out_ += ',';
+ newline();
+ printKV(*begin);
+ }
+ }
+
void printObject(dynamic const& o) const {
if (o.empty()) {
out_ += "{}";
out_ += '{';
indent();
newline();
- auto it = o.items().begin();
- printKV(*it);
- for (++it; it != o.items().end(); ++it) {
- out_ += ',';
- newline();
- printKV(*it);
+ if (opts_.sort_keys) {
+ std::vector<std::pair<dynamic, dynamic>> items(
+ o.items().begin(), o.items().end());
+ std::sort(items.begin(), items.end());
+ printKVPairs(items.begin(), items.end());
+ } else {
+ printKVPairs(o.items().begin(), o.items().end());
}
outdent();
newline();
, encode_non_ascii(false)
, validate_utf8(false)
, allow_trailing_comma(false)
+ , sort_keys(false)
{}
// If true, keys in an object can be non-strings. (In strict
// Allow trailing comma in lists of values / items
bool allow_trailing_comma;
+
+ // Sort keys of all objects before printing out (potentially slow)
+ bool sort_keys;
};
/*
EXPECT_EQ(1.5, dval.items().begin()->first.asDouble());
}
+TEST(Json, SortKeys) {
+ folly::json::serialization_opts opts_on, opts_off;
+ opts_on.sort_keys = true;
+ opts_off.sort_keys = false;
+
+ dynamic value = dynamic::object
+ ("foo", "bar")
+ ("junk", 12)
+ ("another", 32.2)
+ ("a",
+ {
+ dynamic::object("a", "b")
+ ("c", "d"),
+ 12.5,
+ "Yo Dawg",
+ { "heh" },
+ nullptr
+ }
+ )
+ ;
+
+ std::string sorted_keys =
+ R"({"a":[{"a":"b","c":"d"},12.5,"Yo Dawg",["heh"],null],)"
+ R"("another":32.2,"foo":"bar","junk":12})";
+
+ EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_on)));
+ EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_off)));
+
+ EXPECT_EQ(sorted_keys, folly::json::serialize(value, opts_on));
+}
+
BENCHMARK(jsonSerialize, iters) {
folly::json::serialization_opts opts;
for (int i = 0; i < iters; ++i) {