Skip to content

Using STL algorithms with JSON containers with expected results? #1045

Description

@bandzaw

I'd like to use JSON as any other STL container with the same expected results. For example, given this code snippet:

#include <iostream>
#include <map>
#include <algorithm>
#include "json.hpp"


int main()
{
    {
        std::map<std::string,int> diffs;
        std::map<std::string,int> m1{{"key1",42}};
        std::map<std::string,int> m2{{"key2",42}};
        std::set_difference(
            m1.begin(), m1.end(),
            m2.begin(), m2.end(),
        std::inserter(diffs, diffs.end()));
        std::cout << "map diffs: " << diffs.size() << std::endl;
    }
    {
        nlohmann::json diffs = nlohmann::json::array();
        nlohmann::json m1{{"key1",42}};
        nlohmann::json m2{{"key2",42}};
        std::set_difference(
            m1.begin(), m1.end(),
            m2.begin(), m2.end(),
        std::inserter(diffs, diffs.end()));
        std::cout << "json diffs: " << diffs.size() << std::endl;
    }
}

the output is:

map diffs: 1
json diffs: 0

which is not what I expected. I'd really want to be able to compare JSON containers, including their keys.

The reason is that JSON iterators, when dereferenced, only return a reference to the value pointed to by the iterator (compare with std::map returning a std::pair of its key&value).
But then I thought I could use the proxy iterator: iteration_proxy and its key and value methods to work around my problem by writing a custom comparator and use it with std::set_difference:

    {
        nlohmann::json diffs = nlohmann::json::array();
        nlohmann::json m1{{"key1",42}};
        nlohmann::json m2{{"key2",42}};
        auto p1 = m1.items();
        auto p2 = m2.items();
        std::set_difference(
            p1.begin(), p1.end(),
            p2.begin(), p2.end(),
        std::inserter(diffs, diffs.end()),
        [&](const auto& e1, const auto& e2) -> bool {
            return (e1.key() < e2.key()) && (e1.value() < e2.value());
        });
        std::cout << "json diffs: " << diffs.size() << std::endl;
    }

This however, fails to compile. The compiler (g++ 7.2 (on Ubuntu 16.04)) complains that there is no iterator_category or value_type in iteration_proxy_internal. Hmm. From its name, and from the compiler message, I guess the iterator proxy is not an iterator. But, could it easily be extended to support my use case? Or can I solve my problem in another way? Or do I have to resort to writing my own algorithms for the JSON containers?

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

Labels

kind: bugsolution: proposed fixa fix for the issue has been proposed and waits for confirmation

Projects

No projects

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions