通过带有变量属性名称的JSON.NET进行反序列化

时间:2017-08-23 00:24:58

标签: c# json json.net json-deserialization

给出一些看起来像

的json
{
  "id":"123_678",
  "fs_123_678":
   {
     "title":"Apple Parts",
     "data": 134
   }
}

我想将其反序列化为以下类

public class Result
{
   public string Id {get; set;}
   public ResultInfo Info {get; set;}
}

public class ResultInfo
{
   public string Title {get; set;}
   public int Data {get; set;}
}

...但第二个属性(fs_123_678)不是固定名称。我在这里查看了SO上的其他类似帖子,常见的解决方案是使用IDictionary<string, MyPoco>,但只有当变量数据在根级别而不是时才有效。 该属性的名称是100%可预测的,我可以在代码中根据源HTTP请求中使用的值来描述给定JSON响应的内容。诀窍是,如何让JSON deseralizer在业务规则中围绕这个给定的反序列化调用它?我基本上需要一些像[JsonProperty(PropertyName = *insert logic here*)]那样的东西(当然这是不可能的)。

什么是合理的方法来解决这个问题,同时保留对象其余部分的“免费”强类型反序列化?

1 个答案:

答案 0 :(得分:1)

根据dbc在评论中提供的链接,我发现此解决方案似乎有效,但对其他建议持开放态度。我基本上采用了当前的读者流,将其加载为JObject,然后将原始JProperty替换为具有我的模型期望名称的另一个。{/ p>

public class MyCustomResultConverter : JsonConverter
{
    public override bool CanWrite => false;
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var obj = JObject.Load(reader);
        var formData = obj.SelectToken("fs_" + obj.SelectToken("id").Value<string>());
        formData.Parent.Replace(new JProperty("info", formData));

        existingValue = existingValue ?? new FormActionResult();
        serializer.Populate(obj.CreateReader(), existingValue);
        return existingValue;
    }

    public override bool CanConvert(Type objectType)
    {
        return typeof(Result).GetTypeInfo().IsAssignableFrom(objectType);
    }
}

[JsonConverter(typeof(MyCustomResultConverter))]
public class Result
{
   public string Id {get; set;}
   public ResultInfo Info {get; set;}
}