使用GSON在Java中组织JSON响应输出

时间:2015-12-01 22:21:29

标签: java json api curl gson

今天,我决定尝试为自己创建一个应用程序,用于显示当前2015-2016赛季使用Java的过去和现在的足球场。

我目前似乎无法弄清楚如何正确显示JSON。 Web API端点为:http://api.football-data.org/v1/teams/81/fixtures(每天有50个请求限制,没有API令牌)。我正在尝试使用GSON来解析JSON,但文档似乎已经过去了。

这是我到目前为止的代码:

FCBFixtures.java

import java.io.*;
import java.net.*;
import com.google.gson.*;

public class FCBFixtures {

  private static String getJSON(String url, int timeout) {
    HttpURLConnection c = null;
    try {
      URL u = new URL(url);
      c = (HttpURLConnection) u.openConnection();
      c.setRequestMethod("GET");
      c.setRequestProperty("Content-length", "0");
      c.setRequestProperty("X-Auth-Token", "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX");
      c.setUseCaches(false);
      c.setAllowUserInteraction(false);
      c.setConnectTimeout(timeout);
      c.setReadTimeout(timeout);
      c.connect();
      int status = c.getResponseCode();

      switch (status) {
        case 200:
        case 201:
          BufferedReader br = new BufferedReader(new InputStreamReader(c.getInputStream()));
          StringBuilder sb = new StringBuilder();
          String line;
          while ((line = br.readLine()) != null) {
            sb.append(line+"\n");
          }
          br.close();
          return sb.toString();
      }

    } catch (IOException ex) {
        System.out.println(ex.getMessage());
        System.exit(1);
    } finally {
      if (c != null) {
        try {
          c.disconnect();
        } catch (Exception ex) {
            System.out.println(ex.getMessage());
            System.exit(1);
        }
      }
    }
    return null;
  }

  public static void main(String[] args) {
      String json = getJSON("http://api.football-data.org/v1/teams/81/fixtures", 500);
      Data data = new Gson().fromJson(json, Data.class);
      System.out.println(data);
  }
}

Data.java

import java.util.List;

public class Data {
    private String date;
    private String status;
    private Integer matchday;
    private String homeTeamName;
    private String awayTeamName;
    private Integer goalsHomeTeam;
    private Integer goalsAwayTeam;
    private List<Data> fixtures;

    public String getDate() { return date; }
    public String getStatus() { return status; }
    public Integer getMatchday() { return matchday; }
    public String getHomeTeamName() { return homeTeamName; }
    public String getAwayTeamName() { return awayTeamName; }
    public Integer getGoalsHomeTeam() { return goalsHomeTeam; }
    public Integer getGoalsAwayTeam() { return goalsAwayTeam; }
    public List<Data> getFixtures() { return fixtures; }

    public void setDate(String date) { this.date = date; }
    public void setStatus(String status) { this.status = status; }
    public void setMatchday(Integer matchday) { this.matchday = matchday; }
    public void setHomeTeamName(String homeTeamName) { this.homeTeamName = homeTeamName; }
    public void setAwayTeamName(String awayTeamName) { this.awayTeamName = awayTeamName; }
    public void setGoalsHomeTeam(Integer goalsHomeTeam) { this.goalsHomeTeam = goalsHomeTeam; }
    public void setGoalsAwayTeam(Integer goalsAwayTeam) { this.goalsAwayTeam = goalsAwayTeam; }
    public void setFixtures(List<Data> fixtures) { this.fixtures = fixtures; }

    public String toString() {
        if (date!=null) { //it's messy, coded it quickly but it works
            String[] split = date.split("T");
            String[] split2 = split[0].split("-");
            date = split2[1]+"/"+split2[2]+"/"+split2[0];
            String[] split3 = split[1].split(":");
            Integer hour = Integer.parseInt(split3[0])-7; //convert to eastern
            date += " "+hour+":"+split3[1];
        }
        String output = String.format("\n Fixtures:%-1s Matchday:%-1d Date:%-18s Home Team:%-25s Away Team:%-25s", fixtures, matchday, date, homeTeamName, awayTeamName);
        return output;
    }
}

我希望最终能够在自己的行上输出每个匹配日,并且每个变量都有适当的间距。任何帮助/方向将非常感谢。我之前没有任何GSON经验;但是,我之前使用过JSOUP,就像我的知识和情况的一些额外信息一样。

此外,cURL请求是(没有'X-Auth-Token'):curl -H 'X-Response-Control: minified' -X GET http://api.football-data.org/v1/teams/66/fixtures

1 个答案:

答案 0 :(得分:0)

当使用GSON和类似的JSON库时,它的关键是你拥有与JSON结构相匹配的数据结构。查看来自服务器的JSON响应,我看到:

{
    "_links": {
        "_self": {
            "href": "http://api.football-data.org/v1/teams/81/fixtures"
        },
        "team": {
            "href": "http://api.football-data.org/v1/teams/81"
        }
    },
    "count": 44,
    "fixtures": [
        {
            "_links": {
                "self": {
                    "href": "http://api.football-data.org/v1/fixtures/147488"
                },
                "soccerseason": {
                    "href": "http://api.football-data.org/v1/soccerseasons/399"
                },
                "homeTeam": {
                    "href": "http://api.football-data.org/v1/teams/77"
                },
                "awayTeam": {
                    "href": "http://api.football-data.org/v1/teams/81"
                }
            },
            "date": "2015-08-23T16:30:00Z",
            "status": "FINISHED",
            "matchday": 1,
            "homeTeamName": "Athletic Club",
            "awayTeamName": "FC Barcelona",
            "result": {
                "goalsHomeTeam": 0,
                "goalsAwayTeam": 1
            }
        },  
        ...array continues with your Data objects...

您的Data课程在回复中看起来像fixture。有两种方法可以让GSON正确解析它。

  • 为您的响应创建一个表示外部对象的容器。这可能是最常见和最好的方法,因为它非常清楚JSON的结构是什么样的,并且遵循与GSON解析的其余部分相同的格式。

    public static class DataContainer {
        private int count;
        private Data[] fixtures;
    
        public int getCount() {
            return count;
        }
        public void setCount(int count) {
            this.count = count;
        }
    
        public Data[] getFixtures() {
            return fixtures;
        }
        public void setFixtures(Data[] fixtures) {
            this.fixtures = fixtures;
        }
    }
    

    然后将Data个对象解析出数组

    DataContainer data = new Gson().fromJson(json, DataContainer.class);
    for(Data fixture : data.fixtures) {
        System.out.println(fixture);
    }
    
  • 如果您不喜欢包装器选项,您也可以将JSON解析为直接从JsonElement提供的JsonParser。然后,您可以从对象中检索"fixtures"元素并将其转换为Data个对象的数组。

    JsonElement responseElement = new JsonParser().parse(json);
    Data[] dataArray = new Gson().fromJson(responseElement.getAsJsonObject().get("fixtures"), Data[].class);
    for(Data fixture : dataArray ) {
        System.out.println(fixture);
    }
    

班级名称Data非常模糊,可能会考虑镜像API的名称Fixture