JSON 到 JAVA 带动态键的 POJO

JSON to JAVA POJO with dynamic key

我正在尝试从 JSON 转换为 JAVA POJO。

我的 JSON-string 如下所示:

{
  "api": {
    "results": 1,
    "fixtures": [
      {
        "fixture_id": 38480,
        "league_id": 95,
        "lineups": {
          "Lecce": {
            "coach": "F. Liverani",
            "coach_id": 2442,
            "formation": "4-2-3-1",
            "startXI": [
              {
                "team_id": 867,
                "player_id": 31719,
                "player": "M. Vigorito",
                "number": 22,
                "pos": "G"
              },
              {
                "team_id": 867,
                "player_id": 31721,
                "player": "M. Calderoni",
                "number": 27,
                "pos": "D"
              },
              {
                "team_id": 867,
                "player_id": 31725,
                "player": "F. Lucioni",
                "number": 25,
                "pos": "D"
              }
            ],
            "substitutes": [
              {
                "team_id": 867,
                "player_id": 31744,
                "player": "S. Palombi",
                "number": 14,
                "pos": "F"
              },
              {
                "team_id": 867,
                "player_id": 31740,
                "player": "A. Tabanelli",
                "number": 23,
                "pos": "D"
              },
              {
                "team_id": 867,
                "player_id": 31739,
                "player": "M. Scavone",
                "number": 30,
                "pos": "M"
              }
            ]
          },
          "Spezia": {
            "coach": "P. Marino",
            "coach_id": 2899,
            "formation": "4-2-3-1",
            "startXI": [
              {
                "team_id": 515,
                "player_id": 30820,
                "player": "E. Lamanna",
                "number": 1,
                "pos": "G"
              },
              {
                "team_id": 515,
                "player_id": 30829,
                "player": "C. Terzi",
                "number": 19,
                "pos": "D"
              },
              {
                "team_id": 515,
                "player_id": 30824,
                "player": "E. Capradossi",
                "number": 13,
                "pos": "D"
              },
              {
                "team_id": 515,
                "player_id": 30837,
                "player": "L. Mora",
                "number": 6,
                "pos": "M"
              }
            ],
            "substitutes": [
              {
                "team_id": 515,
                "player_id": 30848,
                "player": "D. Okereke",
                "number": 21,
                "pos": "G"
              },
              {
                "team_id": 515,
                "player_id": 30832,
                "player": "M. Crimi",
                "number": 15,
                "pos": "M"
              },
              {
                "team_id": 515,
                "player_id": 30842,
                "player": "S. Bidaoui",
                "number": 26,
                "pos": "D"
              }
            ]
          }
        }
      }
    ]
  }
}

我的问题是“团队”名称是动态的,并且会随着每场比赛的进行而改变 JSON 我收到的字符串。

我已经使用 http://www.jsonschema2pojo.org/ 准备好文件,但它看起来像下面这样:

import java.io.Serializable;
import java.util.HashMap;
import java.util.Map;
import org.codehaus.jackson.annotate.JsonAnyGetter;
import org.codehaus.jackson.annotate.JsonAnySetter;
import org.codehaus.jackson.annotate.JsonIgnore;
import org.codehaus.jackson.annotate.JsonProperty;
import org.codehaus.jackson.annotate.JsonPropertyOrder;
import org.codehaus.jackson.map.annotate.JsonSerialize;

@JsonSerialize(include = JsonSerialize.Inclusion.NON_NULL)
@JsonPropertyOrder({
    "Lecce",
    "Spezia"
})
public class Lineups implements Serializable
{

    @JsonProperty("Lecce")
    private Lecce lecce;
    @JsonProperty("Spezia")
    private Spezia spezia;
    @JsonIgnore
    private Map<String, Object> additionalProperties = new HashMap<String, Object>();
    private final static long serialVersionUID = -2766671198131939159L;

    /**
     * No args constructor for use in serialization
     * 
     */
    public Lineups() {
    }

    /**
     * 
     * @param lecce
     * @param spezia
     */
    public Lineups(Lecce lecce, Spezia spezia) {
        super();
        this.lecce = lecce;
        this.spezia = spezia;
    }

    @JsonProperty("Lecce")
    public Lecce getLecce() {
        return lecce;
    }

    @JsonProperty("Lecce")
    public void setLecce(Lecce lecce) {
        this.lecce = lecce;
    }

