尽管类型正确,但json模式验证失败

时间:2018-03-25 06:47:53

标签: json mongodb jsonschema

我有一个相当大的json架构。有问题的部分是架构中较小的架构,称为" translations",它看起来像这样:

"translations": {
    "bsonType": "object",
    "patternProperties": {
        "id": {
            "bsonType": "string"
        },
        "^[a-z]{2}$": {
            "anyOf": [
                {
                    "bsonType": "object"
                },
                {
                    "bsonType": "array"
                }
            ]
        }
    }
}

正则表达式定义的对象包含更多属性(例如,一个名为" text"的字段),并且数组是这些对象的数组,但我只留下了重要的部分了解结构。

我的问题是,当我根据这个模式验证我的文件时,它会失败每一个,但当我删除" bsonType":" object"从anyOf数组中的第一个对象开始,它可以正常工作。

我的所有文件都是这样的,翻译对象中至少有一个具有正则表达式作为键的对象属于" object"。所以我不明白为什么它们会失败。

我使用的是mongoDB 3.6.0。

以下是失败文件的示例:

 "translations":{  
    "id":"12345",
    "br":{  
       "text":"string1"
    },
    "en":{  
       "text":"string2"
    },
    "ja":[  
       {  
          "text":"string3"
       },
       {  
          "text":"string4"
       }
    ],
    "no":[  
       {  
          "text":"string6"
       },
       {  
          "text":"string7"
       }
    ]
 }

如果它不清楚 - 问题在于,当使用" bsonType":" object"定义模式时,这样的文件会失败。在anyOf数组的第一个对象中,当我取消它时工作。 " bsonType":"数组"在anyOf数组的第二个对象中工作正常。

1 个答案:

答案 0 :(得分:1)

我认为你的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();