将 JSON 反序列化为 C# 对象时,如何映射动态字段名称?
While deserializing a JSON to a C# object, how can I map dynamic field names?
我在尝试将从 API 获得的 JSON 响应映射到我创建的适当对象时遇到问题。以下是 JSON 示例
{
"Count": "1",
"Data": {
"EmployeeMstr": {
"ledger": "GL",
"faid": "_tag_"
}
}
}
我需要创建和对象,以便我可以反序列化上面的 Json。我可以使用 JsonConvert.DeserializeObject<ResponseObject>(jsonResponse)
创建一个对象和 desiarilse。其中 ResponseObject 是我创建的 class,如下所示。
public class ResponseObject
{
public string Count { get; set; }
public string NextUri { get; set; }
public Data Data{ get; set; }
}
public class Data
{
public string EmployeeMstr { get; set; }
}
但问题在于,上面 Json 中的键名称 "EmployeeMstr"
可以是任何名称,具体取决于它来自哪个 table(例如 "HrNewHire" ,"Payroll"
ETC)。我不想为所有分离的 table 创建单独的对象。那么最好的方法是什么,这样我就可以使用这个 class 序列化 JSON 而不管 table 名称是什么?
您可以实现一个 Json 转换器:
这会将变体属性映射到您要设置的 属性。
public class CustomFieldConverter : JsonConverter
{
private readonly Dictionary<string, string> _propertyMappings = new Dictionary<string, string>
{
{"EmployeeMstr", "CustomProperty"},
{"HrNewHire", "CustomProperty"},
{"Payroll", "CustomProperty"}
};
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return objectType.GetTypeInfo().IsClass;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
object instance = Activator.CreateInstance(objectType);
var props = objectType.GetTypeInfo().DeclaredProperties.ToList();
JObject jo = JObject.Load(reader);
foreach (JProperty jp in jo.Properties())
{
if (!_propertyMappings.TryGetValue(jp.Name, out var name))
name = jp.Name;
PropertyInfo prop = props.FirstOrDefault(pi =>
pi.CanWrite && pi.GetCustomAttribute<JsonPropertyAttribute>().PropertyName == name);
prop?.SetValue(instance, jp.Value.ToObject(prop.PropertyType, serializer));
}
return instance;
}
}
您必须在 Class 中设置您的自定义 属性 属性。
[JsonConverter(typeof(CustomFieldConverter))]
public class Data
你可以在这里看到一个详细的例子:
https://www.jerriepelser.com/blog/deserialize-different-json-object-same-class/
您可以使用 JObject 作为 CustomProperty 的类型,以允许映射不同的 json 对象。但我认为你的代码仍然是一些难以理解的东西。
另一种方法是将此 属性 映射到具有以下结构的 class:
public class CustomProperty
{
[JsonProperty("TableName")]
public string TableName{ get; set; }
[JsonProperty("Data")]
public Dictionary<string, object> Properties { get; set; }
}
An 使用 JsonConverter
加载字典中的属性
您可以使用字典来存储键名可以更改的键值。例如,
public class Value
{
public string ledger { get; set; }
public string faid { get; set; }
}
public class ResponseObject
{
public string Count { get; set; }
public Dictionary<string,Value> Data { get; set; } // Change here
public string NextUri { get; set; }
}
示例输出
只需将您的模型替换为 dynamic
JsonConvert.DeserializeObject<dynamic>(jsonResponse)
我在尝试将从 API 获得的 JSON 响应映射到我创建的适当对象时遇到问题。以下是 JSON 示例
{
"Count": "1",
"Data": {
"EmployeeMstr": {
"ledger": "GL",
"faid": "_tag_"
}
}
}
我需要创建和对象,以便我可以反序列化上面的 Json。我可以使用 JsonConvert.DeserializeObject<ResponseObject>(jsonResponse)
创建一个对象和 desiarilse。其中 ResponseObject 是我创建的 class,如下所示。
public class ResponseObject
{
public string Count { get; set; }
public string NextUri { get; set; }
public Data Data{ get; set; }
}
public class Data
{
public string EmployeeMstr { get; set; }
}
但问题在于,上面 Json 中的键名称 "EmployeeMstr"
可以是任何名称,具体取决于它来自哪个 table(例如 "HrNewHire" ,"Payroll"
ETC)。我不想为所有分离的 table 创建单独的对象。那么最好的方法是什么,这样我就可以使用这个 class 序列化 JSON 而不管 table 名称是什么?
您可以实现一个 Json 转换器:
这会将变体属性映射到您要设置的 属性。
public class CustomFieldConverter : JsonConverter
{
private readonly Dictionary<string, string> _propertyMappings = new Dictionary<string, string>
{
{"EmployeeMstr", "CustomProperty"},
{"HrNewHire", "CustomProperty"},
{"Payroll", "CustomProperty"}
};
public override bool CanWrite => false;
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type objectType)
{
return objectType.GetTypeInfo().IsClass;
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
object instance = Activator.CreateInstance(objectType);
var props = objectType.GetTypeInfo().DeclaredProperties.ToList();
JObject jo = JObject.Load(reader);
foreach (JProperty jp in jo.Properties())
{
if (!_propertyMappings.TryGetValue(jp.Name, out var name))
name = jp.Name;
PropertyInfo prop = props.FirstOrDefault(pi =>
pi.CanWrite && pi.GetCustomAttribute<JsonPropertyAttribute>().PropertyName == name);
prop?.SetValue(instance, jp.Value.ToObject(prop.PropertyType, serializer));
}
return instance;
}
}
您必须在 Class 中设置您的自定义 属性 属性。
[JsonConverter(typeof(CustomFieldConverter))]
public class Data
你可以在这里看到一个详细的例子:
https://www.jerriepelser.com/blog/deserialize-different-json-object-same-class/
您可以使用 JObject 作为 CustomProperty 的类型,以允许映射不同的 json 对象。但我认为你的代码仍然是一些难以理解的东西。
另一种方法是将此 属性 映射到具有以下结构的 class:
public class CustomProperty
{
[JsonProperty("TableName")]
public string TableName{ get; set; }
[JsonProperty("Data")]
public Dictionary<string, object> Properties { get; set; }
}
An 使用 JsonConverter
加载字典中的属性您可以使用字典来存储键名可以更改的键值。例如,
public class Value
{
public string ledger { get; set; }
public string faid { get; set; }
}
public class ResponseObject
{
public string Count { get; set; }
public Dictionary<string,Value> Data { get; set; } // Change here
public string NextUri { get; set; }
}
示例输出
只需将您的模型替换为 dynamic
JsonConvert.DeserializeObject<dynamic>(jsonResponse)