简体   繁体   中英

REST HATEOAS: How to serialize nested resources (with Spring HATEOAS)?

I use Spring HATEOAS for creating a REST HATEOAS API in my application. It works well so far, but I'm stuck when it comes to nested resources. What is the right approach for mapping a class hierarchy like this to a REST HATEOAS resource:

public class MyEntity {

    private int id;

    private List<ChildEntity> children;

}


public class ChildEntity {

    private int id;

    private AnotherEntity entity;

}


public class AnotherEntity {
}

I created Resource classes for all of this entities, but when serialising MyEntity, all contained entities get serialized as POJOs although I need them to be serialized as resources too (with links etc). Is there a way to add a resource to a parent resource (and not using the Resources class)? Or do I have to add a @JsonIgnore to children and then manually add the children as resources in my ResourceAssembler ? Wouldnt it then make more sense to use ResourceSupport instead of Resource?

Extending ResourceSupport:

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);
    }

}

The result is:

{
     "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"
        }
    }
}

But you have to consider if this is the right choice to connect different resources. Unless you offer in the controller methods get this embedded resources you would not be able the reach them individually. One solution for that is by using HAL. With HAL you can point to a resource by using _links property or embed this resources in the _embedded property.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM