2016-06-05 6 views
3

Есть случаи, когда данные, сериализованные или неэтериализированные в теле, например, тело 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 представлено различными объектами.

Я хотел бы знать, что является лучшим и наиболее распространенным подходом к этим сценариям. Я могу придумать несколько способов сделать это:

  1. Добавить атрибут идентификатора в класс Player. Мой дизайн не включает идентификатор, потому что он не нужен. Способы идентификации объекта по его ссылке и если они содержатся в коллекции, по их позиции в ней (если коллекция имеет позиции). Это можно считать плохой практикой, но я сделал это намеренно, и я не планирую менять его, если это необходимо.
  2. Также, имея идентификатор игрока, но вместо сериализации/десериализации команд в качестве списка игроков это будет просто список идентификаторов. Информация, содержащаяся в корпусе JSON, будет потеряна, но мы будем иметь более компактные данные.
  3. Придерживаясь моего дизайна без ID, как и в предыдущем пункте, я мог бы иметь список позиций (которые на практике фактически были бы идентификатором игрока, поскольку они служат средством идентификации), поэтому число будет ссылаться игроку в первой позиции в списке .
  4. Изменение контракта и наличие игроков с уникальным именем. Теперь у нас может быть ID, не добавляя в класс новый атрибут. Однако я думаю, что это плохая идея, потому что не обязательно, чтобы все игроки имели разные имена.

Какой был бы лучший подход? Что обычно делается? У вас есть разные предложения?

+0

Я бы напечатать наклейки с именами игроков («Игрок 1» ... «Игрок N») и есть игрок носить их :) – mjn

ответ

0

Я пошел ссылки позиционирования. По-видимому, это не считается плохим подходом.

Таким образом, тело JSON будет выглядеть так:

{ 
    "players": [ 
    { "name": "Player 1" }, 
    { "name": "Player 2" }, 
    { "name": "Player 3" }, 
    { "name": "Player 4" } 
    ], 
    "teams": [ 
    [ 3, 1 ], 
    [ 0, 2 ] 
    ] 
} 
4

я достиг кое-что близко к требованию в вопросе: я использовал Джексон Object Identity Feature, который позволяет определить, что значения некоторого свойства идентифицировать различные экземпляры 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(); 
    } 
} 

здесь является остальная часть 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(); 
    } 
} 

тест:

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 [email protected], Player [email protected], Player [email protected], Player [email protected], Player [email protected], Player [email protected], Player [email protected], Player [email protected]] 
l.teams 
[Team [email protected]:[Player [email protected], Player [email protected]], Team [email protected]:[Player [email protected], Player [email protected]], Team [email protected]:[Player [email protected], Player [email protected]], Team [email protected]:[Player [email protected], Player [email protected]]] 

до сих пор так хорошо, так почему «что-то, что близко к требованию»? мне пришлось немного изменить входной 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"] 
    } 
    ] 
} 
+0

Но для этого требуется, чтобы имя было уникальным идентификатором, не так ли? Это неудобство, о котором я упомянул в своем четвертом пункте. – dabadaba

+0

, но имя является единственным идентификатором! кто еще вы ожидаете, что Джексон (или любой другой парсер) будет идентифицировать уникального игрока? –

+0

ID (в базе данных) – dabadaba

Смежные вопросы