Transformando o retorno da API em objetos com o Wrapper.Net – Parte II
26.03.2012
Em continuação ao tutorial anterior montaremos a estrutura de classe completa para receber os dados do método ViewProductDetails.
Antes de iniciar o tutorial, faça o download dos arquivos do Wrapper .Net diretamente do nosso perfil no GitHub. Com os arquivos em mãos, adicione-os ao projeto no Visual Studio, ou se preferir, façam uma referência à .dll que também está disponível para download.
Nesse nosso tutorial anterior mostramos como serializar o retorno em JSON da API do Buscapé com o Wrapper .Net e transformar esses dados em classes. No tutorial de hoje, vamos dar continuidade a esse assunto, terminando a estrutura de classes para receber os dados completos do método ViewProductDetails.
Hoje nós já sabemos que o segredo todo está no método Deserialize da classe JavaScriptSerializer que irá fazer todo o trabalho pesado do parser para nós. Então, vamos completar a nossa estrutura de classes, a fim de realizar o parser de todo o JSON retornado. No tutorial passado, finalizamos com as seguintes classes:
public class JsonProductWrapper
{
public JsonProducts[] product { get; set; }
}
public class JsonProducts
{
public Product product { get; set; }
}
public class Product
{
public int totalsellers { get; set; }
public string productshortname { get; set; }
public double pricemax { get; set; }
public bool fulldescription { get; set; }
public bool hasmetasearch { get; set; }
public double pricemin { get; set; }
public int id { get; set; }
public int categoryid { get; set; }
}
Porém, o nosso JSON de retorno possui a seguinte estrutura completa:
{"product":[{
"product":{
"totalsellers":9,
"productshortname":"Notebook Apple Macbook Air MC966BZ",
"pricemax":"5399.00",
"fulldescription":true,
"hasmetasearch":false,
"links":[
{"link":{
"type":"product",
"url":"http://compare.buscape.com.br/apple-macbook-air-mc966bz-intel-core-i5-1-7-ghz-4096-mb-256-gb.html?mdapp=100&mddtn=69672797"}},
{"link":{
"type":"specification",
"url":"http://compare.buscape.com.br/prod_ficha?idu=337809"}},
{"link":{
"type":"xml",
"url":"http://sandbox.buscape.com/service/findOfferList/564771466d477a4458664d3d/br/?productId=337809&format=json"}}
],
"pricemin":"4091.91",
"currency":{"abbreviation":"BRL"},
"id":337809,
"categoryid":6424,
"thumbnail":{"url":"http://imagem.buscape.com.br/thumbs/ensopado/6424/200x200_337809_1.jpg"},
"specification":{
"item":[
{"item":{
"value":["13.3 \""],
"label":"Tela"}},
{"item":{
"value":["2 Porta(s)"],
"label":"Entrada USB"}},
{"item":{
"value":["Mac OS X Lion"],
"label":"Sistema Operacional"}}
],
"links":[
{"link":{
"type":"xml",
"url":"http://sandbox.buscape.com/service/viewProductDetails/564771466d477a4458664d3d/br/?productId=337809&format=json"}}
]
},
"quantity":0,
"rating":{
"useraveragerating":{
"specification":{
"item":[
{"item":{
"value":["10.0"],
"label":"Desempenho"}},
{"item":{
"value":["10.0"],
"label":"Duração da Bateria"}},
{"item":{
"value":["10.0"],
"label":"Design"}},
{"item":{
"value":["9.4"],
"label":"Custo-BenefÃcio"}},
{"item":{
"value":["10.0"],
"label":"Qualidade da Imagem"}},
{"item":{
"value":["10.0"],
"label":"Compatibilidade"}},
{"item":{
"value":["10.0"],
"label":"Portabilidade"}}]},
"links":[
{"link":{
"type":"xml",
"url":"http://sandbox.buscape.com/service/viewUserRatings/564771466d477a4458664d3d/br/?productId=337809&format=json"}}],
"rating":"10.0",
"numcomments":3}},
"eco":false,
"productname":"Apple Macbook Air MC966BZ Intel Core i5 1.7 GHz 4096 MB 256 GB"}}],
"category":{
"id":6424,
"thumbnail":{"url":"http://imagem.buscape.com.br/bp5/categorias/6424.jpg"},
"hasoffer":false,
"name":"Notebook",
"parentcategoryid":2,
"links":[
{"link":{
"type":"category",
"url":"http://compare.buscape.com.br/notebook.html?mdapp=100&mddtn=69672797"}},
{"link":{
"type":"xml",
"url":"http://sandbox.buscape.com/service/findProductList/564771466d477a4458664d3d/br/?categoryId=6424&format=json"}}],
"isfinal":true},
"details":{
"message":"success",
"elapsedtime":1,
"status":"success",
"code":0,
"applicationversion":"1.0.0.0",
"date":{
"minute":31,
"valid":true,
"timezone":-180,
"second":15,
"millisecond":280,
"month":3,
"year":2012,
"hour":16,
"day":19,
"xmlschematype":{
"namespaceuri":"http://www.w3.org/2001/XMLSchema",
"prefix":"",
"localpart":"dateTime"},
"eonandyear":{"lowestsetbit":2}},
"applicationpath":"http://bws-apps.buscape.com/mobile/update",
"applicationid":"564771466d477a4458664d3d"},
"schk":false,
"page":1,
"totalresultsavailable":1,
"totalpages":1,
"match":"all",
"totalresultsreturned":1}
Para começar, vamos terminar a estrutura de Produtos parseando todos os dados possíveis. Algumas classes terão que ser adicionadas para representar os objetos do JSON, como por exemplo, Links, Currency, Thumbnail, Specification, Rating. Analisando o nó product com calma podemos identificar melhor sua estrutura e, então, replicá-la em classes do .Net.
Para o nó product então teremos a seguinte estrutura de classes:
public class JsonProductWrapper
{
public JsonProducts[] product { get; set; }
}
#region Product Classes
public class JsonProducts
{
public Product product { get; set; }
}
public class Product
{
public int totalsellers { get; set; }
public string productshortname { get; set; }
public double pricemax { get; set; }
public bool fulldescription { get; set; }
public bool hasmetasearch { get; set; }
public Links[] links { get; set; } // New
public double pricemin { get; set; }
public Currency currency { get; set; } // New
public int id { get; set; }
public int categoryid { get; set; }
public Thumbnail thumbnail { get; set; } // New
public Specification specification { get; set; } // New
public int quantity { get; set; } // New
public Rating rating { get; set; } // New
public bool eco { get; set; } // New
public string productname { get; set; } // New
}
public class Links
{
public Link link { get; set; }
}
public class Link
{
public string type { get; set; }
public string url { get; set; }
}
public class Currency
{
public string abbreviation { get; set; }
}
public class Thumbnail
{
public string url { get; set; }
}
public class Specification
{
public Items[] item { get; set; }
public Links[] links { get; set; }
}
public class Items
{
public Item item { get; set; }
}
public class Item
{
public ArrayList value { get; set; }
public string label { get; set; }
}
public class Rating
{
public UserAverageRating useraveragerating { get; set; }
}
public class UserAverageRating
{
public Specification specification { get; set; }
public Links[] links { get; set; }
public double rating { get; set; }
public int numcomments { get; set; }
}
#endregion Product Classes
1
Analisando a estrutura, podemos ver que algumas classes foram reutilizadas, já que a estrutra básica delas é a mesma. Por exemplo <strong>Links</strong>, temos o objeto links em vários lugares do JSON, porém, ele sempre tem a mesma estrutura, o que nos permite reutilizar a classe.
Assim, finalizamos o nó <strong>products</strong> no JSON, porém, podemos observar que temos mais dados dentro do JSON do que só products. Então, vamos trabalhar novamente a partir da classe <strong>JsonProductWrapper</strong>, para podermos “parsear“ os nós <strong>category</strong>, <strong>details</strong> e outros que não precisarão de classe. Dessa forma a classe <strong>JsonProductWrapper</strong> ficará com a seguinte estrutura:
1
public class JsonProductWrapper
{
public JsonProducts[] product { get; set; }
public JsonCategory category { get; set; }
public JsonDetails details { get; set; }
public bool schk { get; set; }
public int page { get; set; }
public int totalresultsavailable { get; set; }
public int totalpages { get; set; }
public string match { get; set; }
public int totalresultsreturned { get; set; }
}
Vejam que todos os nós “pais” do objeto JSON estão representados na classe acima. Para alguns deles vamos utilizar somente os tipos int, string, bool, pois estes já atendem ao tipo do campo, porém em outros casos, precisamos criar novas classes para representar as estruturas mais complexas, de Category e Details.
#region Category Classes
public class JsonCategory
{
public int id { get; set; }
public Thumbnail thumbnail { get; set; }
public bool hasoffer { get; set; }
public string name { get; set; }
public int parentcategoryid { get; set; }
public Links[] links { get; set; }
public bool isfinal { get; set; }
}
#endregion Category Classes
#region Details Classes
public class JsonDetails
{
public string message { get; set; }
public string elapsedtime { get; set; }
public string status { get; set; }
public int code { get; set; }
public string applicationversion { get; set; }
public Date date { get; set; }
public string applicationpath { get; set; }
public string applicationid { get; set; }
}
public class Date
{
public int minute { get; set; }
public bool valid { get; set; }
public int timezone { get; set; }
public int second { get; set; }
public int millisecond { get; set; }
public int month { get; set; }
public int year { get; set; }
public int hour { get; set; }
public int day { get; set; }
public DateXmlSchemaType xmlschematype { get; set; }
public EonAndYear eonandyear { get; set; }
}
public class DateXmlSchemaType
{
public string namespaceuri { get; set; }
public string prefix { get; set; }
public string localpart { get; set; }
}
public class EonAndYear
{
public int lowestsetbit { get; set; }
}
#endregion Details Classes
Pronto, agora é só utilizar o método Deserialize da classe JavaScriptSerializer para que o .NET faça todo o serviço pesado de converter o JSON em objetos. Agora, podemos acessar os objetos de forma natural para recuperar todos os dados retornados pela API do Buscapé.
Abaixo o código completo que utilizamos nesse tutorial:
public partial class jsonII : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
Apiki_Buscape_API.Apiki_Buscape_API apiBuscape = new Apiki_Buscape_API.Apiki_Buscape_API("564771466d477a4458664d3d", string.Empty, "BR", "json");
string details = apiBuscape.ViewProductDetails(337809, string.Empty);
JavaScriptSerializer deserializer = new JavaScriptSerializer();
JsonProductWrapper productdetails = deserializer.Deserialize<JsonProductWrapper>(details);
}
}
public class JsonProductWrapper
{
public JsonProducts[] product { get; set; }
public JsonCategory category { get; set; }
public JsonDetails details { get; set; }
public bool schk { get; set; }
public int page { get; set; }
public int totalresultsavailable { get; set; }
public int totalpages { get; set; }
public string match { get; set; }
public int totalresultsreturned { get; set; }
}
#region Product Classes
public class JsonProducts
{
public Product product { get; set; }
}
public class Product
{
public int totalsellers { get; set; }
public string productshortname { get; set; }
public double pricemax { get; set; }
public bool fulldescription { get; set; }
public bool hasmetasearch { get; set; }
public Links[] links { get; set; } // New
public double pricemin { get; set; }
public Currency currency { get; set; } // New
public int id { get; set; }
public int categoryid { get; set; }
public Thumbnail thumbnail { get; set; } // New
public Specification specification { get; set; } // New
public int quantity { get; set; } // New
public Rating rating { get; set; } // New
public bool eco { get; set; } // New
public string productname { get; set; } // New
}
public class Links
{
public Link link { get; set; }
}
public class Link
{
public string type { get; set; }
public string url { get; set; }
}
public class Currency
{
public string abbreviation { get; set; }
}
public class Thumbnail
{
public string url { get; set; }
}
public class Specification
{
public Items[] item { get; set; }
public Links[] links { get; set; }
}
public class Items
{
public Item item { get; set; }
}
public class Item
{
public ArrayList value { get; set; }
public string label { get; set; }
}
public class Rating
{
public UserAverageRating useraveragerating { get; set; }
}
public class UserAverageRating
{
public Specification specification { get; set; }
public Links[] links { get; set; }
public double rating { get; set; }
public int numcomments { get; set; }
}
#endregion Product Classes
#region Category Classes
public class JsonCategory
{
public int id { get; set; }
public Thumbnail thumbnail { get; set; }
public bool hasoffer { get; set; }
public string name { get; set; }
public int parentcategoryid { get; set; }
public Links[] links { get; set; }
public bool isfinal { get; set; }
}
#endregion Category Classes
#region Details Classes
public class JsonDetails
{
public string message { get; set; }
public string elapsedtime { get; set; }
public string status { get; set; }
public int code { get; set; }
public string applicationversion { get; set; }
public Date date { get; set; }
public string applicationpath { get; set; }
public string applicationid { get; set; }
}
public class Date
{
public int minute { get; set; }
public bool valid { get; set; }
public int timezone { get; set; }
public int second { get; set; }
public int millisecond { get; set; }
public int month { get; set; }
public int year { get; set; }
public int hour { get; set; }
public int day { get; set; }
public DateXmlSchemaType xmlschematype { get; set; }
public EonAndYear eonandyear { get; set; }
}
public class DateXmlSchemaType
{
public string namespaceuri { get; set; }
public string prefix { get; set; }
public string localpart { get; set; }
}
public class EonAndYear
{
public int lowestsetbit { get; set; }
}
#endregion Details Classes
É isso developers! Continuem acompanhando nossos tutoriais e participem do nosso fórum de discussões.
