Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enormous array created when working with map<int,T> #2220

Closed
2 tasks done
ralwing opened this issue Jun 25, 2020 · 3 comments
Closed
2 tasks done

Enormous array created when working with map<int,T> #2220

ralwing opened this issue Jun 25, 2020 · 3 comments
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@ralwing
Copy link

ralwing commented Jun 25, 2020

When json array object is indexed with some numeric value it creates an array containing nulls, and one single value.

#include <nlohmann/json.hpp>
#include <boost/container/flat_map.hpp>
#include <iostream>

int main()
{
    boost::container::flat_map<int, int> elems;
    elems.emplace(1000000, 2);
    nlohmann::json json;
    for (const auto& point : elems)
    {
        json["data"][point.first] = point.second;
    }
    std::cout << json.dump(2);
}

Which outputs:

{
  "data": [
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null,
    null
[...]

LiveExample

What is the expected behavior?

The value map should be created inside instead.

  • Compiler: MS VS, clang
  • Operating system: windows

Which version of the library did you use?

  • latest release version 3.7.3
  • other release - please state the version: ___
@ralwing ralwing changed the title Enormous array created when working with map<int,X> Enormous array created when working with map<int,T> Jun 25, 2020
@nickaein
Copy link
Contributor

This is expected behavior as you are implicitly creating data as an array.

JSON only allows string keys. Instead, you can try his:

json["data"][std::to_string(point.first)] = point.second;

which outputs:

{
  "data": {
    "1000000": 2
  }
}

@nlohmann nlohmann added kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation and removed kind: bug labels Jun 26, 2020
@ralwing
Copy link
Author

ralwing commented Jun 26, 2020

Thanks for You answer.
But don't You think all arrays should be implemented as a map, thus such cases wouldn't cause errors? Arrays should be created explicitly.

@ralwing ralwing closed this as completed Jun 26, 2020
@nlohmann
Copy link
Owner

But don't You think all arrays should be implemented as a map, thus such cases wouldn't cause errors? Arrays should be created explicitly.

The library treats a JSON value like the combination of a std::vector and a std::map. Both implement operator[]. If you pass a string, we assume a JSON object, and if you pass a number, then we assume a JSON array. As operator[] does not perform bound checking, both implementation must return a reference to the value at the given argument. We decided to implement both like std::map, adding a value at the respective argument. As we cannot only have a vector value at some index, we need to fill all values until that index.

Sorry that this may appear surprising, but these are the reasons for that design decision.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
kind: question solution: proposed fix a fix for the issue has been proposed and waits for confirmation
Projects
None yet
Development

No branches or pull requests

3 participants