json 尽管类型正确,但模式验证失败
json schema validation fails despite correct type
我有一个相当大的 json 架构。有问题的部分是架构中名为 "translations" 的较小架构,看起来像这样:
"translations": {
"bsonType": "object",
"patternProperties": {
"id": {
"bsonType": "string"
},
"^[a-z]{2}$": {
"anyOf": [
{
"bsonType": "object"
},
{
"bsonType": "array"
}
]
}
}
}
其中由正则表达式定义的对象包含更多属性(例如,一个名为 "text" 的字段)并且数组是这些对象的数组,但我只留下了对理解很重要的部分结构。
我的问题是,当我根据这个模式验证我的文件时,它每一个都失败了,但是当我从 anyOf 数组中的第一个对象中删除 "bsonType": "object" ,它工作正常。
我的所有文件都是这样的,翻译对象中至少有一个对象是 "object" 类型的,这些对象以正则表达式作为键。所以我不明白为什么他们会失败。
我用的是mongoDB3.6.0.
这是一个失败的文件示例:
"translations":{
"id":"12345",
"br":{
"text":"string1"
},
"en":{
"text":"string2"
},
"ja":[
{
"text":"string3"
},
{
"text":"string4"
}
],
"no":[
{
"text":"string6"
},
{
"text":"string7"
}
]
}
万一不清楚-问题是当在 anyOf 数组的第一个对象中使用 "bsonType": "object" 定义模式时,像这样的文件会失败,并且可以工作当我把它取下来的时候。 anyOf 数组的第二个对象中的 "bsonType": "array" 工作正常。
我认为你的问题是 id 与正则表达式冲突试试这个:
let MongoClient = require('mongodb').MongoClient;
let collectionName = 'translations';
let scheme = {
$jsonSchema:{
"bsonType": "object",
"patternProperties": {
"^id$":{
"bsonType":"string"
},
"^(?!id)([a-z]{2})$": {
"anyOf": [
{
"bsonType": "object"
},
{
"bsonType": "array"
}
]
}
},
}
};
let goodJson ={
"id": "12345",
"br":{
"text":"string1"
},
"en":{
"text":"string2"
},
"ja":[
{
"text":"string3"
},
{
"text":"string4"
}
],
"no":[
{
"text":"string6"
},
{
"text":"string7"
}
]
};
let badJson ={
"id": "12345",
"br":{
"text":"string1"
},
"en":{
"text":"string2"
},
"ja":[
{
"text":"string3"
},
{
"text":"string4"
}
],
"no":[
{
"text":"string6"
},
{
"text":"string7"
}
],
"nt": "not_object_or_array"
};
async function run() {
let db = await MongoClient.connect('mongodb://localhost:27017/exampleDb');
let dbo = db.db('mydb');
let collections = await dbo.collections();
let collectionsNames = collections.map(c => c.s.name);
if (collectionsNames.includes(collectionName)) {
console.log('dropping collection');
await dbo.collection(collectionName).drop();
}
console.log('creating collection');
await dbo.createCollection(collectionName, {validator: scheme});
let translationCollection = dbo.collection(collectionName);
console.log('this will validate successfully');
await translationCollection.insertOne(goodJson);
console.log('this will raise validation error because: "nt": "not_object_or_array"');
try {
await translationCollection.insertOne(badJson);
} catch(error) {
console.log(error);
}
await db.close();
}
run();
我有一个相当大的 json 架构。有问题的部分是架构中名为 "translations" 的较小架构,看起来像这样:
"translations": {
"bsonType": "object",
"patternProperties": {
"id": {
"bsonType": "string"
},
"^[a-z]{2}$": {
"anyOf": [
{
"bsonType": "object"
},
{
"bsonType": "array"
}
]
}
}
}
其中由正则表达式定义的对象包含更多属性(例如,一个名为 "text" 的字段)并且数组是这些对象的数组,但我只留下了对理解很重要的部分结构。
我的问题是,当我根据这个模式验证我的文件时,它每一个都失败了,但是当我从 anyOf 数组中的第一个对象中删除 "bsonType": "object" ,它工作正常。
我的所有文件都是这样的,翻译对象中至少有一个对象是 "object" 类型的,这些对象以正则表达式作为键。所以我不明白为什么他们会失败。
我用的是mongoDB3.6.0.
这是一个失败的文件示例:
"translations":{
"id":"12345",
"br":{
"text":"string1"
},
"en":{
"text":"string2"
},
"ja":[
{
"text":"string3"
},
{
"text":"string4"
}
],
"no":[
{
"text":"string6"
},
{
"text":"string7"
}
]
}
万一不清楚-问题是当在 anyOf 数组的第一个对象中使用 "bsonType": "object" 定义模式时,像这样的文件会失败,并且可以工作当我把它取下来的时候。 anyOf 数组的第二个对象中的 "bsonType": "array" 工作正常。
我认为你的问题是 id 与正则表达式冲突试试这个:
let MongoClient = require('mongodb').MongoClient;
let collectionName = 'translations';
let scheme = {
$jsonSchema:{
"bsonType": "object",
"patternProperties": {
"^id$":{
"bsonType":"string"
},
"^(?!id)([a-z]{2})$": {
"anyOf": [
{
"bsonType": "object"
},
{
"bsonType": "array"
}
]
}
},
}
};
let goodJson ={
"id": "12345",
"br":{
"text":"string1"
},
"en":{
"text":"string2"
},
"ja":[
{
"text":"string3"
},
{
"text":"string4"
}
],
"no":[
{
"text":"string6"
},
{
"text":"string7"
}
]
};
let badJson ={
"id": "12345",
"br":{
"text":"string1"
},
"en":{
"text":"string2"
},
"ja":[
{
"text":"string3"
},
{
"text":"string4"
}
],
"no":[
{
"text":"string6"
},
{
"text":"string7"
}
],
"nt": "not_object_or_array"
};
async function run() {
let db = await MongoClient.connect('mongodb://localhost:27017/exampleDb');
let dbo = db.db('mydb');
let collections = await dbo.collections();
let collectionsNames = collections.map(c => c.s.name);
if (collectionsNames.includes(collectionName)) {
console.log('dropping collection');
await dbo.collection(collectionName).drop();
}
console.log('creating collection');
await dbo.createCollection(collectionName, {validator: scheme});
let translationCollection = dbo.collection(collectionName);
console.log('this will validate successfully');
await translationCollection.insertOne(goodJson);
console.log('this will raise validation error because: "nt": "not_object_or_array"');
try {
await translationCollection.insertOne(badJson);
} catch(error) {
console.log(error);
}
await db.close();
}
run();