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

init error #92

Closed
likebeta opened this issue Jun 18, 2015 · 4 comments
Closed

init error #92

likebeta opened this issue Jun 18, 2015 · 4 comments

Comments

@likebeta
Copy link
Contributor

code:

#include <iostream>
using namespace std;

#define print(j) cout << " " #j  << ": " << j  << endl

int main(int argc, char** argv)
{
    // case 1
    json j = {
        { "limit", 1000 },
        { "reward", {{ "chip", 1000 },{ "chip", 2000 },{ "chip", 3000 }}}
    };
    print(j);

    // case 2
    j = {
        { "limit", 1000 },
        { "reward", json::array({ { "chip", 1000 }, { "chip", 2000 }, { "chip", 3000 } }) }
    };
    print(j);

    // case 3
    j["limit"] = 1000;
    j["reward"] = json::array({ { "chip", 1000 }, { "chip", 2000 }, { "chip", 3000 } });
    print(j);

    return 0;
}

output:

[king@localhost Project1]$ sh make.sh 
 j: {"limit":1000,"reward":{"chip":1000}}
 j: {"limit":1000,"reward":[["chip",1000],["chip",2000],["chip",3000]]}
 j: {"limit":1000,"reward":[["chip",1000],["chip",2000],["chip",3000]]}

It is strange in case 1, why get this result?

@ropuls
Copy link

ropuls commented Jun 18, 2015

Hi,

in 1), you're initializing the reward with an object type (aka map). This is exactly the same as initializing a map like this:

    std::map<std::string, std::string> m = {
        {"key", "val"},
        {"key", "xxx"}
    };

    printf("%s\n", m["key"].c_str());

the result will be: val, not xxx. This is due to the fact that the map will not replace key's value if it's already present during brace-initialization.

Assuming you want reward to be an array of objects, you would need to:

    json j = {
        { "limit", 1000 },
        { "reward",
          {
              {{ "chip", 1000 }},
              {{ "chip", 2000 }},
              {{ "chip", 3000 }}
          }
        }
    };

which gives you a

{"limit":1000,"reward":[{"chip":1000},{"chip":2000},{"chip":3000}]}

If you want reward to be an array of arrays, then most likely json::array constructs are needed.

Hope it helps,
Roman

@likebeta
Copy link
Contributor Author

Think you very mush. I was hoping for your example, It is very helpful to me.

Now I know the reason. Buf if for some reason, I just want a result as {"limit":1000,"reward":[["chip",1000],["chip",2000],["chip",3000]]}, how to make it? Must I use json::array?

Thanks again

@nlohmann
Copy link
Owner

Hi @likebeta,

the problem is that C++ only supports { and } in initializer lists. For JSON, however, it would be convenient to have two different sets of braces to differentiate between objects and arrays. To this end, I decided to process initializer lists as follows:

  1. If a list contains only elements which are itself lists with two elements and each of the two-element lists has a string as first element, then I treat this as an object.
  2. Anything else is an array.

So in your example {{ "chip", 1000 },{ "chip", 2000 },{ "chip", 3000 }} is exactly an instance of the first rule: the list has three elements, each element is a list of two elements, and each entry has a string as first element. The fact that you use "chip" as key for all elements makes it even more confusing...

So when you want this to be treated as array, you need to tell it explicitly by

json::array({
  { "chip", 1000 }, { "chip", 2000 }, { "chip", 3000 }
})

In fact, this is one of the few situations where you need to help the class to understand what you want.

Sorry for the inconvenience. And thanks to @ropuls for the quick explanation.

Cheers
Niels

@likebeta
Copy link
Contributor Author

@nlohmann @ropuls Think you very mush!

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

No branches or pull requests

3 participants