Integrando C# e C++ via serviço REST - Parte II

No último artigo foi criado um serviço WCF REST em C# com as repostas serializadas via json e um cliente C++ que utilizava a libcurl para consumir o resultado.  Este serviço devolvia uma lista de strings de acordo com a URL acessada, neste artigo será demonstrado como solicitar objetos e acessar suas propriedades utilizando uma biblioteca chamada rapidjson.

Escolhendo a Rapidjson

A escolha da rapidjson se deu pois ela é uma biblioteca que exige a inclusão apenas dos cabeçalhos _(header only) _o que evita a adição de arquivos binários no projeto. Porém existem outras bibliotecas que podem ser utilizadas e que possuem alguns recursos diferentes e no próprio site do json é disponibilizada uma lista com algumas bibliotecas para C++ e demais linguagens.

Alterações no WCF

As primeira mudança necessárias é alterar os métodos expostos pelo WCF para retornarem dados mais aderentes ao formato json, ou seja, é necessário encapsular os retornos das chamadas dentro de objetos, pois antes estávamos apenas retornando arrays nos endpoints. 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// Criação da classe
[DataContract]
public class Library
{
[DataMember]
public List<string> Sections;
}

// alteração no método do serviço
[WebInvoke(Method = "GET", ResponseFormat = WebMessageFormat.Json, UriTemplate = "sections/")]
public Library GetSections()
{
var lib = new Library();
lib.Sections = new List<string>() { "ScienceFiction", "Fantasy" };
return lib;
}

Desta forma as respostas seguirão o seguinte formato:

1
2
3
4
//seções
{"Sections":["ScienceFiction","Fantasy"]}
// livros em uma seção
{"Books":[{"Author":"Isaac Asimov","Copies":10,"Title":"I Robot"},{"Author":"John Scalzi","Copies":5,"Title":"Old Man's War"},{"Author":"Orson Scott Card","Copies":5,"Title":"Ender's Game"}],"Name":"ScienceFiction"}

Alterações no Cliente C++

Com os retornos do WCF modificados é possível utilizar a rapidjson para tratar os objetos.  A função que realiza a chamada da libcurl desenvolvida no artigo anterior não muda, apenas o tratamento da resposta do serviço será através dos objetos fornecidos pela nova biblioteca e o primeiro passo para isso é incluir o header da biblioteca.

1
#include "rapidjson/document.h"

Assim é possível utilizar a classe Document da rapidjson, que é a classe que analisa e transforma os dados recebidos e disponibiliza a informação através de um objeto, para acessar o conteúdo do objeto.

1
2
3
// parser da rapidjson
Document library;
library.Parse(data.c_str());

Caso a execução do comando acima ocorra sem problemas, não é o foco deste artigo as alternativas para o tratamento de erros, será criado um objeto onde é possível acessar as propriedades definidas no WCF através de seus nomes para obter os dados que foram enviados pelo serviço.

1
const Value& books = section["Books"];

O trecho de código acima possibilita o acesso a uma propriedade que neste caso é um array de strings e a rapidjson possui mecanismo de iteração para todas propriedades que são arrays. Desta forma percorrer os valores é simples, porém uma ressalva é que ainda não possui suporte ao foreach do C++.

1
2
for (auto libItems = sections.Begin(); libItems != sections.End(); ++libItems)
std::cout << "Na Seção '" << libItems->GetString() << "' temos: " << std::endl;

Tipos de Dados

Em cada posição do iterador temos uma string que deve ser acessada através do método GetString(). A rapidjson possui diversos métodos de acesso aos dados cobrindo grande parte dos tipos possíveis de retorno:

  • GetBool()
  • GetString()
  • GetUint()
  • GetInt()
  • GetUint64()
  • GetInt64()
  • GetDouble()

E cada método deve ser utilizado de acordo com o tipo da propriedade sendo acessada.

1
std::cout << book["Copies"].GetInt() << " cópias do '" << book["Title"].GetString() << "' de " << book["Author"].GetString() << std::endl;

Com estes recursos foi possível acessar todos os dados do objeto de maneira organizada e simples, levando em consideração o seu tipo.

Resultado

Executando o serviço e cliente teremos o resultado abaixo.

Execução do programa cliente

Código

O código completo deste artigo pode ser acessado em meu repositório no Bitbucket.