    @JsonProperty("Spezia")
    public Spezia getSpezia() {
        return spezia;
    }

    @JsonProperty("Spezia")
    public void setSpezia(Spezia spezia) {
        this.spezia = spezia;
    }

    @JsonAnyGetter
    public Map<String, Object> getAdditionalProperties() {
        return this.additionalProperties;
    }

    @JsonAnySetter
    public void setAdditionalProperty(String name, Object value) {
        this.additionalProperties.put(name, value);
    }

}

只要是莱切和斯佩齐亚,就可以正常工作。如果是其他球队我就不会知道名字和其他信息了。

我自己做映射的时候用另一种方式成功解决了这个问题。 然后我这样解决了:

public static class Lineups {
        private Map<String, Team> team = new LinkedHashMap<>();
        
        public Map<String, Team> getTeam() {
        return team;
        }

        public void setTeam(Map<String, Team> team) {
        this.team = team;
        }

        @JsonAnySetter
        public void setTeam(String key, Team value) {
        this.team.put(key, value);
        }
             
        public Lineups() {
            
        }
    }

但我想组织它并使用注释,因为我在早期设置中收到的 JSON 文件遇到了其他问题。 我尝试在我的新设置中使用与 Map team = new LinkedHashMap<>() 类似的东西,但我无法让它工作。

有没有人可以帮助我解决这个问题并让它与我从 http://www.jsonschema2pojo.org/ 获得的文件一起工作。

自上而下:

第一部分是一个字段名为 api:

