2

我正在为许多资源设计 REST API,我需要维护至少 2 个相同格式的表示(例如 JSON),它们仅在它们公开的数据量上有所不同。

例如,我有通过 REST 公开的书籍、出版商和作者。所以我有 3 个资源集合bookspublishersauthors. 当请求一本书时,我希望它包含关于其作者和出版商的最少信息——只是名称、ID 和指向其完整表示的超链接。

GET /books/12345
200 OK
{
    id: "12345",
    title: "My Book",
    authors: [
        {id:"111", name:"J. Smith", _href:"/authors/111"},
        {id:"222", name:"J.R.R. Tolkien", _href:"/authors/222"}
    ],
    publisher: {id:"333", name:"HarperCollins", _href:"/publishers/333"},
}

当用户请求时,例如/publishers/333,它应该获得更多关于它的信息,而不仅仅是名称和 ID:

{
    id: "333",
    name: "HarperCollins",
    address : { ... },
    contact : { ... },
    logo : { ... }
}

在我的应用程序中,我有 3 个类和Book,其中包含发布者和作者集合。我正在使用 Jackson 和 Spring MVC 通过 REST API 将所有实体公开为 JSON。PublisherAuthorBook

@RequestMapping("/books/{id}")
@ResponseBody
public Book getBook(String id) {
    return getBookById(id);
}

@RequestMapping("/authors/{id}")
@ResponseBody
public Book getAuthor(String id) {
    return getAuthorById(id);
}

现在的问题:

  • 在这种情况下,我如何告诉视图应该呈现哪个对象的哪些字段?
  • 我是否应该将我的每个实体拆分为两个 - 一个是简短的,另一个是完整的表示(例如AuthorReferenceand Author, PublisherReferenceand Publisher)。
  • 如果我选择选项#2,我应该更喜欢组合还是概括?
  • 是否有任何最佳实践如何处理 REST 应用程序中相同实体表示的不同分解?
4

2 回答 2

2

您是否考虑过使用更标准的超媒体格式,例如HAL

这样做,很明显你会在资源和其他资源的链接之间存在差异。例如,它最终可能是:

GET /books/123
200 OK
{
  "id": "123"
  "title": "My Book"
  "_links": {
     "author": [
       { "href": "/authors/111", "title": "J. Smith" },
       { "href": "/authors/321", "title": "Jules Verne" }
     ],
     "publisher": { "href": "/publishers/123", "title": "Harper Collins" }
  }
}

在实施方面,我会说你可以:

  1. 为每个资源表示创建自定义 DTO 类,如下所示:

     public class BookDto {
         @JsonProperty(value="_links")
         public LinkCollection getLinks() { }
    
         public String getTitle() { }
     }
    
  2. 使用相同的类,但在 Jackson 序列化之前使用过滤器修改对象,并使用 @JsonProperty/@JsonIgnore 的某种组合。

于 2013-03-26T15:39:43.637 回答
0

1/ 根据 Spring MVC 文档,要通过 HTTP 序列化您的对象,您必须定义自己的类,使用HttpMessageConverter<T>T实现。 http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/remoting.html#rest-message-conversionBookPublisherAuthor

2/ 没有必要将你的对象一分为二。选择从 an 中选取的字段的逻辑Author包含在AuthorToHttp implement HttpMessageConverter<Author>. AuthorReferenceToHttp implement HttpMessageConverter<Author>当您希望通过 HTTP 发送更少的数据时,只需要开发一个使用。

另一种解决方案可能是或者AuthorReference extend Author一方面Author extend AuthorReferenceAuthorToHttp implement HttpMessageConverter<Author>另一方面AuthorReferenceToHttp implement HttpMessageConverter<AuthorReference>是序列化您的Author.

3/继承/泛化就足够了。不一定需要模式。

复合是错误的选择,您不需要树结构。根据情况,您想要关于作者的所有数据 - 默认行为 - 或关于作者的主要数据 - “代理”行为 -。代理将是一个更好的选择。

4/ 不知道。

于 2013-03-26T20:29:53.577 回答