将属性名称更改为在使用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"
我需要根据派生类的名称将JsonProperty
的Request
名称动态更改为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 中的属性名称是动态的