nlohmann / nlohmann/json

Int and uint compare equal but hashes do not

Open
#5,256 4 comments 0 reactions 0 assignees View on GitHub

@afonsojanu is already working on this.

Since Aug 30, 2026.

  • #5447 by @afonsojanu — open
confirmed kind: bug solution: proposed fix state: please discuss
Dominant language
C++
Stars
50.6k
Forks
7.5k
Avg merge
4d 17h
Merged PRs (30d)
58

Description

Description

On the implementation of std::hash, the C++ specification states:

If k1 == k2 is true, h(k1) == h(k2) is also true

Yet this is not the case for json values of the same numeric value but of signed and unsigned storage types. I can see this behaviour is documented here, but it violates the std::hash contract. While this behaviour is great for distinguishing between the other types, it feels unnatural for it to distinguish between signed and unsigned types.

Reproduction steps
using namespace nlohmann;

int main()
{
    const json a{42};
    const json b{42u};

    assert(a == b);
    assert(std::hash<json>{}(a) == std::hash<json>{}(b));
}
Expected vs. actual results

I would expect assert(std::hash<json>{}(a) == std::hash<json>{}(b)); to succeed because a == b is true, but it actually fails.

I believe the hash<basic_json> implementation should treat signed and unsigned integers the same. This is especially important because the storage type selected by the parser is not specified (currently, see #5255 ).

In all other aspects, signed and unsigned integers are treated the same: there is no distinction made in the JSON standard and they are silently cast between when calling .at() or .get<>().

Minimal code example
// I'd like to be able to write code like this

using namespace nlohmann;

int main()
{
    const json j = R"({"a": 42})"_json;
    const std::unordered_map<json, std::string> m = {{42, "hello"}};
    std::cout << m.at(j.at("a")) << '\n'; // throws std::out_of_range
}
Error messages

Compiler and operating system

GCC 12.2.0, Linux

Library version

3.12.0

Validation

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start at the hash<basic_json> implementation and reproduce the issue with the signed and unsigned 42 examples from the report. Review the linked pull request, then run the relevant unit tests; done means equal json values produce equal hashes and the unordered_map lookup succeeds.

Written by the indexing model from the issue text.

Assessment

Tech stack
cpp
Domain
api
Issue type
Bug
Difficulty
3/5
Estimated time
1-2 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.