NjsonSchema 验证如果 Property1 等于 Something 则需要 Property2

NjsonSchema Validation If Property1 is equal to Something then require Property2

我似乎无法让 const 或 enum 作为 if-then-else JSON 模式验证的一部分工作。

当涉及 1 个验证值时,它们似乎可以互换。 (Reference)

这是我的 JSON 架构

    {
      "$schema": "http://json-schema.org/draft-07/schema#",
      "title": "Test_Schema",
      "description": "A schema for validating a test object",
      "type": "object",
      "additionalProperties": false,
      "properties": {
        "GeneralData": {
          "type": "object",
          "description": "Advsor and admin customer information",
          "properties": {
            "Name": {
              "type": [ "string", "null" ],
              "description": "Customer's advisor name"
            },
            "Age": {
              "type": [ "string", "null" ],
              "description": "Customer's advisor email"
            },
            "Location": {
              "type": [ "string", "null" ],
              "description": "The advisor's manager email'"
            }
          },
          "required": [ "Name", "Location", "Age" ]
        },
        "ClientData": {
          "type": "object",
          "description": "Customer's information",
          "additionalProperties": false,
          "properties": {
            "Title": {
              "type": [ "string", "null" ]
            },
            "Forename": {
              "type": [ "string", "null" ]
            },
            "Surname": {
              "type": [ "string" ]
            }
          },
          "required": [ "Title" ],
          "if": {
            "properties": {
              "Forename": { "enum": [ "Soameonea" ] }
            },
            "required": [ "Forename" ]
          },
          "then": { "required": [ "Surname" ] },
          "else": false 
        }
      }
    }

如果 Forename = "Someone" 我希望必须填写姓氏。

这是我序列化后的 jsonObject:

     {
        "GeneralData": {
            "Name": "Not Relevant",
            "Age": "Not Relevant",
            "Location": "Not Relevant"
        },
        "ClientData": {
            "Title": "SomeTitle",
            "Forename": "Someone",
            "Surname": null
        }
    }

验证码:

     internal void ValidateDataObjectOnSchema()
            {
                var dataObject = PopulateDataObject();
                var json = JsonConvert.SerializeObject(dataObject);
                var result = GetSchema().Validate(json);
                var errors = result.Select(x =>
                {
                    return new Errors() { Title = x.Property, Description = x.Schema.Description };
                });
                var i = errors;
    
            }

      internal JsonSchema GetSchema()
            {
                return JsonSchema.FromFileAsync("Test/testSchema.json").Result;
            }

现在它仍然需要姓氏,即使枚举 Soameonea != Someone and I 只需要 Title。 <== 问题 1

在 JSON 模式中,如果我设置 "Surname":{"type":["string","null]} 那么错误就会消失,但我仍然没有收到错误将 Forename 枚举的 if 条件更改为“某人”。<== 问题 2

如果我将 Enum 替换为 Const,我将无法获得不同的验证输出,因此,如果我能让其中一个起作用,我相信另一个也会随之而来。

我找到了这个问题的几个答案 (),我尝试实现同样的事情,但由于某种原因,我的情况失败了。

我错过了什么?

更新: 正如@Relequestial 在其中一条评论中提到的那样,NJson Schema 似乎只支持 Draft 04,这就是 if-then-else 不起作用的原因,应该使用隐含代替。下面是我使用替代包的解决方案。

相同的代码和 json 可与包 Newtonsoft.Json.Schema (Reference)

一起使用

代码:

  internal void ValidateDataObjectOnSchemaWithNewtonSoftJson()
        {
            var dataObject = PopulateDataObject();
            var settings = new JsonSerializerSettings()
            {
                NullValueHandling = NullValueHandling.Ignore

            };
            var jsonDataObjectString = JsonConvert.SerializeObject(dataObject, settings);
            JObject jsonDataObject = JObject.Parse(jsonDataObjectString);
            var jsonSchemaFile = File.ReadAllText("Test/testSchema.json");
            var schema = JSchema.Parse(jsonSchemaFile);
            ;
            IList<ValidationError> messages;
            var result = jsonDataObject.IsValid(schema, out messages);
            var errors = GetReadableResult(result, messages);

        }

        private List<Errors> GetReadableResult(bool result, IList<ValidationError> messages)
        {
            var errors = new List<Errors>();

            if (!result)
            {
                foreach (var error in messages)
                {
                    if (error.ChildErrors.Count > 0)
                    {
                        errors.Add(
                            new Errors()
                            {
                                Path = error.ChildErrors.FirstOrDefault()?.Path,
                                Kind = error.ChildErrors.FirstOrDefault()?.Message
                            });
                    }
                    else
                    {
                        errors.Add(new Errors()
                        {
                            Path = error.Path,
                            Kind = error.Message
                        });
                    }
                }
            }

            return errors;
        }

JsonSchema:

{
  "$schema": "http://json-schema.org/draft-07/schema#",
  "title": "Test_Schema",
  "description": "A schema for validating a test object",
  "type": "object",
  "additionalProperties": false,
  "properties": {
    "GeneralData": {
      "type": "object",
      "description": "Advsor and admin customer information",
      "properties": {
        "Name": {
          "type": [ "string", "null" ],
          "description": "Customer's advisor name"
        },
        "Age": {
          "type": [ "string", "null" ],
          "description": "Customer's advisor email"
        },
        "Location": {
          "type": [ "string", "null" ],
          "description": "The advisor's manager email'"
        }
      },
      "required": [ "Name", "Location", "Age" ]
    },
    "ClientData": {
      "type": "object",
      "description": "Customer's information",
      "additionalProperties": false,
      "properties": {
        "Title": {
          "type": [ "string", "null" ]
        },
        "Forename": {
          "type": "string"
        },
        "Surname": {
          "type": [ "string" ]
        }
      },
      "required": [ "Title" ],
      "if": {
        "properties": {
          "Forename": { "enum": [ "Someone" ] }
        },
        "required": [ "Forename" ]
      },
      "then": { "required": [ "Surname" ] },
      "else": {}
    }
  }
}

唯一的补充是使 GetReadableResult 对具有多个子项的错误递归。

In the JSON schema if I set "Surname":{"type":["string","null]} then the error disappears

具有空值的 属性 仍然具有值。如果你想说 属性 值不仅必须存在,而且不能为 null,则将 "type": "string" 添加到你的 then 条件中。