Serialize/Deserialize dynamic property name using JSON.NET

后端 未结 3 791
春和景丽
春和景丽 2020-12-20 00:15

I have the following class:

public class MyRequest
{
    public string Type {get;set;}
    public string Source {get;set;}
}

I would like t

相关标签:
3条回答
  • 2020-12-20 00:45

    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

    0 讨论(0)
  • 2020-12-20 01:01

    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

    0 讨论(0)
  • 2020-12-20 01:09

    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>();
    } 
    
    0 讨论(0)
提交回复
热议问题