out_ += '{';
indent();
newline();
- if (opts_.sort_keys) {
+ if (opts_.sort_keys || opts_.sort_keys_by) {
using ref = std::reference_wrapper<decltype(o.items())::value_type const>;
std::vector<ref> refs(o.items().begin(), o.items().end());
- std::sort(refs.begin(), refs.end(), [](ref a, ref b) {
+
+ using SortByRef = FunctionRef<bool(dynamic const&, dynamic const&)>;
+ auto const& sort_keys_by = opts_.sort_keys_by
+ ? SortByRef(opts_.sort_keys_by)
+ : SortByRef(std::less<dynamic>());
+ std::sort(refs.begin(), refs.end(), [&](ref a, ref b) {
// Only compare keys. No ordering among identical keys.
- return a.get().first < b.get().first;
+ return sort_keys_by(a.get().first, b.get().first);
});
printKVPairs(refs.cbegin(), refs.cend());
} else {
#include <iosfwd>
#include <string>
-#include <folly/dynamic.h>
+#include <folly/Function.h>
#include <folly/Range.h>
+#include <folly/dynamic.h>
namespace folly {
bool allow_trailing_comma;
// Sort keys of all objects before printing out (potentially slow)
+ // using dynamic::operator<.
+ // Has no effect if sort_keys_by is set.
bool sort_keys;
+ // Sort keys of all objects before printing out (potentially slow)
+ // using the provided less functor.
+ Function<bool(dynamic const&, dynamic const&) const> sort_keys_by;
+
// Replace invalid utf8 characters with U+FFFD and continue
bool skip_invalid_utf8;
}
TEST(Json, SortKeys) {
- folly::json::serialization_opts opts_on, opts_off;
+ folly::json::serialization_opts opts_on, opts_off, opts_custom_sort;
opts_on.sort_keys = true;
opts_off.sort_keys = false;
+ opts_custom_sort.sort_keys = false; // should not be required
+ opts_custom_sort.sort_keys_by = [](
+ folly::dynamic const& a, folly::dynamic const& b) {
+ // just an inverse sort
+ return b < a;
+ };
+
dynamic value = dynamic::object
("foo", "bar")
("junk", 12)
R"({"a":[{"a":"b","c":"d"},12.5,"Yo Dawg",["heh"],null],)"
R"("another":32.2,"foo":"bar","junk":12})";
+ std::string inverse_sorted_keys =
+ R"({"junk":12,"foo":"bar","another":32.2,)"
+ R"("a":[{"c":"d","a":"b"},12.5,"Yo Dawg",["heh"],null]})";
+
EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_on)));
EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_off)));
+ EXPECT_EQ(value, parseJson(folly::json::serialize(value, opts_custom_sort)));
EXPECT_EQ(sorted_keys, folly::json::serialize(value, opts_on));
+ EXPECT_NE(sorted_keys, folly::json::serialize(value, opts_off));
+ EXPECT_EQ(
+ inverse_sorted_keys, folly::json::serialize(value, opts_custom_sort));
}
TEST(Json, PrintTo) {