2015-06-15 1 views
1

пример моего источникаЗапись, чтобы jsoncpp (C++)

Json::Value root; 
    root["id"]=0; 
      Json::Value text; 
      text["first"]="i"; 
      text["second"]="love"; 
      text["third"]="you"; 
    root["text"]=text; 
    root["type"]="test"; 
    root["begin"]=1; 
    root["end"]=1; 
    Json::StyledWriter writer; 
    string strJson=writer.write(root); 
    cout<<"JSON WriteTest" << endl << strJson <<endl; 

я думал, что написать заказ. но результат

JSON WriteTest { "начать": 1, "конец": 1, "идентификатор": 0, "Текст": { "первый": "Я", «второй ": "любовь", "третий": "вы" }, "типа": "тест" }

я хочу формат JSON является

JSON WriteTest { "идентификатор": 0 , "Текст": { "первый": "я", "второй": "любовь", "третий": "вы" }, "тип" : "тест" "начать": 1, «конец»: 1, }

Как я могу написать заказ Jason?

+2

Заказ не должен иметь значения для приложений для записи или чтения. Поэтому вы должны исправить это. –

ответ

2

Нет, я не думаю, что вы можете. JsonCpp сохраняет свои значения в std::map<CZString, Value>, который всегда сортируется по сравнению с CZString. Поэтому он не знает первоначального заказа, который вы добавили.

0

У меня есть способ решить вашу проблему. Не хотел бы ты попробовать? Мое решение состоит в том, что вы используете boost/property_tree/json_parser.hpp, выход - какой формат вы хотите! О моем Кодексе:

#include <boost/property_tree/json_parser.hpp> 
#include <sstream> 
#include <iostream> 

using namespace std; 
int main() 
{ 
    boost::property_tree::ptree parser, child; 
    parser.put("id", 0); 
    child.put("first", "i"); 
    child.put("second", "love"); 
    child.put("third", "you"); 
    parser.put_child("text", child); 
    parser.put("type", "test"); 
    parser.put("begin", 1); 
    parser.put("end", 1); 
    stringstream ss; 
    boost::property_tree::json_parser::write_json(ss, parser); 
    cout << ss.str() << endl; 
    return 0; 
} 

Прежде чем запускать коды, вы должны установить boost 1.57. Коды хорошо работают в gcc 4.7, повышают 1,57. Результат: {"id": 0, "text": {"first": "i", "second": "love", "third": "you"} , «type»: «test» «begin»: 1, «end»: 1,}. О boost::property_tree::ptree, вы можете нажать here. Для сохранения данных он использовал list<pair<key, ptree>>. Таким образом, он сохранил неупорядоченные данные, если вы не вызвали list.sort(). Я надеюсь это тебе поможет.

+0

Что такое лицензирование? – user3853197

+0

Извините, я не знаю, что вы имеете в виду. О 'boost :: property_tree :: ptree', вы можете нажать [здесь] (http://www.boost.org/doc/libs/1_58_0/doc/html/property_tree.html#property_tree.intro). Моя догадка неверно, он использует 'list >' для сохранения данных. – cwfighter

+0

О boost :: property_tree :: ptree, вы можете нажать здесь. Он использовал 'list >' для сохранения данных. Таким образом, он сохранил неупорядоченные данные, если вы не вызвали 'list.sort()'. – cwfighter

0

Это мой обходной путь к получить упорядоченный выход JSon из jsoncpp

Json::Value root; 
root["*1*id"]=0; 
     Json::Value text; 
     text["*1*first"]="i"; 
     text["*2*second"]="love"; 
     text["*3*third"]="you"; 
root["*2*text"]=text; 
root["*3*type"]="test"; 
root["*4*begin"]=1; 
root["*5*end"]=1; 
Json::StyledWriter writer; 
string resultString=writer.write(root); 
resultString=ReplaceAll(resultString,"*1*", ""); 
resultString=ReplaceAll(resultString,"*2*", ""); 
resultString=ReplaceAll(resultString,"*3*", ""); 
resultString=ReplaceAll(resultString,"*4*", ""); 
resultString=ReplaceAll(resultString,"*5*", ""); 
cout<<"JSON WriteTest" << endl << resultString <<endl; 

с функцией RepleceAll определяется как этого

std::string ReplaceAll(std::string str, const std::string& from, const std::string& to) { 
     size_t start_pos = 0; 
     while((start_pos = str.find(from, start_pos)) != std::string::npos) { 
      str.replace(start_pos, from.length(), to); 
      start_pos += to.length(); // Handles case where 'to' is a substring of 'from' 
     } 
     return str; 
    } 
0

пары ключ-значение в объекте всегда будет отсортирован. Массивы Json не сортируются, они состоят из серии значений без ключей. Объекты, так как именованные коллекции (массивы) пар ключ-значение в скобках в массиве сохраняют свои позиции, например.

{ 
"adressen" : [ 
    { 
    "start" : { 
     "ID" : 1, 
     "key" : "2352KJ25", 
     "lat" : 52.157225922529967, 
     "lon" : 4.5298663828345527 
    } 
    }, 
    { 
    "eind" : { 
     "ID" : 2, 
     "key" : "2352KJ25", 
     "lat" : 52.157225922529967, 
     "lon" : 4.5298663828345527 
    } 
    } 
} 

ID, key, lat, lon сортируются, но start и eind находятся в исходном положении. Так, по крайней мере, ваш первый, второй, третий мог быть

Json::Value text(Json::arrayValue); 
text.append("I"); 
text.append("love"); 
text.append("you"); 

Нет необходимости в тегах первый, второй и третий! Возможно, это поможет вам найти обходное решение.

0

Как отметил The Dark, JsonCpp сохраняет свои значения в std::map<CZString, Value>, который всегда отсортированные по CZString сравнения, не держа отслеживать ни в первоначальном порядке, в котором вы добавили элементы, ни желаемый порядок на выходе.

Но вы можете использовать эту «скрытую функцию» в своей пользе. Я имею в виду, вам просто нужно, чтобы клавиши в нужном порядке выполняли «естественный» порядок CZString. У меня есть метод в моих классах оболочки JSONCPP, которые это делают. Код quick'n'dirty, преобразованный в простой функции, будет что-то вроде этого:

std::string sortedStr(Json::Value & value, std::vector<std::string> sortKeys) 
{ 
    Json::Value sortedValue; // The JSON object to store the new (sorted) hash 
    char newKey[60]; // I use C expressions, modify to C++ if you like 
    // Build new sortedValue 
    int i = 0; 
    for (auto & key : sortKeys) { 
     sprintf(newKey, "SORTEDKEY:%03d-%s", i++, key.c_str()); 
     sortedValue[newKey] = value[key]; 
    } 
    // Write to string, should be sorted on primary keys 
    Json::StyledWriter w; 
    std::string result = w.write(sortedValue); 
    // Remove aux. tags from primary keys 
    std::size_t pos = 0;  
    while ((pos = result.find("SORTEDKEY:", pos)) != std::string::npos) { 
     result.erase(pos, 14); 
    } 
    return result; 
} 

Чтобы использовать его, просто позвоните:

std::string sortedObjStr = sortedValue(myValue, {"first", "second", "third", "fourth"}); 

Обратите внимание, что:

  • I используйте это для относительно небольших объектов (данные конфигурации).
  • Я использую «тег» SORTEDKEY, так как это не будет отображаться нигде в моих данных. Измените в соответствии с вашими потребностями.
  • Я не проверю, что используемые ключи существуют. Вы можете добавить эту проверку.
  • Вы можете использовать это также для создания ограниченного, упорядоченного подмножества исходного объекта.