Спринг Джексон - двунаправленные отношения - разверните ссылки в JSON - PullRequest
0 голосов
/ 26 января 2020

У меня есть два класса, владелец и велосипед. Владелец ссылается на список велосипедов. Bicycle ссылается на владельца.

При запросе я бы хотел, чтобы возвращенный json расширил ссылки на один уровень. Таким образом, каждая запись велосипеда расширила бы владельца ref. И каждая запись владельца расширила бы каждый реф. Конечно, я хочу избежать бесконечной рекурсии!

Так вот, что я хочу.

~ $ curl -H "Авторизация: Bearer $ TOKEN" -k -w "\ n "https://mint191: 8453 / api / v1 / bicycles [{" id ": 1," model ":" civi c "," owner ": {" id ": 1," userName ":" user1 "}}, {" id ": 2," model ":" montpellier "," owner ": {" id ": 2," userName ":" user2 "}}, {" id ": 3 , "model": "cambridge", "owner": {"id": 3, "userName": "user3",}}, {"id": 4, "model": "tern A7", "owner" : {"id": 2, "userName": "user2"}}]

~ $ curl -H "Авторизация: Носитель $ TOKEN" -k -w "\ n" https://mint191 : 8453 / api / v1 / owners [{"id": 1, "userName": "user1", "bicycles": [{"id": 1, "model": "civi c", }]}, {"id": 2, "userName": "user2", "bicycles": [{"id": 2, "model": "montpellier"}, {"id": 4, "model" : "tern A7"}]}, {"id": 3, "userName": "user3", "bicycles": [{"id": 3, "model": "cambridge",}]}]

А вот и классы. Исходя из кода, два приведенных выше вызова API остальных вызовут бесконечную рекурсию.

public class Owner {
   @Id
   @GeneratedValue(strategy = GenerationType.AUTO, generator = "owner_gen")
   private long id;
   @NotNull
   @Size(min = 4, max = 10)
   private String userName;

   @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, mappedBy = "owner")
   private List<Bicycle> bicycles; 
}


public class Bicycle {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "bike_gen")
    private long id;
    private String model;

    @ManyToOne(fetch = FetchType.EAGER)
    @JoinColumn(name = "owner_id", nullable = false)
    private Owner owner;
}

До сих пор я пробовал @JsonManagedReference, @JsonBackReference. Класс, использующий @JsonBackReference, не раскрывается, класс, использующий @JsonManagedReference, раскрывается. И никакой бесконечной рекурсии. Так что почти там.

Я также попробовал @JsonIdentityInfo. Здесь проблема в том, что любая запись указана только один раз. После перечисления любые дальнейшие ссылки на эту запись являются просто идентификатором. Поэтому, если у владельца есть несколько велосипедов, в списке велосипедов будет отображен расширенный владелец для велосипеда A, но только идентификатор владельца для велосипеда B, поскольку этот владелец уже включен в ответ.

Не думаю, что я Я прошу что-то особенно необычное (?), и при просмотре различных страниц всегда используйте очень простые данные или подходите к данным только в одном направлении. Я понимаю, что это больше данных, но это значительно облегчает программирование.

Нужен ли мне специальный сериализатор?

Может кто-нибудь дать совет?

1 Ответ

0 голосов
/ 30 января 2020

Это то, что я сделал.

Я удалил все аннотации Джексона из моделей

В сервисном слое для getbicycle? (единственное, множественное число) и getowner? (множественное число / единственное число) Я добавил код, например, getBicycles ()

public Collection<Bicycle> getBicycles() {
    Collection<Bicycle>bicycles = new ArrayList<>();  
    bicycleRepo.findAll().forEach(bicycles::add);  
    for (Bicycle b: bicycles) {
        b.getOwner().setBicycles(null);
    }
    return bicycles;  
}

и getOwners ()

public Collection<Owner> getOwners() {
    Collection<Owner>owners = new ArrayList<>();  
    ownerRepo.findAll().forEach(owners::add);  

    for  (Owner o : owners) {
        for (Bicycle b : o.getBicycles()) {
            b.setOwner(null);
        } 
    }
    return owners;  
}

Результат не идеален - есть в указанном объекте напечатано значение NULL, но оно дает мне то, что я хочу.

...