# 为.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";
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()
}
};
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);
# 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);
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 && 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
&& x.Aggregate(true, (current, keyValuePair) => current && 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()
}
}
}
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 && int.TryParse(byteLengthProperty.ToString(), out var maxUtf8ByteLength)).
返回maxUtf8ByteLength
返回-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 && int.TryParse(byteLengthProperty.ToString(), out var minUtf8ByteLength))
返回minUtf8ByteLength
返回-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