RAML:对具有不同属性的 GET 和 POST 使用相同的数据类型
RAML: using same data type for GET & POST with differing properties
所以我从我的 RAML 规范中提取了一个 JSON 模式来验证 GET 方法中的输出以及 POST 方法中的输入。
每个这种类型的实体都有一个 "required" ID 属性 - 至少在 'get item' 或 'get collection' 请求中列出这些实体时是必需的。
但是当验证收到的 post 数据以创建这样一个实体时,ID 显然不是必需的(如果无论如何发送它都会被丢弃)。
让 GET 请求需要这个 ID 属性 但不是必需的,或者最好不存在于 POST 请求的类型中的最佳 DRY 方法是什么?
TL;DR: 从下面开始阅读 ;)
例子更容易理解:
对于 GET 请求,类型应如下所示:
properties:
id:
something1:
something2?:
对于 POST 请求,类型应为:
properties:
something1:
something2?:
无需分别定义两者,也无需使用继承为每个资源创建两种类型。
理想情况下我会这样解决,但这似乎行不通:
get:
description: Retrieve a list of <<resourcePathName|!uppercamelcase>>.
responses:
200:
body:
application/json:
type: [ entity_id_object, <<resourcePathName|!singularize|!uppercamelcase>> ][]
example: <<exampleCollection>>
和entity_id_object
只是:
entity_id_object:
properties:
id:
我认为这是因为 <<resourcePathName|!singularize|!uppercamelcase>>
在这个组合中不起作用。
您可以将 id
字段标记为 readOnly
以明确意图,但它不会影响数据验证的方式。
要影响验证,您可以创建一个 "Read" 类型和一个 "Write" 类型,其中 "Read" 类型具有额外需要的 id
属性 .
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"MyWriteEntity": {
"type": "object",
"properties": {
"something1": { "type": "string"},
"something2": { "type": "string"}
},
"required": "something1"
},
"MyReadEntity": {
"allOf": [
{ "$ref": "#/definitions/MyWriteEntity" },
{
"id": { "type": "string", "readOnly": true},
"required": ["id"]
}
]
}
}
}
我还想不出没有两种类型的方法。但是这个例子至少只让你只传递一种类型,并自动将 'NoId' 附加到 POST 请求的类型名称。
#%RAML 1.0
title: My API
version: v1
mediaType: application/json
types:
ResponseNoId:
properties:
something1:
something2?:
ResponseId:
properties:
id:
something1:
something2?:
Response:
ResponseNoId|ResponseId
resourceTypes:
collection:
usage: Use this resourceType to represent a collection of items
description: A collection of <<resourcePathName|!uppercamelcase>>
get:
description: |
Get all <<resourcePathName|!uppercamelcase>>,
optionally filtered
is: [ hasResponseCollection: { typeName: <<typeName>> } ]
post:
description: |
Create a new <<resourcePathName|!uppercamelcase|!singularize>>
is: [ hasRequestItem: { typeName: <<typeName>> } ]
item:
usage: Use this resourceType to represent any single item
description: A single <<typeName>>
get:
description: Get a <<typeName>>
is: [ hasResponseItem: { typeName: <<typeName>> } ]
traits:
hasRequestItem:
body:
application/json:
type: <<typeName>>
hasResponseItem:
responses:
200:
body:
application/json:
type: <<typeName>>
hasResponseCollection:
responses:
200:
body:
application/json:
type: <<typeName>>[]
/myResource:
type: { collection: { typeName: Response } }
get:
/{id}:
type: { item: { typeName: Response } }
post:
body:
application/json:
所以我从我的 RAML 规范中提取了一个 JSON 模式来验证 GET 方法中的输出以及 POST 方法中的输入。
每个这种类型的实体都有一个 "required" ID 属性 - 至少在 'get item' 或 'get collection' 请求中列出这些实体时是必需的。 但是当验证收到的 post 数据以创建这样一个实体时,ID 显然不是必需的(如果无论如何发送它都会被丢弃)。
让 GET 请求需要这个 ID 属性 但不是必需的,或者最好不存在于 POST 请求的类型中的最佳 DRY 方法是什么?
TL;DR: 从下面开始阅读 ;)
例子更容易理解:
对于 GET 请求,类型应如下所示:
properties:
id:
something1:
something2?:
对于 POST 请求,类型应为:
properties:
something1:
something2?:
无需分别定义两者,也无需使用继承为每个资源创建两种类型。
理想情况下我会这样解决,但这似乎行不通:
get:
description: Retrieve a list of <<resourcePathName|!uppercamelcase>>.
responses:
200:
body:
application/json:
type: [ entity_id_object, <<resourcePathName|!singularize|!uppercamelcase>> ][]
example: <<exampleCollection>>
和entity_id_object
只是:
entity_id_object:
properties:
id:
我认为这是因为 <<resourcePathName|!singularize|!uppercamelcase>>
在这个组合中不起作用。
您可以将 id
字段标记为 readOnly
以明确意图,但它不会影响数据验证的方式。
要影响验证,您可以创建一个 "Read" 类型和一个 "Write" 类型,其中 "Read" 类型具有额外需要的 id
属性 .
{
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"MyWriteEntity": {
"type": "object",
"properties": {
"something1": { "type": "string"},
"something2": { "type": "string"}
},
"required": "something1"
},
"MyReadEntity": {
"allOf": [
{ "$ref": "#/definitions/MyWriteEntity" },
{
"id": { "type": "string", "readOnly": true},
"required": ["id"]
}
]
}
}
}
我还想不出没有两种类型的方法。但是这个例子至少只让你只传递一种类型,并自动将 'NoId' 附加到 POST 请求的类型名称。
#%RAML 1.0
title: My API
version: v1
mediaType: application/json
types:
ResponseNoId:
properties:
something1:
something2?:
ResponseId:
properties:
id:
something1:
something2?:
Response:
ResponseNoId|ResponseId
resourceTypes:
collection:
usage: Use this resourceType to represent a collection of items
description: A collection of <<resourcePathName|!uppercamelcase>>
get:
description: |
Get all <<resourcePathName|!uppercamelcase>>,
optionally filtered
is: [ hasResponseCollection: { typeName: <<typeName>> } ]
post:
description: |
Create a new <<resourcePathName|!uppercamelcase|!singularize>>
is: [ hasRequestItem: { typeName: <<typeName>> } ]
item:
usage: Use this resourceType to represent any single item
description: A single <<typeName>>
get:
description: Get a <<typeName>>
is: [ hasResponseItem: { typeName: <<typeName>> } ]
traits:
hasRequestItem:
body:
application/json:
type: <<typeName>>
hasResponseItem:
responses:
200:
body:
application/json:
type: <<typeName>>
hasResponseCollection:
responses:
200:
body:
application/json:
type: <<typeName>>[]
/myResource:
type: { collection: { typeName: Response } }
get:
/{id}:
type: { item: { typeName: Response } }
post:
body:
application/json: