Skip to content

[API Proposal]: Json多态类型处理器,未知类型处理建议 #83160

@bunnyi116

Description

@bunnyi116

这是官方的例子

https://learn.microsoft.com/zh-cn/dotnet/standard/serialization/system-text-json/polymorphism?pivots=dotnet-7-0

[JsonPolymorphic(
    UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToNearestAncestor)]
[JsonDerivedType(typeof(BasePoint))]
[JsonDerivedType(typeof(IPointWithTimeSeries))]
public interface IPoint { }

public interface IPointWithTimeSeries : IPoint { }

public class BasePoint : IPoint { }

public class BasePointWithTimeSeries : BasePoint, IPointWithTimeSeries { }

提议

官方例子中,处理未知类型时,UnknownDerivedTypeHandling = JsonUnknownDerivedTypeHandling.FallBackToBaseType返回上一个派生类,我觉得这样处理不太友好,比如我有一个专门处理未知的派生类,那我所有派生类都得继承这个未知处理的类,属实有点麻烦,且命名不方便。

诺能自定义未知处理类,就可以直接指定该类型。

比如在原有的基础上新增一个布尔属性[JsonDerivedType(typeof(UnknownMessage), bool unknownDefaultHandler = true)] 当然这个未知处理类得是抽象或接口实现的派生类。或者添加新的Attribute,如:JsonDefaultDerivedAttribute,至于怎么命名看你们怎么取了。

image

API Proposal

// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.

namespace System.Text.Json.Serialization
{
    /// <summary>
    /// When placed on a type declaration, indicates that the specified subtype should be opted into polymorphic serialization.
    /// </summary>
    [AttributeUsage(AttributeTargets.Class | AttributeTargets.Interface, AllowMultiple = true, Inherited = false)]
    public class JsonDerivedTypeAttribute : JsonAttribute
    {
        /// <summary>
        /// Initializes a new attribute with specified parameters.
        /// </summary>
        /// <param name="derivedType">A derived type that should be supported in polymorphic serialization of the declared based type.</param>
        public JsonDerivedTypeAttribute(Type derivedType)
        {
            DerivedType = derivedType;
        }

        /// <summary>
        /// Initializes a new attribute with specified parameters.
        /// </summary>
        /// <param name="derivedType">A derived type that should be supported in polymorphic serialization of the declared base type.</param>
        /// <param name="typeDiscriminator">The type discriminator identifier to be used for the serialization of the subtype.</param>
        public JsonDerivedTypeAttribute(Type derivedType, string typeDiscriminator)
        {
            DerivedType = derivedType;
            TypeDiscriminator = typeDiscriminator;
        }

        /// <summary>
        /// Initializes a new attribute with specified parameters.
        /// </summary>
        /// <param name="derivedType">A derived type that should be supported in polymorphic serialization of the declared base type.</param>
        /// <param name="typeDiscriminator">The type discriminator identifier to be used for the serialization of the subtype.</param>
        public JsonDerivedTypeAttribute(Type derivedType, int typeDiscriminator)
        {
            DerivedType = derivedType;
            TypeDiscriminator = typeDiscriminator;
        }


        public JsonDerivedTypeAttribute(Type derivedType, bool isDefaultHandler )
        {
            DerivedType = derivedType;
            TypeDiscriminator = typeDiscriminator;
IsDefaultHandler = isDefaultHandler ;
        }

        /// <summary>
        /// A derived type that should be supported in polymorphic serialization of the declared base type.
        /// </summary>
        public Type DerivedType { get; }

        /// <summary>
        /// The type discriminator identifier to be used for the serialization of the subtype.
        /// </summary>
        public object? TypeDiscriminator { get; }

        /// <summary>
        /// 是否默认处理
        /// </summary>
        public  bool  IsDefaultHandler { get; }

    }
}

API Usage

[JsonPolymorphic(TypeDiscriminatorPropertyName = "type"]
[JsonDerivedType(typeof(UnknownMessage) , true)]
public abstract record Message
{    
    [JsonPropertyName("type")]
    public required string RawType { get; init; }
}

public record UnknownMessage : Message
{    
......
}

Alternative Designs

No response

Risks

No response

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions