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

Sample code in GIF slide outdated (cannot use emplace() with array) #2457

Closed
1 of 3 tasks
windy32 opened this issue Nov 2, 2020 · 14 comments
Closed
1 of 3 tasks

Sample code in GIF slide outdated (cannot use emplace() with array) #2457

windy32 opened this issue Nov 2, 2020 · 14 comments
Assignees
Labels
documentation kind: bug solution: proposed fix a fix for the issue has been proposed and waits for confirmation

Comments

@windy32
Copy link

windy32 commented Nov 2, 2020

What is the issue you have?

I followed the code in the GIF slide to learn to use the library:

// g++ object.cpp -std=c++11 -o object
#include <iomanip>
#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main()
{
    // create null value
    json j;

    // add via member function
    j.push_back({"key", "value"});
    j.emplace("key2", "value");

    // add via += operator
    j += {"another key", false};

    // add via key
    j["pi"] = 3.1415926;
    j["answer"]["everything"] = 42;

    std::cout << std::setw(4) << j << std::endl;
}

Under ubuntu 20.04 (g++ 9.3.0), the output is like this

$ g++ object.cpp -std=c++11 -o object
$ ./object 
terminate called after throwing an instance of 'nlohmann::detail::type_error'
  what():  [json.exception.type_error.311] cannot use emplace() with array
Aborted

Please describe the steps to reproduce the issue.

See steps above

Can you provide a small but working code example?

See code above

What is the expected behavior?

The code in the GIF slides should work without exceptions

And what is the actual behavior instead?

See output above

Which compiler and operating system are you using?

  • Compiler: g++ (Ubuntu 9.3.0-17ubuntu1~20.04) 9.3.0
  • Operating system: Ubuntu 20.04

Which version of the library did you use?

  • latest release version 3.9.1
  • other release - please state the version: ___
  • the develop branch
@windy32
Copy link
Author

windy32 commented Nov 2, 2020

Another example in slide which is not working:

// g++ serialize.cpp -std=c++11 -o serialize
#include <iomanip>
#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main()
{
    json j = {
        {"pi", 3.141},
        {"happy", true},
        {"name", "Niels"},
        {"nothing", nullptr},
        {"answer", {
            {"everything", 42}
        }},
        {"list", {1, 0, 2}},
        {"object", {
          {"currency", "USD"},
          {"value", 42.99}
        }}
    };

    // to stream (works)
    std::cout << std::setw(4) << j << std::endl;

    // implicit (not works)
    std::string s1 = j;
    std::cout << s1 << std::endl;
}

The output is:

$ g++ serialize.cpp -std=c++11 -o serialize
$ ./serialize 
{
    "answer": {
        "everything": 42
    },
    "happy": true,
    "list": [
        1,
        0,
        2
    ],
    "name": "Niels",
    "nothing": null,
    "object": {
        "currency": "USD",
        "value": 42.99
    },
    "pi": 3.141
}
terminate called after throwing an instance of 'nlohmann::detail::type_error'
  what():  [json.exception.type_error.302] type must be string, but is object
Aborted

@windy32
Copy link
Author

windy32 commented Nov 2, 2020

Another one:

// g++ parse.cpp -std=c++11 -o parse
#include <iomanip>
#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main()
{
    // from string (works)
    json j1 = json::parse("[1,null,false]");
    std::cout << std::setw(4) << j1 << std::endl;

    // from stream (not works)
    json j2;
    j2 << "{\"one\": 1, \"two\": 2}";
    std::cout << std::setw(4) << j2 << std::endl;reset   
}

The code cannot be compiled:

$ g++ parse.cpp -std=c++11 -o parse
parse.cpp: In function ‘int main()’:
parse.cpp:16:8: error: no match for ‘operator<< (operand types are ‘json’ {aka ‘nlohmann::basic_json<>’} and ‘const char [21]’)
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |     ~~ ^~ ~~~~~~~~~~~~~~~~~~~~~~~~~~
      |     |     |
      |     |     const char [21]
      |     json {aka nlohmann::basic_json<>}
