限制 JSON 数组仅接受特定类型的项目

问题描述 投票:0回答:1

我有一个中等复杂的 JSON 模式,其中包含一个数组,该数组仅接受两种特定类型的项目。由于某种原因,添加第三种类型的项目后,验证成功。你能帮我找到我忽略的东西吗?

我制作了该方案的一小部分,仅包含受影响的部分:

{
    "$schema": "http://json-schema.org/draft-07/schema#",    
       
    "type": "object",
    "additionalProperties": false,
    
    "properties": {

        "trainzMeshes": {
            "title": "Trainz Meshes",
            "description": "Specifications of Trainz meshes to create as FBX files and comments specified as an array.",
            "type": "array",      
            "additionalItems": false,
            "items": {
                "anyOf": [ 
                    { 
                        "comment": {
                            "$ref": "#/$defs/comment" 
                        },
                        "minItems": 0
                    }, 
                    {
                        "$ref": "#/$defs/trainzMesh",
                        "minItems": 1
                    } 
                ]
            }                          
        },
    },
        

    
    "$defs": {

        "comment": {
            "title": "Comment",
            "description": "A comment to help you remember what comes next. You may include as many comments as you wish.",
            "oneOf": [
                { 
                    "type": "string" 
                },
                { 
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "minItems": 1
                }
            ]            
        },

        "trainzMesh": {
            "title": "Trainz Mesh Composition Wrapper",
            "description": "Container for the specification of a Trainz mesh describing what FBX file and Trainz asset to create from which of your Blender objects.",
            
            "type": "object",
            "required": ["trainzMeshComposition"],
            "additionalProperties": false,

            "properties": {
                "trainzMeshComposition": {
                    "title": "Trainz Mesh Composition Settings",
                    "description": "Specification of a Trainz mesh describing what FBX file and Trainz asset to create from which of your Blender objects. You may include comments as well.",
                    
                    "type": "object",
                    "required": ["name", "blenderExportSpecifications"],
                    "additionalProperties": false,
                    
                    "properties": {

                        "comment": {
                            "$ref": "#/$defs/comment"
                        },

                        "name": {
                            "title": "Trainz Mesh File Name (Pattern)",
                            "description": "Name (pattern) for the FBX files to create.",
                            "type": "string"
                        },

                        "blenderExportSpecifications": {

                            "title": "Blender Export Specifications",
                            "description": "Specifies one or more Blender objects, with optionally assigning a material and UV map to each, to include them in the Trainz mesh FBX file.",
                            
                            "type": "array",
                            "minItems": 1,
                            "additionalItems": false,
                            "items": {
                                "anyOf": [
                                    {   "$ref": "#/$defs/blenderExportSpecification",
                                        "minContains": 1
                                    },
                                    {
                                        "comment": {
                                            "$ref": "#/$defs/comment"
                                        },
                                        "minContains": 0
                                    }
                                ]                                
                            }
                        }            
                    }
                }
            }
        },            


        "blenderExportSpecification": {
            "title": "Blender Export Specification",
            "description": "Specifies one or more Blender objects, with optionally assigning a material and UV map to each, to include them in the Trainz mesh FBX file.",
            
            "type": "object",              
            "anyOf": [
                { "required": ["scopeToCollections"] },
                { "required": ["includeObjectsByName"] },
                { "required": ["includeObjectsByPattern"] },
                { "required": ["includeObjectsByConditions"] },
                { "required": ["excludeObjectsByName"] },
                { "required": ["excludeObjectsByPattern"] },
                { "required": ["excludeObjectsByConditions"] },
                { "required": ["dropModifiers"] },
                { "required": ["material"] },
                { "required": ["uvMap"] }
            ],
            "additionalProperties": false,

            "properties": {

                "scopeToCollections":  {
                    "title": "Scope to Collections",
                    "description": "A regular expression specifying collection name patterns or a list specifying collection names. Only Blender objects contained under referenced collections in your Blender file will be processed for inclusion for exporting.",
                    
                    "oneOf": [
                        {
                            "type": "string"
                        },
                        {
                            "type": "array",
                            "items": {
                                "type": "string"
                            },
                            "minItems": 1
                        }
                    ]
                },

                "includeObjectsByName": {
                    "title": "Include Object(s) By Name",
                    "description": "The name or (in the form of a string array) names of the Blender object(s) to export and to which parameters in this export specification apply.",

                    "oneOf": [
                        {
                            "type": "string"
                        },
                        {
                            "type": "array",
                            "items": {
                                "type": "string"
                            },
                            "minItems": 1
                        }
                    ]
                },

                "includeObjectsByPattern":  {         
                    "title": "Include Objects By Name Pattern",
                    "description": "A regular expression specifying an object name pattern. Only objects within the scope selected by scopeToCollections and matching this pattern will be exported.",
                    "type": "string",
                    "format": "regex"
                },

                "includeObjectsByConditions":  {         
                    "title": "Include Objects By Condition",
                    "description": "A pair of a property name and a value pattern. Only Blender objects having this property with a value matching the specified value pattern will be included in the export.",
                    
                    "type": "array",
                    "minItems": 1,

                    "items": {
                        "$ref": "#/$defs/objectPropertyCondition"
                    }                    
                },

                "excludeObjectsByName": {
                    "title": "Exclude Object(s) By Name",
                    "description": "Name(s) of object(s) to omit when exporting within this export specification.",

                    "oneOf": [
                        {
                            "type": "string" 
                        },
                        {
                            "type": "array",
                            "items": {
                                "type": "string"
                            },
                            "minItems": 1
                        }
                    ]
                },

                "excludeObjectsByPattern":  {         
                    "title": "Exclude Objects By Name Pattern",
                    "description": "A regular expression specifying an object name pattern. Matching objects will be omitted when exporting within this export specification.",
                    "type": "string",
                    "format": "regex"
                },

                "excludeObjectsByConditions":  {         
                    "title": "Exclude Objects By Condition",
                    "description": "A pair of a property name and a value pattern. Blender objects having this property with a value matching the specified value pattern will not be included in the export.",
                    
                    "type": "array",
                    "minItems": 1,

                    "items": {
                        "$ref": "#/$defs/objectPropertyCondition"
                    }                    
                },

                "dropModifiers": {
                    "title": "Modifiers to Drop",
                    "description": "Name(s) of modifiers to hide before exporting the objects.",

                    "oneOf": [
                        {
                            "title": "Name Pattern for Modifiers to Drop",
                            "description": "A regex. Modifiers with a name matching this regex will not be applied.",
                            "type": "string",
                            "format": "regex"                           
                        },
                        {
                            "title": "Names of Modifiers to Drop",
                            "description": "A list of names of modifiers to hide before exporting.",
                            "type": "array",
                            "items": {
                                "type": "string"
                            },
                            "minItems": 1
                        }
                    ]
                },
                
                "material": {
                    "title": "Material to Apply",
                    "description": "Name of the material in your Blender file to apply to the object before exporting. The name shall conform to Trainz specifications.",
                    "type": "string"
                },

                "uvMap": {
                    "title": "UV Map to Apply",
                    "description": "Name of the UV map created for the Blender object to switch to before exporting.",
                    "type": "string"
                }
            }          
        },

        "objectPropertyCondition": {

            "title": "Object Property Condition",
            "description": "Description of a condition composed of a custom property defined for Blender objects and a pattern for matching values",
            
            "required": ["name", "valuePattern"],
            "additionalProperties": false,
            
            "properties": {

                "name": {
                    "title": "Condition Property Name",
                    "description": "Name of the property containing the condition.",
                    "type": "string"
                },

                "valuePattern": {   
                    "title": "Condition Value Pattern",
                    "description": "A pattern which the value of the property shall match to meet the condition.",
                    "type": "string",
                    "format": "regex"
                }
            }            
                 
        }
    }
}

