在某些情况下,在主体中序列化或反序列化的数据(例如,JSON主体)包含对同一对象的引用.例如,一个包含玩家列表的JSON主体,以及由这些玩家组成的团队列表:
{
"players": [
{ "name": "Player 1" },
{ "name": "Player 2" },
{ "name": "Player 3" },
{ "name": "Player 4" },
{ "name": "Player 5" },
{ "name": "Player 6" },
{ "name": "Player 7" },
{ "name": "Player 8" }
],
"teams": [
{
"name": "Team 1",
"players": [
{ "name": "Player 1"},
{ "name": "Player 2"}
]
},
{
"name": "Team 2",
"players": [
{ "name": "Player 3"},
{ "name": "Player 4"}
]
},
{
"name": "Team 3",
"players": [
{ "name": "Player 5"},
{ "name": "Player 6"}
]
},
{
"name": "Team 4",
"players": [
{ "name": "Player 7"},
{ "name": "Player 8"}
]
}
]
}
Run Code Online (Sandbox Code Playgroud)
可以想象,玩家X指的是同一个对象,但可能最终会出现一个不需要的场景,其中玩家X由不同的对象表示.
我想知道这些场景的最佳和最常见的方法是什么.我可以想到几种方法:
Player类添加ID属性.我的设计不包含ID,因为它不需要.识别对象的方式是通过引用,如果它们包含在集合中,则通过它们在其中的位置(如果集合具有位置).这可能被认为是一种不好的做法,但我故意这样做,除非必要,否则我不打算改变它.什么是最好的方法?通常做什么?你有不同的建议吗?
我达到了一个接近问题要求的东西:我使用了杰克逊的对象身份特征,它允许定义某个属性的值来识别POJO的不同实例:
@JsonIdentityInfo(generator=ObjectIdGenerators.PropertyGenerator.class,
property="name", scope=Player.class)
public class Player
{
public String name;
public Player() {}
public Player(String name) { this.name = name; }
public String toString() {
// prints name and java object id
return name + "-" + super.toString();
}
}
Run Code Online (Sandbox Code Playgroud)
以下是使用的POJO的其余部分:
public class League
{
public List<Player> players;
public List<Team> teams;
}
public class Team
{
public String name;
public List<Player> players;
public Team() {}
public Team(String name) { this.name = name; }
public String toString() {
return name + "-" + super.toString() + ":" + players.toString();
}
}
Run Code Online (Sandbox Code Playgroud)
测试方法:
public static void main(String[] args)
{
ObjectMapper objectMapper = new ObjectMapper();
try (Reader reader = new FileReader("C:/Temp/xx.json")) {
League l = objectMapper.readValue(reader, League.class);
System.out.println("l.players");
System.out.println(l.players);
System.out.println("l.teams");
System.out.println(l.teams);
} catch (Exception e) {
e.printStackTrace();
}
}
Run Code Online (Sandbox Code Playgroud)
输出清楚地表明在玩家和团队中使用相同的对象:
l.players
[Player 1-test.JSONTest$Player@641147d0, Player 2-test.JSONTest$Player@6e38921c, Player 3-test.JSONTest$Player@64d7f7e0, Player 4-test.JSONTest$Player@27c6e487, Player 5-test.JSONTest$Player@49070868, Player 6-test.JSONTest$Player@6385cb26, Player 7-test.JSONTest$Player@38364841, Player 8-test.JSONTest$Player@28c4711c]
l.teams
[Team 1-test.JSONTest$Team@59717824:[Player 1-test.JSONTest$Player@641147d0, Player 2-test.JSONTest$Player@6e38921c], Team 2-test.JSONTest$Team@146044d7:[Player 3-test.JSONTest$Player@64d7f7e0, Player 4-test.JSONTest$Player@27c6e487], Team 3-test.JSONTest$Team@1e9e725a:[Player 5-test.JSONTest$Player@49070868, Player 6-test.JSONTest$Player@6385cb26], Team 4-test.JSONTest$Team@15d9bc04:[Player 7-test.JSONTest$Player@38364841, Player 8-test.JSONTest$Player@28c4711c]]
Run Code Online (Sandbox Code Playgroud)
到目前为止这么好,为什么"接近要求的东西"呢?我不得不稍微改变输入json,以便杰克逊能够正确识别出球队中的球员是否参考球员名单中的球员:
{
"players": [
{ "name": "Player 1" },
{ "name": "Player 2" },
{ "name": "Player 3" },
{ "name": "Player 4" },
{ "name": "Player 5" },
{ "name": "Player 6" },
{ "name": "Player 7" },
{ "name": "Player 8" }
],
"teams": [
{
"name": "Team 1",
"players": [ "Player 1", "Player 2"]
},
{
"name": "Team 2",
"players": [ "Player 3", "Player 4"]
},
{
"name": "Team 3",
"players": [ "Player 5", "Player 6"]
},
{
"name": "Team 4",
"players": [ "Player 7", "Player 8"]
}
]
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1337 次 |
| 最近记录: |