nlohmann / json

JSON for Modern C++
https://json.nlohmann.me
MIT License
41.46k stars 6.59k forks source link

json::count returns only 0 or 1 #4052

Closed sgshulman closed 1 year ago

sgshulman commented 1 year ago

Description

json may contain duplicated keys in the object but json::count returns only 0 or 1. We also have json::contains method, which returns true of false. So, these two methods seems to do the same thing.

I use json as a configuration file for my program. Once I had misprint/copy-paste error with json object having duplicated keys. I decided to check the configuration file for duplicated keys in object (to avoid such errors in the future) but discovered that count method does not provide such a possibility.

Reproduction steps

Use count method on json with duplicated keys and check the return value (see code example below).

Expected vs. actual results

count method returns actual number of keys in object, which may exceed 1.

Minimal code example

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

int main()
{
    nlohmann::json json = R"({
        "x": 1,
        "x": 2
    })"_json;

    std::cout << json.count("x") << std::endl; // 1 but 2 is expected
}

Error messages

No response

Compiler and operating system

clang++14

Library version

3.11.2

Validation

nlohmann commented 1 year ago

That is not a bug, but documented behavior: https://json.nlohmann.me/api/basic_json/count

sgshulman commented 1 year ago

Thank you for your answer very much!

Now I see that json using both std::map and nlohman::ordered_map is not able to contain elements with the same name. std::multimap may contain such elements, but do not provide operator[] (operator[] for multimap is a strange thing indeed). It also looks like json::emplace does not support same keys.

I'll have to find a better way to catch such errors.

nlohmann commented 1 year ago

You could use the parser callback mechanism (https://json.nlohmann.me/features/parsing/parser_callbacks/) to check for duplicate keys when you read the config file. I have not done it, but it should work with event parse_event_t::key.

sgshulman commented 1 year ago

Thank you very much for this advice!!!

I made a brief experiment and it seems to work fine. It is a good question, how to implement it effective for a general use case, but in my case a simple class with std::vector<std::set<std::string>> inside may be a reasonable choice.

Great thanks for your library!