Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Add links into projection's nested object

I use Spring Data REST's projections feature in order to have some nested-typed objects inside JSON:

{
   "id": 1,
   "name": "TEST",
   "user": {
      "id": 1,
      "name": "user1"
   },
   _links: {
       self: {
           href: "http://localhost:8082/accounts/1{?projection}",
           templated: true
       },
       user: {
           href: "http://localhost:8082/accounts/1/users"
       },
    }
}

How can I generate links inside the nested object? I want the following JSON representation:

{
       "id": 1,
       "name": "TEST",
       "user": {
          "id": 1,
          "name": "user1",
          _links: {
              self: {
                  href: "http://localhost:8082/users/1",
                  templated: true
              },
           }
       },
       _links: {
           self: {
               href: "http://localhost:8082/accounts/1{?projection}",
               templated: true
           },
           user: {
               href: "http://localhost:8082/accounts/1/users"
           },
        }
    }

P.S. I saw this question, but don't have an idea how to use it in my case (if it's possible at all)

like image 916
nKognito Avatar asked May 19 '15 13:05

nKognito


1 Answers

I stumbled across this question, looking for a solution. After some fiddling with the Spring Data REST docs section on Excerpts I have found out how to achieve this.

I assume Account is your root object and you want it to have a nested collection of Users, where each user in turn has _links.

1: Add an Excerpt for the Users object (this is a handy technique anyway to hide unimportant details on list collections)

@Projection(name = "userExcerpt", types = { User.class })
public interface UserExcerpt {
    String getName(); 
    String getEmail(); 
    ...
}

2: Associate the Excerpt with your UserRepository

@RepositoryRestResource(excerptProjection = UserExcerpt.class)
public abstract interface UserRepository extends JpaRepository<User, Long> ...

3: Add a Projection for Account:

@Projection(types = {Account.class})
public interface AccountUsersProjection {

    String getName();
    ...
    Set<UserExcerpt> getUsers();
}

The important bit here is that your Projection needs to reference UserExcerpt instead of User. This way the result returned from GET /accounts/projection=accountUsersProjectionwill look like this:

{
  "_embedded" : {
    "accounts" : [ {
      "name" : "ProjA",
      "users" : [ {
        "name" : "Customer Admin",
        "email" : "[email protected]",
        "_links" : {
          "self" : {
            "href" : "http://localhost:8080/users/2{?projection}",
            "templated" : true
          }, ...
        }
      } ], 
      "_links" : {
        "self" : {
          "href" : "http://localhost:8080/accounts/1"
        },
        ...
      }
    }  ]
  },
  "_links" : {
    "self" : {
      "href" : "http://localhost:8080/accounts"
    },
    ...
  },
  "page" : {
    "size" : 50,
    "totalElements" : 2,
    "totalPages" : 1,
    "number" : 0
  }
}
like image 70
Johannes Rudolph Avatar answered Sep 25 '22 06:09

Johannes Rudolph