I'm having an issue where the rapidjson library appears to be inconsistent as to when it reports IsObject()
as true
.
Sometimes when I call value.IsObject()
after retrieving a Value
from a Document
, it correctly reports it as an Object
. But sometimes it reports what I think should be an Object
as not an Object
.
A toy program is below.
It seems I am unintentionally mutating the document somehow, as the 2nd lookup for vegetables::celery
remarkably fails.
#define _CRT_SECURE_NO_DEPRECATE
#include <rapidjson/document.h>
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
#include <string.h>
#include <stdio.h>
using namespace rapidjson;
int getInt(Document& jsonDoc, const char* propertyName)
{
if (!jsonDoc.IsObject()) {
puts("Err: jsonDoc not an object");
return 0;
}
char* str = strdup(propertyName);
char* p = strtok(str, ":");
printf("Looking for property `%s`\n", p);
if (!jsonDoc.HasMember(p))
{
printf(" - Error: %s not found, property %s\n", p, propertyName);
free(str);
return 0;
}
else
{
printf(" - found property '%s'\n", p);
}
rapidjson::Value& v = jsonDoc[p];
while (p = strtok(0, ":"))
{
printf("Looking for property `%s`\n", p);
if (v.IsObject())
{
puts(" - v is an object so I can look");
}
else
{
printf(" - ERROR: v is NOT an object, I can't search for %s, property %s not found\n", p, propertyName);
free(str);
return 0;
}
if (!v.HasMember(p))
{
printf(" - Error while digging: %s not found, property %s\n", p, propertyName);
free(str);
return 0;
}
else
printf(" - found property '%s'\n", p);
// otherwise,
v = v[p]; // advance deeper into the tree
}
int val = v.GetInt();
printf(" - json got value %s=%d\n", propertyName, val);
free(str);
return val;
}
void test1()
{
const char* json = R"STR({
"fruits":{
"apples":1,
"oranges":553,
"bananas":900
},
"vegetables":{
"celery":10000,
"cabbage":10000
}
})STR";
Document d;
d.Parse(json);
int apples = getInt(d, "fruits::apples");
int oranges = getInt(d, "fruits::oranges");
int bananas = getInt(d, "fruits::bananas");
int celery = getInt(d, "vegetables::celery");
celery = getInt(d, "vegetables::celery");
int cabbage = getInt(d, "vegetables::cabbage");
}
int main()
{
test1();
return 0;
}
CodePudding user response:
Two issues here.
First and main:
rapidjson::Value& v = jsonDoc[p];
...
v = v[p];
Since v is not a variable, but a reference, you don't set it to a new object, but change the original object it references to, damaging it.
Use rapidjson
library Pointers if you need to change the object beneath or you can use a trick like here:
rapidjson::Value* v = &(jsonDoc[p]);
...
v = &(*v)[p];
Second
In some returns in if-else you have the memory leak with str
, you free it only at the end of the function.