针对 API 测试,我们需要验证 Response 中的一些字段类型,是否缺省等,现在有一些开源的插件就可以实现,很方便。
之前 Java API 测试 《 REST Assured 系列汇总 》有介绍 REST Assured JSON Schema 验证,可以参考下面三篇文章:
REST Assured 54 - What Is JSON Schema?
REST Assured 55 - JSON Schema Validation In Rest Assured
REST Assured 56 - JSON Schema Validation Without Rest Assured
今天介绍 C# API 测试有关 JSON Schema validation,怎么将 JSON 生成 C# 类文件,以及如何验证 JSON Schema。
主要有三种方式将 JSON response 自动生成 C# 类 JSON Schema,各有特色。
用在线工具 quicktype 生成最方便了, 还可以进行一些设置。
例如:简单的一个 JSON
{
"ID": "1002",
"Name": "ABCD",
"City": "city",
"Country": "USA",
"hobby": ["reading", "travel"]
}
Visual Studio 有个 “Paste Special” 功能用来创建 JSON c# classes.
Visual Studio – -> Edit — > Paste Special
具体步骤如下:
{
"ID": "1002",
"Name": "ABCD",
"City": "city",
"Country": "USA",
"hobby": ["reading", "travel"]
}
public class Rootobject
{
public string ID { get; set; }
public string Name { get; set; }
public string City { get; set; }
public string Country { get; set; }
public string[] hobby { get; set; }
}
NJsonSchema 是一个 .NET library 用来读,生成,验证 JSON Schema. 它提供了基本的 APIs,可以用来从一个 JSON Schema 生成 C# 类,或生成 TypeScript 类,或接口。更多细节可参考《 Autogenerate C# Class using JSON string or JSON Schema 》
using NJsonSchema.CodeGeneration.CSharp;
using JsonSchema = NJsonSchema.JsonSchema;
namespace ConsoleApp
{
public class Generator
{
static void Main(string[] args)
{
string json = File.ReadAllText("js.json");
var schemaFromFile = JsonSchema.FromSampleJson(json);
var classGenerator = new CSharpGenerator(schemaFromFile, new CSharpGeneratorSettings
{
ClassStyle = CSharpClassStyle.Poco,
});
var codeFile = classGenerator.GenerateFile();
File.WriteAllText("JSONSchemaClass.cs", codeFile);
}
}
}
//----------------------
//
// Generated using the NJsonSchema v10.8.0.0 (Newtonsoft.Json v9.0.0.0) (http://NJsonSchema.org)
//
//----------------------
namespace MyNamespace
{
#pragma warning disable // Disable all warnings
[System.CodeDom.Compiler.GeneratedCode("NJsonSchema", "10.8.0.0 (Newtonsoft.Json v9.0.0.0)")]
public partial class Anonymous
{
[Newtonsoft.Json.JsonProperty("ID", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string ID { get; set; }
[Newtonsoft.Json.JsonProperty("Name", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string Name { get; set; }
[Newtonsoft.Json.JsonProperty("City", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string City { get; set; }
[Newtonsoft.Json.JsonProperty("Country", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public string Country { get; set; }
[Newtonsoft.Json.JsonProperty("hobby", Required = Newtonsoft.Json.Required.DisallowNull, NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore)]
public System.Collections.Generic.ICollection<string> Hobby { get; set; }
private System.Collections.Generic.IDictionary<string, object> _additionalProperties;
[Newtonsoft.Json.JsonExtensionData]
public System.Collections.Generic.IDictionary<string, object> AdditionalProperties
{
get { return _additionalProperties ?? (_additionalProperties = new System.Collections.Generic.Dictionary<string, object>()); }
set { _additionalProperties = value; }
}
}
}
可以参考这遍文章《 C# JSON Schema validation 》这个例子还能运用在异步代码上。
namespace ConsoleApp
{
using NJsonSchema;
using System;
using System.Threading.Tasks;
class ValidateJSONSchema
{
static async Task Main()
{
var jsonSchema = @"
{
""type"": ""object"",
""properties"": {
""name"": {
""type"": ""string""
},
""age"": {
""type"": ""integer"",
""minimum"": 0
},
""isMarried"": {
""type"": ""boolean""
}
}
}
";
var jsonDataValid = @"
{
""name"": ""Jay"",
""age"": 20,
""isMarried"": true
}
";
var jsonDataInvalid = @"
{
""name"": ""Jay"",
""age"": ""20"",
""isMarried"": ""true""
}
";
var schema = await JsonSchema.FromJsonAsync(jsonSchema);
var errorsForValidJson = schema.Validate(jsonDataValid);
var errorsForInvalidJson = schema.Validate(jsonDataInvalid);
Console.WriteLine("valid errors:");
foreach (var error in errorsForValidJson) Console.WriteLine(error);
Console.WriteLine("invalid errors:");
foreach (var error in errorsForInvalidJson) Console.WriteLine(error);
}
}
}
运行结果如下:
利用前面介绍的方法,将生成的 C# 类 JSON Schema 文件添加到项目中。
using Newtonsoft.Json;
namespace ConsoleApp
{
public class JSONSchema
{
[JsonProperty("ID", Required = Required.Always)]
public string Id { get; set; }
[JsonProperty("Name", Required = Required.Always)]
public string Name { get; set; }
[JsonProperty("City", Required = Required.Always)]
public string City { get; set; }
[JsonProperty("Country", Required = Required.Always)]
public string Country { get; set; }
[JsonProperty("hobby", Required = Required.Always)]
public List<string> Hobby { get; set; }
}
}
利用反射机制将 C# 类解析成 JsonSchema
string schemaName = “JSONSchema”;
Type type = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x => x.Name == schemaName);
var schema = JsonSchema.FromType(type);
using Newtonsoft.Json.Linq;
using NJsonSchema;
using System.Reflection;
namespace ConsoleApp
{
public class ValidateJSONSchema
{
static void Main(string[] args)
{
//string data = "";
string jsonDataValid = @"
{
""ID"": ""1002"",
""Name"": ""ABCD"",
""City"": ""city"",
""Country"": ""USA"",
""hobby"": [""reading"", ""travel""]
}
";
string schemaName = "JSONSchema";
Type type = Assembly.GetExecutingAssembly().GetTypes().FirstOrDefault(x => x.Name == schemaName);
if (type == null)
throw new Exception($"Schema {schemaName} not found");
JToken Data = JToken.Parse(jsonDataValid);
var schema = Data.Type == JTokenType.Array ?
JsonSchema.FromType(typeof(List<>).MakeGenericType(new[] { type })) :
JsonSchema.FromType(type);
var errors = schema.Validate(jsonDataValid);
Console.WriteLine(errors.Count.ToString());
Console.WriteLine(string.Join(System.Environment.NewLine, errors));
}
}
}