Commit 43a79f74 authored by Dylan Yudaken's avatar Dylan Yudaken Committed by Facebook Github Bot

Allow custom sorting function for JSON serializer

Summary: In some situations it is useful to be able to sort the JSON keys according to some different scheme for readability, so allow the sorting function to be changed by the serializer_opts

Reviewed By: yfeldblum

Differential Revision: D4782077

fbshipit-source-id: 032fa60a38804452bd1c22c67ba897521cb2cd1d
parent 5a66fe5d
......@@ -113,12 +113,17 @@ private:
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 {
......
......@@ -43,8 +43,9 @@
#include <iosfwd>
#include <string>
#include <folly/dynamic.h>
#include <folly/Function.h>
#include <folly/Range.h>
#include <folly/dynamic.h>
namespace folly {
......@@ -95,8 +96,14 @@ namespace json {
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;
......
......@@ -438,10 +438,17 @@ TEST(Json, ParseNumbersAsStrings) {
}
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)
......@@ -462,10 +469,18 @@ TEST(Json, SortKeys) {
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) {
......
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