[英]How to define resource ID required for updating but not required for creating in JSON schema
[英]How to validate http PATCH data with a JSON schema having required fields
我正在嘗試驗證帶有必填字段的經典 JSON 架構(帶有Ajv和json-server ),但對於 HTTP PATCH 請求。
POST 沒關系,因為數據是完整到達的,不應該省略任何內容。
但是,當嘗試修補現有資源時,模式的必填字段會出現問題。
這是我目前正在為 POST 做的事情:
const schema = require('./movieSchema.json');
const validate = new Ajv().compile(schema);
// ...
movieValidation.post('/:id', function (req, res, next) {
const valid = validate(req.body);
if (!valid) {
const [err] = validate.errors;
let field = (err.keyword === 'required') ? err.params.missingProperty : err.dataPath;
return res.status(400).json({
errorMessage: `Erreur de type '${err.keyword}' sur le champs '${field}' : '${err.message}'`
});
}
next();
});
...但是如果我對movieValidation.patch(...)
做同樣的事情並嘗試只發送這塊數據:
{
"release_date": "2020-07-15",
"categories": [
"Action",
"Aventure",
"Science-Fiction",
"Thriller"
]
}
...它將無法通過整個驗證(而所有字段都可以並且它們驗證架構)
這是我完整的moviesSchema.json
:
{
"type": "object",
"$schema": "http://json-schema.org/draft-07/schema#",
"properties": {
"title": {
"title": "Titre",
"type": "string",
"description": "Titre complet du film"
},
"release_date": {
"title": "Date de sortie",
"description": "Date de sortie du film au cinéma",
"type": "string",
"format": "date",
"example": "2019-06-28"
},
"categories": {
"title": "Catégories",
"description": "Catégories du film",
"type": "array",
"items": {
"type": "string"
}
},
"description": {
"title": "Résumé",
"description": "Résumé du film",
"type": "string"
},
"poster": {
"title": "Affiche",
"description": "Affiche officielle du film",
"type": "string",
"pattern": "^https?:\/\/"
},
"backdrop": {
"title": "Fond",
"description": "Image de fond",
"type": "string",
"pattern": "^https?:\/\/"
}
},
"required": [
"title",
"release_date",
"categories",
"description"
],
"additionalProperties": false
}
現在,我使用與原始模式相同的不同模式完成了這個技巧,但最后沒有required
的子句。 但我不喜歡這個解決方案,因為它不必要地復制代碼(而且它一點也不優雅)。
是否有任何巧妙的解決方案/工具可以正確實現這一目標? 謝謝
如果您正確使用 HTTP PATCH,則還有另一種方法可以解決此問題。
PATCH 請求的主體應該是某種差異媒體類型,而不是普通的 JSON。 diff 媒體類型定義了一組操作(添加、刪除、替換)來轉換 JSON。 然后將差異應用於原始資源,從而生成資源的新 state。 幾個 JSON 差異媒體類型是JSON 補丁(更強大)和JSON 合並補丁(更自然)。
如果您驗證 PATCH 的請求正文,您並沒有真正驗證您的資源,而是在驗證 diff 格式。 但是,如果您首先將補丁應用到您的資源,那么您可以使用完整架構驗證結果(然后根據結果保留更改或 400)。
請記住,在 REST 中,重要的是資源和表示,而不是請求和響應。
擁有多個模式並不少見,每個要驗證的有效負載一個。
在你的情況下,看起來你做了完全正確的事情。
您可以使用引用 ( $ref
) 對架構進行重復數據刪除,將您的屬性子架構拆分為單獨的文件。
你最終會得到一個包含 model 的模式,以及所述 model 的每個表示的模式,但沒有重復(如果可能)。
如果您需要有關 go 的更多指導,請發表評論,我將更新答案並提供更多詳細信息。
這是一個如何做你想做的事的例子。 您將需要創建多個模式文件,並在需要驗證 POST 或 PATCH 請求時引用正確的模式。 我已將示例簡化為僅包含“標題”。
在一個模式中,您有類似...
{
"$id": "https://example.com/object/movie",
"$schema": "http://json-schema.org/draft-07/schema#",
"definitions": {
"movie": {
"properties": {
"title": {
"$ref": "#/definitions/title"
}
},
"additionalProperties": false
},
"title": {
"title": "Titre",
"type": "string",
"description": "Titre complet du film"
}
}
}
然后你會有一個用於 POST 和 PATCH ......
{
"$id": "https://example.com/movie/patch",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [{
"$ref": "/object/movie#/definitions/movie"
}],
}
{
"$id": "https://example.com/movie/post",
"$schema": "http://json-schema.org/draft-07/schema#",
"allOf": [{
"$ref": "/object/movie#/definitions/movie"
}],
"required": ["title"]
}
將example.com
更改為您要用於 ID 的任何域。 然后,您需要將所有模式加載到實現中。
加載后,引用將起作用,因為它們基於 URI 解析,對每個模式資源使用$id
。
請注意 POST 和 PATCH 模式中的$ref
值不以#
開頭,這意味着目標不是 THIS 模式資源。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.