implemented deflatten function
This commit is contained in:
parent
007359675b
commit
f834965b44
3 changed files with 177 additions and 2 deletions
81
src/json.hpp
81
src/json.hpp
|
@ -8855,7 +8855,6 @@ basic_json_parser_63:
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// return referenced value
|
|
||||||
reference get(reference j) const
|
reference get(reference j) const
|
||||||
{
|
{
|
||||||
pointer result = &j;
|
pointer result = &j;
|
||||||
|
@ -8880,6 +8879,49 @@ basic_json_parser_63:
|
||||||
return *result;
|
return *result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reference get2(reference j) const
|
||||||
|
{
|
||||||
|
pointer result = &j;
|
||||||
|
|
||||||
|
for (const auto& reference_token : reference_tokens)
|
||||||
|
{
|
||||||
|
switch (result->m_type)
|
||||||
|
{
|
||||||
|
case value_t::null:
|
||||||
|
{
|
||||||
|
if (reference_token == "0")
|
||||||
|
{
|
||||||
|
result = &result->operator[](0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = &result->operator[](reference_token);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::object:
|
||||||
|
{
|
||||||
|
result = &result->operator[](reference_token);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::array:
|
||||||
|
{
|
||||||
|
result = &result->operator[](static_cast<size_t>(std::stoi(reference_token)));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
throw std::domain_error("unresolved reference token '" + reference_token + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *result;
|
||||||
|
}
|
||||||
|
|
||||||
const_reference get(const_reference j) const
|
const_reference get(const_reference j) const
|
||||||
{
|
{
|
||||||
const_pointer result = &j;
|
const_pointer result = &j;
|
||||||
|
@ -9042,6 +9084,35 @@ basic_json_parser_63:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@param[in] value flattened JSON
|
||||||
|
|
||||||
|
@return deflattened JSON
|
||||||
|
*/
|
||||||
|
static basic_json deflatten(const basic_json& value)
|
||||||
|
{
|
||||||
|
if (not value.is_object())
|
||||||
|
{
|
||||||
|
throw std::domain_error("only objects can be deflattened");
|
||||||
|
}
|
||||||
|
|
||||||
|
basic_json result;
|
||||||
|
|
||||||
|
// iterate the JSON object values
|
||||||
|
for (const auto& element : *value.m_value.object)
|
||||||
|
{
|
||||||
|
if (not element.second.is_primitive())
|
||||||
|
{
|
||||||
|
throw std::domain_error("values in object must be primitive");
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign value to reference pointed to by JSON pointer
|
||||||
|
json_pointer(element.first).get2(result) = element.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -9053,6 +9124,14 @@ basic_json_parser_63:
|
||||||
json_pointer::flatten("", *this, result);
|
json_pointer::flatten("", *this, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@return the original JSON from a flattened version
|
||||||
|
*/
|
||||||
|
basic_json deflatten() const
|
||||||
|
{
|
||||||
|
return json_pointer::deflatten(*this);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8165,7 +8165,6 @@ class basic_json
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
/// return referenced value
|
|
||||||
reference get(reference j) const
|
reference get(reference j) const
|
||||||
{
|
{
|
||||||
pointer result = &j;
|
pointer result = &j;
|
||||||
|
@ -8190,6 +8189,49 @@ class basic_json
|
||||||
return *result;
|
return *result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
reference get2(reference j) const
|
||||||
|
{
|
||||||
|
pointer result = &j;
|
||||||
|
|
||||||
|
for (const auto& reference_token : reference_tokens)
|
||||||
|
{
|
||||||
|
switch (result->m_type)
|
||||||
|
{
|
||||||
|
case value_t::null:
|
||||||
|
{
|
||||||
|
if (reference_token == "0")
|
||||||
|
{
|
||||||
|
result = &result->operator[](0);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = &result->operator[](reference_token);
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::object:
|
||||||
|
{
|
||||||
|
result = &result->operator[](reference_token);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::array:
|
||||||
|
{
|
||||||
|
result = &result->operator[](static_cast<size_t>(std::stoi(reference_token)));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
throw std::domain_error("unresolved reference token '" + reference_token + "'");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return *result;
|
||||||
|
}
|
||||||
|
|
||||||
const_reference get(const_reference j) const
|
const_reference get(const_reference j) const
|
||||||
{
|
{
|
||||||
const_pointer result = &j;
|
const_pointer result = &j;
|
||||||
|
@ -8352,6 +8394,35 @@ class basic_json
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@param[in] value flattened JSON
|
||||||
|
|
||||||
|
@return deflattened JSON
|
||||||
|
*/
|
||||||
|
static basic_json deflatten(const basic_json& value)
|
||||||
|
{
|
||||||
|
if (not value.is_object())
|
||||||
|
{
|
||||||
|
throw std::domain_error("only objects can be deflattened");
|
||||||
|
}
|
||||||
|
|
||||||
|
basic_json result;
|
||||||
|
|
||||||
|
// iterate the JSON object values
|
||||||
|
for (const auto& element : *value.m_value.object)
|
||||||
|
{
|
||||||
|
if (not element.second.is_primitive())
|
||||||
|
{
|
||||||
|
throw std::domain_error("values in object must be primitive");
|
||||||
|
}
|
||||||
|
|
||||||
|
// assign value to reference pointed to by JSON pointer
|
||||||
|
json_pointer(element.first).get2(result) = element.second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -8363,6 +8434,14 @@ class basic_json
|
||||||
json_pointer::flatten("", *this, result);
|
json_pointer::flatten("", *this, result);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@return the original JSON from a flattened version
|
||||||
|
*/
|
||||||
|
basic_json deflatten() const
|
||||||
|
{
|
||||||
|
return json_pointer::deflatten(*this);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12213,7 +12213,24 @@ TEST_CASE("JSON pointers")
|
||||||
{"/object/~01", "tilde1"}
|
{"/object/~01", "tilde1"}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// check if flattened result is as expected
|
||||||
CHECK(j.flatten() == j_flatten);
|
CHECK(j.flatten() == j_flatten);
|
||||||
|
|
||||||
|
// check if deflattened result is as expected
|
||||||
|
CHECK(j_flatten.deflatten() == j);
|
||||||
|
|
||||||
|
// explicit roundtrip check
|
||||||
|
CHECK(j.flatten().deflatten() == j);
|
||||||
|
|
||||||
|
// roundtrip for primitive values
|
||||||
|
json j_null;
|
||||||
|
CHECK(j_null.flatten().deflatten() == j_null);
|
||||||
|
json j_number = 42;
|
||||||
|
CHECK(j_number.flatten().deflatten() == j_number);
|
||||||
|
json j_boolean = false;
|
||||||
|
CHECK(j_boolean.flatten().deflatten() == j_boolean);
|
||||||
|
json j_string = "foo";
|
||||||
|
CHECK(j_string.flatten().deflatten() == j_string);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue