csharp-schema的例子1

亚马逊SPAPI

# 为.NET提供验证器实施示例

对于C# .NET应用,Newtonsoft Json.NET Schema (opens new window)库支持JSON Schema Draft 2019-09和自定义词汇. 以下例子演示了如何利用[Newtonsoft Json.NET Schema](https //www.newtonsoft.com/jsonschema)库来验证具有Amazon产品类型定义Meta-Schema实例的有效载荷.没有要求使用这个特定的库或示例实现.亚马逊不为第三方-party JSON Schema库提供技术支持,这仅作为一个例子提供.

# Schema Configuration

当使用Newtonsoft Json.NET Schema (opens new window)来验证带有自定义词汇的Amazon产品类型定义Meta-Schema的实例时,在解析Amazon产品类型定义Meta-Schema的实例时,元-schema被配置为JSchemaResolver,自定义关键词验证被配置为JSchemaReaderSettings.

常量

// 亚马逊产品类型定义Meta-Schema.的$id
var schemaId = "https://schemas.amazon.com/selling-partners/definitions/product-types/meta-schema/v1";

// 亚马逊产品类型定义Meta-Schema.的本地拷贝
var metaSchemaPath = "./amazon-product-type-definition-meta-schema-v1.json";

// 亚马逊产品类型定义Meta-Schema.实例的本地拷贝
var luggageSchemaPath = "./luggage.json";
1
2
3
4
5
6
7
8

配置Meta-Schema

// 模式解析器,使用模式的本地副本,而不是从网络上检索它们.
var resolver = new JSchemaPreloadedResolver();

// 将元模式添加到解析器中.
resolver.Add(new Uri(schemaId), File.ReadAllText(metaSchemaPath));

