recommend using explicit from JSON conversions

This commit is contained in:
Théo DELRIEU 2018-11-19 14:25:29 +01:00
parent da81e7be22
commit 7b961368d5
No known key found for this signature in database
GPG key ID: 7D6E00D1DF01DEAF

View file

@ -291,19 +291,17 @@ Note the difference between serialization and assignment:
// store a string in a JSON value // store a string in a JSON value
json j_string = "this is a string"; json j_string = "this is a string";
// retrieve the string value (implicit JSON to std::string conversion) // retrieve the string value
std::string cpp_string = j_string; auto cpp_string = j_string.get<std::string>();
// retrieve the string value (explicit JSON to std::string conversion) // retrieve the string value (alternative when an variable already exists)
auto cpp_string2 = j_string.get<std::string>(); std::string cpp_string2;
// retrieve the string value (alternative explicit JSON to std::string conversion) j_string.get_to(cpp_string2);
std::string cpp_string3;
j_string.get_to(cpp_string3);
// retrieve the serialized value (explicit JSON serialization) // retrieve the serialized value (explicit JSON serialization)
std::string serialized_string = j_string.dump(); std::string serialized_string = j_string.dump();
// output of original string // output of original string
std::cout << cpp_string << " == " << cpp_string2 << " == " << cpp_string3 << " == " << j_string.get<std::string>() << '\n'; std::cout << cpp_string << " == " << cpp_string2 << " == " << j_string.get<std::string>() << '\n';
// output of serialized value // output of serialized value
std::cout << j_string << " == " << serialized_string << std::endl; std::cout << j_string << " == " << serialized_string << std::endl;
``` ```
@ -428,7 +426,7 @@ for (auto& element : j) {
} }
// getter/setter // getter/setter
const std::string tmp = j[0]; const auto tmp = j[0].get<std::string>();
j[1] = 42; j[1] = 42;
bool foo = j.at(2); bool foo = j.at(2);
@ -611,33 +609,38 @@ j_original.merge_patch(j_patch);
### Implicit conversions ### Implicit conversions
The type of the JSON object is determined automatically by the expression to store. Likewise, the stored value is implicitly converted. Supported types can be implicitly converted to JSON values.
It is recommended to **NOT USE** implicit conversions **FROM** a JSON value.
You can find more details about this recommendation [here](https://www.github.com/nlohmann/issues/958).
```cpp ```cpp
// strings // strings
std::string s1 = "Hello, world!"; std::string s1 = "Hello, world!";
json js = s1; json js = s1;
std::string s2 = js; auto s2 = js.get<std::string>();
// NOT RECOMMENDED
std::string s3 = js;
std::string s4;
s4 = js;
// Booleans // Booleans
bool b1 = true; bool b1 = true;
json jb = b1; json jb = b1;
bool b2 = jb; auto b2 = jb.get<bool>();
// NOT RECOMMENDED
bool b3 = jb;
bool b4;
b4 = jb;
// numbers // numbers
int i = 42; int i = 42;
json jn = i; json jn = i;
double f = jn; auto f = jn.get<double>();
// NOT RECOMMENDED
// etc. double f2 = jb;
``` double f3;
f3 = jb;
You can also explicitly ask for the value:
```cpp
std::string vs = js.get<std::string>();
bool vb = jb.get<bool>();
int vi = jn.get<int>();
// etc. // etc.
``` ```
@ -695,7 +698,7 @@ std::cout << j << std::endl;
// {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"} // {"address":"744 Evergreen Terrace","age":60,"name":"Ned Flanders"}
// conversion: json -> person // conversion: json -> person
ns::person p2 = j; auto p2 = j.get<ns::person>();
// that's it // that's it
assert(p == p2); assert(p == p2);
@ -727,10 +730,9 @@ Likewise, when calling `get<your_type>()` or `get_to(your_type&)`, the `from_jso
Some important things: Some important things:
* Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined). * Those methods **MUST** be in your type's namespace (which can be the global namespace), or the library will not be able to locate them (in this example, they are in namespace `ns`, where `person` is defined).
* Those methods **MUST** be available (e.g., properly headers must be included) everywhere you use the implicit conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise. * Those methods **MUST** be available (e.g., properly headers must be included) everywhere you use these conversions. Look at [issue 1108](https://github.com/nlohmann/json/issues/1108) for errors that may occur otherwise.
* When using `get<your_type>()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.) * When using `get<your_type>()`, `your_type` **MUST** be [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible). (There is a way to bypass this requirement described later.)
* In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior. * In function `from_json`, use function [`at()`](https://nlohmann.github.io/json/classnlohmann_1_1basic__json_a93403e803947b86f4da2d1fb3345cf2c.html#a93403e803947b86f4da2d1fb3345cf2c) to access the object values rather than `operator[]`. In case a key does not exist, `at` throws an exception that you can handle, whereas `operator[]` exhibits undefined behavior.
* In case your type contains several `operator=` definitions, code like `your_variable = your_json;` [may not compile](https://github.com/nlohmann/json/issues/667). You need to write `your_variable = your_json.get<decltype(your_variable)>();` or `your_json.get_to(your_variable);` instead.
* You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these. * You do not need to add serializers or deserializers for STL types like `std::vector`: the library already implements these.