在某些情况下,正文中序列化或反序列化的数据(例如,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"}
]
}
]
}
您可以想象 Player X 指的是同一个对象,但可能最终会出现一个不需要的场景,其中 Player X 由不同的对象表示。
我想知道这些方案的最佳和最常用的方法是什么。我可以想到几种方法:
Player
课程添加ID属性。我的设计不包含ID,因为它不需要。识别对象的方式是通过引用,如果它们包含在集合中,则通过它们在其中的位置(如果集合具有位置)。这可能被认为是一种不好的做法,但我故意这样做,除非必要,否则我不打算改变它。最好的方法是什么?通常做什么?你有不同的建议吗?
答案 0 :(得分:5)
我达到了接近问题要求的东西: 我使用了杰克逊的Object Identity Feature,它允许定义某个属性的值来识别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();
}
}
以下是使用的POJO的其余部分:
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();
}
}
测试方法:
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]]
输出清楚地表明在玩家和团队中使用相同的对象:
{
"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"]
}
]
}
到目前为止一直很好,所以为什么&#34;接近要求的东西&#34;? 我不得不稍微改变输入json,以便杰克逊能够正确识别出球队中的球员是否参考了球员名单中的球员:
$ba = 'whatever';
$results =
DB::select(DB::raw("SELECT
t.id, t.AvgStyle, r.RateDesc
FROM (
SELECT
p.id, ROUND(AVG(s.Value)) AS AvgStyle
FROM posts p
INNER JOIN styles s
ON s.post_id = p.id
WHERE author = ?
GROUP BY p.id
) t
INNER JOIN rates r
ON r.digit = t.AvgStyle"
, )[$ba]); // @everton We just needed to move it one parentheses
答案 1 :(得分:0)
我去了定位参考。显然,它不一定被认为是一种糟糕的方法。
所以JSON主体就是这样的:
{
"players": [
{ "name": "Player 1" },
{ "name": "Player 2" },
{ "name": "Player 3" },
{ "name": "Player 4" }
],
"teams": [
[ 3, 1 ],
[ 0, 2 ]
]
}