簡體   English   中英

如何使用具有必填字段的 JSON 模式驗證 http PATCH 數據

[英]How to validate http PATCH data with a JSON schema having required fields

我正在嘗試驗證帶有必填字段的經典 JSON 架構(帶有Ajvjson-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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM