Reputation: 300
I have an issue when trying to map a JSON response I get from an API into an appropriate object that I made. Following is the JSON example
{
"Count": "1",
"Data": {
"EmployeeMstr": {
"ledger": "GL",
"faid": "_tag_"
}
}
}
I need to create and object so that i can deserialize the above Json. I can create an object and desiarilse using JsonConvert.DeserializeObject<ResponseObject>(jsonResponse)
. Where ResponseObject is the class I created like following.
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; }
}
But the issue with this is, the key name "EmployeeMstr"
in the above Json can be anything depending upon which table it is coming from ( like "HrNewHire" ,"Payroll"
etc). I don't want to create separate object for all seperated tables. So what could be the best approach so that I can use this class to serialize the JSON irrespective of what that table name is?
Upvotes: 0
Views: 1997
Reputation: 372
just replace your Model to dynamic
JsonConvert.DeserializeObject<dynamic>(jsonResponse)
Upvotes: 0
Reputation: 18155
You could use a Dictionary to store the key values where the Key names could change. For example,
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; }
}
Sample Output
Upvotes: 2
Reputation: 234
You could implement a Json Converter:
This maps the variant properties to the property you want to set.
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;
}
}
You have to set the attribute in the Class where your custom property its.
[JsonConverter(typeof(CustomFieldConverter))]
public class Data
you can see a detailed example here:
https://www.jerriepelser.com/blog/deserialize-different-json-object-same-class/
You can use JObject as type of CustomProperty to allow to maps distinct json objects. But I think your code will remain something unintelligible.
Other way is to maps this property to a class with this structure:
public class CustomProperty
{
[JsonProperty("TableName")]
public string TableName{ get; set; }
[JsonProperty("Data")]
public Dictionary<string, object> Properties { get; set; }
}
An loads the properties in a dictionary with a JsonConverter
Upvotes: 0