我有这个基于该方案的 JSON:

{   
    "trainzMeshes": [
        { "comment": "*****************************************************************" },
        { "comment": "  STATION NAME DISPLAY - SIZE S                                  " },
        { "comment": "*****************************************************************" },
        { "comment": "---------------------------- Lod 0 ------------------------------" },
        {
            "trainzMeshComposition": {
                "name": "name-display-S-daytime-lod0n",
                "blenderExportSpecifications": [
                    {
                        "includeObject": [
                            "Name Display Console - S [lod0]",
                            "Name Display - S - Default [lod0]"
                        ]
                    }
                ]
            }
        }
    ]
}

我的 VS Code 验证器以及 Newtonsoft 的验证器(位于 https://www.jsonschemavalidator.net/)发现 JSON 符合该架构,而我希望“includeObject”违反该架构,原因有两个。

  1. 如果“includeObject”键被认为是子模式“blenderExportSpecification”的一部分,它有几个属性,但它们都不是“includeObject”,而且additionalProperties设置为false。因此,如果它被视为“blenderExportSpecification”的一部分,则会发生违规。
  2. 如果验证器发现带有“includeObject”的对象不是“blenderExportSpecification”类型的对象,我预计会在数组级别失败,因为它不是两种允许的类型之一。

我尝试了很多东西,例如将“oneOf”更改为“anyOf”,将oneOf > items结构更改为items > oneOf,但我没有办法让它失败。

json jsonschema json-schema-validator
1个回答
0
投票

您的

anyOf
架构不受约束,因为您将
comment
定义为属性,但没有使用
properties
关键字,JSON 架构将其解释为属性
comment
不受约束。希望这是有道理的。

您还对

minItems
minContains
进行了一些无效使用,因为您没有使用
contains
关键字,所以未使用它。此外,作为
$ref
的同级关键字,这些关键字的位置也不正确。

试试这个...

{
    "$schema": "http://json-schema.org/draft-07/schema#",
    "type": "object",
    "additionalProperties": false,
    "properties": {
        "trainzMeshes": {
            "title": "Trainz Meshes",
            "description": "Specifications of Trainz meshes to create as FBX files and comments specified as an array.",
            "type": "array",
            "additionalItems": false,
            "items": {
                "anyOf": [
                    {
                        "type": "object",
                        "additionalProperties": false,
                        "properties": {
                            "comment": {
                                "$ref": "#/$defs/comment"
                            }
                        }
                    },
                    {
                        "$ref": "#/$defs/trainzMesh"
                    }
                ]
            }
        }
    },
    "$defs": {
        "comment": {
            "title": "Comment",
            "description": "A comment to help you remember what comes next. You may include as many comments as you wish.",
            "oneOf": [
                {
                    "type": "string"
                },
                {
                    "type": "array",
                    "items": {
                        "type": "string"
                    },
                    "minItems": 1
                }
            ]
        },
        "trainzMesh": {
            "title": "Trainz Mesh Composition Wrapper",
            "description": "Container for the specification of a Trainz mesh describing what FBX file and Trainz asset to create from which of your Blender objects.",
            "type": "object",
            "required": [
                "trainzMeshComposition"
            ],
            "additionalProperties": false,
            "properties": {
                "trainzMeshComposition": {
                    "title": "Trainz Mesh Composition Settings",
                    "description": "Specification of a Trainz mesh describing what FBX file and Trainz asset to create from which of your Blender objects. You may include comments as well.",
                    "type": "object",
                    "required": [
                        "name",
                        "blenderExportSpecifications"
                    ],
                    "additionalProperties": false,
                    "properties": {
                        "comment": {
                            "$ref": "#/$defs/comment"
                        },
                        "name": {
                            "title": "Trainz Mesh File Name (Pattern)",
                            "description": "Name (pattern) for the FBX files to create.",
                            "type": "string"
                        },
                        "blenderExportSpecifications": {
                            "title": "Blender Export Specifications",
                            "description": "Specifies one or more Blender objects, with optionally assigning a material and UV map to each, to include them in the Trainz mesh FBX file.",
                            "type": "array",
                            "minItems": 1,
                            "additionalItems": false,
                            "items": {
                                "anyOf": [
                                    {
                                        "$ref": "#/$defs/blenderExportSpecification"
                                    },
                                    {
                                        "type": "object",
                                        "additionalProperties": false,
                                        "properties": {
                                            "comment": {
                                                "$ref": "#/$defs/comment"
                                            }
                                        }
                                    }
                                ]
                            }
                        }
                    }
                }
            }
        },
        "blenderExportSpecification": {
            "title": "Blender Export Specification",
            "description": "Specifies one or more Blender objects, with optionally assigning a material and UV map to each, to include them in the Trainz mesh FBX file.",
            "type": "object",
            "anyOf": [
                {
                    "required": [
                        "scopeToCollections"
                    ]
                },
                {
                    "required": [
                        "includeObjectsByName"
                    ]
                },
                {
                    "required": [
                        "includeObjectsByPattern"
                    ]
                },
                {
                    "required": [
                        "includeObjectsByConditions"
                    ]
                },
                {
                    "required": [
                        "excludeObjectsByName"
                    ]
                },
                {
                    "required": [
                        "excludeObjectsByPattern"
                    ]
                },
                {
                    "required": [
                        "excludeObjectsByConditions"
                    ]
                },
                {
                    "required": [
                        "dropModifiers"
                    ]
                },
                {
                    "required": [
                        "material"
                    ]
                },
                {
                    "required": [
                        "uvMap"
                    ]
                }
            ],
            "additionalProperties": false,
            "properties": {
                "scopeToCollections": {
                    "title": "Scope to Collections",
                    "description": "A regular expression specifying collection name patterns or a list specifying collection names. Only Blender objects contained under referenced collections in your Blender file will be processed for inclusion for exporting.",
                    "oneOf": [
                        {
                            "type": "string"
                        },
                        {
                            "type": "array",
                            "items": {
                                "type": "string"
                            },
                            "minItems": 1
                        }
                    ]
                },
                "includeObjectsByName": {
                    "title": "Include Object(s) By Name",
                    "description": "The name or (in the form of a string array) names of the Blender object(s) to export and to which parameters in this export specification apply.",
                    "oneOf": [
                        {
                            "type": "string"
                        },
                        {
                            "type": "array",
                            "items": {
                                "type": "string"
                            },
                            "minItems": 1
                        }
                    ]
                },
                "includeObjectsByPattern": {
                    "title": "Include Objects By Name Pattern",
                    "description": "A regular expression specifying an object name pattern. Only objects within the scope selected by scopeToCollections and matching this pattern will be exported.",
                    "type": "string",
                    "format": "regex"
                },
                "includeObjectsByConditions": {
                    "title": "Include Objects By Condition",
                    "description": "A pair of a property name and a value pattern. Only Blender objects having this property with a value matching the specified value pattern will be included in the export.",
                    "type": "array",
                    "minItems": 1,
                    "items": {
                        "$ref": "#/$defs/objectPropertyCondition"
                    }
                },
                "excludeObjectsByName": {
                    "title": "Exclude Object(s) By Name",
                    "description": "Name(s) of object(s) to omit when exporting within this export specification.",
                    "oneOf": [
                        {
                            "type": "string"
                        },
                        {
                            "type": "array",
                            "items": {
                                "type": "string"
                            },
                            "minItems": 1
                        }
                    ]
                },
                "excludeObjectsByPattern": {
                    "title": "Exclude Objects By Name Pattern",
                    "description": "A regular expression specifying an object name pattern. Matching objects will be omitted when exporting within this export specification.",
                    "type": "string",
                    "format": "regex"
                },
                "excludeObjectsByConditions": {
                    "title": "Exclude Objects By Condition",
                    "description": "A pair of a property name and a value pattern. Blender objects having this property with a value matching the specified value pattern will not be included in the export.",
                    "type": "array",
                    "minItems": 1,
                    "items": {
                        "$ref": "#/$defs/objectPropertyCondition"
                    }
                },
                "dropModifiers": {
                    "title": "Modifiers to Drop",
                    "description": "Name(s) of modifiers to hide before exporting the objects.",
                    "oneOf": [
                        {
                            "title": "Name Pattern for Modifiers to Drop",
                            "description": "A regex. Modifiers with a name matching this regex will not be applied.",
                            "type": "string",
                            "format": "regex"
                        },
                        {
                            "title": "Names of Modifiers to Drop",
                            "description": "A list of names of modifiers to hide before exporting.",
                            "type": "array",
                            "items": {
                                "type": "string"
                            },
                            "minItems": 1
                        }
                    ]
                },
                "material": {
                    "title": "Material to Apply",
                    "description": "Name of the material in your Blender file to apply to the object before exporting. The name shall conform to Trainz specifications.",
                    "type": "string"
                },
                "uvMap": {
                    "title": "UV Map to Apply",
                    "description": "Name of the UV map created for the Blender object to switch to before exporting.",
                    "type": "string"
                }
            }
        },
        "objectPropertyCondition": {
            "title": "Object Property Condition",
            "description": "Description of a condition composed of a custom property defined for Blender objects and a pattern for matching values",
            "required": [
                "name",
                "valuePattern"
            ],
            "additionalProperties": false,
            "properties": {
                "name": {
                    "title": "Condition Property Name",
                    "description": "Name of the property containing the condition.",
                    "type": "string"
                },
                "valuePattern": {
                    "title": "Condition Value Pattern",
                    "description": "A pattern which the value of the property shall match to meet the condition.",
                    "type": "string",
                    "format": "regex"
                }
            }
        }
    }
}

差异


根据您对附加要求的评论进行编辑:

  • 我只想允许一个
    trainzMesh
    对象和任意数量的
    comment
    对象

这是一种方法。

  • 始终要求第一个索引是
    trainzMesh
    对象。我们将
    items
    作为数组
    []
    来实现。这会创建位置参数。
  • 我添加了约束
    minItems: 1
    以始终至少需要
    trainzMesh
    对象。
    comment
    是可选的。
  • 任何其他数组项都必须是
    comment
    对象,并且该对象模式中不允许使用
    additionalProperties
"$schema": "http://json-schema.org/draft-07/schema#",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "trainzMeshes": {
      "title": "Trainz Meshes",
      "description": "Specifications of Trainz meshes to create as FBX files and comments specified as an array.",
      "type": "array",
      "minItems": 1,
      "items": [
        {
          "$ref": "#/$defs/trainzMesh"
        }
      ],
      "additionalItems": {
        "type": "object",
        "additionalProperties": false,
        "properties": {
          "comment": {
            "$ref": "#/$defs/comment"
          }
        }
      }
    }
  }
© www.soinside.com 2019 - 2024. All rights reserved.