very first draft of a JSON pointer API

This commit is contained in:
Niels 2016-04-11 23:17:03 +02:00
parent 507322e6f2
commit 726051e9b7
3 changed files with 175 additions and 0 deletions

View file

@ -8844,6 +8844,79 @@ basic_json_parser_64:
/// the lexer
lexer m_lexer;
};
public:
class json_pointer
{
public:
/// empty reference token
json_pointer() = default;
/// nonempty reference token
json_pointer(const std::string& s)
{
split(s);
}
/// return referenced value
reference get(reference j)
{
reference result = j;
for (const auto& reference_token : reference_tokens)
{
switch (result.m_type)
{
case value_t::object:
result = result[reference_token];
continue;
case value_t::array:
result = result[std::stoi(reference_token)];
continue;
default:
throw std::domain_error("unresolved reference token '" + reference_token + "'");
}
}
return result;
}
private:
/// the reference tokens
std::vector<std::string> reference_tokens {};
/// split the string input to reference tokens
void split(std::string reference_string)
{
// special case: empty reference string -> no reference tokens
if (reference_string.empty())
{
return;
}
// check if nonempty reference string begins with slash
if (reference_string[0] != '/')
{
throw std::domain_error("JSON pointer must be empty or begin with '/'");
}
// tokenize reference string
auto ptr = std::strtok(&reference_string[0], "/");
while (ptr != nullptr)
{
reference_tokens.push_back(ptr);
ptr = std::strtok(NULL, "/");
}
// special case: reference string was just "/"
if (reference_tokens.empty())
{
reference_tokens.push_back("");
}
}
};
};

View file

@ -8123,6 +8123,79 @@ class basic_json
/// the lexer
lexer m_lexer;
};
public:
class json_pointer
{
public:
/// empty reference token
json_pointer() = default;
/// nonempty reference token
json_pointer(const std::string& s)
{
split(s);
}
/// return referenced value
reference get(reference j)
{
reference result = j;
for (const auto& reference_token : reference_tokens)
{
switch (result.m_type)
{
case value_t::object:
result = result[reference_token];
continue;
case value_t::array:
result = result[std::stoi(reference_token)];
continue;
default:
throw std::domain_error("unresolved reference token '" + reference_token + "'");
}
}
return result;
}
private:
/// the reference tokens
std::vector<std::string> reference_tokens {};
/// split the string input to reference tokens
void split(std::string reference_string)
{
// special case: empty reference string -> no reference tokens
if (reference_string.empty())
{
return;
}
// check if nonempty reference string begins with slash
if (reference_string[0] != '/')
{
throw std::domain_error("JSON pointer must be empty or begin with '/'");
}
// tokenize reference string
auto ptr = std::strtok(&reference_string[0], "/");
while (ptr != nullptr)
{
reference_tokens.push_back(ptr);
ptr = std::strtok(NULL, "/");
}
// special case: reference string was just "/"
if (reference_tokens.empty())
{
reference_tokens.push_back("");
}
}
};
};

View file

@ -12052,6 +12052,35 @@ TEST_CASE("Unicode", "[hide]")
}
}
TEST_CASE("JSON pointers")
{
SECTION("examples from RFC 6901")
{
json j = R"(
{
"foo": ["bar", "baz"],
"": 0,
"a/b": 1,
"c%d": 2,
"e^f": 3,
"g|h": 4,
"i\\j": 5,
"k\"l": 6,
" ": 7,
"m~n": 8
}
)"_json;
json::json_pointer jp0("");
json::json_pointer jp1("/foo");
//json::json_pointer jp2("/foo/0");
auto jp0_ = jp0.get(j);
auto jp1_ = jp1.get(j);
//auto jp2_ = jp2.get(j);
}
}
TEST_CASE("regression tests")
{
SECTION("issue #60 - Double quotation mark is not parsed correctly")