JSON超媒体API与表格和链接 [英] JSON Hypermedia Api with forms and links

查看:179
本文介绍了JSON超媒体API与表格和链接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正处于规划REST API的早期阶段,我希望它遵守REST的HATEOAS约束。但我也想提供一个JSON格式。所以我的问题是,是否有约定用于表示JSON中的链接和表单。



我找到了链接的例子,看起来这是一种很常见的方式代表链接:

 links:[
{rel:self,href: http://example.org/entity/1},
{rel:friends,href:http://example.org/entity/1/friends}]

另一方面表示形式并不是我所见过的。我在想,也许有人坐下来思考一些事情,但考虑了所有的注意事项:

 forms :[
{rel:new client,action:/ clients,method:post,
fields:[name:string, zipcode:int,signedup:date,state:[Alabama,...] ...]}]

这个灵感来自于这段视频,Jon Moore建议JSON不适用于超媒体api:

http://oredev.org/2010/sessions/hypermedia-apis



一个非常好的演讲!



所有的输入值得赞赏!

解决方案

我已经调查过这个话题了一段时间,但我不确定哪些可能的解决方案可以使用ppl,哪些不可以。只有几个例子可用...所以我需要一些专家的评论...(我的例子将主要在HAL + JSON中。)



1 。)



我有一种感觉,链接关系应该只是GET,因为在HTML中它们是用于包含样式表之类的东西。我想其他的ppl也有同样的感觉,因为IANA链接有一个编辑表单和一个 create-form 关系。
$ b


  • 因此,第一个可能的解决方案是使用表单关系对链接进行解除引用,因此可以下载写入操作的表单描述。这些表单描述可以包含HTML片段或我们可以用来生成表单的模式。例如



    只要提及您可以使用相同的方法,通过在标头中发送相同的链接并发送原始JSON作为body。

      {
    _links:{
    edit-form:{
    href:http:// example .com / users / 1?form = edit,
    type:text / html,
    title:编辑用户
    }
    }







    那么如果链接关系是不只是为了阅读的目的吗?


    <2>。

    然后我们可以使用HAL的内置功能:


    • 如果我们发送数据,那么我们可以使用类型描述请求主体而不是响应主体。 OFC。在这种情况下,不应该有响应主体,否则这种解决方案会令人困惑。

        {
      _links :{
      curies:[
      {
      name:my,
      href:http://example.com/rels/{rel} ,
      templated:true
      }
      ],
      my:edit:{
      href:http://example.com/用户/ 1,
      type:application / vnd.example.user + json,
      title:编辑用户
      }
      } $ b $在这种情况下,客户端将知道 my:edit

      / code>表示这是一个编辑表单,并且通过检查MIME类型,它将知道要显示的表单类型。

    • 解决方案将自定义链接关系用于同一目的:

        {
      _links:{
      curies:[
      {
      name:my,
      href:http://example.com/rels/{rel},
      templated:true
      }
      ],
      my:edit-user:{
      href:http://example.com/users/1 ,
      type:application / json,
      title:编辑用户
      }
      }
      }

      因此,通过获取文档 http://example.com/rels/edit-user 我们可以找到关于如何构建用于编辑用户的表单的描述,因此我们可以在客户端支持 my:edit-user 链接关系。文档可以包含可选的HTML表单或某种模式,或者使用表单描述词汇表的RDF文档等。 我们可以按照相同的方法通过链接的配置文件属性。例如:

        {
      _links:{
      curies:[
      {
      name:my,
      href:http://example.com/rels/{rel},
      模板化:true
      }
      ],
      my:edit:{
      href:http://example.com/users/1,
      type:application / json,
      title:编辑用户,
      profile:http://example.com/profiles/user
      }
      }





      $ b因此在这里链接关系表示这是一个编辑表单, profile 描述如何在 http://example.com/profiles/user URL下生成表单。




    <3>。


    或者我们可以使用自定义属性来扩展HAL。 / p>


    • 例如

        {
      _forms/ dougrain-forms> dougrain-forms
      这样做: :{
      edit:{
      href:http://example.com/users/1,
      headers:{
      content-type :application / json
      },
      title:编辑用户,
      method:PUT,
      schema:{
      required:[
      name
      ],
      type:object,
      properties:{
      name:{
      type:string
      }
      },
      title:用户属性
      }
      }
      }


    • 只要我们没有,您可以使用其他方法一个标准关于HAL和HAL表单,例如我宁愿使用类似猫鼬模式的解决方案:

        {
      name:John,
      _links:{
      curies:[
      {
      name:my,
      href:http://example.com/rels/{rel},
      模板化:true
      $ b $,
      my:edit:{
      href:http://example.com/users/1,
      type: application / json,
      title:编辑用户,
      method:PUT,
      _embedded:{
      schema:{
      name:字符串
      }
      }
      }
      }
      }


      4。)



      不要使用链接关系和简单的JSON格式(如HAL),而是使用带有一个或多个词汇表的RDF。使用RDF比较困难,但它是将客户从REST服务中解耦出来的细粒度解决方案,而HAL仅仅是一个粗粒度的解决方案...


      • 例如 JSON-LD Hydra 和一个自定义词汇:

          {
        @context:[
        http://www.w3.org/ns/hydra/core,
        https://example.com/docs#
        ],
        @id:https://example.com/users/1,
        name:John,
        操作:{
        @键入:ReplaceResourceOperation,
        title:编辑用户,
        method:PUT,
        expect:{
        @id: https://example.com/docs#User,
        supportedProperty:{
        @type:SupportedProperty,
        title:name,
        property:https://example.com/docs#User.name,
        range:http://www.w3.org/2001/XMLSchema#string,
        required:true
        }
        }
        }
        }



      I am in the early stages of planning a REST api, and I would like for it to adhere to the HATEOAS constraint of REST. But I would also like to provide a JSON format. So my question is if there are conventions out there to represent links and forms in JSON.

      I have found examples of links, and it looks like this is a pretty common way of representing links:

      "links": [ 
      {"rel": "self", "href":"http://example.org/entity/1"},
      {"rel": "friends", "href":"http://example.org/entity/1/friends"}] 
      

      Representing forms on the other hand, is not something that I have seen much of. I was thinking that perhaps somebody had sat down and thought up something along these lines, but considered all the caveats:

      "forms" : [
      {"rel" : "new client", "action" : "/clients", "method": "post", 
      "fields" : ["name":"string", "zipcode":"int", "signedup":"date", "state": ["Alabama",...]...]}]
      

      The inspiration for this comes from looking at this video, where Jon Moore suggests that JSON is not a good format for a hypermedia api:

      http://oredev.org/2010/sessions/hypermedia-apis

      A really good talk by the way!

      All input is appreciated!

      解决方案

      I have investigated this topic for a while, but I am not certain about which possible solutions ppl use and which not. There are only a few examples available... So I'll need some review from experts... (My examples will be mostly in HAL+JSON.)

      1.)

      I have a feeling that link relations should be GET only, because in HTML they are for including things like stylesheets. I guess other ppl had the same feeling, because there is an edit-form and a create-form by IANA link relations.

      • So the first possible solution to dereference links with form relations and so download the form descriptions for the write operations. These form descriptions can contains HTML fragments or a schema which we can use to generate the forms. For example

        Just to mention you can use the same approach by sending the same links in the header and send raw JSON as body.

        {
            "_links": {
                "edit-form": {
                    "href": "http://example.com/users/1?form=edit",
                    "type": "text/html",
                    "title": "Edit user"
                }
            }
        }
        

      So what if link relations are not just for read purposes?

      2.)

      Then we can use the built-in features of HAL:

      • If we send data, then we can use the type to describe the request body instead of the response body. Ofc. in this case there should not be a response body, or this solution will be confusing.

            {
                "_links": {
                    "curies": [
                        {
                            "name": "my",
                            "href": "http://example.com/rels/{rel}",
                            "templated": true
                        }
                    ],
                    "my:edit": {
                        "href": "http://example.com/users/1",
                        "type": "application/vnd.example.user+json",
                        "title": "Edit user"
                    }
                }
            }
        

        So in this case the client will know that my:edit means that this is an edit form, and by checking the MIME type it will know what type of form to display.

      • An alternative solution to use the custom link relation for the same purpose:

            {
                "_links": {
                    "curies": [
                        {
                            "name": "my",
                            "href": "http://example.com/rels/{rel}",
                            "templated": true
                        }
                    ],
                    "my:edit-user": {
                        "href": "http://example.com/users/1",
                        "type": "application/json",
                        "title": "Edit user"
                    }
                }
            }
        

        So by fetching the docs http://example.com/rels/edit-user we can find a description about how to build a form for editing users and so we can support the my:edit-user link relation in our client. The docs can contain optionally a HTML form or some schema, or an RDF document using a form description vocab, etc...

      • We can follow the same approach by the profile property of the links. For example:

            {
                "_links": {
                    "curies": [
                        {
                            "name": "my",
                            "href": "http://example.com/rels/{rel}",
                            "templated": true
                        }
                    ],
                    "my:edit": {
                        "href": "http://example.com/users/1",
                        "type": "application/json",
                        "title": "Edit user",
                        "profile": "http://example.com/profiles/user"
                    }
                }
            }
        

        So in here the link relation means that this is an edit form and the profile describes how to generate the form under the http://example.com/profiles/user URL.

      3.)

      Or we can extend HAL using custom properties.

      • For example dougrain-forms does this:

            {
                "_forms": {
                    "edit": {
                        "href": "http://example.com/users/1",
                        "headers": {
                            "content-type": "application/json"
                        },
                        "title": "Edit user",
                        "method": "PUT",
                        "schema": {
                            "required": [
                                "name"
                            ],
                            "type": "object",
                            "properties": {
                                "name": {
                                    "type": "string"
                                }
                            },
                            "title": "user properties"
                        }
                    }
                }
            }
        

      • But you can use any alternative approach as long as we don't have a standard about HAL and about HAL forms, for example I would rather use a mongoose schema like solution:

            {
                "name": "John",
                "_links": {
                    "curies": [
                        {
                            "name": "my",
                            "href": "http://example.com/rels/{rel}",
                            "templated": true
                        }
                    ],
                    "my:edit": {
                        "href": "http://example.com/users/1",
                        "type": "application/json",
                        "title": "Edit user",
                        "method": "PUT",
                        "_embedded": {
                            "schema": {
                                "name": "String"
                            }
                        }
                    }
                }
            }
        

      4.)

      Don't use link relations and simple JSON formats like HAL, use RDF with one or more vocabulary instead. It is harder to use RDF, but it is a fine grained solution for decoupling clients from REST services, while HAL is just a coarse grained solution...

      • For example JSON-LD with Hydra and a custom vocab:

        {
            "@context": [
                "http://www.w3.org/ns/hydra/core",
                "https://example.com/docs#"
            ],
            "@id": "https://example.com/users/1",
            "name": "John",
            "operation": {
                "@type": "ReplaceResourceOperation",
                "title": "Edit user",
                "method": "PUT",
                "expects": {
                    "@id": "https://example.com/docs#User",
                    "supportedProperty": {
                        "@type": "SupportedProperty",
                        "title": "name",
                        "property": "https://example.com/docs#User.name",
                        "range": "http://www.w3.org/2001/XMLSchema#string",
                        "required": true
                    }
                }
            }
        }
        

      这篇关于JSON超媒体API与表格和链接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