Skip to content

Commit c995030

Browse files
committed
unflatten
1 parent c970175 commit c995030

File tree

2 files changed

+32
-216
lines changed

2 files changed

+32
-216
lines changed

include/jsoncons_ext/jsonpointer/jsonpointer.hpp

Lines changed: 10 additions & 208 deletions
Original file line numberDiff line numberDiff line change
@@ -1336,206 +1336,8 @@ namespace jsonpointer {
13361336

13371337
enum class unflatten_options {none,assume_object = 1};
13381338

1339-
#if 0
1340-
template <typename Json>
1341-
Json safe_unflatten (Json& value)
1342-
{
1343-
using char_type = typename Json::char_type;
1344-
1345-
if (!value.is_object() || value.empty())
1346-
{
1347-
return value;
1348-
}
1349-
bool safe = true;
1350-
std::size_t index = 0;
1351-
for (const auto& item : value.object_range())
1352-
{
1353-
std::size_t n;
1354-
auto r = jsoncons::utility::dec_to_integer(item.key().data(),item.key().size(), n);
1355-
if (!r || (index++ != n))
1356-
{
1357-
safe = false;
1358-
break;
1359-
}
1360-
}
1361-
1362-
if (safe)
1363-
{
1364-
using value_type = std::pair<std::basic_string<char_type>,Json*>;
1365-
std::vector<value_type> temp;
1366-
Json j(json_array_arg);
1367-
j.reserve(value.size());
1368-
for (auto& item : value.object_range())
1369-
{
1370-
basic_json_pointer<char_type> jptr(item.key());
1371-
temp.push_back(std::make_pair(jptr.back(), &item.value()));
1372-
j.emplace_back(std::move(item.value()));
1373-
}
1374-
std::sort(temp.begin(), temp.end(), [](const value_type& a, const value_type& b)
1375-
{if (a.first.size() < b.first.size()) return true; if (a.first.size() > b.first.size()) return false; return a.first < b.first;}
1376-
);
1377-
Json a(json_array_arg);
1378-
for (auto& item : j.array_range())
1379-
{
1380-
a.emplace_back(safe_unflatten (item));
1381-
}
1382-
return a;
1383-
}
1384-
else
1385-
{
1386-
Json o(json_object_arg);
1387-
for (auto& item : value.object_range())
1388-
{
1389-
o.try_emplace(item.key(), safe_unflatten (item.value()));
1390-
}
1391-
return o;
1392-
}
1393-
}
1394-
1395-
template <typename Json>
1396-
jsoncons::optional<Json> try_unflatten_array(const Json& value)
1397-
{
1398-
using char_type = typename Json::char_type;
1399-
using string_type = typename basic_json_pointer<char_type>::string_type;
1400-
1401-
std::size_t max_depth{0};
1402-
std::vector<basic_json_pointer<char_type>> tokens;
1403-
for (const auto& item : value.object_range())
1404-
{
1405-
tokens.push_back(basic_json_pointer<char_type>{item.key()});
1406-
if (tokens.back().tokens().size() > max_depth)
1407-
{
1408-
max_depth = tokens.back().tokens().size();
1409-
}
1410-
}
1411-
1412-
auto tokens_ptr = tokens.begin();
1413-
for (const auto& item : value.object_range())
1414-
{
1415-
auto first = tokens_ptr->begin()->begin();
1416-
auto penultimate = first + (tokens_ptr->begin()->size() - 1);
1417-
auto last = tokens_ptr->begin()->end();
1418-
1419-
1420-
1421-
++tokens_ptr;
1422-
}
1423-
1424-
if (JSONCONS_UNLIKELY(!value.is_object()))
1425-
{
1426-
JSONCONS_THROW(jsonpointer_error(jsonpointer_errc::argument_to_unflatten_invalid));
1427-
}
1428-
1429-
Json result; // why not array
1430-
1431-
for (const auto& item: value.object_range())
1432-
{
1433-
Json* part = &result;
1434-
basic_json_pointer<char_type> ptr(item.key());
1435-
std::size_t index = 0;
1436-
for (auto it = ptr.begin(); it != ptr.end(); )
1437-
{
1438-
const auto& s = *it;
1439-
std::size_t n{0};
1440-
auto r = jsoncons::utility::dec_to_integer(s.data(), s.size(), n);
1441-
if (r.ec == std::errc{} && (index++ == n))
1442-
{
1443-
if (!part->is_array())
1444-
{
1445-
*part = Json(json_array_arg);
1446-
}
1447-
if (++it != ptr.end())
1448-
{
1449-
if (n+1 > part->size())
1450-
{
1451-
Json& ref = part->emplace_back();
1452-
part = std::addressof(ref);
1453-
}
1454-
else
1455-
{
1456-
part = &part->at(n);
1457-
}
1458-
}
1459-
else
1460-
{
1461-
Json& ref = part->emplace_back(item.value());
1462-
part = std::addressof(ref);
1463-
}
1464-
}
1465-
else if (part->is_object())
1466-
{
1467-
if (++it != ptr.end())
1468-
{
1469-
auto res = part->try_emplace(s,Json());
1470-
part = &(res.first->value());
1471-
}
1472-
else
1473-
{
1474-
auto res = part->try_emplace(s, item.value());
1475-
part = &(res.first->value());
1476-
}
1477-
}
1478-
else
1479-
{
1480-
return jsoncons::optional<Json>();
1481-
}
1482-
}
1483-
}
1484-
1485-
return result;
1486-
}
1487-
1488-
template <typename Json>
1489-
Json unflatten_to_object(const Json& value, unflatten_options options = unflatten_options::none)
1490-
{
1491-
using char_type = typename Json::char_type;
1492-
1493-
if (JSONCONS_UNLIKELY(!value.is_object()))
1494-
{
1495-
JSONCONS_THROW(jsonpointer_error(jsonpointer_errc::argument_to_unflatten_invalid));
1496-
}
1497-
Json result;
1498-
1499-
for (const auto& item: value.object_range())
1500-
{
1501-
Json* part = &result;
1502-
basic_json_pointer<char_type> ptr(item.key());
1503-
for (auto it = ptr.begin(); it != ptr.end(); )
1504-
{
1505-
auto s = *it;
1506-
if (++it != ptr.end())
1507-
{
1508-
auto res = part->try_emplace(s,Json());
1509-
part = &(res.first->value());
1510-
}
1511-
else
1512-
{
1513-
auto res = part->try_emplace(s, item.value());
1514-
part = &(res.first->value());
1515-
}
1516-
}
1517-
}
1518-
1519-
return options == unflatten_options::none ? safe_unflatten (result) : result;
1520-
}
1521-
1522-
template <typename Json>
1523-
Json unflatten(const Json& value, unflatten_options options = unflatten_options::none)
1524-
{
1525-
if (options == unflatten_options::none)
1526-
{
1527-
jsoncons::optional<Json> j = try_unflatten_array(value);
1528-
return j ? *j : unflatten_to_object(value,options);
1529-
}
1530-
else
1531-
{
1532-
return unflatten_to_object(value,options);
1533-
}
1534-
}
1535-
#endif
1536-
15371339
template <typename Iterator,typename StringT>
1538-
Iterator find_last(Iterator first, Iterator last, std::size_t offset, const StringT& token)
1340+
Iterator find_inner_last(Iterator first, Iterator last, std::size_t offset, const StringT& token)
15391341
{
15401342
Iterator it = first;
15411343
while (it != last && *(it->first.tokens().begin() + offset) == token)
@@ -1568,13 +1370,13 @@ namespace jsonpointer {
15681370
}
15691371
else
15701372
{
1571-
auto last2 = find_last(it, last, offset, *jt);
1373+
auto inner_last = find_inner_last(it, last, offset, *jt);
15721374
if (options == unflatten_options{})
15731375
{
1574-
auto res = try_unflatten_array<Json,Iterator>(it, last2, offset+1);
1376+
auto res = try_unflatten_array<Json,Iterator>(it, inner_last, offset+1);
15751377
if (!res)
15761378
{
1577-
jo.try_emplace(*jt, unflatten_object<Json,Iterator>(it, last2, offset+1, options));
1379+
jo.try_emplace(*jt, unflatten_object<Json,Iterator>(it, inner_last, offset+1, options));
15781380
}
15791381
else
15801382
{
@@ -1583,9 +1385,9 @@ namespace jsonpointer {
15831385
}
15841386
else
15851387
{
1586-
jo.try_emplace(*jt, unflatten_object<Json,Iterator>(it, last2, offset+1, options));
1388+
jo.try_emplace(*jt, unflatten_object<Json,Iterator>(it, inner_last, offset+1, options));
15871389
}
1588-
it = last2;
1390+
it = inner_last;
15891391
}
15901392
}
15911393
return jsoncons::optional<Json>{std::move(jo)};
@@ -1618,17 +1420,17 @@ namespace jsonpointer {
16181420
}
16191421
else
16201422
{
1621-
auto last2 = find_last(it, last, offset, *jt);
1622-
auto res = try_unflatten_array<Json,Iterator>(it, last2, offset+1);
1423+
auto inner_last = find_inner_last(it, last, offset, *jt);
1424+
auto res = try_unflatten_array<Json,Iterator>(it, inner_last, offset+1);
16231425
if (!res)
16241426
{
1625-
m.emplace(std::make_pair(n,unflatten_object<Json,Iterator>(it, last2, offset+1, unflatten_options{})));
1427+
m.emplace(std::make_pair(n,unflatten_object<Json,Iterator>(it, inner_last, offset+1, unflatten_options{})));
16261428
}
16271429
else
16281430
{
16291431
m.emplace(std::make_pair(n,std::move(*res)));
16301432
}
1631-
it = last2;
1433+
it = inner_last;
16321434
}
16331435
}
16341436

test/jsonpointer/src/jsonpointer_flatten_tests.cpp

Lines changed: 22 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,20 @@ TEST_CASE("jsonpointer flatten/unflatten test")
245245
json flattened = jsonpointer::flatten(input);
246246
json unflattened = jsonpointer::unflatten(flattened);
247247

248+
//std::cout << unflattened << "\n";
249+
CHECK(input == unflattened);
250+
}
251+
SECTION("test2")
252+
{
253+
json input = json::parse(R"(
254+
{
255+
"arr": ["0", "1", "2", "3", "4", "5", "6","7","8", "9", "10", "11"]
256+
}
257+
)");
258+
259+
json flattened = jsonpointer::flatten(input);
260+
json unflattened = jsonpointer::unflatten(flattened);
261+
248262
//std::cout << unflattened << "\n";
249263
CHECK(input == unflattened);
250264
}
@@ -276,13 +290,13 @@ TEST_CASE("jsonpointer unflatten tests 3")
276290
]
277291
)");
278292

