Repository: mesos Updated Branches: refs/heads/master cfa168f51 -> 7933de5ca
Added a JSON::Object::find. Review: https://reviews.apache.org/r/24541 Project: http://git-wip-us.apache.org/repos/asf/mesos/repo Commit: http://git-wip-us.apache.org/repos/asf/mesos/commit/7933de5c Tree: http://git-wip-us.apache.org/repos/asf/mesos/tree/7933de5c Diff: http://git-wip-us.apache.org/repos/asf/mesos/diff/7933de5c Branch: refs/heads/master Commit: 7933de5ca19974af8b908f643ff2891bd7d8bd80 Parents: cfa168f Author: Benjamin Hindman <[email protected]> Authored: Sun Aug 10 23:49:02 2014 -0700 Committer: Benjamin Hindman <[email protected]> Committed: Mon Aug 11 15:51:05 2014 -0700 ---------------------------------------------------------------------- .../3rdparty/stout/include/stout/json.hpp | 93 ++++++++++++++++++-- .../3rdparty/stout/tests/json_tests.cpp | 56 ++++++++++++ 2 files changed, 140 insertions(+), 9 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/mesos/blob/7933de5c/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp b/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp index 0ce002c..d98d953 100644 --- a/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp +++ b/3rdparty/libprocess/3rdparty/stout/include/stout/json.hpp @@ -22,6 +22,7 @@ #include <list> #include <map> #include <string> +#include <vector> #include <boost/type_traits/is_arithmetic.hpp> #include <boost/utility/enable_if.hpp> @@ -29,6 +30,8 @@ #include <stout/check.hpp> #include <stout/foreach.hpp> +#include <stout/result.hpp> +#include <stout/strings.hpp> #include <stout/try.hpp> #include <stout/unreachable.hpp> @@ -79,6 +82,23 @@ struct Number struct Object { + // Returns the JSON value (specified by the type) given a "path" + // into the structure, for example: + // + // Result<JSON::Array> array = object.find<JSON::Array>("nested.array"); + // + // Will return 'None' if no field could be found called 'array' + // within a field called 'nested' of 'object' (where 'nested' must + // also be a JSON object). + // + // Returns an error if a JSON value of the wrong type is found, or + // an intermediate JSON value is not an object that we can do a + // recursive find on. + // + // TODO(benh): Support paths that index, e.g., 'nested.array[4].field'. + template <typename T> + Result<T> find(const std::string& path) const; + std::map<std::string, Value> values; }; @@ -159,20 +179,75 @@ struct Value : internal::Variant : internal::Variant(value) {} template <typename T> - bool is() const - { - const T* t = boost::get<T>(this); - return t != NULL; - } + bool is() const; template <typename T> - const T& as() const - { - return *CHECK_NOTNULL(boost::get<T>(this)); - } + const T& as() const; }; +template <typename T> +bool Value::is() const +{ + const T* t = boost::get<T>(this); + return t != NULL; +} + + +template <> +inline bool Value::is<Value>() const +{ + return true; +} + + +template <typename T> +const T& Value::as() const +{ + return *CHECK_NOTNULL(boost::get<T>(this)); +} + + +template <> +inline const Value& Value::as<Value>() const +{ + return *this; +} + + + +template <typename T> +Result<T> Object::find(const std::string& path) const +{ + const std::vector<std::string>& names = strings::split(path, ".", 2); + + if (names.empty()) { + return None(); + } + + std::map<std::string, Value>::const_iterator entry = values.find(names[0]); + + if (entry == values.end()) { + return None(); + } + + const Value& value = entry->second; + + if (names.size() == 1) { + if (!value.is<T>()) { + // TODO(benh): Use a visitor to print out the type found. + return Error("Found JSON value of wrong type"); + } + return value.as<T>(); + } else if (!value.is<Object>()) { + // TODO(benh): Use a visitor to print out the intermediate type. + return Error("Intermediate JSON value not an object"); + } + + return value.as<Object>().find<T>(names[1]); +} + + struct Comparator : boost::static_visitor<bool> { Comparator(const Value& _value) http://git-wip-us.apache.org/repos/asf/mesos/blob/7933de5c/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp ---------------------------------------------------------------------- diff --git a/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp b/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp index ee82d15..3bfc8e6 100644 --- a/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp +++ b/3rdparty/libprocess/3rdparty/stout/tests/json_tests.cpp @@ -175,3 +175,59 @@ TEST(JsonTest, parse) EXPECT_SOME_EQ(object, JSON::parse(stringify(object))); } + + +TEST(JsonTest, Find) +{ + JSON::Object object; + + JSON::Object nested1; + + JSON::Object nested2; + nested2.values["string"] = "string"; + nested2.values["integer"] = -1; + nested2.values["double"] = -1.42; + nested2.values["null"] = JSON::Null(); + + JSON::Array array; + array.values.push_back("hello"); + + nested2.values["array"] = array; + + nested1.values["nested2"] = nested2; + + object.values["nested1"] = nested1; + + ASSERT_NONE(object.find<JSON::String>("nested.nested.string")); + ASSERT_NONE(object.find<JSON::String>("nested1.nested2.none")); + + ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array")); + ASSERT_ERROR(object.find<JSON::String>("nested1.nested2.array.foo")); + + ASSERT_SOME_EQ( + JSON::String("string"), + object.find<JSON::String>("nested1.nested2.string")); + + ASSERT_SOME_EQ( + JSON::Number(-1), + object.find<JSON::Number>("nested1.nested2.integer")); + + ASSERT_SOME_EQ( + JSON::Number(-1.42), + object.find<JSON::Number>("nested1.nested2.double")); + + ASSERT_SOME_EQ( + JSON::Null(), + object.find<JSON::Null>("nested1.nested2.null")); + + Result<JSON::Array> result = + object.find<JSON::Array>("nested1.nested2.array"); + + ASSERT_SOME(result); + ASSERT_FALSE(result.get().values.empty()); + ASSERT_TRUE(result.get().values.front().is<JSON::String>()); + ASSERT_EQ("hello", result.get().values.front().as<JSON::String>()); + + // Also test getting JSON::Value when you don't know the type. + ASSERT_SOME(object.find<JSON::Value>("nested1.nested2.null")); +}
