从语言文件创建JSON对象

时间:2016-06-16 20:40:41

标签: c++ json file c++11

我的翻译文件如下:

#: this is just some comment
msgid ""
"this is a line.\n"
"this is a newline.\n"
"this is another newLine".
msgstr ""
"this can be filled in.\n"
"or left blank."
#: just another comment
msgid "Pizza"
msgstr ""

正如您所看到的,msgid可以是多行或单行。同样适用于msgstr

我的所有翻译文件都是这样的。如何使用上面的数据示例创建一个包含两个键的json对象:

[
    {
        "msgid": "this is a line.\nthis is a newline.\nthis is another newLine.",
        "msgstr": "this can be filled in.\n or left blank."
    },
    {
        "msgid": "Pizza",
        "msgstr": ""
    }
]

我可以访问我知道如何使用的json库。我正在努力解决循环数据的for(each)循环。

目前我有这段代码:

std::ifstream input(findFile("language.po"));
Json::Value jsonRoot = Json:arrayValue;
for( std::string line; getline( input, line ); )
{
    Json::Value Translation = Json::objectValue;
    if(line.find("msgid") == 0) {
        //messageId found
        Translation["msgid"] = line;
    } else if(line.find("msgstr") == 0) {
        //translated string was found
        Translation["msgstr"] = line;
    }
    jsonRoot.append(Translation);
}

然而,这为我不想要的每一行创建了一个新的json数组。

此时,当前输出(未测试)应如下所示:

[
    {
        "msgid": ""
    },
    {
        "msgstr": ""
    },
    {
        "msgid": "Pizza"
    },
    {
        "msgstr": ""
    }
]

2 个答案:

答案 0 :(得分:1)

我会写一个简单的状态机:

enum class State { INIT, ID, STR } state = State::INIT;

std::string buffer;

while (!end_of_file()) {
   auto s = get_next_line();

   if (is_comment(s)) {
      // do nothing

   } else if (is_msgid(s)) {

      if (state != State::STR) {
         buffer += s; // depending on how you read a line, you may have to add EOL here

      } else {
         put_msgid_into_json(buffer);
         buffer = s;
      }
      state = State::ID;

   } else if (is_msgstr(s)) {

      if (state != State::ID) {
         buffer += s; // depending on how you read a line, you may have to add EOL here

      } else {
         put_msgstr_into_json(buffer);
         buffer = s;
      }
      state = State::STR;

   }
}

if (state == State::ID) {
  put_msgid_into_json(buffer);
} else if (state == State::STR) {
  put_msgstr_into_json(buffer);
}

答案 1 :(得分:1)

您的循环正在向阵列添加每一行,而不管每行的内容如何。你需要的是一个状态机,所以你只需要将完成的对象添加到数组中,你需要在前一行中添加延续行,直到你到达下一个字段开始,你需要解析这些行来删除行前缀和引号。 / p>

尝试更像这样的事情:

std::ifstream input(findFile("language.po").string());

std::string msgid, msgstr;
std::string *field = NULL;
std::string::size_type start, end;

Json::Value jsonRoot = Json::arrayValue;

for( std::string line; std::getline( input, line ); )
{
    if (line.compare(0, 1, "#") == 0)
        continue;

    if (line.compare(0, 6, "msgid ") == 0)
    {
        if (!msgid.empty())
        {
            Json::Value Translation = Json::objectValue;
            Translation["msgid"] = msgid;
            Translation["msgstr"] = msgstr;
            jsonRoot.append(Translation);
        }

        msgid.clear();
        msgstr.clear();
        field = &msgid;
        start = 6;
    }
    else if (!field)
    {
        continue;
    }
    else if (line.compare(0, 7, "msgstr ") == 0)
    {
        field = &msgstr;
        start = 7;
    }
    else
    {
        start = 0;
    }

    start = line.find('\"', start);
    if (start == std::string::npos)
        continue;

    ++start;
    end = line.find('\"', start);
    if (end != std::string::npos)
        *field += line.substr(start, end-start);
    else
        *field += line.substr(start);
}

if (!msgid.empty())
{
    Json::Value Translation = Json::objectValue;
    Translation["msgid"] = msgid;
    Translation["msgstr"] = msgstr;
    jsonRoot.append(Translation);
}