What is the problem with this java class that consumes a rest service?

0

I have a servlet:

import br.edu.ifpb.pos.model.Art;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.List;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.ws.rs.client.Client;
import javax.ws.rs.client.ClientBuilder;
import javax.ws.rs.client.WebTarget;
import javax.ws.rs.core.Response;

public class ArtistaServlet extends HttpServlet {

    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {
//    https://api.vagalume.com.br/rank.php&type=art&radio=coca-cola-fm&apikey=660a4395f992ff67786584e238f501aa  
        String uri = "https://api.vagalume.com.br";
        Client client = ClientBuilder.newClient();
        WebTarget root = client.target(uri).path("rank.php");

        WebTarget comments = root.queryParam("type", "art")
                .queryParam("radio", "coca-cola-fm")
                .queryParam("apikey", "660a4395f992ff67786584e238f501aa");
        Response resp = comments.request().get();
        String json = resp.readEntity(String.class);
        ObjectMapper mapper = new ObjectMapper()
                .configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
        List<Art> lista = mapper.readValue(json, new TypeReference<List<Art>>(){
        });
        lista.forEach(c -> System.out.println(c.name()));




            System.out.println(json);
        response.setContentType("text/html;charset=UTF-8");
        try (PrintWriter out = response.getWriter()) {
            out.println("<!DOCTYPE html>");
            out.println("<html>");
            out.println("<head>");
            out.println("<title>API</title>");
            out.println("</head>");
            out.println("<body>");
            for (Art art : lista) {
            out.println("<h3> " + art.name() + "   rank = "  +  art.rank() + "</h3>");            
            }
            out.println("</body>");
            out.println("</html>");
        }
    }
}

and this interface:

package br.edu.ifpb.pos.model;

import com.fasterxml.jackson.databind.annotation.JsonDeserialize;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import org.immutables.value.Value;

@Value.Immutable
@JsonDeserialize(as = ImmutableArt.class)
@JsonSerialize(as = ImmutableArt.class)
public interface Art {

    public String id();
    public String name();
    public String url();
    public String pic_small();
    public String pic_medium();
    public String uniques();
    public String views();
    public String rank();

}

I used the same logic to consume some rest services, but with api da vagalume I could not captures the list of artists ...
Here is the project that has these classes in github

Here's the error:

com.fasterxml.jackson.databind.JsonMappingException: Can not deserialize instance of java.util.ArrayList out of START_OBJECT token
 at [Source: {"art":{"month":{"period":{"year":"2017","month":"12"},"all":[{"id":"3ade68b7g30dd1ea3","name":"Ed Sheeran","url":"https:\/\/www.vagalume.com.br\/ed-sheeran\/","pic_small":"https:\/\/s2.vagalume.com\/ed-sheeran\/images\/profile.jpg","pic_medium":"https:\/\/s2.vagalume.com\/ed-sheeran\/images\/ed-sheeran.jpg","uniques":"208002","views":"366369","rank":"202.6"},{"id":"3ade68b7gb9e80ea3","name":"Demi Lovato","url":"https:\/\/www.vagalume.com.br\/demi-lovato\/","pic_small":"https:\/\/s2.vagalume.com\/demi-lovato\/images\/profile.jpg","pic_medium":"https:\/\/s2.vagalume.com\/demi-lovato\/images\/demi-lovato.jpg","uniques":"189935","views":"281442","rank":"185.0"},{"id":"3ade68b7g3ea23ea3","name":"Kell Smith","url":"https:\/\/www.vagalume.com.br\/kell-smith\/","pic_small":"https:\/\/s2.vagalume.com\/kell-smith\/images\/profile.jpg","pic_medium":"https:\/\/s2.vagalume.com\/kell-smith\/images\/kell-smith.jpg","uniques":"106449","views":"141385","rank":"103.7"},{"id":"3ade68b7g27d72ea3","name":"Thiago Matheus","url":"https:\/\/www.vagalume.com.br\/thiago-matheus\/","pic_small":"https:\/\/s2.vagalume.com\/thiago-matheus\/images\/profile.jpg","pic_medium":"https:\/\/s2.vagalume.com\/thiago-matheus\/images\/thiago-matheus.jpg","uniques":"95219","views":"108237","rank":"92.8"},{"id":"3ade68b6g6b94fda3","name":"Can\u00e7\u00f5es de Natal","url":"https:\/\/www.vagalume.com.br\/cancoes-de-natal\/","pic_small":"https:\/\/s2.vagalume.com\/cancoes-de-natal\/images\/profile.jpg","pic_medium":"https:\/\/s2.vagalume.com\/cancoes-de-natal\/images\/cancoes-de-natal.jpg","uniques":"93987","views":"244174","rank":"91.6"},{"id":"3ade68b5g1b38eda3","name":"Bruno e Marrone","url":"https:\/\/www.vagalume.com.br\/bruno-e-marrone\/","pic_small":"https:\/\/s2.vagalume.com\/bruno-e-marrone\/images\/profile.jpg","pic_medium":"https:\/\/s2.vagalume.com\/bruno-e-marrone\/images\/bruno-e-marrone.jpg","uniques":"87188","views":"146422","rank":"84.9"},{"id":"3ade68b7gc8cb1ea3","name":"Anitta","url":"https:\/\/www.vagalume.com.br\/anitta\/","pic_small":"https:\/\/s2.vagalume.com\/anitta\/images\/profile.jpg","pic_medium":"https:\/\/s2.vagalume.com\/anitta\/images\/anitta.jpg","uniques":"85509","views":"134193","rank":"83.3"},{"id":"3ade68b7gc2b03ea3","name":"1Kilo","url":"https:\/\/www.vagalume.com.br\/1kilo\/","pic_small":"https:\/\/s2.vagalume.com\/1kilo\/images\/profile.jpg","pic_medium":"https:\/\/s2.vagalume.com\/1kilo\/images\/1kilo.jpg","uniques":"84077","views":"140543","rank":"81.9"},{"id":"3ade68b7g73521ea3","name":"Henrique e Juliano","url":"https:\/\/www.vagalume.com.br\/henrique-e-juliano\/","pic_small":"https:\/\/s2.vagalume.com\/henrique-e-juliano\/images\/profile.jpg","pic_medium":"https:\/\/s2.vagalume.com\/henrique-e-juliano\/images\/henrique-e-juliano.jpg","uniques":"75953","views":"162824","rank":"74.0"},{"id":"3ade68b6g39a2fda3","name":"Jorge e Mateus","url":"https:\/\/www.vagalume.com.br\/jorge-e-mateus\/","pic_small":"https:\/\/s2.vagalume.com\/jorge-e-mateus\/images\/profile.jpg","pic_medium":"https:\/\/s2.vagalume.com\/jorge-e-mateus\/images\/jorge-e-mateus.jpg","uniques":"75295","views":"175375","rank":"73.3"}]}}}; line: 1, column: 1]
    at com.fasterxml.jackson.databind.JsonMappingException.from(JsonMappingException.java:148)

