I have the following class:
public class MyRequest
{
public string Type {get;set;}
public string Source {get;set;}
}
I would like t
My solution is: First create APIResultModel class:
public class APIResultModel<T> where T: APIModel, new()
{
public string ImmutableProperty { get; set; }
public T Result { get; set; }
public APIResultModel<T> Deserialize(string json)
{
var jObj = JObject.Parse(json);
T t = new T();
var result = jObj[t.TypeName()];
jObj.Remove(t.TypeName());
jObj["Result"] = result;
return jObj.ToObject<APIResultModel<T>>();
}
}
Second create APIModel abstract Class:
public abstract class APIModel
{
public abstract string TypeName();
}
Third create dynamic content Model class:
public class MyContentModel: APIModel
{
public string Property {get; set;}
public override string TypeName()
{
return "JsonKey";
}
}
When you need to deserialize a json string:
var jsonModel = new APIResultModel<MyContentModel>();
jsonModel = jsonModel.Deserialize(json);
MyContentModel dynimacModel = jsonModel.Result;
The Deserialize function is come from @Eser
You could create a custom JsonConverter to handle the dynamic property name:
public class MyRequestConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(MyRequest);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JObject jo = JObject.Load(reader);
string type = (string)jo["type"];
MyRequest req = new MyRequest
{
Type = type,
Source = (string)jo[type ?? ""]
};
return req;
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
MyRequest req = (MyRequest)value;
JObject jo = new JObject(
new JProperty("type", req.Type),
new JProperty(req.Type, req.Source));
jo.WriteTo(writer);
}
}
To use the converter, add a [JsonConverter]
attribute to your class like this:
[JsonConverter(typeof(MyRequestConverter))]
public class MyRequest
{
public string Type { get; set; }
public string Source { get; set; }
}
Here is a working round-trip demo: https://dotnetfiddle.net/o7NDTV
I would write custom serialization/deserialization methods
var req1 = new MyRequest() { Type = "card", Source = "SomeValue" };
var json = Serialize(req1);
var req2 = Deserialize<MyRequest>(json);
string Serialize<T>(T obj)
{
var jObj = JObject.FromObject(obj);
var src = jObj["Source"];
jObj.Remove("Source");
jObj[(string)jObj["Type"]] = src;
return jObj.ToString(Newtonsoft.Json.Formatting.Indented);
}
T Deserialize<T>(string json)
{
var jObj = JObject.Parse(json);
var src = jObj[(string)jObj["Type"]];
jObj.Remove((string)jObj["Type"]);
jObj["Source"] = src;
return jObj.ToObject<T>();
}