3

私は C++ を初めて使用し、文字列からさまざまなデータを削除して JSON として解析する方法を理解できません。

私が見つけた最も文書化された JSON パーサー、jansson を使用することになりました。私は最初のハードルで立ち往生していますが、それは素晴らしいようです。

私のプログラムは、次の形式の文字列を受け取ります。

5::/chat:{"name":"steve","args":[{"connection":"true"}, { "chatbody" : "I am the body" }]}

中括弧の外側はすべて次のように削除しました。

std::string str=message;
unsigned pos = str.find("{");
std::string string = str.substr (pos);

それは残します:

{
    "name": "steve",
    "args": [
        {
            "connection": "true"
        },
        {
            "chatbody": "I am the body"
        }
    ]
}

これを解析するステージ1で立ち往生しています。文字列を char に変換してから json_loads を使用しようとしましたが、何も役に立ちません...

全体は次のようになります。

void processJson(string message)
{
    json_t *root;
    json_error_t error;
    size_t i;

    std::string str=message;
    unsigned pos = str.find("{");
    std::string str3 = str.substr (pos);

    const char * c = str.c_str();

    json_t *data, *sha, *name;

    root = json_loads(c, 0, &error);
    data = json_array_get(root, i);        
    cout << data;

    if(!json_is_object(root))
    {
      fprintf(stderr, "error: commit data %d is not an object\n", i + 1);
    }

}

値を取得する必要がありますが、取得するのは 01、02、03 だけです....

is_json_object は次のように述べています。

error: commit data 1068826 is not an object
error: commit data 1068825 is not an object
error: commit data 1068822 is not an object

私は何を間違っていますか?どうすればこれを適切にフォーマットできますか? 最終的には配列を反復処理する必要がありますが、これを乗り越えることはできません。これは単なる初心者の間違いだと確信しています。

-編集-

厳密なサイズ要件のため、Boost の使用を避けようとしています。

4

4 に答える 4

4

JSON フォーマットについては、C++ を介してプリティ プリント ソリューションを検索しましたが、役に立ちませんでした。最後に、最終的に C++ に変換した Java コードをいくつか見つけました。JSON フォーマットについては、次のことを試してください。

std::string formattedJson(char *json)
{
    std::string pretty;

    if (json == NULL || strlen(json) == 0)
    {
        return pretty;
    }

    std::string str     = std::string(json);
    bool        quoted  = false;
    bool        escaped = false;
    std::string INDENT  = "    ";
    int         indent  = 0;
    int         length  = (int) str.length();
    int         i;

    for (i = 0 ; i < length ; i++)
    {
        char ch = str[i];

        switch (ch)
        {
            case '{':
            case '[':
                pretty += ch;

                if (!quoted)
                {
                    pretty += "\n";

                    if (!(str[i+1] == '}' || str[i+1] == ']'))
                    {
                        ++indent;

                        for (int j = 0 ; j < indent ; j++)
                        {
                            pretty += INDENT;
                        }
                    }
                }

                break;

            case '}':
            case ']':
                if (!quoted)
                {
                    if ((i > 0) && (!(str[i-1] == '{' || str[i-1] == '[')))
                    {
                        pretty += "\n";

                        --indent;

                        for (int j = 0 ; j < indent ; j++)
                        {
                            pretty += INDENT;
                        }
                    }
                    else if ((i > 0) && ((str[i-1] == '[' && ch == ']') || (str[i-1] == '{' && ch == '}')))
                    {
                        for (int j = 0 ; j < indent ; j++)
                        {
                            pretty += INDENT;
                        }
                    }
                }

                pretty += ch;

                break;

            case '"':
                pretty += ch;
                escaped = false;

                if (i > 0 && str[i-1] == '\\')
                {
                    escaped = !escaped;
                }

                if (!escaped)
                {
                    quoted = !quoted;
                }

                break;

            case ',':
                pretty += ch;

                if (!quoted)
                {
                    pretty += "\n";

                    for (int j = 0 ; j < indent ; j++)
                    {
                        pretty += INDENT;
                    }
                }

                break;

            case ':':
                pretty += ch;

                if (!quoted)
                {
                    pretty += " ";
                }

                break;

            default:
                pretty += ch;

                break;
        }
    }

    return pretty;
}
于 2016-12-29T20:49:52.913 に答える
4

JSON ファイルを自動的に解析する機能を備えた Boost のプロパティ ツリーのような既存のソリューションをいつでも使用できます。文字通り、次の 2 つのヘッダーを追加するのと同じくらい簡単です。

#include <boost/property_tree/ptree.hpp>
#include <boost/property_tree/json_parser.hpp>

そして、この小さなコード スニペットを追加します。ここで、jsonfile は明らかにファイル名を意味します。

boost::property_tree::ptree jsontree;
boost::property_tree::read_json(jsonfile, jsontree);

JSON ツリーから情報を抽出したい場合は、次のように行うことができます。ここで、type は抽出するデータのタイプで、insert.key.path.here はキーへのパスで、それぞれの親を持ちますピリオドで区切られたキー。

jsonfile.get<type>(insert.key.path.here);

さらに、そこにある JSON 文字列が有効であるとは思えません。JSON 文字列自体の余分な部分を削除することはできましたが、ここに問題があると思います。

"connection" : true,

ここで JSON 文字列の有効性を確認できます: http://jsonformatter.curiousconcept.com/

于 2013-07-07T18:31:23.153 に答える
2

Casablanca (REST C++ SDK)には、HTTP 機能を使用しない場合でも使用できる非常に優れた JSON パーサーがあります。

JSON パーサー ファイルを静的ライブラリに抽出し、それを既存のプロジェクトにリンクできます。抽出するファイルは次のとおりです。

src\json\json.cpp
src\json\json_parsing.cpp
src\json\json_serialization.cpp
src\utilities\asyncrt_utils.cpp

include\cpprest\json.h
include\cpprest\xxpublic.h
include\cpprest\basic_types.h
include\cpprest\asyncrt_utils.h

最近プロジェクトの静的ライブラリとして使用したので、これが機能することを確認できます。

Jansson も使用しようとしましたが、Casablanca のパーサーの方が使いやすく、Unicode サポートが優れています。

于 2014-01-14T09:30:46.670 に答える