Firefly API json file:

{
  "art": {
    "week": {
      "period": {
        "year": "2011",
        "week": "34"
      },
      "all": [{
        "id": "3ade68b7g98d71ea3",
        "name": "Bruno Mars",
        "url": "https://www.vagalume.com.br/bruno-mars/",
        "pic_small": "https://www.vagalume.com.br/bruno-mars/images/profile.jpg",
        "pic_medium": "https://www.vagalume.com.br/bruno-mars/images/bruno-mars.jpg",
        "uniques": "84709",
        "views": "183162"
      }]
    }
  }
}

I suspected that my initial structure did not conform to API json. So I started mapping the json file to java classes in my tests, minus the Month . It does not appear explicitly in json. How to deduce it?

    
asked by anonymous 21.12.2017 / 21:19

1 answer

1

The schema of the JSON you are trying to deserialize does not match the interface structure that you have set up. Its Art interface corresponds to an element of array called all , which is not the root element of the JSON document. all is a property of month , which is a property of art .

You have to create the remaining interfaces:

Rank

@Value.Immutable
@JsonDeserialize(as = ImmutableRank.class)
@JsonSerialize(as = ImmutableRank.class)
public interface Rank {
    public Art art();
}

Art

Move Art to:

@Value.Immutable
@JsonDeserialize(as = ImmutableArt.class)
@JsonSerialize(as = ImmutableArt.class)
public interface Art {
    public Month month();
}

Month

@Value.Immutable
@JsonDeserialize(as = ImmutableMonth.class)
@JsonSerialize(as = ImmutableMonth.class)
public interface Month {
    public Period period();

    public List<All> all();
}

Period

@Value.Immutable
@JsonDeserialize(as = ImmutablePeriod.class)
@JsonSerialize(as = ImmutablePeriod.class)
public interface Period {
    public String month();
    public String year();
}

All

@Value.Immutable
@JsonDeserialize(as = ImmutableAll.class)
@JsonSerialize(as = ImmutableAll.class)
public interface All {
    public String id();
    public String name();
    public String url();
    public String pic_small();
    public String pic_medium();
    public String uniques();
    public String views();
    public String rank();
}

Ordering

Rank rank = mapper.readValue(json, Rank.class);
rank.art().month().all().forEach(a -> System.out.println(a.name()));
    
22.12.2017 / 13:11