mirror of
https://github.com/nlohmann/json.git
synced 2025-01-19 07:43:03 +08:00
very first draft of a JSON pointer API
This commit is contained in:
parent
507322e6f2
commit
726051e9b7
73
src/json.hpp
73
src/json.hpp
@ -8844,6 +8844,79 @@ basic_json_parser_64:
|
|||||||
/// the lexer
|
/// the lexer
|
||||||
lexer m_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
|
/// the lexer
|
||||||
lexer m_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")
|
TEST_CASE("regression tests")
|
||||||
{
|
{
|
||||||
SECTION("issue #60 - Double quotation mark is not parsed correctly")
|
SECTION("issue #60 - Double quotation mark is not parsed correctly")
|
||||||
|
Loading…
Reference in New Issue
Block a user