Closed clabnet closed 3 years ago
Hi, thank you for the query!
There are multiple ways of finding the size of vec, but I think the easiest and most versatile is to use a std::vector. Please see the following example:
#include <string>
#include <json_struct.h>
const char json[] = R"json(
{
"vec" : [
{ "key" : 4, "value": 1.0 },
{ "key" : 5, "value": 2.0 },
{ "key" : 6, "value": 3.0 }
]
}
)json";
struct VecMember
{
std::string key;
double value;
JS_OBJ(key, value);
};
struct JsonObject
{
std::vector<VecMember> vec;
JS_OBJ(vec);
};
int main()
{
JsonObject obj;
JS::ParseContext parseContext(json);
if (parseContext.parseTo(obj) != JS::Error::NoError)
{
std::string errorStr = parseContext.makeErrorString();
fprintf(stderr, "Error parsing struct %s\n", errorStr.c_str());
return -1;
}
fprintf(stdout, "Vec has size %zu\n", obj.vec.size());
return 0;
}
Hope this answers the question. If it does please close the issue.
Hi @jorgen , thank you for your fast response.
Your reply is very valuable, but my problem is a little too complicated.
I try to be more precise. My json_data
is contained into config.json
file:
{
"webInterface": "localhost",
"......"; "......",
"moduleList": [
{ "id": 0, "name": "MAINTENANCE" },
{ "id": 1, "name": "CORE" },
{ "id": 2, "name": "BLA BLA" }
]
}
and my struct is here : https://pastebin.com/embed_js/fp7WYs6c
Please note on this code the struct TypeHandler<ModuleList<T>>
part and the MODULELIST_COUNT
define.
When I read the config.json file,
std::ifstream ifs(config_file.c_str());
if (!ifs) {
throw std::invalid_argument("Can't open app config file " + config_file);
}
std::string json_data((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>());
spdlog::trace(json_data);
I can't parse securely the entire json into Config
struct because I can't know how much elements of array the user can be defined. The user can be define one, two, "n" element on moduleList array.
The final goal: I would remove from the source code the MODULELIST_COUNT define constant, but I don't know.
Sorry for the long post and thank you for your time.
Regards,
right! ok. so you want to have a static sized buffer, but want to populate it with dynamic data? so I assume you will have som size variable keeping count of how much of the buffer is filled up? Since you have already a type handler we can modify it "by copying the array type handler spesialisation" and make it fit your needs. I have adjusted the example, does this fit the bill? We have some more options if it doesn't do what you want it to :D
#include <string>
#include <json_struct.h>
const char json[] = R"json(
{
"vec" : [
{ "key" : 4, "value": 1.0 },
{ "key" : 5, "value": 2.0 },
{ "key" : 6, "value": 3.0 }
]
}
)json";
struct VecMember
{
std::string key;
double value;
JS_OBJ(key, value);
};
struct ModuleList
{
enum
{
ReservedSize = 16
};
VecMember modules[ReservedSize];
int size = 0;
};
namespace JS
{
template <>
struct TypeHandler<ModuleList>
{
static inline Error to(ModuleList &to_type, ParseContext &context)
{
if (context.token.value_type != Type::ArrayStart)
return JS::Error::ExpectedArrayStart;
context.nextToken();
for (size_t i = 0; i < ModuleList::ReservedSize; i++)
{
if (context.error != JS::Error::NoError)
return context.error;
if (context.token.value_type == Type::ArrayEnd)
{
to_type.size = i;
break;
}
context.error = TypeHandler<VecMember>::to(to_type.modules[i], context);
if (context.error != JS::Error::NoError)
return context.error;
context.nextToken();
}
if (context.token.value_type != Type::ArrayEnd)
return JS::Error::ExpectedArrayEnd;
return context.error;
}
static inline void from(const ModuleList &from_type, Token &token, Serializer &serializer)
{
token.value_type = Type::ArrayStart;
token.value = DataRef("[");
serializer.write(token);
token.name = DataRef("");
for (size_t i = 0; i < from_type.size; i++)
TypeHandler<VecMember>::from(from_type.modules[i], token, serializer);
token.name = DataRef("");
token.value_type = Type::ArrayEnd;
token.value = DataRef("]");
serializer.write(token);
}
};
} // namespace JS
struct JsonObject
{
ModuleList vec;
JS_OBJ(vec);
};
int main()
{
JsonObject obj;
JS::ParseContext parseContext(json);
if (parseContext.parseTo(obj) != JS::Error::NoError)
{
std::string errorStr = parseContext.makeErrorString();
fprintf(stderr, "Error parsing struct %s\n", errorStr.c_str());
return -1;
}
fprintf(stdout, "Vec has size %zu\n", obj.vec.size);
return 0;
}
Hi! I just added a new type to json_struct called JS::ArrayVariableContent. It is basically the code above but removes the need for a more advanced type handler.
https://github.com/jorgen/json_struct/blob/master/tests/json-struct-array-varlength.cpp
Can I close this issue now?
Sorry for delay, tomorrow I send you my solution.
Many thanks for your proposal, but I have found a short road. I have set MODULELIST_COUNT to 32 (fortunately I know how the max number of elements the user can create) and defined
std::vector<Module> moduleList;
It work as is.
Good to hear you, and many thanks @jorgen.
Best regards.
closed
Hi, on this array "vec" : [ { "key" : 4, "value": 1.0 }, { "key" : 5, "value": 2.0 }, { "key" : 6, "value": 3.0 } ] how to know the number of elements ? On this sample, 3. Thank's