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();