-
-
Notifications
You must be signed in to change notification settings - Fork 6.7k
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
Deserialize std::map with std::nan #1154
Comments
The reason for this is that the > a = [0/0, 1/0, -1/0]
[ NaN, Infinity, -Infinity ]
> JSON.stringify(a)
'[null,null,null]' Parsing
I don't really like any of these options. What do you think? |
I see. What about something like this?
That is, an optional parameter to be used as a value in case of |
I'm not sure if we can provide such an overload for all situations where the |
Well, assuming that I well understood what you are proposing, a user-defined function would be more flexible too. |
Great. Can I close the issue? |
Now I am quite sure that I misunderstood your "user-defined function"! If you meant that "the user will write some code to workaround the issue", how can I retrieve just the key of the pair in case that there is an exception in the value? |
With "user-defined" function I meant that the problem is conceptually solvable with a function using only the public interface of the library. I write "conceptually", because you may not be able to write code like map<int64_t, double> reloaded_map = j.get<std::map<int64_t, double>>(); but rather need to define a function like void my_conversion(const json& j, std::map<int64_t, double>& dest) in which you need to take care about only copying the non-null values. For this, the #include <iostream>
#include "json.hpp"
using json = nlohmann::json;
void my_conversion(const json& j, std::map<std::string, double>& dest)
{
for (auto& el: j.items())
{
if (el.value().is_number())
{
dest[el.key()] = el.value();
}
}
}
int main()
{
json j = {{"foo", 43.12}, {"bar", nullptr}};
std::map<std::string, double> m;
my_conversion(j, m);
std::cout << m.size() << std::endl;
} |
In my case, I have a #include <iostream>
#include <iomanip>
#include <map>
#include "rawdata/ext/json/json.hpp"
#include <fstream>
using namespace std;
using json = nlohmann::json;
int main()
{
// a map with a nan-value pair
map<int64_t, double> test_map;
test_map[123] = 1.2342;
test_map[434] = std::nan("");
test_map[999] = 243.12;
// storage file
string file_path = "test.json";
// serialization
json j;
j["data"] = test_map;
string json_str = j.dump(3);
cout << "json str: " << json_str << endl;
// write to disk
std::ofstream ofs( file_path );
if(!ofs)
{
cerr << "issue in opening " << file_path << endl;
exit( -1 );
}
ofs << json_str;
ofs.close();
// de-serialization
std::ifstream ifs( file_path );
if(!ifs)
{
cerr << "issue in opening " << file_path << endl;
exit( -1 );
}
json j2;
ifs >> j2;
ifs.close();
try
{
map<int64_t, double> reloaded_map;
for(auto& el : j2["data"].items())
{
if(el.value().is_number())
{
reloaded_map[std::stoll(el.key())] = el.value();
}
else
{
reloaded_map[std::stoll(el.key())] = std::nan("");
}
}
for(const auto& pair: reloaded_map)
{
cout << "- " << pair.first << ": " << pair.second << endl;
}
}
catch(const std::exception& e)
{
cerr << "issue in parsing json: " << e.what() << endl;
}
} This is the output:
What am I doing wrong? |
When you map key type is not a string, the map will not be serialized to an object, because JSON requires string keys. Instead, the map is serialized to a list of pairs: {"data":[[123,1.2342],[434,null],[999,243.12]]} Then you can simply iterate the list of these pairs and check whether each second entry is a number: #include <iostream>
#include "json.hpp"
using json = nlohmann::json;
int main()
{
// a map with a nan-value pair
std::map<int64_t, double> test_map;
test_map[123] = 1.2342;
test_map[434] = std::nan("");
test_map[999] = 243.12;
// serialization
json j;
j["data"] = test_map;
// roundtrip
json j2 = json::parse(j.dump());
std::map<int64_t, double> reloaded_map;
for (auto& entry : j2["data"])
{
assert(entry.is_array());
assert(entry.size() == 2);
if (entry[1].is_number())
{
reloaded_map[entry[0]] = entry[1];
}
}
for (const auto& pair: reloaded_map)
{
std::cout << "- " << pair.first << ": " << pair.second << std::endl;
}
} |
It worked. Thank you! |
What is the issue you have?
Using the 'develop' branch, I get:
[json.exception.type_error.302] type must be number, but is null
when I deserialize anstd::map
withstd::nan
as pair value.Please describe the steps to reproduce the issue. Can you provide a small but working code example?
What is the expected behavior?
No throwing an exception.
Which compiler and operating system are you using? Is it a supported compiler?
Visual Studio 2015
Did you use a released version of the library or the version from the
develop
branch?develop
branch.The text was updated successfully, but these errors were encountered: