Exclude some fields of Spring-data-rest resource

大兔子大兔子 提交于 2020-01-01 02:25:09

问题


I'm trying to use Spring-data-rest with spring-data-mongodb to expose read-only resources.

The problem I met, is that I want to have different views of my documents. Let's say I have some private information in a document, I don't want to expose them publicly.

So I tried several ways. I read this post https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring describing how to use JsonView in order to select the fields we want to expose.

I've tried like this :

@RepositoryRestResource(collectionResourceRel = "recommandation", path =    "recommandations")
interface RecommandationRepository extends MongoRepository<Recommendation,   ObjectId> {

@Override
@JsonView(View.Public.class)
Iterable<Recommendation> findAll(Iterable<ObjectId> objectIds);
... // other find methods
}

It doesn't works. It is however said in the comments : https://spring.io/blog/2014/12/02/latest-jackson-integration-improvements-in-spring#comment-1725671983 The answer suggests to use @Projections However @Projections result in url like that : "…/recommandations{?projection}" It means that the projection is just an option, so the full object is still exposed.

There is another method described here https://github.com/spring-projects/spring-data-rest/wiki/Configuring-the-REST-URL-path It suggests to use @RestResource(exported = false) annotation for the fields we don't want to expose.

But it's not flexible. If I want to expose a public read-only API and a private full access API. This annotation can't be disabled per api.

Is there another suggestion ?


回答1:


The important point is that Spring Data REST uses Jackson serialization parameters based on the domain object, not the repository definition. One simple way to hide a particular field from appearing in the JSON is like this:

@Entity
public class User {

    @Id @GeneratedValue
    private Long id;

    private String name;

    @JsonIgnore
    private String password;
    ...

In this example, my User object will NEVER export a password field no matter how this entity is used. Jackson supports either putting this on the field, or putting on the corresponding getter method.

When you put @JsonIgnore in the domain model, it makes it the default definition. Projections are options to alter what fields get rendered. Look at the following example:

@Projection(name = "noImages", types = {Item.class})
public interface NoImages {

    public Link getHtmlUrl();

}

This project can only be used when rendering Item domain objects. It isn't the default view, but instead an option to use via ?projection=noImages. But don't forget: when it comes time to apply Jackson serialization, the project will override the domain model's settings. This means you can write a projection for that User object up above and have it include String getPassword(). This would override the domain model's default setting an in turn export a password. Responsibility is yours.

One last thing. Spring Data REST supports Excerpt Projections. The most common use case is where you have a Customer object related to an Address object. By default, the relationship to see a customer's address would show a URI to navigate. But if you are wanting the address information all the time, you can avoid this extra GET operation by creating a projection that renders the address details. Then you can configure that for Customer objects, turn on this projection by default and essentially inline the address details whenever you fetch a customer record.

I realize the reference docs aren't quite up to date on all these details. You can track our progress to update the docs suitably as follows:

  • https://jira.spring.io/browse/DATAREST-449
  • https://jira.spring.io/browse/DATAREST-450
  • https://jira.spring.io/browse/DATAREST-451
  • https://jira.spring.io/browse/DATAREST-452
  • https://jira.spring.io/browse/DATAREST-453
  • https://jira.spring.io/browse/DATAREST-454

There is also a bug in that the ALPS metadata from Spring Data REST also needs to filter out domain fields tagged with @JsonIgnore (see https://jira.spring.io/browse/DATAREST-463)

P.S. @RestResource is deprecated and not the recommended approach to setting what fields get exported. Instead, use @JsonIgnore as shown earlier.




回答2:


Per @johannes-rudolph suggestion...

Consider applying this setting to the field (or property if you're mapping from accessors):

@JsonProperty(access = JsonProperty.Access.WRITE_ONLY)    
private String password;

This does what the access value implies: marking the associated field as write-only. Thus the value can be set but not retrieved via the Jackson/JSON serialized form.



来源:https://stackoverflow.com/questions/28322376/exclude-some-fields-of-spring-data-rest-resource

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!