Как я могу добавить членов в документ rapidjson, используя целые числа в качестве ключа/имени?

Я использую цикл for и хочу использовать итератор i в качестве ключа/имени при добавлении члена в документ. Например, я хочу, чтобы документ выглядел так:

{"1":"123.321","2":"456.654"}

Вот что я пробовал до сих пор.

<сильный>1. Преобразование i в const char*

rapidjson::Value newDouble(6);
for(int i = 0;i<laserScan.size();i++){
    newDouble.SetDouble(laserScan[i]);
    const char* index = std::to_string(i).c_str();
    d.AddMember(index,newDouble,d.GetAllocator());
}

Это генерирует ошибку компилятора, сообщающую мне, что AddMember может принимать аргументы только типа rapidjson::GenericValue&:

error: no matching function for call to ‘rapidjson::GenericDocument<rapidjson::UTF8<> >::AddMember(const char*&, rapidjson::Value&, rapidjson::MemoryPoolAllocator<>&)’
     d.AddMember(index,newDouble,d.GetAllocator());//add this name-value pair to the JSON string

<сильный>2. Преобразование i в строку с использованием типов rapidjson

rapidjson::Value newDouble(6), newStringIndex(5);
for(int i = 0;i<laserScan.size();i++){    
    newDouble.SetDouble(laserScan[i]);
    const char* index = std::to_string(i).c_str();
    size = (rapidjson::SizeType)std::strlen(index);
    newStringIndex.SetString(rapidjson::StringRef(index,size));
    d.AddMember(newStringIndex,newDouble,d.GetAllocator());
}

Это вызывает следующую ошибку времени выполнения из класса Writer:

Assertion `!hasRoot_' failed.

Почему я запутался

Разве решение № 1 не должно быть таким же, как и следующее?

d.AddMember("1",newDouble,d.GetAllocator());    

Это работает, когда я пытаюсь это сделать, но я не могу понять, почему преобразование целого числа в const char* не будет.


person cemanuel    schedule 25.10.2015    source источник


Ответы (2)


Хотя вы уже нашли обходной путь, я хотел бы указать, почему оригинальное решение не работает.

Проблема решения № 1 заключается в том, что указатель index недействителен при выходе из области видимости.

Как указано в учебнике, вы можете создать ключевую строку с распределителем, чтобы сделать ее копию:

std::string s = std::to_string(i)
Value index(s.c_str(), s.size(), d.GetAllocator()); // copy string
d.AddMember(index, newDouble, d.GetAllocator());

И для вашего обходного пути вы можете просто:

dataArray.PushBack(laserScan[i], allocator);
person Milo Yip    schedule 02.11.2015

Я нашел обходной путь. Вместо того, чтобы делать все ключи целыми числами, я просто добавил ключевые «индексы» с соответствующим значением, представляющим собой массив всех индексов. Затем я добавил еще один массив под названием «данные», который содержал массив всех данных:

rapidjson::Document document;
rapidjson::Document::AllocatorType& allocator = document.GetAllocator();
rapidjson::Value dataArray(rapidjson::kArrayType), ;

for(int i = 0;i<laserScan.size();i++){                 
    dataArray.PushBack(rapidjson::Value().SetDouble(laserScan[i]),allocator);
}
document.AddMember("data",dataArrary,allocator);
person cemanuel    schedule 26.10.2015
comment
Спасибо Milo Yip за документацию - для исправления потребовалось несколько строк со страницы руководств. - person cemanuel; 26.10.2015