的对象
{
    "api": {
class Root {
    @JsonProperty("api") private API api;
}

下一部分是一个对象,有两个字段,分别是resultsfixtures,其中fixtures是一个数组或者是一个List,我们一般更喜欢使用List:

        "results": 1,
        "fixtures": [
class API {
    @JsonProperty("results")  private int results;
    @JsonProperty("fixtures") private List<Fixture> fixtures; // array
}

下一部分是一个包含三个字段的对象,这些字段分别名为 fixture_idleague_idlineups,其中 lineups 是一个 associative array,在 Java 是 Map<String, ?>:

            {
                "fixture_id": 38480,
                "league_id": 95,
                "lineups": {
                    "Lecce": {
class Fixture {
    @JsonProperty("fixture_id") private int fixtureId;
    @JsonProperty("league_id")  private int leagueId;
    @JsonProperty("lineups")    private Map<String, Lineup> lineups; // associative array
}

剩下的还不错straight-forward:

                        "coach": "F. Liverani",
                        "coach_id": 2442,
                        "formation": "4-2-3-1",
                        "startXI": [
                            ...
                        ],
                        "substitutes": [
                            ...
                        ]
class Lineup {
    @JsonProperty("coach")       private String coach;
    @JsonProperty("coach_id")    private int coachId;
    @JsonProperty("formation")   private String formation;
    @JsonProperty("startXI")     private List<Player> startXI;
    @JsonProperty("substitutes") private List<Player> substitutes;
}
                            {
                                "team_id": 867,
                                "player_id": 31719,
                                "player": "M. Vigorito",
                                "number": 22,
                                "pos": "G"
                            },
class Player {
    @JsonProperty("team_id")   private int teamId;
    @JsonProperty("player_id") private int playerId;
    @JsonProperty("player")    private String player;
    @JsonProperty("number")    private int number;
    @JsonProperty("pos")       private String pos;
}

我通常非常喜欢代码注释(代码文档),但是 JSON 解析 - 代码行是如此self-explanatory,似乎没有必要。我正在练习使用 JSON 库 javax.json...

我不使用 Java 的 Component Annotations(以前称为 Java Beans) , 所以写 constructorsgetters 是我习惯的常规方式。

这是我的版本...比其他版本长,但是可读性高并且添加/删除方法非常简单。

import java.io.*;
import javax.json.*;
import java.util.*;

public class S
{
    public static class Player
    {
        public final String name, position;
        public final int playerId, teamId, number;
        public final boolean starting;

        public Player(String name, String position, int playerId, int teamId, int number, boolean starting)
        { 
            this.name=name; this.position=position;
            this.playerId=playerId; this.teamId=teamId; this.number=number;
            this.starting=starting;
        }

        public String toString()
        {
            return
                "Name:      " + name      + '\n' +
                "Position:  " + position  + '\n' +
                "Number:    " + number    + '\n' +
                "Starting:  " + (starting ? "Starting Lineup" : "Substitute") + '\n';
        }
    }

    public static class Team extends Vector<Player>
    {
        public final String teamName, coachName, formation;
        public final int coachId;

        public Team(String teamName, String coachName, int coachId, String formation)
        {
            this.teamName=teamName; this.coachName=coachName; this.coachId=coachId;
            this.formation=formation;
        }

        public Player findByName(String name)
        {
            for (Player player : this) if (player.name.equalsIgnoreCase(name)) return player;
            return null;
        }

        public Player findByNumber(int number)
        {
            for (Player player : this) if (player.number == number) return player;
            return null;
        }

        public Player findByPosition(String position)
        {
            for (Player player : this) if (player.position.equalsIgnoreCase(position)) return player;
            return null;
        }

        public String toString()
        {
            StringBuffer sb = new StringBuffer();
            sb.append(
                "Team Name:    " + teamName + '\n' +
                "Coach Name:   " + coachName + '\n' +
                "Formation:    " + formation + "\n\n"
            );
            for (Player player : this) sb.append(player.toString() + "\n");
            return sb.toString();
        }
    }

    public static void main(String[] argv) throws IOException
    {
        Reader r = new FileReader("teams.json");
        JsonObject teamsList = Json
            .createReader(r)
            .readObject()
            .getJsonObject("api")
            .getJsonArray("fixtures")
            .getJsonObject(0)
            .getJsonObject("lineups");
        
        Vector<Team> teams = new Vector<>();

        for (String teamName : teamsList.keySet())
        {
            JsonObject      teamObj         = teamsList.getJsonObject(teamName);
            String          coachName       = teamObj.getString("coach");
            int             coachId         = teamObj.getInt("coach_id");
            String          formation       = teamObj.getString("formation");
            JsonArray       startingLineup  = teamObj.getJsonArray("startXI");
            JsonArray       substitutes     = teamObj.getJsonArray("substitutes");
            List<JsonArray> lineups         = new Vector<>();
            Team            team            = new Team(teamName, coachName, coachId, formation);
            int             count           = 0;

            teams.add(team);
            lineups.add(startingLineup);
            lineups.add(substitutes);

            for (JsonArray lineup : lineups)
            {
                boolean starting = (count++ == 0);
                for (JsonObject playerObj : lineup.getValuesAs(JsonObject.class))
                {
                    int     teamId          = playerObj.getInt("team_id");
                    int     playerId        = playerObj.getInt("player_id");
                    String  name            = playerObj.getString("player");
                    int     number          = playerObj.getInt("number");
                    String  position        = playerObj.getString("pos");

                    Player player = new Player(name, position, playerId, teamId, number, starting);
                    team.add(player);
                }
            }
        }

        for (Team team : teams) System.out.println(team.toString() + "\n");
    }
}

此代码将产生此输出:

Team Name:    Lecce
Coach Name:   F. Liverani
Formation:    4-2-3-1

Name:      M. Vigorito
Position:  G
Number:    22
Starting:  Starting Lineup

Name:      M. Calderoni
Position:  D
Number:    27
Starting:  Starting Lineup

Name:      F. Lucioni
Position:  D
Number:    25
Starting:  Starting Lineup

Name:      S. Palombi
Position:  F
Number:    14
Starting:  Substitute

Name:      A. Tabanelli
Position:  D
Number:    23
Starting:  Substitute

Name:      M. Scavone
Position:  M
Number:    30
Starting:  Substitute


Team Name:    Spezia
Coach Name:   P. Marino
Formation:    4-2-3-1

Name:      E. Lamanna
Position:  G
Number:    1
Starting:  Starting Lineup

Name:      C. Terzi
Position:  D
Number:    19
Starting:  Starting Lineup

Name:      E. Capradossi
Position:  D
Number:    13
Starting:  Starting Lineup

Name:      L. Mora
Position:  M
Number:    6
Starting:  Starting Lineup

Name:      D. Okereke
Position:  G
Number:    21
Starting:  Substitute

Name:      M. Crimi
Position:  M
Number:    15
Starting:  Substitute

Name:      S. Bidaoui
Position:  D
Number:    26
Starting:  Substitute