Mat*_*ttB 7 c# .net-core-3.1 system.text.json
我不相信我正在考虑如何在解析 json 结果时正确使用 JsonConverter 进行多态性。
在我的场景中,我的目标是 TFS 中的 Git 策略配置。策略配置:
"value": [
{
"createdBy": {
"displayName": "username",
"url": "url",
"id": "id",
"uniqueName": "user",
"imageUrl": "url"
},
"createdDate": "2020-03-21T18:17:24.3240783Z",
"isEnabled": true,
"isBlocking": true,
"isDeleted": false,
"settings": {
"minimumApproverCount": 1,
"creatorVoteCounts": false,
"allowDownvotes": false,
"resetOnSourcePush": true,
"scope": [{
"refName": "refs/heads/master",
"matchKind": "Exact",
"repositoryId": "id"
}
]
},
"_links": {
"self": {
"href": "url"
},
"policyType": {
"href": "url"
}
},
"revision": 1,
"id": 974,
"url": "url",
"type": {
"id": "id",
"url": "url",
"displayName": "Minimum number of reviewers"
},
{...}]
Run Code Online (Sandbox Code Playgroud)
更多settings示例:需要合并策略
"settings": {
"useSquashMerge": true,
"scope": [
{
"refName": "refs/heads/master",
"matchKind": "Exact",
"repositoryId": "id"
}
]
}
Run Code Online (Sandbox Code Playgroud)
所需的审稿人
"settings": {
"requiredReviewerIds": [
"id"
],
"scope": [
{
"refName": "refs/heads/master",
"matchKind": "Exact",
"repositoryId": "id"
}
]
}
Run Code Online (Sandbox Code Playgroud)
在上面的 json 片段中,设置对象因配置类型而异。
与可以动态序列化/反序列化设置对象相比,编写转换器的最佳方法是什么?我已经阅读了几篇关于此的文章,但无法完全理解它。
这就是我目前反序列化我所有 API 结果的方式,到目前为止它们都是简单的结果集。
async Task<List<T>> ParseResults<T>( HttpResponseMessage result, string parameter )
{
List<T> results = new List<T>();
if ( result.IsSuccessStatusCode )
{
using var stream = await result.Content.ReadAsStreamAsync();
JsonDocument doc = JsonDocument.Parse( stream );
JsonElement collection = doc.RootElement.GetProperty( parameter ).Clone();
foreach ( var item in collection.EnumerateArray() )
{
results.Add( JsonSerializer.Deserialize<T>( item.ToString() ) );
}
}
return results;
}
Run Code Online (Sandbox Code Playgroud)
我的集成测试。
PolicyConfiguration 是我试图反序列化的类型。
[Test]
public async Task Get_TestMasterBranchPolicyConfigurations()
{
HttpResponseMessage result = await GetResult( $"{_collection}/ProductionBuildTesting/_apis/policy/configurations?api-version=4.1" );
List<PolicyConfiguration> configurations = await ParseResults<PolicyConfiguration>( result, "value" );
Assert.AreEqual( 16, configurations.Count );
JsonPrint( configurations );
}
Run Code Online (Sandbox Code Playgroud)
我目前针对这种解析情况的课程
public class CreatedBy
{
[JsonPropertyName( "displayName" )]
public string DisplayName { get; set; }
[JsonPropertyName( "url" )]
public string Url { get; set; }
[JsonPropertyName( "id" )]
public Guid Id { get; set; }
[JsonPropertyName( "uniqueName" )]
public string UniqueName { get; set; }
[JsonPropertyName( "imageUrl" )]
public string ImageUrl { get; set; }
}
public class PolicyConfigurationScope
{
[JsonPropertyName( "refName" )]
public string RefName { get; set; }
[JsonPropertyName( "matchKind" )]
public string MatchKind { get; set; }
[JsonPropertyName( "repositoryId" )]
public Guid RepositoryId { get; set; }
}
public class PolicyConfigurationSettings_MinimumNumberOfReviewers
{
[JsonPropertyName( "minimumApproverCount" )]
public int MinimumApproverCount { get; set; }
[JsonPropertyName( "creatorVoteCounts" )]
public bool CreatorVoteCounts { get; set; }
[JsonPropertyName( "allowDownvotes" )]
public bool AllowDownvotes { get; set; }
[JsonPropertyName( "resetOnSourcePush" )]
public bool ResetOnSourcePush { get; set; }
[JsonPropertyName( "scope" )]
public List<PolicyConfigurationScope> Scope { get; set; }
}
public class PolicyConfigurationType
{
[JsonPropertyName( "id" )]
public Guid Id { get; set; }
[JsonPropertyName( "url" )]
public string Url { get; set; }
[JsonPropertyName( "displayName" )]
public string DisplayName { get; set; }
}
public class PolicyConfiguration
{
[JsonPropertyName( "createdBy" )]
public CreatedBy CreatedBy { get; set; }
[JsonPropertyName( "createdDate" )]
public DateTime CreatedDate { get; set; }
[JsonPropertyName( "isEnabled" )]
public bool IsEnabled { get; set; }
[JsonPropertyName( "isBlocking" )]
public bool IsBlocking { get; set; }
[JsonPropertyName( "isDeleted" )]
public bool IsDeleted { get; set; }
//[JsonPropertyName( "settings" )]
//public PolicyConfigurationSettings_MinimumNumberOfReviewersSettings Settings { get; set; }
[JsonPropertyName( "revision" )]
public int Revision { get; set; }
[JsonPropertyName( "id" )]
public int Id { get; set; }
[JsonPropertyName( "url" )]
public string Url { get; set; }
[JsonPropertyName( "type" )]
public PolicyConfigurationType Type { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我最终以与之前使用鉴别器看到的文章相同的方式解决了我的问题。因为我不控制 API 提要,所以我没有可以驱散的鉴别器,所以我依赖于 Json 对象的属性。
需要创建一个转换器:
public class PolicyConfigurationSettingsConverter : JsonConverter<PolicyConfigurationSettings>
{
public override PolicyConfigurationSettings Read( ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options )
{
JsonDocument doc;
JsonDocument.TryParseValue( ref reader, out doc );
if ( doc.RootElement.TryGetProperty( "minimumApproverCount", out _ ) )
return JsonSerializer.Deserialize<MinimumNumberOfReviewers>( doc.RootElement.ToString(), options );
if ( doc.RootElement.TryGetProperty( "useSquashMerge", out _ ) )
return JsonSerializer.Deserialize<RequireAMergeStrategy>( doc.RootElement.ToString(), options );
if ( doc.RootElement.TryGetProperty( "scope", out _ ) )
return JsonSerializer.Deserialize<PolicyConfigurationSettingsScope>( doc.RootElement.ToString(), options );
return null;
}
public override void Write( Utf8JsonWriter writer, [DisallowNull] PolicyConfigurationSettings value, JsonSerializerOptions options )
{
if ( value.GetType() == typeof( MinimumNumberOfReviewers ) )
JsonSerializer.Serialize( writer, ( MinimumNumberOfReviewers )value, options );
if ( value.GetType() == typeof( RequireAMergeStrategy ) )
JsonSerializer.Serialize( writer, ( RequireAMergeStrategy )value, options );
if ( value.GetType() == typeof( PolicyConfigurationSettingsScope ) )
JsonSerializer.Serialize( writer, ( PolicyConfigurationSettingsScope )value, options );
}
}
Run Code Online (Sandbox Code Playgroud)
然后需要创建一个JsonSerializerOptions对象来添加Converter
public static JsonSerializerOptions PolicyConfigurationSettingsSerializerOptions()
{
var serializeOptions = new JsonSerializerOptions();
serializeOptions.Converters.Add( new PolicyConfigurationSettingsConverter() );
return serializeOptions;
}
Run Code Online (Sandbox Code Playgroud)
将选项传递到您的 Serializer/Deserializer 语句中。
下面是PolicyConfigurationSettings班级
public abstract class PolicyConfigurationSettings
{
[JsonPropertyName( "scope" )]
public List<PolicyConfigurationScope> Scope { get; set; }
}
public class MinimumNumberOfReviewers : PolicyConfigurationSettings
{
[JsonPropertyName( "minimumApproverCount" )]
public int MinimumApproverCount { get; set; }
[JsonPropertyName( "creatorVoteCounts" )]
public bool CreatorVoteCounts { get; set; }
[JsonPropertyName( "allowDownvotes" )]
public bool AllowDownvotes { get; set; }
[JsonPropertyName( "resetOnSourcePush" )]
public bool ResetOnSourcePush { get; set; }
}
public class RequireAMergeStrategy : PolicyConfigurationSettings
{
[JsonPropertyName( "useSquashMerge" )]
public bool UseSquashMerge { get; set; }
}
public class PolicyConfigurationSettingsScope : PolicyConfigurationSettings { }
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
4337 次 |
| 最近记录: |