279-
std::cout << "(1) " << input << "\n";
280-
std::cout << "(2) " << flattened << "\n";
293+
//std::cout << "(1) " << input << "\n";
294+
//std::cout << "(2) " << flattened << "\n";
281295

282296
json unflattened = jsonpointer::unflatten(flattened);
283297
CHECK(expected == unflattened);
284-
std::cout << "(3) " << unflattened << "\n";
285-
std::cout << "(4) " << expected << "\n";
298+
//std::cout << "(3) " << unflattened << "\n";
299+
//std::cout << "(4) " << expected << "\n";
286300
}
287301
SECTION("default test 2")
288302
{
@@ -301,13 +315,13 @@ TEST_CASE("jsonpointer unflatten tests 3")
301315
]
302316
)");
303317

304-
std::cout << "(1) " << input << "\n";
305-
std::cout << "(2) " << flattened << "\n";
318+
//std::cout << "(1) " << input << "\n";
319+
//std::cout << "(2) " << flattened << "\n";
306320

307321
json unflattened = jsonpointer::unflatten(flattened);
308322
CHECK(expected == unflattened);
309-
std::cout << "(3) " << unflattened << "\n";
310-
std::cout << "(4) " << expected << "\n";
323+
//std::cout << "(3) " << unflattened << "\n";
324+
//std::cout << "(4) " << expected << "\n";
311325
}
312326
}
313327

0 commit comments

Comments
 (0)