将 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)