nlohmann / json Goto Github PK
View Code? Open in Web Editor NEWJSON for Modern C++
Home Page: https://json.nlohmann.me
License: MIT License
JSON for Modern C++
Home Page: https://json.nlohmann.me
License: MIT License
In member functions like dump
and type_name
, return std::string
instead const std::string
. Returning const values cause unnecessary copies to occur.
When encoding the JSON string with the dump method, it will insert some spaces (after ":" or ",") even without pretty print active. It will add some undesired extra bytes when the data is just going over the wire. In my case it is important as I am encoding JSON Web Tokens (JWT), and every byte its important as the token is being transmitted in every request.
I'm using the following code right now:
json customers;
for (...)
{
customers.push_back(...)
}
cout << customers;
However, if the for loop doesnt happen, I would like to return an empty array (eg []
)
Is they an other way to get this behaviour without doing json customers= json::parse("[]");
?
Since you're using C++11, wouldn't it be better to manage object ownership using unique_ptr?
I will issue a pull request when I start using your library.
Just as other containers, iterators should be used to identify the element to be deleted from a container.
Appears when -Wdeprecated
is enabled on clang.
src/json.hpp:2076:26: warning: definition of implicit copy constructor for 'iterator' is deprecated because it has a user-declared copy assignment
operator [-Wdeprecated]
inline iterator& operator=(const iterator& other) noexcept
^
test/unit.cpp:2471:37: note: implicit copy constructor for 'iterator' first required here
json::iterator it = j.begin();
In file included from test/unit.cpp:13:
src/json.hpp:2579:32: warning: definition of implicit copy constructor for 'const_iterator' is deprecated because it has a user-declared copy
assignment operator [-Wdeprecated]
inline const_iterator& operator=(const const_iterator& other) noexcept
^
test/unit.cpp:2496:38: note: implicit copy constructor for 'const_iterator' first required here
json::const_iterator it = j_const.begin();
^
There are also some warnings involving floating point comparisons when Wfloat-equal
is enabled:
src/json.hpp:1567:53: warning: comparing floating point with == or != is unsafe [-Wfloat-equal]
return lhs.m_value.number_float == static_cast<number_float_t>(rhs.m_value.number_integer);
~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
test/unit.cpp:127:21: note: in instantiation of member function 'nlohmann::operator==' requested here
CHECK(j == j_reference);
^
test/catch.hpp:8925:44: note: expanded from macro 'CHECK'
#define CHECK( expr ) INTERNAL_CATCH_TEST( expr, Catch::ResultDisposition::ContinueOnFailure, "CHECK" )
^
test/catch.hpp:1484:39: note: expanded from macro 'INTERNAL_CATCH_TEST'
} while( Catch::isTrue( false && (expr) ) ) // expr here is never evaluated at runtime but it forces the compiler to give it a look
^
In file included from test/unit.cpp:13:
src/json.hpp:1571:53: warning: comparing floating point with == or != is unsafe [-Wfloat-equal]
return lhs.m_value.number_float == rhs.m_value.number_float;
~~~~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~~~~
src/json.hpp:4235:35: warning: comparing floating point with == or != is unsafe [-Wfloat-equal]
if (float_val == int_val)
~~~~~~~~~ ^ ~~~~~~~
Considering the JSON below,
{
"names": ["Tim", "Tom"],
"num": [1, 2]
}
I want to get a vector of string. I realized that I could only use auto a = json["name"]
and then process it using for-range loop. However, if I want to explicitly define the return type then I will get an error. For instance, both vector<string> names = j["names"]
and vector<string> names = j["names"].get<vector<string>>()
will give me an error:
./json.hpp:829:24: error: no matching constructor for initialization of 'std::__1::vector<std::__1::basic_string<char>,
std::__1::allocator<std::__1::basic_string<char> > >'
return T(m_value.array->begin(), m_value.array->end());
I can see that json library couldn't cast to vector<string>
; however, it will work if I want to get num
even explicitly like this: vector<float> f = j["num"].get<vector<float>>()
.
Now, I'm wondering if I am doing it wrong or it's not implemented?
Thanks,
Amir.
This is simply wrong:
case (value_t::number_float):
{
return std::to_string(m_value.number_float);
}
The to_string use std::locale what can change the point to comma (happened with us, because in QT the QApplication create change this) what is not good for json. You have to use always point instead of comma (json rpc standard)
Robert Ramey
╭╴ (master=)╶╮
╰ jeff@siegfried:json $ uname -a
Linux siegfried 3.16.0-33-generic #44-Ubuntu SMP Thu Mar 12 12:19:35 UTC 2015 x86_64 x86_64 x86_64 GNU/Linux
╭╴ (master=)╶╮
╰ jeff@siegfried:json $ make
g++ -std=c++11 -Wall -Wextra -pedantic -Weffc++ -Wcast-align -Wcast-qual -Wctor-dtor-privacy -Wdisabled-optimization -Wformat=2 -Winit-self -Wmissing-declarations -Wmissing-include-dirs -Wold-style-cast -Woverloaded-virtual -Wredundant-decls -Wshadow -Wsign-conversion -Wsign-promo -Wstrict-overflow=5 -Wswitch -Wundef -Wno-unused -Wnon-virtual-dtor -Wreorder -Wdeprecated -Wfloat-equal -I src -I test test/unit.cpp -o json_unit
In file included from test/unit.cpp:11:0:
test/catch.hpp:264:57: warning: ‘const T& Catch::operator+(const T&, Catch::StreamEndStop)’ should return by value [-Weffc++]
T const& operator + ( T const& value, StreamEndStop ) {
^
test/catch.hpp: In copy constructor ‘Catch::NotImplementedException::NotImplementedException(const Catch::NotImplementedException&)’:
test/catch.hpp:280:9: warning: ‘Catch::NotImplementedException::m_what’ should be initialized in the member initialization list [-Weffc++]
NotImplementedException( NotImplementedException const& ) {}
^
test/catch.hpp:280:9: warning: ‘Catch::NotImplementedException::m_lineInfo’ should be initialized in the member initialization list [-Weffc++]
In file included from test/unit.cpp:11:0:
test/catch.hpp: At global scope:
test/catch.hpp:478:7: warning: ‘class Catch::MethodTestCase’ only defines a private destructor and has no friends [-Wctor-dtor-privacy]
class MethodTestCase : public SharedImpl {
^
test/catch.hpp: In constructor ‘Catch::AssertionInfo::AssertionInfo()’:
test/catch.hpp:645:9: warning: ‘Catch::AssertionInfo::macroName’ should be initialized in the member initialization list [-Weffc++]
AssertionInfo() {}
^
test/catch.hpp:645:9: warning: ‘Catch::AssertionInfo::lineInfo’ should be initialized in the member initialization list [-Weffc++]
test/catch.hpp:645:9: warning: ‘Catch::AssertionInfo::capturedExpression’ should be initialized in the member initialization list [-Weffc++]
test/catch.hpp:645:9: warning: ‘Catch::AssertionInfo::resultDisposition’ should be initialized in the member initialization list [-Weffc++]
test/catch.hpp: In constructor ‘Catch::AssertionResultData::AssertionResultData()’:
test/catch.hpp:659:9: warning: ‘Catch::AssertionResultData::reconstructedExpression’ should be initialized in the member initialization list [-Weffc++]
AssertionResultData() : resultType( ResultWas::Unknown ) {}
^
test/catch.hpp:659:9: warning: ‘Catch::AssertionResultData::message’ should be initialized in the member initialization list [-Weffc++]
...
From an email:
Anyway, a quite serious bug is when one tries to iterate over a empty container (array or object), which results in a segmentation fault due to a 0x0 this pointer. I fixed this by changing the iterator constructors to check if the container is empty, and in that case set the “object_” pointer to a nullptr.
The proposed code fix:
json::const_iterator::const_iterator(const json* j) : object_(j)
{
if (object_ != nullptr)
{
if (object_->type_ == value_type::array)
{
if (object_->empty())
// Explicit empty check added
{
object_ = nullptr;
}
else
{
vi_ = new array_t::const_iterator(object_->value_.array->begin());
}
}
else if (object_->type_ == value_type::object)
// *else if* is mandatory since the previous
{
// block can set pointer to nullptr!
if (object_->empty())
// Explicit empty check added
{
object_ = nullptr;
}
else
{
oi_ = new object_t::const_iterator(object_->value_.object->begin());
}
}
}
}
A typical operation is to find if a json
object has a given key, this is typically done like:
json j;
bool has_key = j.find("key") != j.end();
The standard containers (std::map
, std::set
,...) offer a count
member function that counts the number of occurrences of a key, such that one can:
std::map<std::string, int> m;
bool has_key = m.count("key"); // -> count == 0? false : true
It would be nice to have something similar since this is a very common operation.
Supporting both C++98 and C++11 at the same time makes maintenance harder.
If you construct a string of the JSON payload using dump()
and then use parse()
to deserialize it, the contents of the former object don't match the latter when there are escape characters. Example pseudo-code
void test_case()
{
nlohmann::json fields;
fields["one"] = std::string("one");
fields["two"] = std::string("two three");
fields["three"] = std::string("three \"four\"");
std::string payload = fields.dump();
nlohmann::json parsed_fields = fields_t::parse(payload);
test_check_eq(parsed_fields.size(), fields.size());
test_check_eq(parsed_fields["one"], fields["one"]);
test_check_eq(parsed_fields["two"], fields["two"]);
test_check_eq(parsed_fields["three"], fields["three"]);
}
Here parsed_fields["three"] == std::string("three \\\"four\\\"")
. If this is expected, then what should be done to parsed_fields
in this case to recover the original contents?
I was about to use this for a C++ project in Visual Studio 2013, but the header fails compilation entirely, thanks to a myriad of errors:
1>------ Build started: Project: jsondummy, Configuration: Debug Win32 ------
1> main.cpp
1>d:\github\jsondummy\src\json.hpp(137): error C2061: syntax error : identifier 'iterator'
1> d:\github\jsondummy\src\json.hpp(4893) : see reference to class template instantiation 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>' being compiled
1>d:\github\jsondummy\src\json.hpp(137): error C2238: unexpected token(s) preceding ';'
1>d:\github\jsondummy\src\json.hpp(143): error C2061: syntax error : identifier 'const_iterator'
1>d:\github\jsondummy\src\json.hpp(143): error C2238: unexpected token(s) preceding ';'
1>d:\github\jsondummy\src\json.hpp(149): error C2061: syntax error : identifier 'reverse_iterator'
1>d:\github\jsondummy\src\json.hpp(149): error C2238: unexpected token(s) preceding ';'
1>d:\github\jsondummy\src\json.hpp(155): error C2061: syntax error : identifier 'const_reverse_iterator'
1>d:\github\jsondummy\src\json.hpp(155): error C2238: unexpected token(s) preceding ';'
1>d:\github\jsondummy\src\json.hpp(382): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(385): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(402): warning C4346: 'std::is_constructible<ObjectType<StringType,nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>,>::key_type,V::key_type>::value' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(402): error C2146: syntax error : missing ',' before identifier 'and'
1>d:\github\jsondummy\src\json.hpp(402): error C2065: 'and' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(402): error C2143: syntax error : missing ',' before 'std::is_constructible<nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>,V::mapped_type>::value'
1>d:\github\jsondummy\src\json.hpp(402): error C2977: 'std::enable_if' : too many template arguments
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtr1common(67) : see declaration of 'std::enable_if'
1>d:\github\jsondummy\src\json.hpp(403): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\github\jsondummy\src\json.hpp(426): error C2065: 'not' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(426): warning C4346: 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::iterator' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(426): error C2923: 'std::is_same' : 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::iterator' is not a valid template type argument for parameter '_Ty2'
1>d:\github\jsondummy\src\json.hpp(426): error C2143: syntax error : missing ',' before 'std::integral_constant<bool,false>::value'
1>d:\github\jsondummy\src\json.hpp(427): error C2146: syntax error : missing ',' before identifier 'and'
1>d:\github\jsondummy\src\json.hpp(427): error C2065: 'and' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(427): error C2146: syntax error : missing ',' before identifier 'not'
1>d:\github\jsondummy\src\json.hpp(427): error C2065: 'not' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(427): warning C4346: 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::const_iterator' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(427): error C2923: 'std::is_same' : 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::const_iterator' is not a valid template type argument for parameter '_Ty2'
1>d:\github\jsondummy\src\json.hpp(427): error C2143: syntax error : missing ',' before 'std::integral_constant<bool,false>::value'
1>d:\github\jsondummy\src\json.hpp(428): error C2146: syntax error : missing ',' before identifier 'and'
1>d:\github\jsondummy\src\json.hpp(428): error C2065: 'and' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(428): error C2146: syntax error : missing ',' before identifier 'not'
1>d:\github\jsondummy\src\json.hpp(428): error C2065: 'not' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(428): warning C4346: 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::reverse_iterator' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(428): error C2923: 'std::is_same' : 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::reverse_iterator' is not a valid template type argument for parameter '_Ty2'
1>d:\github\jsondummy\src\json.hpp(428): error C2143: syntax error : missing ',' before 'std::integral_constant<bool,false>::value'
1>d:\github\jsondummy\src\json.hpp(429): error C2146: syntax error : missing ',' before identifier 'and'
1>d:\github\jsondummy\src\json.hpp(429): error C2065: 'and' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(429): error C2146: syntax error : missing ',' before identifier 'not'
1>d:\github\jsondummy\src\json.hpp(429): error C2065: 'not' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(429): warning C4346: 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::const_reverse_iterator' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(429): error C2923: 'std::is_same' : 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::const_reverse_iterator' is not a valid template type argument for parameter '_Ty2'
1>d:\github\jsondummy\src\json.hpp(429): error C2143: syntax error : missing ',' before 'std::integral_constant<bool,false>::value'
1>d:\github\jsondummy\src\json.hpp(430): error C2146: syntax error : missing ',' before identifier 'and'
1>d:\github\jsondummy\src\json.hpp(430): error C2065: 'and' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(430): error C2146: syntax error : missing ',' before identifier 'not'
1>d:\github\jsondummy\src\json.hpp(430): error C2065: 'not' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(430): error C2143: syntax error : missing ',' before 'std::is_same<V,ArrayType<nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>,>::iterator>::value'
1>d:\github\jsondummy\src\json.hpp(431): warning C4346: 'std::is_same<V,ArrayType<nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>,>::iterator>::value' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(431): error C2146: syntax error : missing ',' before identifier 'and'
1>d:\github\jsondummy\src\json.hpp(431): error C2065: 'and' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(431): error C2146: syntax error : missing ',' before identifier 'not'
1>d:\github\jsondummy\src\json.hpp(431): error C2065: 'not' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(431): error C2143: syntax error : missing ',' before 'std::is_same<V,ArrayType<nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>,>::const_iterator>::value'
1>d:\github\jsondummy\src\json.hpp(432): warning C4346: 'std::is_same<V,ArrayType<nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>,>::const_iterator>::value' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(432): error C2146: syntax error : missing ',' before identifier 'and'
1>d:\github\jsondummy\src\json.hpp(432): error C2065: 'and' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(432): error C2143: syntax error : missing ',' before 'std::is_constructible<nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>,V::value_type>::value'
1>d:\github\jsondummy\src\json.hpp(432): error C2977: 'std::enable_if' : too many template arguments
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtr1common(67) : see declaration of 'std::enable_if'
1>d:\github\jsondummy\src\json.hpp(433): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\github\jsondummy\src\json.hpp(434): error C2535: 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::basic_json(const V &)' : member function already defined or declared
1> d:\github\jsondummy\src\json.hpp(404) : see declaration of 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::basic_json'
1>d:\github\jsondummy\src\json.hpp(485): warning C4346: 'std::is_constructible<NumberIntegerType,T>::value' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(485): error C2146: syntax error : missing ',' before identifier 'and'
1>d:\github\jsondummy\src\json.hpp(485): error C2065: 'and' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(485): error C2143: syntax error : missing ',' before 'std::numeric_limits<T>::is_integer'
1>d:\github\jsondummy\src\json.hpp(485): error C2977: 'std::enable_if' : too many template arguments
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtr1common(67) : see declaration of 'std::enable_if'
1>d:\github\jsondummy\src\json.hpp(486): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\github\jsondummy\src\json.hpp(487): warning C4346: 'std::numeric_limits<T>::is_integer' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(487): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(502): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(594): warning C4346: 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::iterator' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(594): error C2923: 'std::is_same' : 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::iterator' is not a valid template type argument for parameter '_Ty2'
1>d:\github\jsondummy\src\json.hpp(595): error C2146: syntax error : missing ',' before identifier 'or'
1>d:\github\jsondummy\src\json.hpp(595): error C2065: 'or' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(595): warning C4346: 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::const_iterator' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(595): error C2923: 'std::is_same' : 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::const_iterator' is not a valid template type argument for parameter '_Ty2'
1>d:\github\jsondummy\src\json.hpp(596): error C2143: syntax error : missing ',' before 'std::integral_constant<bool,false>::value'
1>d:\github\jsondummy\src\json.hpp(596): error C2977: 'std::enable_if' : too many template arguments
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtr1common(67) : see declaration of 'std::enable_if'
1>d:\github\jsondummy\src\json.hpp(597): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\github\jsondummy\src\json.hpp(748): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(761): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(762): warning C4346: 'std::is_nothrow_move_constructible<nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>::value_t>::value' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(762): error C2061: syntax error : identifier 'value'
1>d:\github\jsondummy\src\json.hpp(767): error C2091: function returns function
1>d:\github\jsondummy\src\json.hpp(779): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(838): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(851): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(857): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(863): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(869): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(875): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(881): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(887): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(893): error C3646: 'noexcept' : unknown override specifier
1>d:\github\jsondummy\src\json.hpp(906): warning C4346: 'std::is_convertible<ObjectType<StringType,nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>,>::key_type,T::key_type>::value' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(906): error C2146: syntax error : missing ',' before identifier 'and'
1>d:\github\jsondummy\src\json.hpp(906): error C2065: 'and' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(907): error C2143: syntax error : missing ',' before 'std::is_convertible<nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>,T::mapped_type>::value'
1>d:\github\jsondummy\src\json.hpp(907): error C2977: 'std::enable_if' : too many template arguments
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtr1common(67) : see declaration of 'std::enable_if'
1>d:\github\jsondummy\src\json.hpp(907): error C4430: missing type specifier - int assumed. Note: C++ does not support default-int
1>d:\github\jsondummy\src\json.hpp(943): warning C4346: 'std::is_convertible<nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>,T::value_type>::value' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(943): error C2146: syntax error : missing ',' before identifier 'and'
1>d:\github\jsondummy\src\json.hpp(943): error C2065: 'and' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(943): error C2146: syntax error : missing ',' before identifier 'not'
1>d:\github\jsondummy\src\json.hpp(943): error C2065: 'not' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(943): error C2143: syntax error : missing ',' before 'std::is_same<nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>,T::value_type>::value'
1>d:\github\jsondummy\src\json.hpp(944): warning C4346: 'std::is_same<nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,AllocatorType>,T::value_type>::value' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(944): error C2146: syntax error : missing ',' before identifier 'and'
1>d:\github\jsondummy\src\json.hpp(944): error C2065: 'and' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(944): error C2146: syntax error : missing ',' before identifier 'not'
1>d:\github\jsondummy\src\json.hpp(944): error C2065: 'not' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(944): error C2143: syntax error : missing ',' before 'std::is_arithmetic<T>::value'
1>d:\github\jsondummy\src\json.hpp(945): warning C4346: 'std::is_arithmetic<T>::value' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(945): error C2146: syntax error : missing ',' before identifier 'and'
1>d:\github\jsondummy\src\json.hpp(945): error C2065: 'and' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(945): error C2146: syntax error : missing ',' before identifier 'not'
1>d:\github\jsondummy\src\json.hpp(945): error C2065: 'not' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(945): error C2143: syntax error : missing ',' before 'std::is_convertible<std::string,T>::value'
1>d:\github\jsondummy\src\json.hpp(946): warning C4346: 'std::is_convertible<std::string,T>::value' : dependent name is not a type
1> prefix with 'typename' to indicate a type
1>d:\github\jsondummy\src\json.hpp(946): error C2146: syntax error : missing ',' before identifier 'and'
1>d:\github\jsondummy\src\json.hpp(946): error C2065: 'and' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(946): error C2146: syntax error : missing ',' before identifier 'not'
1>d:\github\jsondummy\src\json.hpp(946): error C2065: 'not' : undeclared identifier
1>d:\github\jsondummy\src\json.hpp(947): error C2143: syntax error : missing ',' before 'nlohmann::has_mapped_type<T>::value'
1>d:\github\jsondummy\src\json.hpp(947): error C2977: 'std::enable_if' : too many template arguments
1> c:\program files (x86)\microsoft visual studio 12.0\vc\include\xtr1common(67) : see declaration of 'std::enable_if'
1>d:\github\jsondummy\src\json.hpp(947): fatal error C1003: error count exceeds 100; stopping compilation
========== Build: 0 succeeded, 1 failed, 0 up-to-date, 0 skipped ==========
This is on VS2013, and as far as I know it supports 90% of the standard (but not some of what you're using here, like noexcept
).
Are you planning to support Visual Studio/Windows some time later on?
Currently the parser assumes if a '' is before a double quote, the double quote isn't the end of the string.
Note that there are more complicated cases like this (and their expansion) which need to be handled properly which probably will take more code to support properly: ("\"", "\") of arbitrary length. A reverse search which checks if the number of '' preceding the quote is even or odd would do it: https://github.com/nlohmann/json/blob/master/src/json.cc#L2050
Performance in backslash-heavy strings may suffer a lot though. Might be better to do a pure forward scan of the string counting backslashes as you go (Lots of memory access, but it should all be prefetched + L1 cached by current x86, x64 CPUs).
When iterating over a json
object, e.g. using a range-based for loop, one only gets the values, and it is impossible right now to get the key of each value. It would be nice to be able to iterate over the keys, since this allows you to get the value afterwards if you want too.
Another alternative is a key.value pair iterator like map.
I cannot encode a unsigned long or unsigned long long value without casting it to int, with its corresponding overflow. It is required, i.e., for storing a timestamp in milliseconds from epoch.
Currently,
{{"a","b"},{"c","d"}}
will be treated as object, and there is no way to express it as array of two arrays with two strings each.
As tgockel points out:
I can't say it's a great solution, but in JSON Voorhees, I went with free functions called array and object to disambiguate the initializer_list syntax. It also solves the issue of {} ambiguously meaning an empty object or empty array (and accidentally making an array when given string_views or something).
Such free functions could solve the above problem:
{array({"a","b"}), array({"c","d"})}
As proposed in http://www.reddit.com/r/cpp/comments/2rbhn3/json_for_modern_c_what_if_json_was_part_of_modern/cnh7ox4, it would be nice to template the string container that is used inside the json class.
Create an overload of the to_string
member function that handles indentation (spaces) and line breaks.
const std::string to_string(int indent) const noexcept
I expected that small doubles would be represented in dumped JSON as a javascript number in scientific notation, but instead it just appears as 0.000000
Example:
#include <iostream>
#include "json.hpp"
using json = nlohmann::json;
main() {
double d = 1.23456e-89;
json j = d;
std::cout << "d=" << d << " j=" << j << std::endl;
}
Expected output: d=1.23456e-89 j=1.23456e-89
Actual output: d=1.23456e-89 j=0.000000
Looking at the json code, it appears this is due to using std::to_string()
for all numbers, which is equivalent to sprintf("%f", ...)
whereas sprintf("%g", ...)
would be more appropriate. To fix this, the dump function would need to use something other than to_string to format floating point numbers. I'll try to put together a PR for this although C++ is far from my best language.
As wished in http://www.reddit.com/r/cpp/comments/2rbhn3/json_for_modern_c_what_if_json_was_part_of_modern/cnelnzq:
I think this would be fare more useful as a header only library. I'm down for sending a PR with the change if you are.
And as I wrote:
Good idea! But I think it would be more useful if there would be a script that reads the source files json.cc and json.h and creates a header-only version. That way, both approaches can be followed at the same time.
The snippet to reproduce the error:
struct A {
nlohmann::json j;
auto has_entry(std::string n) {
return j.find(n) != j.end() ? true : false;
}
};
what the error looks like:
src/json.hpp:1073:20: error: 'm_it' is a private member of 'nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long,
double, std::allocator>::const_iterator'
result.m_it.object_iterator = m_value.object->find(key);
^
This is not catched by the unit tests because they are compiled by defining private=public
.
A "better" way to do that could be to have a separate file only for those tests that "need" private=public
.
This might be clang 3.6 specific, since I'm the only one who seems to be having problems.
I worked around this issue by including the library as follows:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wfloat-equal"
#pragma clang diagnostic ignored "-Wdeprecated"
#define private public
#include <json.hpp>
#define private private
#pragma clang diagnostic pop
There are currently some lines that are not covered by test cases:
Right now the library uses member-functions .begin()
and .end()
when serializing sequences: see e.g. here.
As a consequence some types cannot be serialized.
Right now there is no way of erasing a key.
I know this isn't strictly json
-compliant, but I would love to have numbers as keys.
Say I try:
std::map data<double, double> = {{1.0, 2.0}, {3.0, 4.0}};
I would like to be able to:
json j_data(data);
In order to get:
{1.0:2.0, 3.0:4.0}
I think the strength of json
is that it can take a little bit of abuse.
Thanks.
Similar to a STL container json should support a custom allocator.
json o;
o["foo"] = 23;
o["bar"] = false;
o["baz"] = 3.141;
// find an entry
if (o.find("foo") != o.end()) {
// there is an entry with key "foo"
}
in my example
key:"Heart_COL"
type:"HEX"
val:"DF01140234340000"
auto it = jsonData.find("type");
std::cout << *it << '\n';
the printf data is "Heart_COL"
Hi.
There is no documentation on what compilers are supported, or which C++ features are required. I've tried to include the header in a project with MSVC 2013, and I get plenty of compile errors (with MinGW it compiles fine). I know MSVC might not have good enough C++11 support, so that's somewhat expected. I'm wondering, though, if anybody has attempted some newer pre-release of MSVC and if it is worth it at all trying to get it compile, sending patches, etc.
Thank you.
PD: In case it's useful, the first error I have is with the declaration of using iterator = basic_json::iterator:
c:\users\alex\documents\helloworld\json/src/json.hpp(142) : error C2061: syntax error : identifier 'iterator'
c:\users\alex\documents\helloworld\json/src/json.hpp(4335) : see reference to class template instantiation 'nlohmann::basic_json<ObjectType,ArrayType,StringType,BooleanType,NumberIntegerType,NumberFloatType,Allocator>' being compiled
c:\users\alex\documents\helloworld\json/src/json.hpp(142) : error C2238: unexpected token(s) preceding ';'
Later on I get plenty of unrecognized noexcept. The later could be worked around with a macro, I think, but I have no idea on the former, or other template magic involved.
The code should be moved into a namespace not to pollute the global namespace.
mr_ewg points out:
I think your
json::find
functions have undefined behaviour (doubledelete
in the case that thenew
throws)
This needs to be checked.
In JSON, double quotation mark in a JSON string is escaped as \"
, such as
["\"foo\""]
should be escaped as "foo"
. But this library did not handle it and parsed it as \"foo\"
.
I reproduced the bug with the following test case:
SECTION("escape_dobulequote")
{
auto s = "[\"\\\"foo\\\"\"]";
json j = json::parse(s);
CHECK(j == json({"\"foo\""}));
}
Results:
test/unit.cpp:6351: FAILED:
CHECK( j == json({"\"foo\""}) )
with expansion:
["\\\"foo\\\""] == "\"foo\""
Hi. Thanks for great lib!
Is there support for removing item/items from array?
E.g.:
json j;
j["name"] = { "testname", "yetanothername" };
j["name"].erase("testname");
$ ./a.out
terminate called after throwing an instance of 'std::runtime_error'
what(): cannot use at with array
Add examples in the documentation for:
The following functions are not yet documented:
A common use case in web development is the need for flatten and unflatten functions, that is the ability to flatten a json object into a map of javascript assignment strings and vice versa.
{
"member1" : true,
"member2" : "Hello World",
"member3" : [1, {"member4" : 4, "member5" : 6.5}, 3]
}
into
prefix "whatever"
key = whatever.member1
value = true
key = whatever.member2
value = "Hello World"
key = whatever.member3[0]
value = 1
key = whatever.member1[1].member4
value = 4
key = whatever.member1[1].member5
value = 6.5
key = whatever.member3[2]
value = 3
function sighatures would be something like
map<string, json_primitive_that_insn't_object_or_array> flatten(json_object_or_array, symbol_name);
json_object_or_array unflatten(map<string, json_primitive_that_insn't_object_or_array>, symbol_name);
The type of the map would be string to a json primitive that isn't an object or an array.
The use case is that the keys in the map could be used as form field names. PHP and jQuery both are already doing this natively. Wouldn't it be nice if C++ had equal or better footing for web development.
If I have:
{
"england": {
"name": "euro",
"value": 57.99
},
"mexico": {
"name": "peso",
"value": 31.99
},
"us": {
"name": "USD",
"value": 42.99
}
}
And I want to iterate through each, how would I do so?
My attempt so far has been similar to the following:
std::ifstream input_file( const string file_path );
nlohmann::json currencies_json;
currencies_json << input_file;
input_file.close();
unordered_map <string, currency_class> currencies;
for ( const auto currency_json: currencies_json ) {
currency_class new_currency;
new_currency[ "country" ] = ???
new_currency[ "name" ] = ???
new_currency[ "value"] = ???
currencies[ country ] = new_currency;
}
I've tried it a a few ways including - for example - creating a string for new_currency[ "country" ]
first and then storing it in it like new_currency[ "country" ] = my_string
, but I get errors such as:
no member named 'key' in 'nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double, std::allocator>'
or
[....]:1073:20: error: 'm_it' is a private member of 'nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>,
bool, long long, double, std::allocator>::const_iterator'
result.m_it.object_iterator = m_value.object->find(key);
^
[...]:89:32: note: in instantiation of member function 'nlohmann::basic_json<std::map, std::vector, std::__1::basic_string<char>, bool, long long, double,
std::allocator>::find' requested here
const auto iterator = currencies.find("country");
^
[...]/build/dependencies/json-prefix/src/json/src/json.hpp:3007:96: note: declared private here
internal_iterator<typename array_t::const_iterator, typename object_t::const_iterator> m_it;
Could you provide some guidance? I'd really appreciate it!
It would be nice to measure the test case coverage somehow.
The Readme currently states:
Furthermore, we allow for more escape symbols in strings as the JSON specification. While this may not be a problem in reality, we are aware of it, but as long as we have a hand-written parser, we won't invest too much to be fully compliant.
And in fact, anything between two unescaped quotes will be treated as strings. However, the JSON standard is very explicit how a string may look like:
As long as the class does not implement this string specification, the class is not fully JSON compliant.
It is unclear how parser handles non-ascii strings. It would be nice to have it and have a statement about the i18n
Hi,
Is there a way we could Serialize the output like PHP's Serialize version?
Currently it outputs in one line as a string. Would be helpful if it could support additional method such as this one.
Let me know!
Thanks.
P.S Kudos for the awesome work you've done. Very nice, clean and easier to use!
Let's say I have the json from the example readme:
nlohmann::json all = {
{"pi", 3.141},
{"happy", true},
{"name", "Niels"},
{"nothing", nullptr},
{"answer", {
{"everything", 42}
}},
{"list", {1, 0, 2}},
{"object", {
{"currency", "USD"},
{"value", 42.99}
}}
};
I will iterate over it the following way:
for (nlohmann::json::iterator it = all.begin(); it != all.end(); ++it) {
std::cout << it.key() << std::endl;
}
I would expect this:
pi
happy
name
nothing
answer
list
object
Instead, I get:
answer
happy
list
name
nothing
object
pi
Why is this the default? Can it be turned off?
The Catch Unit Test Framework should help to avoid future bugs. The current way of testing does not make sense.
http://en.cppreference.com/w/cpp/io/c/fprintf
snprintf will format infinity and nan doubles as Inf/Infinity or nan/nan(char_sequence) respectively. This can break the validity of a json.dump() document:
Line 2279 in 1580eee
You can check for infinity/nan w/ std::isinfinite/std::isnan - not sure what you'd like to actually do in those scenarios (some specific/configurable string representation?)
I'm trying to iterate over a json input file containing an unknown number of molecules (see below). For each of these the key is the name which I currently have found no way to extract. Is this possible?
Code:
#include <faunus/json.hpp>
#include <iostream>
#include <fstream>
/*
* minimal.json:
* {
* "moleculelist" : {
* "salt" : { "atoms":"Na Cl", "atomic":true, "Ninit":1 },
* "water" : { "atoms":"H H O", "atomic":false, "Ninit":55 }
* }
* }
*/
using json = nlohmann::json;
int main() {
std::ifstream f("minimal.json");
if (f) {
json j;
j << f;
if ( ! j["moleculelist"].empty() )
for ( auto &mol : j["moleculelist"] )
if ( mol.is_object() ) {
// how to get entry keys? (i.e. "salt", "water", etc.)
for ( auto &i : mol )
std::cout << i << "\n";
}
}
}
g++-4.8.1 generates the following two errors while g++-4.9.2 does not generate any error (OS: ubuntu-12.04).
g++-4.8 -std=c++11 -I src -I test test/unit.cpp -o json_unit
In file included from test/unit.cpp:25:0:
src/json.hpp: In instantiation of ‘T nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType>::erase(T) [with T = nlohmann::basic_json<>::const_iterator; typename std::enable_if<(std::is_same<V, nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType>::iterator>::value || std::is_same<V, nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType>::const_iterator>::value), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::basic_string<char>; BooleanType = bool; NumberIntegerType = long int; NumberFloatType = double; AllocatorType = std::allocator]’:
test/unit.cpp:2655:80: required from here
src/json.hpp:1286:44: error: no matching function for call to ‘std::vector<nlohmann::basic_json<> >::erase(__gnu_cxx::__normal_iterator<const nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<> > >&)’
result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
^
src/json.hpp:1286:44: note: candidates are:
In file included from /usr/include/c++/4.8/vector:69:0,
from /usr/include/c++/4.8/bits/random.h:34,
from /usr/include/c++/4.8/random:50,
from /usr/include/c++/4.8/bits/stl_algo.h:65,
from /usr/include/c++/4.8/algorithm:62,
from test/catch.hpp:62,
from test/unit.cpp:11:
/usr/include/c++/4.8/bits/vector.tcc:134:5: note: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator) [with _Tp = nlohmann::basic_json<>; _Alloc = std::allocator<nlohmann::basic_json<> >; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<> > >; typename std::_Vector_base<_Tp, _Alloc>::pointer = nlohmann::basic_json<>*]
vector<_Tp, _Alloc>::
^
/usr/include/c++/4.8/bits/vector.tcc:134:5: note: no known conversion for argument 1 from ‘__gnu_cxx::__normal_iterator<const nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<> > >’ to ‘std::vector<nlohmann::basic_json<> >::iterator {aka __gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<> > >}’
/usr/include/c++/4.8/bits/vector.tcc:146:5: note: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp, _Alloc>::iterator) [with _Tp = nlohmann::basic_json<>; _Alloc = std::allocator<nlohmann::basic_json<> >; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<> > >; typename std::_Vector_base<_Tp, _Alloc>::pointer = nlohmann::basic_json<>*]
vector<_Tp, _Alloc>::
^
/usr/include/c++/4.8/bits/vector.tcc:146:5: note: candidate expects 2 arguments, 1 provided
In file included from test/unit.cpp:25:0:
src/json.hpp: In instantiation of ‘T nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType>::erase(T, T) [with T = nlohmann::basic_json<>::const_iterator; typename std::enable_if<(std::is_same<V, nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType>::iterator>::value || std::is_same<V, nlohmann::basic_json<ObjectType, ArrayType, StringType, BooleanType, NumberIntegerType, NumberFloatType, AllocatorType>::const_iterator>::value), int>::type <anonymous> = 0; ObjectType = std::map; ArrayType = std::vector; StringType = std::basic_string<char>; BooleanType = bool; NumberIntegerType = long int; NumberFloatType = double; AllocatorType = std::allocator]’:
test/unit.cpp:2671:95: required from here
src/json.hpp:1348:44: error: no matching function for call to ‘std::vector<nlohmann::basic_json<> >::erase(__gnu_cxx::__normal_iterator<const nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<> > >&, __gnu_cxx::__normal_iterator<const nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<> > >&)’
result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
^
src/json.hpp:1348:44: note: candidates are:
In file included from /usr/include/c++/4.8/vector:69:0,
from /usr/include/c++/4.8/bits/random.h:34,
from /usr/include/c++/4.8/random:50,
from /usr/include/c++/4.8/bits/stl_algo.h:65,
from /usr/include/c++/4.8/algorithm:62,
from test/catch.hpp:62,
from test/unit.cpp:11:
/usr/include/c++/4.8/bits/vector.tcc:134:5: note: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator) [with _Tp = nlohmann::basic_json<>; _Alloc = std::allocator<nlohmann::basic_json<> >; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<> > >; typename std::_Vector_base<_Tp, _Alloc>::pointer = nlohmann::basic_json<>*]
vector<_Tp, _Alloc>::
^
/usr/include/c++/4.8/bits/vector.tcc:134:5: note: candidate expects 1 argument, 2 provided
/usr/include/c++/4.8/bits/vector.tcc:146:5: note: std::vector<_Tp, _Alloc>::iterator std::vector<_Tp, _Alloc>::erase(std::vector<_Tp, _Alloc>::iterator, std::vector<_Tp, _Alloc>::iterator) [with _Tp = nlohmann::basic_json<>; _Alloc = std::allocator<nlohmann::basic_json<> >; std::vector<_Tp, _Alloc>::iterator = __gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<> > >; typename std::_Vector_base<_Tp, _Alloc>::pointer = nlohmann::basic_json<>*]
vector<_Tp, _Alloc>::
^
/usr/include/c++/4.8/bits/vector.tcc:146:5: note: no known conversion for argument 1 from ‘__gnu_cxx::__normal_iterator<const nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<> > >’ to ‘std::vector<nlohmann::basic_json<> >::iterator {aka __gnu_cxx::__normal_iterator<nlohmann::basic_json<>*, std::vector<nlohmann::basic_json<> > >}’
make: *** [json_unit] Error 1
Something in the C++11 object handling seems to be broken.
What would be the best way to iterate over a json object and print the attribute names?
My goal would be to have something like this:
example json:
{
"example": {
"a": "hello",
"b": "world",
"c": "text"
}
}
example printing code:
auto j = nlohmann::json::parse(Read_Entire_File_Into_String("example.json"));
auto element = j["example"];
for (auto const& it: element) {
std::cout << it.attribute_name() << std::endl;
}
// I made up 'Read_Entire_File_Into_String', but it does what you'd expect.
// the attribute_name() method doesn't exist, but I wish that it had.
example results:
a
b
c
Not everything has an attribute name, in which case, it could return an empty string, throw an exception, or return std::optional.
I thought this might be easy to implement, but it appears that all of the attribute names are stored in the parent object, which means that when we iterate over an object, each iterator points to an object that has no way of finding out its own attribute name.
for example, if I were to edit json.hpp
and give the basic_json
class this public member function:
inline string_t attribute_name() const noexcept
{
std::string str;
if (m_type == value_t::object){
for (auto i = m_value.object->cbegin(); i != m_value.object->cend(); ++i){
str += escape_string(i->first) + " ";
}
}
return str;
}
and run client code like this:
#include "json.hpp"
#include <iostream>
void Recursive_Print(nlohmann::json const& element, unsigned int depth);
int main(){
auto element = nlohmann::json::parse(Read_Entire_File_Into_String("changelog.json"));
if (element.is_null()){ std::cout << "null " << element.attribute_name() << std::endl;}
if (element.is_boolean()){std::cout << "bool " << element.attribute_name() << std::endl;}
if (element.is_number()){std::cout << "number " << element.attribute_name() << std::endl;}
if (element.is_object()){std::cout << "object " << element.attribute_name() << std::endl;}
if (element.is_array()){std::cout << "array " << element.attribute_name() << std::endl;}
if (element.is_string()){std::cout << "string " << element.attribute_name() << std::endl;}
}
void Recursive_Print(nlohmann::json const& element, unsigned int depth){
for (auto const& it: element) {
Print_Character_N_Times('-',depth);
if (it.is_null()){ std::cout << "null " << it.attribute_name() << std::endl;}
if (it.is_boolean()){std::cout << "bool " << it.attribute_name() << std::endl;}
if (it.is_number()){std::cout << "number " << it.attribute_name() << std::endl;}
if (it.is_object()){std::cout << "object " << it.attribute_name() << std::endl; Recursive_Print(it,++depth);}
if (it.is_array()){std::cout << "array " << it.attribute_name() << std::endl; Recursive_Print(it,++depth);}
if (it.is_string()){std::cout << "string " << it.attribute_name() << std::endl;}
}
}
//PRETTY MESSY. BUT YOU GET THE GIST
it would result in the following:
object example
-object a b c
--string
--string
--string
I think that illustrates my point about attribute names being stored in the parents.
Anyway, do you have any thoughts on how I could accomplish this?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.