System.Text.Json and Dynamically Parsing polymorphic objects

前端 未结 2 686
不思量自难忘°
不思量自难忘° 2020-12-12 03:44

I don\'t believe I am wrapping my head around how to properly use JsonConverter for polymorphism in parsing json results.

In my scenario, I am targeting Git Policy

相关标签:
2条回答
  • 2020-12-12 03:59

    In net 5.0 with System.Text.Json.JsonSerializer, what works for a class like this:

    public class A
    {
        public B Data { get; set; }
    }
    public class B
    {
        public long Count { get; set; }
    }
    

    is using:

    System.Text.Json.JsonSerializer.Deserialize<A>("{{\"data\":{\"count\":10}}}", new JsonSerializerOptions { PropertyNameCaseInsensitive = true, IncludeFields = true })
    

    which is weird that is not the default.

    0 讨论(0)
  • 2020-12-12 04:05

    I ended up solving my issue in slightly the same way I had seen a previous article using a discriminator. Since I do not control the API feeds, I do not have a discriminator to drive off of, so I am relying on the properties of the Json object.

    Need to create a Converter:

    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 );
        }
    }
    

    Then need to create a JsonSerializerOptions object to add the Converter

    public static JsonSerializerOptions PolicyConfigurationSettingsSerializerOptions()
    {
        var serializeOptions = new JsonSerializerOptions();
        serializeOptions.Converters.Add( new PolicyConfigurationSettingsConverter() );
        return serializeOptions;
    }
    

    Pass the options into your Serializer/Deserializer statement.

    Below is the PolicyConfigurationSettings class

    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 { }
    
    0 讨论(0)
提交回复
热议问题