使用通用RootObject在根位置处理具有不同属性名称的JSON

时间:2015-02-16 11:39:22

标签: c# json.net

我正在使用Json.Net,我正在寻找有关如何在运行时反序列化期间更改JsonProperty名称的想法。为什么你会问,主要是因为我不喜欢有大量的" RootObject"浮动的类具有完全相同的结构。

考虑以下"根对象"。

 public class Rootobject1
 {
     [JsonProperty("tasks")]
     public List<Task> Data { get; set; }
 }

 public class Rootobject2
 {
     [JsonProperty("projects")]
     public List<Project> Data { get; set; }
 }

 public class Rootobject3
 {
     [JsonProperty("countries")]
     public List<Country> Data { get; set; }
 }

看起来像是一大堆冗余代码。所以我在寻找选择。一些想到的是:

对某些简单条件逻辑使用属性参数的东西:

 public class Rootobject<T>
 {
     [JsonProperty("projects", whenType=typeof(Project))]
     [JsonProperty("tasks", whenType=typeof(Task))]
     [JsonProperty("countries", whenType=typeof(Country))]
     public List<T> Data { get; set; }
 }

或者可能是运行时配置的内容?

 var projects = JsonConvert.DeserializeObject<Rootobject<Project>>(json, RootName="projects")

 var tasks = JsonConvert.DeserializeObject<Rootobject<Tasks>>(json, RootName="tasks")

所以我很好奇,有没有人想出一个创造性和优雅的方式处理这个?

1 个答案:

答案 0 :(得分:2)

您可以使用自定义合约解析程序执行此操作。解析器可以有效地更改序列化程序在运行时查找的JSON属性名称。以下是您需要的代码:

class CustomResolver : DefaultContractResolver
{
    string rootName;

    public CustomResolver(string rootName)
    {
        this.rootName = rootName;
    }

    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        IList<JsonProperty> props = base.CreateProperties(type, memberSerialization);

        if (type.IsGenericType && type.GetGenericTypeDefinition() == typeof(RootObject<>))
        {
            JsonProperty prop = props.First(p => p.UnderlyingName == "Data");
            prop.PropertyName = this.rootName;
        }

        return props;
    }
}

下一部分是创建一个帮助方法,以便在反序列化时应用解析器:

public static RootObject<T> Deserialize<T>(string json, string rootName)
{
    JsonSerializerSettings settings = new JsonSerializerSettings();
    settings.ContractResolver = new CustomResolver(rootName);
    return JsonConvert.DeserializeObject<RootObject<T>>(json, settings);
}

然后,您可以在问题中根据需要调用帮助程序:

RootObject<Project> projects = Deserialize<Project>(projectJson, "projects");

此处完整演示:https://dotnetfiddle.net/yEBLkx