如何使用具有必填字段的JSON模式验证http PATCH数据

如何解决如何使用具有必填字段的JSON模式验证http PATCH数据

我正在尝试使用必填字段验证经典的JSON模式(带有Ajvjson-server),但用于HTTP PATCH请求。

对于POST来说是可以的,因为数据已全部到达并且不应遗漏任何内容。

但是,尝试修补现有资源时,架构的 required 字段会引起问题。

这是我目前正在做的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","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","pattern": "^https?:\/\/"
        },"backdrop": {
            "title": "Fond","description": "Image de fond","pattern": "^https?:\/\/"
        }
    },"required": [
        "title","release_date","categories","description"
    ],"additionalProperties": false
}

现在,我使用了与原始模式相同的模式来完成技巧,但是最后没有required子句。但是我不喜欢这种解决方案,因为它不必要地复制了代码(而且一点也不优雅)。

是否有任何聪明的解决方案/工具可以正确实现这一目标? 谢谢

解决方法

具有多个模式(要验证的每个有效负载一个)并不罕见。

根据您的情况,您似乎做对了正确的事情。

您可以使用引用($ref)对架构进行重复数据删除,将属性子方案拆分为一个单独的文件。

您最终得到一个包含模型的架构,以及用于该模型的每种表示形式的架构,但没有重复(如果可能)。

如果您需要有关如何精确操作的更多指导,请发表评论,我将用更多详细信息更新答案。


这是您如何做自己想做的一个例子。 您将需要创建多个模式文件,并在需要验证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","allOf": [{
    "$ref": "/object/movie#/definitions/movie"
  }],}
{
  "$id": "https://example.com/movie/post","required": ["title"]
}

example.com更改为您要用于ID的任何域。 然后,您需要将所有模式加载到实现中。

加载后,引用将基于URI解析而起作用,并为每个架构资源使用$id

请注意,POST和PATCH模式中的$ref值不是以#开头,这意味着目标不是此模式资源。

,

如果正确使用HTTP PATCH,则有另一种方法可以解决此问题。

PATCH请求的主体应该是某种差异媒体类型,而不是纯JSON。 diff媒体类型定义了一组要转换JSON的操作(添加,删除,替换)。然后将差异应用于原始资源,从而导致资源处于新状态。 JSON Patch(更强大)和JSON Merge Patch(更自然)是几种JSON diff媒体类型。

如果您验证PATCH的请求正文,则不是在验证资源,而是在验证diff格式。但是,如果您首先将补丁应用于资源,则可以使用完整架构验证结果(然后根据结果保留更改或保留400)。

请记住,在REST中,重要的是资源和表示形式,而不是请求和响应。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐


依赖报错 idea导入项目后依赖报错,解决方案:https://blog.csdn.net/weixin_42420249/article/details/81191861 依赖版本报错:更换其他版本 无法下载依赖可参考:https://blog.csdn.net/weixin_42628809/a
错误1:代码生成器依赖和mybatis依赖冲突 启动项目时报错如下 2021-12-03 13:33:33.927 ERROR 7228 [ main] o.s.b.d.LoggingFailureAnalysisReporter : *************************** APPL
错误1:gradle项目控制台输出为乱码 # 解决方案:https://blog.csdn.net/weixin_43501566/article/details/112482302 # 在gradle-wrapper.properties 添加以下内容 org.gradle.jvmargs=-Df
错误还原:在查询的过程中,传入的workType为0时,该条件不起作用 <select id="xxx"> SELECT di.id, di.name, di.work_type, di.updated... <where> <if test=&qu
报错如下,gcc版本太低 ^ server.c:5346:31: 错误:‘struct redisServer’没有名为‘server_cpulist’的成员 redisSetCpuAffinity(server.server_cpulist); ^ server.c: 在函数‘hasActiveC
解决方案1 1、改项目中.idea/workspace.xml配置文件,增加dynamic.classpath参数 2、搜索PropertiesComponent,添加如下 <property name="dynamic.classpath" value="tru
删除根组件app.vue中的默认代码后报错:Module Error (from ./node_modules/eslint-loader/index.js): 解决方案:关闭ESlint代码检测,在项目根目录创建vue.config.js,在文件中添加 module.exports = { lin
查看spark默认的python版本 [root@master day27]# pyspark /home/software/spark-2.3.4-bin-hadoop2.7/conf/spark-env.sh: line 2: /usr/local/hadoop/bin/hadoop: No s
使用本地python环境可以成功执行 import pandas as pd import matplotlib.pyplot as plt # 设置字体 plt.rcParams['font.sans-serif'] = ['SimHei'] # 能正确显示负号 p
错误1:Request method ‘DELETE‘ not supported 错误还原:controller层有一个接口,访问该接口时报错:Request method ‘DELETE‘ not supported 错误原因:没有接收到前端传入的参数,修改为如下 参考 错误2:cannot r
错误1:启动docker镜像时报错:Error response from daemon: driver failed programming external connectivity on endpoint quirky_allen 解决方法:重启docker -> systemctl r
错误1:private field ‘xxx‘ is never assigned 按Altʾnter快捷键,选择第2项 参考:https://blog.csdn.net/shi_hong_fei_hei/article/details/88814070 错误2:启动时报错,不能找到主启动类 #
报错如下,通过源不能下载,最后警告pip需升级版本 Requirement already satisfied: pip in c:\users\ychen\appdata\local\programs\python\python310\lib\site-packages (22.0.4) Coll
错误1:maven打包报错 错误还原:使用maven打包项目时报错如下 [ERROR] Failed to execute goal org.apache.maven.plugins:maven-resources-plugin:3.2.0:resources (default-resources)
错误1:服务调用时报错 服务消费者模块assess通过openFeign调用服务提供者模块hires 如下为服务提供者模块hires的控制层接口 @RestController @RequestMapping("/hires") public class FeignControl
错误1:运行项目后报如下错误 解决方案 报错2:Failed to execute goal org.apache.maven.plugins:maven-compiler-plugin:3.8.1:compile (default-compile) on project sb 解决方案:在pom.
参考 错误原因 过滤器或拦截器在生效时,redisTemplate还没有注入 解决方案:在注入容器时就生效 @Component //项目运行时就注入Spring容器 public class RedisBean { @Resource private RedisTemplate<String
使用vite构建项目报错 C:\Users\ychen\work>npm init @vitejs/app @vitejs/create-app is deprecated, use npm init vite instead C:\Users\ychen\AppData\Local\npm-