REST HATEOAS: как сериализовать вложенные ресурсы (с помощью Spring HATEOAS)?

Я использую Spring HATEOAS для создания REST HATEOAS API в своем приложении. Пока это работает хорошо, но я застрял, когда дело доходит до вложенных ресурсов. Каков правильный подход для сопоставления такой иерархии классов с ресурсом REST HATEOAS:

public class MyEntity {

    private int id;

    private List<ChildEntity> children;

}


public class ChildEntity {

    private int id;

    private AnotherEntity entity;

}


public class AnotherEntity {
}

Я создал ресурс классы для всех этих объектов, но при сериализации MyEntity все содержащиеся объекты сериализуются как POJO, хотя мне нужно, чтобы они также сериализовались как ресурсы (со ссылками и т. д.). Есть ли способ добавить ресурс к родительскому ресурсу (и не используя класс ресурсов)? Или мне нужно добавить @JsonIgnore к дочерним элементам, а затем вручную добавить дочерние элементы в качестве ресурсов в моем ResourceAssembler? Тогда не будет ли разумнее использовать ResourceSupport вместо Resource?


person krinklesaurus    schedule 08.09.2015    source источник


Ответы (1)


Расширение поддержки ресурсов:

public class MyEntityResource extends ResourceSupport {

    private int identificator;

    private List<ChildEntityResource> children;

    public int getIdentificator() {
        return identificator;
    }

    public void setIdentificator(int id) {
        this.identificator = identificator;
    }

    public List<ChildEntityResource> getChildren() {
        return children;
    }

    public void setChildren(List<ChildEntityResource> children) {
        this.children = children;
    }

}

public class ChildEntityResource extends ResourceSupport {

    private int identificator;

    private AnotherEntityResource entity;

    public int getIdentificator() {
        return identificator;
    }

    public void setIdentificator(int identificator) {
        this.identificator = identificator;
    }

    public AnotherEntityResource getEntity() {
        return entity;
    }

    public void setEntity(AnotherEntityResource entity) {
        this.entity = entity;
    }
}

public class AnotherEntityResource extends ResourceSupport {

    private String value;


    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }
}

@RestController
public class EntityController {
    @RequestMapping(value = "/entity", method = RequestMethod.GET)
    public ResponseEntity<MyEntityResource> index() {

        AnotherEntityResource anotherEntityResource  = new AnotherEntityResource();
        anotherEntityResource.add(new Link("link-for-another-entity-resource", "rel-1"));

        anotherEntityResource.setValue("value for Another Entity","rel-2");

        ChildEntityResource childEntityResource = new ChildEntityResource();
        childEntityResource.setIdentificator(20);
        childEntityResource.setEntity(anotherEntityResource);
        childEntityResource.add(new Link("link-for-child-entity-resource", "rel-3"));

        MyEntityResource entityResource = new MyEntityResource();

        entityResource.setIdentificator(100);
        entityResource.setChildren(Arrays.asList(childEntityResource));
        entityResource.add(new Link("link-for-entity-resource"));

        return new ResponseEntity<MyEntityResource>(entityResource,  HttpStatus.OK);
    }

}

@SpringBootApplication
public class Application {

    public static void main(String[] args) {
         SpringApplication.run(Application.class, args);
    }

}

Результат:

{
     "identificator": 100,
     "children": [
         {
             "identificator": 20,
             "entity": {
                 "value": "value for Another Entity",
                 "_links": {
                     "rel-1": {
                         "href": "link-for-another-entity-resource"
                    }
                }
            },
            "_links": {
                "rel-2": {
                    "href": "link-for-child-entity-resource"
                } 
            }
        }
    ],
    "_links": {
        "rel-3": {
            "href": "link-for-entity-resource"
        }
    }
}

Но вы должны подумать, является ли это правильным выбором для подключения разных ресурсов. Если вы не предложите методы контроллера для получения этих встроенных ресурсов, вы не сможете получить к ним доступ по отдельности. Одним из решений для этого является использование HAL. С помощью HAL вы можете указать на ресурс, используя свойство _links, или внедрить эти ресурсы в свойство _embedded.

person Osvaldo Pina    schedule 12.09.2015