英文:
JSON to JAVA POJO with dynamic key
问题
import java.util.Map;
import org.codehaus.jackson.annotate.JsonAnySetter;
public class Lineups {
private Map<String, Team> team;
public Map<String, Team> getTeam() {
return team;
}
@JsonAnySetter
public void setTeam(String key, Team value) {
team.put(key, value);
}
// Rest of your class
}
Please note that the key issue in your previous attempt might have been that the team
map wasn't initialized before using it in the setTeam
method. Make sure that the team
map is properly initialized before using it.
Additionally, ensure you have the appropriate imports for the Team
class and other related classes. If you're still encountering issues, please provide more context or error messages for further assistance.
英文:
I am trying to convert from JSON to JAVA POJO.
My JSON-string looks like the following:
{
"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"
}
]
}
}
}
]
}
}
My problem is that the "Team" names are dynamical and will change for each match fixture JSON String I receive.
I have used http://www.jsonschema2pojo.org/ to get ready files but then it looks like the following:
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);
}
}
This works fine as long as it is Lecce and Spezia. If it is other teams I will not get the names and the other information.
I have succeded to fix this in another way when I made the mapping myself.
Then I solved it like this:
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() {
}
}
But I wanted to organize it and use anotations since I got other problems with the JSON files I recieved in my earlier setup.
I have tried to use something similar with Map<String, Team> team = new LinkedHashMap<>() in my new setup but I can´t get it to work.
Are there anybody that can assist me in how to solve this and get it to work with the files I get from http://www.jsonschema2pojo.org/.
答案1
得分: 2
首先是一个带有名为 `api` 的字段的对象:
{
"api": {
class Root {
@JsonProperty("api") private API api;
}
接下来是一个带有两个字段 results
和 fixtures
的对象,其中 fixtures
是一个数组或 List
,通常我们更倾向于使用 List
:
"results": 1,
"fixtures": [
class API {
@JsonProperty("results") private int results;
@JsonProperty("fixtures") private List<Fixture> fixtures; // array
}
然后是一个带有三个字段 fixture_id
、league_id
和 lineups
的对象,其中 lineups
是一个关联数组,在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; // 关联数组
}
其余部分相对简单:
"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;
}
<details>
<summary>英文:</summary>
Talking it from the top:
First part is an object with field named `api`:
```lang-json
{
"api": {
class Root {
@JsonProperty("api") private API api;
}
Next part is an object with two fields named results
and fixtures
, where fixtures
is an array or a List
, and we generally prefer using List
:
"results": 1,
"fixtures": [
class API {
@JsonProperty("results") private int results;
@JsonProperty("fixtures") private List<Fixture> fixtures; // array
}
Next part is an object with three fields named fixture_id
, league_id
, and lineups
, where lineups
is an associative array, which in Java is a 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
}
The rest is pretty 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;
}
答案2
得分: 0
我通常会对代码注释(代码文档)非常深入地进行处理,但对于诸如JSON解析之类的事情 - 代码行都是如此不言自明,以至于似乎是不必要的。我正在练习使用JSON库 javax.json
...
我不使用Java的组件注解(曾被称为Java Beans),所以以常规方式编写构造函数
和getter
是我习惯的方式。
以下是我的版本... 它比其他版本更长,但非常易读,并且非常简单地添加/删除方法。
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
英文:
I usually get really into code comments (Code Documentation), but with things like JSON Parsing - the lines of code are so self-explanatory, that it just seems unnecessary. I am practicing using the JSON Library javax.json
...
I do not use Java's Component Annotations (used to be called Java Beans), so writing constructors
and getters
the regular way is what I'm used to.
Here is my version... It is longer than the other version, but highly readable and adding / removing methods is extremely simple.
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");
}
}
This code will produce this output:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论