I'm attempting to loop through a list of objects within a JSON to find the object with a matching KVP (in C++ using RapidJSON). I've managed to retrieve the value using a hardcoded pointer but cannot get the function GetValueByPointer(document, "PointerString")
to accept the dynamic string I am building.
The JSON looks like this:
{ "_id" : { "$oid" : "5d0985973f1c0000ee000000" },
"Location" : [ { "lat" : "39.4005", "lon" : "-106.106"} ],
"Weather" : [ { "timestamp" : "2019-06-05T00:00:00", ...}, { "timestamp" : "2019-06-05T01:00:00", ...}}
This works:
Document document;
document.Parse(json);
Value* a = GetValueByPointer(document, "/Weather/1/timestamp");
std::cout << a->GetString() << std::endl;
This doesn't work:
Value* a = GetValueByPointer(document, "/Weather/1/timestamp");
int i = 1;
std::string base = "/Weather/";
std::string tail = "/timestamp";
std::string PointerString;
std::string TSString = "";
while(TSString != "2019-06-05T09:00:00") {
PointerString=base;
PointerString.append(std::to_string(i));
PointerString.append(tail);
PointerString = "\"" + PointerString + "\"";
Value* timestamp = GetValueByPointer(document, PointerString);
TSString = timestamp->GetString();
std::cout << TSString << std::endl;
i++;
}
The error I get no matter what I try and convert my PointerString to is:
/usr/local/include/rapidjson/pointer.h:1156:30: note: template argument deduction/substitution failed:
MGOIO.cc:145:62: note: mismatched types ‘const CharType [N]’ and ‘std::__cxx11::string {aka std::__cxx11::basic_string<char>}’
Value* timestamp = GetValueByPointer(document, PointerString);
^
When I output PointerString
to the screen it looks good to me:
"/Weather/1/timestamp"
Any help is most appreciated!
If you look at Pointer.h
, you see the various templated definitions of GetValueByPointer()
.
template <typename T>
typename T::ValueType* GetValueByPointer(T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
return pointer.Get(root, unresolvedTokenIndex);
}
template <typename T>
const typename T::ValueType* GetValueByPointer(const T& root, const GenericPointer<typename T::ValueType>& pointer, size_t* unresolvedTokenIndex = 0) {
return pointer.Get(root, unresolvedTokenIndex);
}
template <typename T, typename CharType, size_t N>
typename T::ValueType* GetValueByPointer(T& root, const CharType (&source)[N], size_t* unresolvedTokenIndex = 0) {
return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
}
template <typename T, typename CharType, size_t N>
const typename T::ValueType* GetValueByPointer(const T& root, const CharType(&source)[N], size_t* unresolvedTokenIndex = 0) {
return GenericPointer<typename T::ValueType>(source, N - 1).Get(root, unresolvedTokenIndex);
}
Now, what you hope for is implicit type conversion from a std::string -> GenericPointer<...>
, which won't happen, because of the C++ rule, that there is at most 1 implicit type conversion permitted. Here, you would need std::string -> const CharType(&source)[N] -> GenericPointer<...>
, which is one implicit conversion too many.
I think the easiest way to fix your predicament would be you write your own version of this function (as you probably will call it a couple of times), templated as the others, of course and which takes a const std::string &
or a const std::basic_string<CharType>&
and do the conversion explicitly.
That, plus removing the line I mentioned in my comment should work.