Parsing JSON in C++ con Rapidjson

Mattepuffo's logo
Parsing JSON in C++ con Rapidjson

Parsing JSON in C++ con Rapidjson

Per fare il parsing di una struttra JSON in C++ ci stanno molte librerie; io mi sono buttato su Rapidjson.

La documentazione sul sito ufficiale non è proprio il massimo, ma nel complesso è abbastanza semplice da implementare e includere nel nostro progetto.

Scaricate la libreria e aggiungete la cartella rapidjson al progetto; dentro ci stanno diversi file .h.

Quello che faremo è usare CURL per prendere i dati da remoto, fare il cast di CURLcode in string, e infine parsare i dati JSON.

Cominciamo come al solito dal file di intestazione:

#ifndef READ_H
#define    READ_H

#include <iostream>
#include <curl/curl.h>
#include <iomanip>
#include "rapidjson/document.h"
#include "rapidjson/rapidjson.h"

using namespace std;
using namespace rapidjson;

extern "C" int readCurlHelper(char *data, size_t size, size_t nmemb, string *buffer);

class Read {
public:
    Read();
    virtual ~Read();
    void read(string file);
    size_t curlToString(char *data, size_t size, size_t nmemb, string *buffer);
private:
    string response;
    string url;
    CURL *curl;
    CURLcode res;
    struct curl_slist *headers;
    Document document;
};

#endif

Rispetto all'ultimo articolo, abbiamo aggiunto le librerie rapidjson e un oggetto Document.

Il nostro file di implementazione sarà una cosa del genere:

#include "read.h"

extern "C" int readCurlHelper(char *data, size_t size, size_t nmemb, string *buffer) {
    Read *that = (Read *) buffer;
    return that->curlToString(data, size, nmemb, NULL);
}

Read::Read() {
    headers = NULL;
    url = "http://www.sito.com/";
}

void Read::read(string file) {
    curl_slist_append(headers, "Accept: application/json");
    curl_slist_append(headers, "Content-Type: application/json");
    curl_slist_append(headers, "charset: utf-8");
    curl = curl_easy_init();
    string completeUrl;
    completeUrl = url.append(file);
    if (curl) {
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_URL, completeUrl.c_str());
        curl_easy_setopt(curl, CURLOPT_HTTPGET, 1);
        curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headers);
        curl_easy_setopt(curl, CURLOPT_WRITEFUNCTION, &readCurlHelper);
        curl_easy_setopt(curl, CURLOPT_WRITEDATA, this);
        res = curl_easy_perform(curl);
        curl_easy_cleanup(curl);
        if (res == CURLE_OK) {
            const char *json = response.c_str();
            if (document.Parse < 0 > (json).HasParseError()) {
                cout << document.GetParseError() << "\n" << document.GetErrorOffset() << endl;
            } else {
                cout << left << setw(6) << "ID" << right << setw(8) << "Valore" << right << setw(30) << "Causale" << right << setw(12) << "Conto" << setw(13) << right << "Data" << endl;
                cout << "----------------------------------------------------------------------" << endl;
                for (SizeType i = 0; i < document.Size(); i++) {
                    cout << left << setw(6) << document[i]["id"].GetString()
                            << right << setw(8) << document[i]["valore"].GetString()
                            << right << setw(30) << document[i]["causale"].GetString()
                            << right << setw(12) << document[i]["conto"].GetString()
                            << right << setw(13) << document[i]["data"].GetString() << endl;
                }
                document.Empty();
                document.Clear();
            }
        } else {
            cerr << "Error: " << curl_easy_strerror(res) << endl;
        }
        response.empty();
        response.clear();
    }
}

size_t Read::curlToString(char *data, size_t size, size_t nmemb, string *buffer) {
    response.append(data, size * nmemb);
    return size * nmemb;
}

Read::~Read() {
}

Qui il cast da CURLcode a string ci serve per parsare la stringa JSON che riceviamo dal server.

Il tutto avviene dopo il controllo di CURL_OK.

Prima trasformiamo la stringa in un puntatore const char; questo lo diamo in pasto a rapidjson.

Se non ci sono errori di parsing stampiamo la risposta a video.

Per visualizzare meglio i dati ho usato vari setw, ma ovviamente non sono obbligatori.

Nel ciclo for stampiamo tutti i valori della stringa JSON che ci servono; le chiavi gliele passiamo come stringhe.

Dopo facciamo un pò di pulizia.

 

Direi che è tutto; in tre articoli abbiamo visto come usare CURL per fare richieste al server e come fare il parsing di una stringa JSON; ovviamente non è detto che il server risponda in JSON, ma ad oggi è un formato veramente comune e io lo uso spesso.

Ciao!


Condividi

Commentami!