Разобрать файл json из AWS S3 с C ++ и Jsoncpp - PullRequest
0 голосов
/ 06 февраля 2019

У меня есть эта функция C ++, которая загружает файлы S3 как istreams , используя AWS SDK C ++:

std::istream& s3read(std::string bucket, std::string key) {
    Aws::Client::ClientConfiguration aws_conf;
    aws_conf.region = Aws::Environment::GetEnv("AWS_REGION");
    aws_conf.caFile = "/etc/pki/tls/certs/ca-bundle.crt";
    Aws::S3::S3Client s3_client(aws_conf);
    Aws::S3::Model::GetObjectRequest object_request;
    object_request.WithBucket(bucket.c_str()).WithKey(key.c_str());
    auto get_object_outcome = s3_client.GetObject(object_request);

    if (get_object_outcome.IsSuccess()) {
        std::istream& res = get_object_outcome.GetResult().GetBody();
        return res;
    } else {
        ...
    };
};

Я вызываю ее из main.cpp и пытаюсьчтобы разобрать его с Jsoncpp :

std::istream& stream = s3read(bucket, key);
Json::Value json;
Json::Reader reader;
reader.parse(stream, json);

Однако, я продолжаю получать ошибка сегментации .Почему?

Мне кажется, проблема в том, что reader.parse нужны двоичные данные, а istream - нет.Но, если я прав, как я могу проанализировать поток как двоичный?

1 Ответ

0 голосов
/ 06 февраля 2019

Ваша классическая проблема возврат ссылки на временную

Вы можете немного изменить дизайн своего кода, чтобы избежать этого.Например:

static Json::Value parse_json(std::istream& src) {
     Json::Value ret;
     Json::Reader reader;
     reader.parse(src, ret);
     return ret;  
}
// Aws::String is actually same thing to std::string except the allocator
// in case of Android, otherwise this is std::string as it is. 
// You can use function like s3read("foo","bar");  
Json::Value s3read_json(const Aws::String& bucket,const Aws::String& key) {
    static constexpr const char *FILE_NAME = "/etc/pki/tls/certs/ca-bundle.crt";

    Aws::Client::ClientConfiguration aws_conf;
    aws_conf.region = Aws::Environment::GetEnv("AWS_REGION");
    aws_conf.caFile = FILE_NAME;

    Aws::S3::S3Client s3_client(aws_conf);
    Aws::S3::Model::GetObjectRequest object_request;
    object_request.WithBucket( bucket ).WithKey( key );

    auto object_outcome = s3_client.GetObject(object_request);

    if (object_outcome.IsSuccess()) {
        auto result = object_outcome.GetResult();
        // destructor of object_outcome is not yet called
        return parse_json( result.GetBody() );
    } else {
        ...
        // throw std::runtime_error("S3 connection failed");
    };
};
...