In file included from parse.cpp:4:
json.hpp:23338:26: note: candidate: ‘std::istream& nlohmann::operator<<(nlohmann::basic_json<>&, std::istream&)’
23338 |     friend std::istream& operator<<(basic_json& j, std::istream& i)
      |                          ^~~~~~~~
json.hpp:23338:66: note:   no known conversion for argument 2 from ‘const char [21]’ to ‘std::istream&’ {aka ‘std::basic_istream<char>&’}
23338 |     friend std::istream& operator<<(basic_json& j, std::istream& i)
      |                                                    ~~~~~~~~~~~~~~^
json.hpp:23044:26: note: candidate: ‘std::ostream& nlohmann::operator<<(std::ostream&, const nlohmann::basic_json<>&)’
23044 |     friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
      |                          ^~~~~~~~
json.hpp:23044:51: note:   no known conversion for argument 1 from ‘json’ {aka ‘nlohmann::basic_json<>’} to ‘std::ostream&’ {aka ‘std::basic_ostream<char>&’}
23044 |     friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
      |                                     ~~~~~~~~~~~~~~^
In file included from /usr/include/c++/9/string:55,
                 from /usr/include/c++/9/bits/locale_classes.h:40,
                 from /usr/include/c++/9/bits/ios_base.h:41,
                 from /usr/include/c++/9/iomanip:40,
                 from parse.cpp:2:
/usr/include/c++/9/bits/basic_string.h:6416:5: note: candidate: ‘template<class _CharT, class _Traits, class _Alloc> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::__cxx11::basic_string<_CharT, _Traits, _Alloc>&)’
 6416 |     operator<<(basic_ostream<_CharT, _Traits>& __os,
      |     ^~~~~~~~
/usr/include/c++/9/bits/basic_string.h:6416:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/bits/ios_base.h:46,
                 from /usr/include/c++/9/iomanip:40,
                 from parse.cpp:2:
/usr/include/c++/9/system_error:217:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::error_code&)’
  217 |     operator<<(basic_ostream<_CharT, _Traits>& __os, const error_code& __e)
      |     ^~~~~~~~
/usr/include/c++/9/system_error:217:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from parse.cpp:2:
/usr/include/c++/9/iomanip:79:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, std::_Resetiosflags)’
   79 |     operator<<(basic_ostream<_CharT, _Traits>& __os, _Resetiosflags __f)
      |     ^~~~~~~~
/usr/include/c++/9/iomanip:79:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from parse.cpp:2:
/usr/include/c++/9/iomanip:109:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, std::_Setiosflags)’
  109 |     operator<<(basic_ostream<_CharT, _Traits>& __os, _Setiosflags __f)
      |     ^~~~~~~~
/usr/include/c++/9/iomanip:109:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from parse.cpp:2:
/usr/include/c++/9/iomanip:143:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, std::_Setbase)’
  143 |     operator<<(basic_ostream<_CharT, _Traits>& __os, _Setbase __f)
      |     ^~~~~~~~
/usr/include/c++/9/iomanip:143:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from parse.cpp:2:
/usr/include/c++/9/iomanip:178:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, std::_Setfill<_CharT>)’
  178 |     operator<<(basic_ostream<_CharT, _Traits>& __os, _Setfill<_CharT> __f)
      |     ^~~~~~~~
/usr/include/c++/9/iomanip:178:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from parse.cpp:2:
/usr/include/c++/9/iomanip:208:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, std::_Setprecision)’
  208 |     operator<<(basic_ostream<_CharT, _Traits>& __os, _Setprecision __f)
      |     ^~~~~~~~
/usr/include/c++/9/iomanip:208:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from parse.cpp:2:
/usr/include/c++/9/iomanip:238:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, std::_Setw)’
  238 |     operator<<(basic_ostream<_CharT, _Traits>& __os, _Setw __f)
      |     ^~~~~~~~
