I've not used C in over 20 years, so I am a bit rusty on this.
I am using the nlohmann/json json.h library and need to convert a JSON string that is an array of objects to an actual array.
As an example, I need to take this kind of response from a TRESTResponse object and turn it into a C array:
RESTRequest1->Execute();
String Content = RESTResponse1->Content;
Where Content =
"[{"fullname":"Norm A","e_mail":null,"phone":"999-555-4971"},{"fullname":"Norm C","e_mail":"[email protected]","phone":"999-555-8887"},{"fullname":"Norma Jn","e_mail":null,"phone":"999-555-5947"},{"fullname":"Norma & Frank L","e_mail":null,"phone":"999-555-1790"},{"fullname":"Norm Sh","e_mail":null,"phone":"999-555-7545"},{"fullname":"Norm S","e_mail":null,"phone":"999-555-9955"}]"
and get it into an array of objects. I have been unsuccessful with the library. While I can get an array into json properly, I can't seem to get json back to an array.
I've looked at some similar posts on Stackoverflow, but I did not see one that concerns the nlohmann/json library.
CodePudding user response:
[EDIT] Added an example that uses your input data. [Demo]
// Outputs:
//
// [
// (Norm A, null, 999-555-4971),
// (Norm C, [email protected], 999-555-8887),
// (Norma Jn, null, 999-555-5947),
// (Norma & Frank L, null, 999-555-1790),
// (Norm Sh, null, 999-555-7545),
// (Norm S, null, 999-555-9955)
// ]
The example below loads a JSON node of array type into a std::vector
.
The input JSON string only contains a node writers
whose content is an array of strings:
{
"writers": [
"Winston Groom",
"Eric Roth"
]
}
We load it into a JSON node with:
nlohmann::json j = nlohmann::json::parse(json_str);
We parse the "value" for the writers
"key", i.e. the array, with:
j.at("writers").get_to(writers);
This will make use of the available from_json(const nlohmann::json&, YourCustomType&)
in order to do the parsing.
The struct Writers
parses the JSON node into a std::vector<Writer>
with:
writers.data = j.get<std::vector<Writer>>();
And the struct Writer
parses the JSON node into a std::string
with:
j.get_to(writer.name);
#include <iostream> // cout
#include <nlohmann/json.hpp>
#include <ostream>
#include <string>
#include <vector>
struct Writer
{
std::string name{};
};
void from_json(const nlohmann::json& j, Writer& writer)
{
j.get_to(writer.name);
}
struct Writers
{
std::vector<Writer> data{};
};
void from_json(const nlohmann::json& j, Writers& writers)
{
writers.data = j.get<std::vector<Writer>>();
}
int main()
{
std::string json_str{R"({"writers": ["Winston Groom", "Eric Roth"]})"};
Writers writers{};
nlohmann::json j = nlohmann::json::parse(json_str.c_str());
j.at("writers").get_to(writers);
for (const auto& writer : writers.data)
{
std::cout << writer.name << ", ";
}
}
// Outputs:
//
// Winston Groom, Eric Roth,
CodePudding user response:
At a guess, you were probably running into a problem because your input data contains null
for a number of the strings (some of the email addresses).
To fix that, you need to explicitly check for is_null
before attempting to convert the source to an std::string
. At a quick guess, for a null
input, you'd probably want to just leave that string empty. For that, your from_json
would look something like this:
void from_json(json const &j, Person &p) {
j.at("fullname").get_to(p.name);
if (!j.at("e_mail").is_null())
j.at("e_mail").get_to(p.email);
j.at("phone").get_to(p.phone);
}
That's enough to work for the sample data, but depending on the data involved, you might want/need to protect against a null name and/or phone numbers as well (which you'd do in the same way as shown above for the email address).
A complete demo program using this would might look roughly like this:
#include <sstream>
#include <string>
#include <iostream>
#include "nlohmann/json.hpp"
using json = nlohmann::json;
std::string input { R"(
[{"fullname":"Norm A","e_mail":null,"phone":"999-555-4971"},{"fullname":"Norm C","e_mail":"[email protected]","phone":"999-555-8887"},{"fullname":"Norma Jn","e_mail":null,"phone":"999-555-5947"},{"fullname":"Norma & Frank L","e_mail":null,"phone":"999-555-1790"},{"fullname":"Norm Sh","e_mail":null,"phone":"999-555-7545"},{"fullname":"Norm S","e_mail":null,"phone":"999-555-9955"}]
)"};
namespace P {
struct Person {
std::string name;
std::string email;
std::string phone;
friend std::ostream &operator<<(std::ostream &os, Person const &p) {
return os << "name: " << p.name << ", email: " << p.email << ", phone: " << p.phone;
}
};
void from_json(json const &j, Person &p) {
j.at("fullname").get_to(p.name);
if (!j.at("e_mail").is_null())
j.at("e_mail").get_to(p.email);
j.at("phone").get_to(p.phone);
}
}
int main() {
json j = json::parse(input);
std::vector<P::Person> people;
j.get_to(people);
for (auto const &person : people) {
std::cout << person << "\n";
}
}