very first draft of a JSON pointer API
This commit is contained in:
parent
507322e6f2
commit
726051e9b7
3 changed files with 175 additions and 0 deletions
73
src/json.hpp
73
src/json.hpp
|
@ -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("");
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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("");
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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")
|
||||
|
|
Loading…
Reference in a new issue