/usr/include/c++/9/iomanip:238:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from parse.cpp:2:
/usr/include/c++/9/iomanip:311:5: note: candidate: ‘template<class _CharT, class _Traits, class _MoneyT> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, std::_Put_money<_MoneyT>)’
  311 |     operator<<(basic_ostream<_CharT, _Traits>& __os, _Put_money<_MoneyT> __f)
      |     ^~~~~~~~
/usr/include/c++/9/iomanip:311:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from parse.cpp:2:
/usr/include/c++/9/iomanip:363:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, std::_Put_time<_CharT>)’
  363 |     operator<<(basic_ostream<_CharT, _Traits>& __os, _Put_time<_CharT> __f)
      |     ^~~~~~~~
/usr/include/c++/9/iomanip:363:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/iostream:39,
                 from parse.cpp:3:
/usr/include/c++/9/ostream:506:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, _CharT)’
  506 |     operator<<(basic_ostream<_CharT, _Traits>& __out, _CharT __c)
      |     ^~~~~~~~
/usr/include/c++/9/ostream:506:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/iostream:39,
                 from parse.cpp:3:
/usr/include/c++/9/ostream:511:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, char)’
  511 |     operator<<(basic_ostream<_CharT, _Traits>& __out, char __c)
      |     ^~~~~~~~
/usr/include/c++/9/ostream:511:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/iostream:39,
                 from parse.cpp:3:
/usr/include/c++/9/ostream:517:5: note: candidate: ‘template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, char)’
  517 |     operator<<(basic_ostream<char, _Traits>& __out, char __c)
      |     ^~~~~~~~
/usr/include/c++/9/ostream:517:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<char, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/iostream:39,
                 from parse.cpp:3:
/usr/include/c++/9/ostream:523:5: note: candidate: ‘template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, signed char)’
  523 |     operator<<(basic_ostream<char, _Traits>& __out, signed char __c)
      |     ^~~~~~~~
/usr/include/c++/9/ostream:523:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<char, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/iostream:39,
                 from parse.cpp:3:
/usr/include/c++/9/ostream:528:5: note: candidate: ‘template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, unsigned char)’
  528 |     operator<<(basic_ostream<char, _Traits>& __out, unsigned char __c)
      |     ^~~~~~~~
/usr/include/c++/9/ostream:528:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<char, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/iostream:39,
                 from parse.cpp:3:
/usr/include/c++/9/ostream:548:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const _CharT*)’
  548 |     operator<<(basic_ostream<_CharT, _Traits>& __out, const _CharT* __s)
      |     ^~~~~~~~
/usr/include/c++/9/ostream:548:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/ostream:702,
                 from /usr/include/c++/9/iostream:39,
                 from parse.cpp:3:
/usr/include/c++/9/bits/ostream.tcc:321:5: note: candidate: ‘template<class _CharT, class _Traits> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const char*)’
  321 |     operator<<(basic_ostream<_CharT, _Traits>& __out, const char* __s)
      |     ^~~~~~~~
/usr/include/c++/9/bits/ostream.tcc:321:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/iostream:39,
                 from parse.cpp:3:
/usr/include/c++/9/ostream:565:5: note: candidate: ‘template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const char*)’
  565 |     operator<<(basic_ostream<char, _Traits>& __out, const char* __s)
      |     ^~~~~~~~
/usr/include/c++/9/ostream:565:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<char, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/iostream:39,
                 from parse.cpp:3:
/usr/include/c++/9/ostream:578:5: note: candidate: ‘template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const signed char*)’
  578 |     operator<<(basic_ostream<char, _Traits>& __out, const signed char* __s)
      |     ^~~~~~~~
/usr/include/c++/9/ostream:578:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<char, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/iostream:39,
                 from parse.cpp:3:
/usr/include/c++/9/ostream:583:5: note: candidate: ‘template<class _Traits> std::basic_ostream<char, _Traits>& std::operator<<(std::basic_ostream<char, _Traits>&, const unsigned char*)’
  583 |     operator<<(basic_ostream<char, _Traits>& __out, const unsigned char* __s)
      |     ^~~~~~~~
