added a flatten function
This commit is contained in:
parent
3401954f5b
commit
007359675b
3 changed files with 217 additions and 52 deletions
111
src/json.hpp
111
src/json.hpp
|
@ -8907,32 +8907,6 @@ basic_json_parser_63:
|
||||||
/// the reference tokens
|
/// the reference tokens
|
||||||
std::vector<std::string> reference_tokens {};
|
std::vector<std::string> reference_tokens {};
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief replace all occurrences of a substring by another string
|
|
||||||
|
|
||||||
@param[in,out] s the string to manipulate
|
|
||||||
@param[in] f the substring to replace with @a t
|
|
||||||
@param[out] t the string to replace @a f
|
|
||||||
|
|
||||||
@return The string @a s where all occurrences of @a f are replaced
|
|
||||||
with @a t.
|
|
||||||
|
|
||||||
@pre The search string @a f must not be empty.
|
|
||||||
*/
|
|
||||||
static void replace_substring(std::string& s,
|
|
||||||
const std::string& f,
|
|
||||||
const std::string& t)
|
|
||||||
{
|
|
||||||
assert(not f.empty());
|
|
||||||
|
|
||||||
for (
|
|
||||||
size_t pos = s.find(f); // find first occurrence of f
|
|
||||||
pos != std::string::npos; // make sure f was found
|
|
||||||
s.replace(pos, f.size(), t), // replace with t
|
|
||||||
pos = s.find(f, pos + t.size()) // find next occurrence of f
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// split the string input to reference tokens
|
/// split the string input to reference tokens
|
||||||
void split(std::string reference_string)
|
void split(std::string reference_string)
|
||||||
{
|
{
|
||||||
|
@ -8993,7 +8967,92 @@ basic_json_parser_63:
|
||||||
reference_tokens.push_back(reference_token);
|
reference_tokens.push_back(reference_token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief replace all occurrences of a substring by another string
|
||||||
|
|
||||||
|
@param[in,out] s the string to manipulate
|
||||||
|
@param[in] f the substring to replace with @a t
|
||||||
|
@param[out] t the string to replace @a f
|
||||||
|
|
||||||
|
@return The string @a s where all occurrences of @a f are replaced
|
||||||
|
with @a t.
|
||||||
|
|
||||||
|
@pre The search string @a f must not be empty.
|
||||||
|
|
||||||
|
@since version 2.0.0
|
||||||
|
*/
|
||||||
|
static void replace_substring(std::string& s,
|
||||||
|
const std::string& f,
|
||||||
|
const std::string& t)
|
||||||
|
{
|
||||||
|
assert(not f.empty());
|
||||||
|
|
||||||
|
for (
|
||||||
|
size_t pos = s.find(f); // find first occurrence of f
|
||||||
|
pos != std::string::npos; // make sure f was found
|
||||||
|
s.replace(pos, f.size(), t), // replace with t
|
||||||
|
pos = s.find(f, pos + t.size()) // find next occurrence of f
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@param[in] reference_string the reference string to the current value
|
||||||
|
@param[in] value the value to consider
|
||||||
|
@param[in,out] result the result object to insert values to
|
||||||
|
*/
|
||||||
|
static void flatten(const std::string reference_string,
|
||||||
|
const basic_json& value,
|
||||||
|
basic_json& result)
|
||||||
|
{
|
||||||
|
switch (value.m_type)
|
||||||
|
{
|
||||||
|
case value_t::array:
|
||||||
|
{
|
||||||
|
// iterate array and use index as reference string
|
||||||
|
for (size_t i = 0; i < value.m_value.array->size(); ++i)
|
||||||
|
{
|
||||||
|
flatten(reference_string + "/" + std::to_string(i),
|
||||||
|
value.m_value.array->operator[](i), result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::object:
|
||||||
|
{
|
||||||
|
// iterate object and use keys as reference string
|
||||||
|
for (const auto& element : *value.m_value.object)
|
||||||
|
{
|
||||||
|
// escape "~"" to "~0" and "/" to "~1"
|
||||||
|
std::string key(element.first);
|
||||||
|
replace_substring(key, "~", "~0");
|
||||||
|
replace_substring(key, "/", "~1");
|
||||||
|
|
||||||
|
flatten(reference_string + "/" + key,
|
||||||
|
element.second, result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// add primitive value with its reference string
|
||||||
|
result[reference_string] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@return an object that maps JSON pointers to primitve values
|
||||||
|
*/
|
||||||
|
basic_json flatten() const
|
||||||
|
{
|
||||||
|
basic_json result(value_t::object);
|
||||||
|
json_pointer::flatten("", *this, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8217,32 +8217,6 @@ class basic_json
|
||||||
/// the reference tokens
|
/// the reference tokens
|
||||||
std::vector<std::string> reference_tokens {};
|
std::vector<std::string> reference_tokens {};
|
||||||
|
|
||||||
/*!
|
|
||||||
@brief replace all occurrences of a substring by another string
|
|
||||||
|
|
||||||
@param[in,out] s the string to manipulate
|
|
||||||
@param[in] f the substring to replace with @a t
|
|
||||||
@param[out] t the string to replace @a f
|
|
||||||
|
|
||||||
@return The string @a s where all occurrences of @a f are replaced
|
|
||||||
with @a t.
|
|
||||||
|
|
||||||
@pre The search string @a f must not be empty.
|
|
||||||
*/
|
|
||||||
static void replace_substring(std::string& s,
|
|
||||||
const std::string& f,
|
|
||||||
const std::string& t)
|
|
||||||
{
|
|
||||||
assert(not f.empty());
|
|
||||||
|
|
||||||
for (
|
|
||||||
size_t pos = s.find(f); // find first occurrence of f
|
|
||||||
pos != std::string::npos; // make sure f was found
|
|
||||||
s.replace(pos, f.size(), t), // replace with t
|
|
||||||
pos = s.find(f, pos + t.size()) // find next occurrence of f
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// split the string input to reference tokens
|
/// split the string input to reference tokens
|
||||||
void split(std::string reference_string)
|
void split(std::string reference_string)
|
||||||
{
|
{
|
||||||
|
@ -8303,7 +8277,92 @@ class basic_json
|
||||||
reference_tokens.push_back(reference_token);
|
reference_tokens.push_back(reference_token);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@brief replace all occurrences of a substring by another string
|
||||||
|
|
||||||
|
@param[in,out] s the string to manipulate
|
||||||
|
@param[in] f the substring to replace with @a t
|
||||||
|
@param[out] t the string to replace @a f
|
||||||
|
|
||||||
|
@return The string @a s where all occurrences of @a f are replaced
|
||||||
|
with @a t.
|
||||||
|
|
||||||
|
@pre The search string @a f must not be empty.
|
||||||
|
|
||||||
|
@since version 2.0.0
|
||||||
|
*/
|
||||||
|
static void replace_substring(std::string& s,
|
||||||
|
const std::string& f,
|
||||||
|
const std::string& t)
|
||||||
|
{
|
||||||
|
assert(not f.empty());
|
||||||
|
|
||||||
|
for (
|
||||||
|
size_t pos = s.find(f); // find first occurrence of f
|
||||||
|
pos != std::string::npos; // make sure f was found
|
||||||
|
s.replace(pos, f.size(), t), // replace with t
|
||||||
|
pos = s.find(f, pos + t.size()) // find next occurrence of f
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@param[in] reference_string the reference string to the current value
|
||||||
|
@param[in] value the value to consider
|
||||||
|
@param[in,out] result the result object to insert values to
|
||||||
|
*/
|
||||||
|
static void flatten(const std::string reference_string,
|
||||||
|
const basic_json& value,
|
||||||
|
basic_json& result)
|
||||||
|
{
|
||||||
|
switch (value.m_type)
|
||||||
|
{
|
||||||
|
case value_t::array:
|
||||||
|
{
|
||||||
|
// iterate array and use index as reference string
|
||||||
|
for (size_t i = 0; i < value.m_value.array->size(); ++i)
|
||||||
|
{
|
||||||
|
flatten(reference_string + "/" + std::to_string(i),
|
||||||
|
value.m_value.array->operator[](i), result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case value_t::object:
|
||||||
|
{
|
||||||
|
// iterate object and use keys as reference string
|
||||||
|
for (const auto& element : *value.m_value.object)
|
||||||
|
{
|
||||||
|
// escape "~"" to "~0" and "/" to "~1"
|
||||||
|
std::string key(element.first);
|
||||||
|
replace_substring(key, "~", "~0");
|
||||||
|
replace_substring(key, "/", "~1");
|
||||||
|
|
||||||
|
flatten(reference_string + "/" + key,
|
||||||
|
element.second, result);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// add primitive value with its reference string
|
||||||
|
result[reference_string] = value;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*!
|
||||||
|
@return an object that maps JSON pointers to primitve values
|
||||||
|
*/
|
||||||
|
basic_json flatten() const
|
||||||
|
{
|
||||||
|
basic_json result(value_t::object);
|
||||||
|
json_pointer::flatten("", *this, result);
|
||||||
|
return result;
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -12168,6 +12168,53 @@ TEST_CASE("JSON pointers")
|
||||||
CHECK_THROWS_WITH(json::json_pointer("/~"), "escape error: '~' must be followed with '0' or '1'");
|
CHECK_THROWS_WITH(json::json_pointer("/~"), "escape error: '~' must be followed with '0' or '1'");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SECTION("flatten")
|
||||||
|
{
|
||||||
|
json j =
|
||||||
|
{
|
||||||
|
{"pi", 3.141},
|
||||||
|
{"happy", true},
|
||||||
|
{"name", "Niels"},
|
||||||
|
{"nothing", nullptr},
|
||||||
|
{
|
||||||
|
"answer", {
|
||||||
|
{"everything", 42}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
{"list", {1, 0, 2}},
|
||||||
|
{
|
||||||
|
"object", {
|
||||||
|
{"currency", "USD"},
|
||||||
|
{"value", 42.99},
|
||||||
|
{"", "empty string"},
|
||||||
|
{"/", "slash"},
|
||||||
|
{"~", "tilde"},
|
||||||
|
{"~1", "tilde1"}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
json j_flatten =
|
||||||
|
{
|
||||||
|
{"/pi", 3.141},
|
||||||
|
{"/happy", true},
|
||||||
|
{"/name", "Niels"},
|
||||||
|
{"/nothing", nullptr},
|
||||||
|
{"/answer/everything", 42},
|
||||||
|
{"/list/0", 1},
|
||||||
|
{"/list/1", 0},
|
||||||
|
{"/list/2", 2},
|
||||||
|
{"/object/currency", "USD"},
|
||||||
|
{"/object/value", 42.99},
|
||||||
|
{"/object/", "empty string"},
|
||||||
|
{"/object/~1", "slash"},
|
||||||
|
{"/object/~0", "tilde"},
|
||||||
|
{"/object/~01", "tilde1"}
|
||||||
|
};
|
||||||
|
|
||||||
|
CHECK(j.flatten() == j_flatten);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_CASE("regression tests")
|
TEST_CASE("regression tests")
|
||||||
|
|
Loading…
Reference in a new issue