Как можно сопоставить имена полей Dynami c при десериализации объекта JSON с объектом C#? - PullRequest
0 голосов
/ 10 марта 2020

У меня проблема при попытке отобразить ответ JSON, полученный от API, в соответствующий объект, который я создал. Ниже приведен пример JSON

{
    "Count": "1",
    "Data": {
        "EmployeeMstr": {
            "ledger": "GL",
            "faid": "_tag_"
        }
    }
}

Мне нужно создать и возразить, чтобы я мог десериализовать вышеприведенное Json. Я могу создать объект и удалить его, используя JsonConvert.DeserializeObject<ResponseObject>(jsonResponse). Где ResponseObject - это класс, который я создал следующим образом.

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; }
    }

Но проблема с этим заключается в том, что имя ключа "EmployeeMstr" в приведенном выше Json может быть любым в зависимости от того, из какой таблицы оно исходит ( как "HrNewHire" ,"Payroll" et c). Я не хочу создавать отдельный объект для всех отдельных таблиц. Итак, что может быть лучшим подходом, чтобы я мог использовать этот класс для сериализации JSON независимо от того, что это имя таблицы?

Ответы [ 3 ]

1 голос
/ 10 марта 2020

Вы можете использовать словарь для хранения значений ключей, где имена ключей могут меняться. Например,

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; }
}

Пример вывода

enter image description here

0 голосов
/ 10 марта 2020

просто замените вашу модель на dynamic JsonConvert.DeserializeObject<dynamic>(jsonResponse)

0 голосов
/ 10 марта 2020

Вы можете реализовать конвертер 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;
    }
}

Вы должны установить атрибут в классе, где Ваше пользовательское свойство его.

[JsonConverter(typeof(CustomFieldConverter))]
public class Data

подробный пример вы можете увидеть здесь:

https://www.jerriepelser.com/blog/deserialize-different-json-object-same-class/

Вы можете использовать JObject в качестве типа CustomProperty, позволяющий отображать отдельные json объекты. Но я думаю, что ваш код останется чем-то непонятным.

Другой способ - сопоставить это свойство с классом с такой структурой:

public class CustomProperty
{
    [JsonProperty("TableName")]
    public string TableName{ get; set; }

    [JsonProperty("Data")]
    public Dictionary<string, object> Properties { get; set; }
}

An загружает свойства в словаре с помощью JsonConverter

...