/usr/include/c++/9/ostream:583:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<char, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/iostream:39,
                 from parse.cpp:3:
/usr/include/c++/9/ostream:691:5: note: candidate: ‘template<class _Ostream, class _Tp> typename std::enable_if<std::__and_<std::__not_<std::is_lvalue_reference<_Tp> >, std::__is_convertible_to_basic_ostream<_Ostream>, std::__is_insertable<typename std::__is_convertible_to_basic_ostream<_Tp>::__ostream_type, const _Tp&, void> >::value, typename std::__is_convertible_to_basic_ostream<_Tp>::__ostream_type>::type std::operator<<(_Ostream&&, const _Tp&)’
  691 |     operator<<(_Ostream&& __os, const _Tp& __x)
      |     ^~~~~~~~
/usr/include/c++/9/ostream:691:5: note:   template argument deduction/substitution failed:
/usr/include/c++/9/ostream: In substitution of ‘template<class _Ostream, class _Tp> typename std::enable_if<std::__and_<std::__not_<std::is_lvalue_reference<_Tp> >, std::__is_convertible_to_basic_ostream<_Ostream>, std::__is_insertable<typename std::__is_convertible_to_basic_ostream<_Tp>::__ostream_type, const _Tp&, void> >::value, typename std::__is_convertible_to_basic_ostream<_Tp>::__ostream_type>::type std::operator<<(_Ostream&&, const _Tp&) [with _Ostream = nlohmann::basic_json<>&; _Tp = char [21]]’:
parse.cpp:16:11:   required from here
/usr/include/c++/9/ostream:691:5: error: no type named ‘type’ in ‘struct std::enable_if<false, void>’
In file included from /usr/include/c++/9/memory:81,
                 from json.hpp:43,
                 from parse.cpp:4:
