有没有办法合并Joi Schemas?

Und*_*ion 7 validation merge object joi

有没有办法将两个joi模式合并为一个模式?

架构1

{
  alpha: Joi.number().required(),
  beta: Joi.string().required(),
  chalie: Joi.object({
    xray: Joi.number().required(),
  }).required()
}
Run Code Online (Sandbox Code Playgroud)

架构1

{
  delta: Joi.string().required(),
  echo: Joi.number().required(),
  charlie: Joi.object({
    zulu: Joi.string().required(),
  }).required()
}
Run Code Online (Sandbox Code Playgroud)

合并架构:

{
  alpha: Joi.number().required(),
  beta: Joi.string().required(),
  chalie: Joi.object({
    xray: Joi.number().required(),
    zulu: Joi.string().required(),
  }).required()
  delta: Joi.string().required(),
  echo: Joi.number().required(),
}
Run Code Online (Sandbox Code Playgroud)

没有嵌套对象,它很容易完成Object.assign,但即使深层对象合并也不能与嵌套对象一起使用,因为嵌套对象是一个函数调用.

sza*_*ata 9

我想知道同样的事情,因为我想合并两个不同的模式,发现这个:https : //github.com/hapijs/joi/blob/v9.0.4/API.md#anyconcatschema

const a = Joi.string().valid('a');
const b = Joi.string().valid('b');
const ab = a.concat(b);
Run Code Online (Sandbox Code Playgroud)

希望能帮到你


orl*_*aqp 8

你试过 Joi.append 吗?

https://github.com/hapijs/joi/blob/v13.5.2/API.md#objectkeysschema

// Validate key a
const base = Joi.object().keys({
    a: Joi.number()
});

// Validate keys a, b.
const extended = base.append({
    b: Joi.string()
});
Run Code Online (Sandbox Code Playgroud)

更新(2020-05-03):

一个简单的方法来完成这将是这样的:

var base = Joi.object({ firstname: Joi.string() });
var fullName = base.keys({ lastName: Joi.number() });
Run Code Online (Sandbox Code Playgroud)

  • 如果您尝试附加架构,这会导致“断言错误[ERR_ASSERTION]:对象架构不能是 joi 架构” (2认同)

mrB*_*rna 5

使用普通的javascript对象不是我的选择。我尝试使用该.keys方法进行扩展,但是它会覆盖现有键(在这种情况下为charlie)。

我确定的解决方案使用.reach:示例:

const Joi = require('joi');
const originalSchema = Joi.object({
  a: { 
    deep: {
      b: Joi.string()
    }    
  },
  c: Joi.string()
});
const extendedSchema = Joi.object({
  a: { 
    deep: Joi
      .reach(originalSchema, 'a.deep')
      .keys({ anotherB: Joi.string() })
  },
  c: Joi.reach(originalSchema, 'c')
});

// No errors
extendedSchema.validate({ a: { deep: { b: 'hi', anotherB: 'hi' } }, c: 'wow' })
Run Code Online (Sandbox Code Playgroud)


Tin*_*ino 5

Joi.object()扩展运算符...为我解决了这个问题。(乔伊版本17)

import * as Joi from 'joi'

const childSchema: {
    PORT: Joi.number(),
}

const parentSchema = Joi.object({
    NODE_ENV: Joi.string(),
    APP_NAME: Joi.string(),
    ...childSchema,
})
Run Code Online (Sandbox Code Playgroud)


小智 -1

虽然您可以使用 Javascript 的Object.assign(),但我认为您正在寻找的是 Joi 的.keys() 功能。

在你的代码中,我会这样做:

const schema1 = Joi.object({
  alpha: Joi.number().required(),
  beta: Joi.string().required(),
  charlie: Joi.object({
    xray: Joi.number().required(),
  }).required()
});

const schema2 = Joi.object({
  delta: Joi.string().required(),
  echo: Joi.number().required(),
  charlie: Joi.object({
    zulu: Joi.string().required(),
  }).required()
});

const mergedSchema = schema1.keys(schema2);
Run Code Online (Sandbox Code Playgroud)

还有一个有趣的注意事项是关于使用直接 JS 对象与将它们包装在Joi.object();中。

使用 {} 表示法时,您只是定义一个普通的 JS 对象,它不是架构对象。您可以将其传递给验证方法,但不能调用该对象的 validate() 方法,因为它只是一个普通的 JS 对象。

此外,每次将 {} 对象传递给 validate() 方法,都会在每次验证时执行昂贵的架构编译操作。

当您使用 Joi.object([schema]) 时,它会第一次编译,因此您可以多次将其传递给 validate() 方法,并且不会增加任何开销。

所以你可以接受Ankh 的建议并使用直接的 JS 对象:

const schema1 = {
  alpha: Joi.number().required(),
  beta: Joi.string().required(),
  charlie: Joi.object({
    xray: Joi.number().required(),
  }).required()
};

const schema2 ={
  delta: Joi.string().required(),
  echo: Joi.number().required(),
  charlie: Joi.object({
    zulu: Joi.string().required(),
  }).required()
};

const mergedSchema = Object.assign({}, schema1, schema2);
Run Code Online (Sandbox Code Playgroud)

但会带来相关的性能损失。