将属性名称更改为在使用Json.net进行序列化时已实例化的派生类名称

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将属性名称更改为在使用Json.net进行序列化时已实例化的派生类名称相关的知识,希望对你有一定的参考价值。

我正在尝试使用最新版本的NewtonSoft.JSON在.NET(标准)中序列化(和反序列化)我的对象。

这是我的课程:

public class BaseRequest

    public string UserName get; set; 

BaseRequest派生的请求(我还有许多从BaseRequest派生的此类类:]

public class GetDeviceRequest : BaseRequest

    public string SerialNumber  get; set; 

我序列化为Json的请求是通过类创建的:

public class CommunicationRequest

    public CommunicationRequest()  

    public CommunicationRequest(BaseRequest baseRequest, string version ="1.1")
    
        this.Version = version;
        this.Request = baseRequest;
    

    public string Version  get; set;  = "1.1";
    public BaseRequest Request  get; set; 

我用于序列化的代码。我尚未测试反序列化,但是它应该以相同的方式工作

GetDeviceRequest getDeviceRequest = new GetDeviceRequest()

    SerialNumber = "123456789",
    UserName = "john.doe"
;

CommunicationRequest request = new CommunicationRequest(getDeviceRequest);

var settings = new JsonSerializerSettings

    ContractResolver = new CamelCasePropertyNamesContractResolver()
;

var json = JsonConvert.SerializeObject(request, settings);

我得到的JSON:


   "version":"1.1",
   "request":      
         "serialNumber":"123456789",
         "username":"john.doe"
   

我想要的是:


   "version":"1.1",
   "getDeviceRequest":      
         "serialNumber":"123456789",
         "username":"john.doe"
   

我需要根据派生类的名称将JsonPropertyRequest名称动态更改为GetDeviceRequest

我本可以做的事情:

[JsonProperty("DerievedClassName")]
public BaseRequest Request  get; set; 

这显然对我不起作用,因为未实例化该对象,并且我无法使类型使用Request.GetType()之类的东西。

似乎方法是实现我的ICustomContractResolver,但是我无法为我的用例获得一个有效的CustomContractResolver

有没有一种方法可以序列化我想要的方法?

答案

您将需要为JsonConverter类使用自定义CommunicationRequest来处理动态属性名称,并能够在反序列化时将其解析为正确的类型(假设您要对此进行往返操作)。类似于以下内容的内容可能会适合您的需求,但可能需要进行一些调整。

public class CommunicationRequestConverter : JsonConverter

    NamingStrategy NamingStrategy  get; set; 

    public CommunicationRequestConverter(NamingStrategy namingStrategy)
    
        NamingStrategy = namingStrategy;
    

    public override bool CanConvert(Type objectType)
    
        return objectType == typeof(CommunicationRequest);
    

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    
        CommunicationRequest req = (CommunicationRequest)value;
        JObject jo = new JObject(
            new JProperty(GetPropertyName("Version"), req.Version),
            new JProperty(GetPropertyName(req.Request.GetType().Name), 
                          JObject.FromObject(req.Request, serializer))
        );
        jo.WriteTo(writer);
    

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    
        JObject jo = JObject.Load(reader);

        string versionPropertyName = GetPropertyName("Version");
        JProperty requestProperty = jo.Properties().FirstOrDefault(p => p.Name != versionPropertyName);

        Type baseRequestType = Assembly.GetAssembly(typeof(BaseRequest)).GetTypes()
            .Where(t => t.IsClass && GetPropertyName(t.Name) == requestProperty.Name)
            .First();

        CommunicationRequest req = new CommunicationRequest
        
            Version = (string)jo[versionPropertyName],
            Request = (BaseRequest)requestProperty.Value.ToObject(baseRequestType, serializer)
        ;

        return req;
    

    private string GetPropertyName(string name)
    
        return NamingStrategy.GetPropertyName(name, false);
    

像这样设置序列化器设置:

var ns = new CamelCaseNamingStrategy();
var settings = new JsonSerializerSettings  
    ContractResolver = new DefaultContractResolver  NamingStrategy = ns ,
    Converters = new List<JsonConverter>  new CommunicationRequestConverter(ns) ,
    Formatting = Formatting.Indented
;

这里是往返演示:https://dotnetfiddle.net/kufBae

以上是关于将属性名称更改为在使用Json.net进行序列化时已实例化的派生类名称的主要内容,如果未能解决你的问题,请参考以下文章

Json.NET 反序列化或序列化 json 字符串并将属性映射到运行时定义的不同属性名称

将 JSON 反序列化为 C# 类,其中 JSON 中的属性名称是动态的

使属性反序列化但不使用 json.net 序列化

JSON.NET 将对象 序列化为 JSON字符串时,能否指定,某个属性不被转化。

Json.NET:单个属性的不同JSON模式

Json.NET - CustomCreationConverter 中单个属性的默认反序列化行为