// 配置带有解析器和关键字验证器的阅读器设置,以便在解析meta-schema.的实例时使用
var readerSettings = new JSchemaReaderSettings
    {
        Resolver = resolver,
        Validators = new List<JsonValidator> {
        {
            new MaxUniqueItemsKeywordValidator(),
            new MaxUtf8ByteLengthKeywordValidator(),
            新的MinUtf8ByteLengthKeywordValidator()
        }
    };
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

加载Meta-Schema实例

var luggageSchema = JSchema.Parse(File.ReadAllText(luggageSchemaPath), readerSettings);
1

# Payload Validation

有了Amazon产品类型定义Meta-Schema的实例作为`JSchema'实例加载,可以使用instance.验证有效载荷

//为有效载荷创建一个JObject(这可以在代码中构建,也可以从文件中读取,等等.).
var payload = JObject.Parse(File.ReadAllText("./payload.json"));

// 验证payload并获得任何结果的验证信息.
var valid = payload.IsValid(luggageSchema, out IList<string> errorMessages);
1
2
3
4
5

如果payload是有效的,IsValid将返回true和一个空的错误信息列表. 否则IsValid将返回false和一个错误信息列表.

# 关键词验证

Newtonsoft Json.NET Schema (opens new window) 支持通过使用实现JsonValidator接口的类来验证自定义词汇,并提供验证逻辑.

https://www.newtonsoft.com/jsonschema/help/html/CustomJsonValidators.htm (opens new window).

下面的例子说明了 "JsonValidator "接口的实现,验证了Amazon产品类型定义Meta-Schema.实例中的自定义词汇

# MaxUniqueItemsKeyword Class

using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;

命名空间AmazonProductTypeSchemaValidator
{
    /**
     * "maxUniqueItems "关键词的验证器实例.
     */
    public class MaxUniqueItemsKeywordValidator : JsonValidator
    {
        public override void Validate(JToken value, JsonValidatorContext context).
        {
            var maxUniqueItems = GetMaxUniqueItems(context.Schema);
            
            // 获取方案元素上配置的选择器属性,如果它们存在的话. 否则,这个验证器
            // 默认为使用所有属性.
            var selectors = GetSelectors(context.Schema);

            //只在值是一个数组的情况下进行处理.
            如果(value.Type != JTokenType.Array)返回
            
            // 为每个项目的属性(selectors)创建一个属性-value字典,并计算每个组合的出现次数
            //每个组合的出现次数.
            var uniqueItemCounts = new Dictionary<IDictionary<string, string>, int>(new UniqueKeyComparer());
            foreach (var instance in value)
            {
                // 只处理数组中属于对象的实例.
                如果(instance.Type != JTokenType.Object)继续

                var instanceObject = JObject.FromObject(instance);
                var uniqueKeys = instanceObject.Properties()
                    .Where(property => selectors.Count == 0 || selectors.Contains(property.Name))
                    .ToDictionary(property => property.Name, property => property.Value.ToString())

                var count = uniqueItemCounts.GetValueOrDefault(uniqueKeys, 0) + 1;
                uniqueItemCounts[uniqueKeys] = count;
            }
            
            // 找到第一个有太多实例的选择器组合.
            var (uniqueKey, itemCount) = uniqueItemCounts.FirstOrDefault(entry => entry.Value > maxUniqueItems);
            如果(itemCount > 0)的话
            {
                var selectorValues = string.Join(", ", uniqueKey.Select(keyValuePair => $"{keyValuePair.Key}={keyValuePair.Value}").ToList()_
                context.RaiseError($"每个选择器值的组合只能出现{maxUniqueItems}次." +"下面的选择器值组合是什么?
                                   $"下面的选择器值组合出现的次数太多{{{selectorValues}}}");
            }
        }

        public override bool CanValidate(JSchema schema); }
        {
            return GetMaxUniqueItems(schema) >= 0;
        }

        私有的静态IList<string> GetSelectors(JSchema schema) 列表
        {
            var selectors = new List<string>();
            
            var schemaObject = JObject.FromObject(schema);
            var selectorsProperty = schemaObject["selectors"];

            if (selectorsProperty.HasValues)
                selectors.AddRange(selectorsProperty.Select(selector => selector.ToString()));

            返回选择器
        }

        private static int GetMaxUniqueItems(JSchema schema).
        {
            var schemaObject = JObject.FromObject(schema);
            var maxUniqueItemsProperty = schemaObject["maxUniqueItems"];

            如果(maxUniqueItemsProperty != null &amp;&amp; int.TryParse(maxUniqueItemsProperty.ToString(), out var maxUniqueItems)).
                返回maxUniqueItems

            返回-1
        }

        /**
         * "深度 "比较器,用于唯一键字典,以便能够作为字典的键.使用
         */
        private class UniqueKeyComparer : IEqualityComparer<IDictionary<string, string>>
        {
            public bool Equals(IDictionary<string, string> x, IDictionary<string, string> y)
            {
                返回 x.Count == y.Count 
                       &amp;&amp; x.Aggregate(true, (current, keyValuePair) => current &amp;&amp; keyValuePair.Value == y[keyValuePair.Key])
            }

            public int GetHashCode(IDictionary<string, string> obj).
            {
                返回("Keys_" + string.Join(", ", obj.Select(o => o.Key))
                        + "_Values_" + string.Join(",", obj.Select(o => o.Value)).GetHashCode()
            }
        }
    }

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98

# MaxUtf8ByteLengthKeyword Class

using System.Text;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;

命名空间AmazonProductTypeSchemaValidator
{
    /**
     * "maxUtf8ByteLength "关键词的验证器实例.
     */
    public class MaxUtf8ByteLengthKeywordValidator : JsonValidator
    {
        public override void Validate(JToken value, JsonValidatorContext context).
        {
            var maxUtf8ByteLength = GetMaxUtf8ByteLength(context.Schema);
            if (Encoding.UTF8.GetBytes(value.ToString()).Length > maxUtf8ByteLength)
                context.RaiseError($"Value must be less than or equal {maxUtf8ByteLength} bytes in length.");
        }

        public override bool CanValidate(JSchema schema).
        {
            return GetMaxUtf8ByteLength(schema) >= 0;
        }

        private static int GetMaxUtf8ByteLength(JSchema schema)
        {
            var schemaObject = JObject.FromObject(schema);
            var byteLengthProperty = schemaObject["maxUtf8ByteLength"];

            如果(byteLengthProperty != null &amp;&amp; int.TryParse(byteLengthProperty.ToString(), out var maxUtf8ByteLength)).
                返回maxUtf8ByteLength

            返回-1
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35

# MinUtf8ByteLengthKeyword Class

using System.Text;
using Newtonsoft.Json.Linq;
using Newtonsoft.Json.Schema;

命名空间AmazonProductTypeSchemaValidator
{
    /**
     * "minUtf8ByteLength "关键词的验证器实例.
     */
    public class MinUtf8ByteLengthKeywordValidator : JsonValidator
    {
        public override void Validate(JToken value, JsonValidatorContext context).
        {
            var minUtf8ByteLength = GetMinUtf8ByteLength(context.Schema);
            if (Encoding.UTF8.GetBytes(value.ToString()).Length < minUtf8ByteLength)
                context.RaiseError($"Value must be greater than or equal {minUtf8ByteLength} bytes in length.");
        }

        public override bool CanValidate(JSchema schema).
        {
            return GetMinUtf8ByteLength(schema) >= 0;
        }

        private static int GetMinUtf8ByteLength(JSchema schema)
        {
            var schemaObject = JObject.FromObject(schema);
            var byteLengthProperty = schemaObject["minUtf8ByteLength"];

            如果(byteLengthProperty != null &amp;&amp; int.TryParse(byteLengthProperty.ToString(), out var minUtf8ByteLength))
                返回minUtf8ByteLength

            返回-1
        }
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35