/usr/include/c++/9/bits/shared_ptr.h:66:5: note: candidate: ‘template<class _Ch, class _Tr, class _Tp, __gnu_cxx::_Lock_policy _Lp> std::basic_ostream<_CharT, _Traits>& std::operator<<(std::basic_ostream<_CharT, _Traits>&, const std::__shared_ptr<_Tp, _Lp>&)’
   66 |     operator<<(std::basic_ostream<_Ch, _Tr>& __os,
      |     ^~~~~~~~
/usr/include/c++/9/bits/shared_ptr.h:66:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘std::basic_ostream<_CharT, _Traits>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/valarray:603,
                 from json.hpp:67,
                 from parse.cpp:4:
/usr/include/c++/9/bits/valarray_after.h:413:5: note: candidate: ‘template<class _Dom1, class _Dom2> std::_Expr<std::__detail::_BinClos<std::__shift_left, std::_Expr, std::_Expr, _Dom1, _Dom2>, typename std::__fun<std::__shift_left, typename _Dom1::value_type>::result_type> std::operator<<(const std::_Expr<_Dom1, typename _Dom1::value_type>&, const std::_Expr<_Dom2, typename _Dom2::value_type>&)’
  413 |     _DEFINE_EXPR_BINARY_OPERATOR(<<, __shift_left)
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/9/bits/valarray_after.h:413:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘const std::_Expr<_Dom1, typename _Dom1::value_type>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/valarray:603,
                 from json.hpp:67,
                 from parse.cpp:4:
/usr/include/c++/9/bits/valarray_after.h:413:5: note: candidate: ‘template<class _Dom> std::_Expr<std::__detail::_BinClos<std::__shift_left, std::_Expr, std::_Constant, _Dom, typename _Dom::value_type>, typename std::__fun<std::__shift_left, typename _Dom1::value_type>::result_type> std::operator<<(const std::_Expr<_Dom1, typename _Dom1::value_type>&, const typename _Dom::value_type&)’
  413 |     _DEFINE_EXPR_BINARY_OPERATOR(<<, __shift_left)
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/9/bits/valarray_after.h:413:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘const std::_Expr<_Dom1, typename _Dom1::value_type>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/valarray:603,
                 from json.hpp:67,
                 from parse.cpp:4:
/usr/include/c++/9/bits/valarray_after.h:413:5: note: candidate: ‘template<class _Dom> std::_Expr<std::__detail::_BinClos<std::__shift_left, std::_Constant, std::_Expr, typename _Dom::value_type, _Dom>, typename std::__fun<std::__shift_left, typename _Dom1::value_type>::result_type> std::operator<<(const typename _Dom::value_type&, const std::_Expr<_Dom1, typename _Dom1::value_type>&)’
  413 |     _DEFINE_EXPR_BINARY_OPERATOR(<<, __shift_left)
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/9/bits/valarray_after.h:413:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   mismatched types ‘const std::_Expr<_Dom1, typename _Dom1::value_type>’ and ‘const char [21]’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/valarray:603,
                 from json.hpp:67,
                 from parse.cpp:4:
/usr/include/c++/9/bits/valarray_after.h:413:5: note: candidate: ‘template<class _Dom> std::_Expr<std::__detail::_BinClos<std::__shift_left, std::_Expr, std::_ValArray, _Dom, typename _Dom::value_type>, typename std::__fun<std::__shift_left, typename _Dom1::value_type>::result_type> std::operator<<(const std::_Expr<_Dom1, typename _Dom1::value_type>&, const std::valarray<typename _Dom::value_type>&)’
  413 |     _DEFINE_EXPR_BINARY_OPERATOR(<<, __shift_left)
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/9/bits/valarray_after.h:413:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘const std::_Expr<_Dom1, typename _Dom1::value_type>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from /usr/include/c++/9/valarray:603,
                 from json.hpp:67,
                 from parse.cpp:4:
/usr/include/c++/9/bits/valarray_after.h:413:5: note: candidate: ‘template<class _Dom> std::_Expr<std::__detail::_BinClos<std::__shift_left, std::_ValArray, std::_Expr, typename _Dom::value_type, _Dom>, typename std::__fun<std::__shift_left, typename _Dom1::value_type>::result_type> std::operator<<(const std::valarray<typename _Dom::value_type>&, const std::_Expr<_Dom1, typename _Dom1::value_type>&)’
  413 |     _DEFINE_EXPR_BINARY_OPERATOR(<<, __shift_left)
      |     ^~~~~~~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/9/bits/valarray_after.h:413:5: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   mismatched types ‘const std::_Expr<_Dom1, typename _Dom1::value_type>’ and ‘const char [21]’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from json.hpp:67,
                 from parse.cpp:4:
/usr/include/c++/9/valarray:1193:1: note: candidate: ‘template<class _Tp> std::_Expr<std::__detail::_BinClos<std::__shift_left, std::_ValArray, std::_ValArray, _Tp, _Tp>, typename std::__fun<std::__shift_left, _Tp>::result_type> std::operator<<(const std::valarray<_Tp>&, const std::valarray<_Tp>&)’
 1193 | _DEFINE_BINARY_OPERATOR(<<, __shift_left)
      | ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/9/valarray:1193:1: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘const std::valarray<_Tp>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from json.hpp:67,
                 from parse.cpp:4:
/usr/include/c++/9/valarray:1193:1: note: candidate: ‘template<class _Tp> std::_Expr<std::__detail::_BinClos<std::__shift_left, std::_ValArray, std::_Constant, _Tp, _Tp>, typename std::__fun<std::__shift_left, _Tp>::result_type> std::operator<<(const std::valarray<_Tp>&, const typename std::valarray<_Tp>::value_type&)’
 1193 | _DEFINE_BINARY_OPERATOR(<<, __shift_left)
      | ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/9/valarray:1193:1: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   ‘json’ {aka ‘nlohmann::basic_json<>’} is not derived from ‘const std::valarray<_Tp>’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~
In file included from json.hpp:67,
                 from parse.cpp:4:
/usr/include/c++/9/valarray:1193:1: note: candidate: ‘template<class _Tp> std::_Expr<std::__detail::_BinClos<std::__shift_left, std::_Constant, std::_ValArray, _Tp, _Tp>, typename std::__fun<std::__shift_left, _Tp>::result_type> std::operator<<(const typename std::valarray<_Tp>::value_type&, const std::valarray<_Tp>&)’
 1193 | _DEFINE_BINARY_OPERATOR(<<, __shift_left)
      | ^~~~~~~~~~~~~~~~~~~~~~~
/usr/include/c++/9/valarray:1193:1: note:   template argument deduction/substitution failed:
parse.cpp:16:11: note:   mismatched types ‘const std::valarray<_Tp>’ and ‘const char [21]’
   16 |     j2 << "{\"one\": 1, \"two\": 2}";
      |           ^~~~~~~~~~~~~~~~~~~~~~~~~~

@gregmarr
Copy link
Contributor

gregmarr commented Nov 9, 2020

"I followed the code in the GIF slide to learn to use the library:"

What is "the GIF slide"?

// create null value
json j;

// add via member function
j.push_back({"key", "value"});
j.emplace("key2", "value");

// add via += operator
j += {"another key", false};

emplace is for objects, you need emplace_back for arrays.

// implicit (not works)
std::string s1 = j;
std::cout << s1 << std::endl;

j is an object, not a string, so you want j.dump();

// from stream (not works)
json j2;
j2 << "{\"one\": 1, \"two\": 2}";

This is not "from stream", this is "from string" just like j1, so you need to do what you did in j1, or actually have the data in a stream, not a string.

@windy32
Copy link
Author

windy32 commented Nov 10, 2020

"I followed the code in the GIF slide to learn to use the library:"

What is "the GIF slide"?

// create null value
json j;

// add via member function
j.push_back({"key", "value"});
j.emplace("key2", "value");

// add via += operator
j += {"another key", false};

emplace is for objects, you need emplace_back for arrays.

// implicit (not works)
std::string s1 = j;
std::cout << s1 << std::endl;

j is an object, not a string, so you want j.dump();

// from stream (not works)
json j2;
j2 << "{\"one\": 1, \"two\": 2}";

This is not "from stream", this is "from string" just like j1, so you need to do what you did in j1, or actually have the data in a stream, not a string.

I mean the gif image included on top of README.md. (it says "this is an animated GIF. Please waitfor a feature slideshow")

The code above are copied from the gif image. Some code seems to be incorrect or outdated. This git image should be checked against the latest library and updated.

@gregmarr
Copy link
Contributor

Interesting. I never noticed that gif before.

I see that the first one you reported (slide 5) is indeed a bug, the push_back should be making j an object, so the emplace should work.

The second is slide 10.

The third one is slide 11.

@nlohmann Can you verify the code on these slides? I think the code on 5 should work, but AFAIK the code on 10 and 11 doesn't.

@nlohmann
Copy link
Owner

I'll check.

@nlohmann
Copy link
Owner

First of, @windy32 thanks so much for checking the GIF. You seem to be the first one in a long time to have a look at it...

Slide 5 (Object construction)

j.push_back({"key", "value"});

creates an array

[["key","value"]]

so the following emplace does not work.

If j would already be an object, then everything would be fine.

The bug is that in code

void push_back(initializer_list_t init)
{
    if (is_object() && init.size() == 2 && (*init.begin())->is_string())
    {
        basic_json&& key = init.begin()->moved_or_copied();
        push_back(typename object_t::value_type(
                      std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
    }
    else
    {
        push_back(basic_json(init));
    }
}

The if does not take null values into account, which it should. However, changing this would be a breaking change, so I'm afraid there is little we can do now other than to extend the documentation.

Slide 10 (Serialization)

This works for me with this:

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

using json = nlohmann::json;

int main()
{
    json j = "foo";

    // implicit
    std::string s1 = j;

    // explicit
    auto s2 = j.dump();

    // pretty-printed
    int indent = 4;
    std::string s3 = j.dump(indent);

    // to stream
    std::cout << j << std::endl;

    // pretty-printed
    std::cout << std::setw(indent)
              << j << std::endl;
}

What did I overlook?

Slide 11 (Deserialization / Parsing)

This does not work:

// from stream
json j2;
j2 << "{\"one\": 1, \"two\": 2}";

The operator is only overloaded for std::istream:

friend std::istream& operator<<(basic_json& j, std::istream& i)
{
    return operator>>(i, j);
}

which makes sense as we need to return a stream.

I guess I was too proud to present all ways how to parse JSON and tried to make one example fit the slide.

@gregmarr
Copy link
Contributor

gregmarr commented Nov 10, 2020

Slide 5: So you need to do json j = json::object(); first and then it will work?

Slide 10: I was assuming that j was a full object and not restricted to strings only.

Slide 11: Did you perhaps mean j2 << std::stringstream("{\"one\": 1, \"two\": 2}"); and then simplify too much?

@windy32
Copy link
Author

windy32 commented Nov 11, 2020

Slide 10: I was assuming that j was a full object and not restricted to strings only.

Yes. After changing j into a full object:

// g++ serialize-v2.cpp -std=c++11 -o serialize-v2
#include <iomanip>
#include <iostream>
#include "json.hpp"

using json = nlohmann::json;

int main()
{
    // json j = "foo";
    json j = {
        {"pi", 3.141},
        {"happy", true},
        {"name", "Niels"},
        {"nothing", nullptr},
        {"answer", {
            {"everything", 42}
        }},
        {"list", {1, 0, 2}},
        {"object", {
          {"currency", "USD"},
          {"value", 42.99}
        }}
    };

    // implicit
    std::string s1 = j;

    // explicit
    auto s2 = j.dump();

    // pretty-printed
    int indent = 4;
    std::string s3 = j.dump(indent);

    // to stream
    std::cout << j << std::endl;

    // pretty-printed
    std::cout << std::setw(indent)
              << j << std::endl;
}

The serialization does not work:

$ ./serialize-v2 
terminate called after throwing an instance of 'nlohmann::detail::type_error'
  what():  [json.exception.type_error.302] type must be string, but is object
Aborted

It is rare that j is just a plain text.

@nlohmann
Copy link
Owner

Yes. The slides is about conversion. If the JSON contains a string, then it can be converted to std::string. Same with numbers which can be converted to, say, double.

@windy32
Copy link
Author

windy32 commented Nov 11, 2020

Yes. The slides is about conversion. If the JSON contains a string, then it can be converted to std::string. Same with numbers which can be converted to, say, double.

The description is a bit misleading. Users may expect that an "implicit serialization" and an "explicit serialization" to have the same functionality.

@gregmarr
Copy link
Contributor

Yes, I expected that "implicit" and "explicit" would have the same output. For implicit and explicit extraction of a value of the type stored in j, perhaps

std::string s1 = j;
auto s2 = j.get<std::string>();

@stale
Copy link

stale bot commented Dec 25, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated label Dec 25, 2020
@nlohmann nlohmann added documentation and removed state: stale the issue has not been updated in a while and will be closed automatically soon unless it is updated labels Dec 26, 2020
@nlohmann nlohmann self-assigned this Jul 17, 2021
@nlohmann nlohmann added the solution: proposed fix a fix for the issue has been proposed and waits for confirmation label Jul 17, 2021
@nlohmann nlohmann added this to the Release 3.9.2 milestone Jul 17, 2021
nlohmann added a commit that referenced this issue Jul 17, 2021
@nlohmann
Copy link
Owner

I finally fixed the GIF.

harry75369 pushed a commit to harry75369/json that referenced this issue Aug 8, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
documentation kind: bug 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