序列化时可以自定义和缩短多态类型鉴别器属性名称和值吗?

问题描述 投票:0回答:2

是否可以在序列化/反序列化期间缩短类型鉴别器属性名称和值?我无权访问类型本身,因此在我的情况下,应该通过配置序列化器本身来完成。我需要将属性名称设置为

"__type"
,将属性值设置为某个自定义名称。

我知道可以在

System.Web.Script.Serialization
JavaScriptTypeResolver
中使用,但我需要在 .NET Core System.Text.Json 中实现。

这是一个如何使用

JavaScriptTypeResolver
完成此操作的示例(该示例基于 这个 MS 示例):

var people = new Person[] { new Person { Name = "AbcPerson" } };

var serialized = new JavaScriptSerializer(new CustomTypeResolver()).Serialize(people);
Console.WriteLine(serialized);

...

public class Person
{
    public string Name { get; set; }
}

public class CustomTypeResolver : JavaScriptTypeResolver
{
    private readonly IDictionary<string, Type> _typeIds
        = new Dictionary<string, Type> { { "P", typeof(Person) } };

    public override Type ResolveType(string id)
    {
        _typeIds.TryGetValue(id, out var result);
        return result;
    }

    public override string ResolveTypeId(Type type)
    {
        return _typeIds.SingleOrDefault(x => x.Value == type).Key;
    }
}

输出为:

[{"__type":"P","姓名":"AbcPerson"}]

编辑:部分解决方案是使用这样的属性

[JsonDerivedType(typeof(Person), typeDiscriminator: "P")]
。但是输出是这样的

[{"$type":"P","姓名":"AbcPerson"}]

我面临着将

$type
更改为
__type
的问题。

c# serialization polymorphism system.text.json
2个回答
1
投票

要将类型鉴别器属性名称更改为

"__type"
(这是
JavaScriptSerializer
DataContractJsonSerializer
使用的鉴别器名称),您需要在要为其发出类型的每个类型上设置
[JsonPolymorphic(TypeDiscriminatorPropertyName = "__type")]
类型鉴别器。例如,如果您的数据模型具有基本类型
Person
和派生类型
Adult
,您需要按如下方式修改它们:

[JsonPolymorphic(TypeDiscriminatorPropertyName = "__type")] // Add this here
[JsonDerivedType(typeof(Person), typeDiscriminator: "P")]
[JsonDerivedType(typeof(Adult), typeDiscriminator: "A")]
public class Person
{
    public string Name { get; set; }
}

[JsonPolymorphic(TypeDiscriminatorPropertyName = "__type")] // And also here
[JsonDerivedType(typeof(Adult), typeDiscriminator: "A")]
public class Adult : Person;

演示小提琴#1 这里

或者,如果您无法轻松修改数据模型,您可以通过 JsonTypeInfo 修饰符

更改
鉴别器名称

public static partial class JsonExtensions
{
    public const string MyTypeDiscriminatorPropertyName = "__type";
    
    public static Action<JsonTypeInfo> SetupMyTypeDiscriminatorPropertyName() => 
        SetupTypeDiscriminatorPropertyName(MyTypeDiscriminatorPropertyName);

    public static Action<JsonTypeInfo> SetupTypeDiscriminatorPropertyName(string name) => 
        (JsonTypeInfo typeInfo) =>
    {
        if (typeInfo.PolymorphismOptions != null)
            typeInfo.PolymorphismOptions.TypeDiscriminatorPropertyName = name;
    };
}

然后在选项中使用它,例如如下:

var options = new JsonSerializerOptions
{
    TypeInfoResolver = new DefaultJsonTypeInfoResolver() 
        .WithAddedModifier(JsonExtensions.SetupMyTypeDiscriminatorPropertyName()),
    // Add other options as required.
};

var json = JsonSerializer.Serialize(people, options);

var people2 = JsonSerializer.Deserialize<Person []>(json, options);

演示小提琴 #2 这里

另请参阅:


0
投票

我想你想使用 System.Text.Json 库。 如果您的目标是根据某些自定义规则重命名 json 属性,您可以执行以下操作:

using System;
using System.Collections.Generic;
using System.Text.Json;
using System.Text.Json.Serialization;

class CustomType
{
    public int Id { get; set; }
    public string Name { get; set; }
    public InnerCustomType InnerCustomType { get; set; }
}

class InnerCustomType
{
    public int Id { get; set; }
    public string Name { get; set; }
}

class CustomNamingPolicy : JsonNamingPolicy
{
    Dictionary<string, string> propertyRenamingRules = new Dictionary<string, string>()
    {
        { "InnerCustomType", "ICT" }
    };

    public override string ConvertName(string name)
    {
        // Customize the conversion of class names as needed
        string alternativeName;
        if(propertyRenamingRules.TryGetValue(name, out alternativeName))
            return alternativeName;
            
        return name;
    }
}

class Program
{
    static void Main()
    {
        CustomType customObject = new CustomType { Id = 1, Name = "Example", InnerCustomType = new InnerCustomType { Id = 2, Name = "Example 2" }  };

        JsonSerializerOptions options = new JsonSerializerOptions
        {
            PropertyNamingPolicy = new CustomNamingPolicy(),
            WriteIndented = true
        };

        // Serialize the object using the custom naming policy
        string jsonString = JsonSerializer.Serialize(customObject, options);

        Console.WriteLine(jsonString);
    }
}

此代码打印此 json:

{
  "Id": 1,
  "Name": "Example",
  "ICT": {
    "Id": 2,
    "Name": "Example 2"
  }
}

我建议您查看此页面以获取有关 CustomNamingPolicy 的更多文档:https://learn.microsoft.com/en-us/dotnet/standard/serialization/system-text-json/customize-properties?pivots =dotnet-8-0

© www.soinside.com 2019 - 2024. All rights reserved.