C# 反序列化可以具有不同类型的属性名称

C# 反序列化可以具有不同类型的属性名称,c#,json,.net-core,json.net,C#,Json,.net Core,Json.net,我从提供商处接收数据,数据可能如下所示: { "data": [ { "propertyNames":[ { "a":"a1", "b":"b1", ... "z":"z1" }, {

我从提供商处接收数据,数据可能如下所示:

{
    "data": [
        {
            "propertyNames":[
                {
                    "a":"a1",
                    "b":"b1",
                    ...
                    "z":"z1"
                },
                {
                    "a":"a2",
                    "b":"b2",
                    ...
                    "z":"z2"
                },
            ],
            ...
            "otherProperty": "abc"
        },
        {
            "propertyNames":{
                "1": {
                    "a":"a1",
                    "b":"b1",
                    ...
                    "z":"z1"
                },
                "2": {
                    "a":"a2",
                    "b":"b2",
                    ...
                    "z":"z2"
                },
            },
            ...
            "otherProperty": "bce"
        }
    ]
}
因此,实际上,propertyNames可以是以下类型:

[JsonProperty("propertyNames")]
Dictionary<string, MyObject> PropertyNames {get;set;}

[JsonProperty("propertyNames")]
List<MyObject> PropertyNames {get;set;}

我如何反序列化它?

有多种选择,您可以选择如何实现这一点

例如,您可以将其用作类型

[JsonProperty("propertyNames")]
JObject PropertyNames {get;set;}
不幸的是,您必须写下复杂的逻辑来解析其中的信息

您还可以创建自定义


你可以有多种选择来解决这个问题

例如,您可以将其用作类型

[JsonProperty("propertyNames")]
JObject PropertyNames {get;set;}
不幸的是,您必须写下复杂的逻辑来解析其中的信息

您还可以创建自定义


假设propertyNames对象中的属性名称都是整数,可以使用ListToDictionaryConverter from to按如下方式定义数据模型:

数据模型:

public class MyObject
{
    public string a { get; set; }
    public string b { get; set; }
    public string z { get; set; }
}

public class Datum
{
    [JsonConverter(typeof(ListToDictionaryConverter<MyObject>))]
    public List<MyObject> propertyNames { get; set; }
    public string otherProperty { get; set; }
}

public class RootObject
{
    public List<Datum> data { get; set; }
}
在索引1和2处有值,在索引0处为null的列表中

演示小提琴1

或者,如果希望propertyNames的类型为Dictionary,则可以按如下方式修改模型和转换器:

public class Datum
{
    [JsonConverter(typeof(IntegerDictionaryToListConverter<MyObject>))]
    public Dictionary<int, MyObject> propertyNames { get; set; }
    public string otherProperty { get; set; }
}

public class IntegerDictionaryToListConverter<T> : JsonConverter where T : class
{
    // From this answer https://stackoverflow.com/a/41559688/3744182
    // To https://stackoverflow.com/questions/41553379/display-json-object-array-in-datagridview
    public override bool CanConvert(Type objectType)
    {
        return typeof(Dictionary<int, T>).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var dictionary = existingValue as IDictionary<int, T> ?? (IDictionary<int, T>)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
        if (reader.TokenType == JsonToken.StartObject)
            serializer.Populate(reader, dictionary);
        else if (reader.TokenType == JsonToken.StartArray)
        {
            var list = serializer.Deserialize<List<T>>(reader);
            for (int i = 0; i < list.Count; i++)
                dictionary.Add(i, list[i]);
        }
        else
        {
            throw new JsonSerializationException(string.Format("Invalid token {0}", reader.TokenType));
        }
        return dictionary;
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}
演示小提琴2


如果属性名称不总是整数,则可以稍微修改转换器以反序列化为字典。

假设propertyNames对象中的属性名称都是整数,则可以使用ListToDictionaryConverter from-to按如下方式定义数据模型:

数据模型:

public class MyObject
{
    public string a { get; set; }
    public string b { get; set; }
    public string z { get; set; }
}

public class Datum
{
    [JsonConverter(typeof(ListToDictionaryConverter<MyObject>))]
    public List<MyObject> propertyNames { get; set; }
    public string otherProperty { get; set; }
}

public class RootObject
{
    public List<Datum> data { get; set; }
}
在索引1和2处有值,在索引0处为null的列表中

演示小提琴1

或者,如果希望propertyNames的类型为Dictionary,则可以按如下方式修改模型和转换器:

public class Datum
{
    [JsonConverter(typeof(IntegerDictionaryToListConverter<MyObject>))]
    public Dictionary<int, MyObject> propertyNames { get; set; }
    public string otherProperty { get; set; }
}

public class IntegerDictionaryToListConverter<T> : JsonConverter where T : class
{
    // From this answer https://stackoverflow.com/a/41559688/3744182
    // To https://stackoverflow.com/questions/41553379/display-json-object-array-in-datagridview
    public override bool CanConvert(Type objectType)
    {
        return typeof(Dictionary<int, T>).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        if (reader.TokenType == JsonToken.Null)
            return null;
        var dictionary = existingValue as IDictionary<int, T> ?? (IDictionary<int, T>)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
        if (reader.TokenType == JsonToken.StartObject)
            serializer.Populate(reader, dictionary);
        else if (reader.TokenType == JsonToken.StartArray)
        {
            var list = serializer.Deserialize<List<T>>(reader);
            for (int i = 0; i < list.Count; i++)
                dictionary.Add(i, list[i]);
        }
        else
        {
            throw new JsonSerializationException(string.Format("Invalid token {0}", reader.TokenType));
        }
        return dictionary;
    }

    public override bool CanWrite { get { return false; } }

    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }
}
演示小提琴2


如果属性名不总是整数,您可以稍微修改转换器,将其反序列化为字典。

您可以添加反序列化的结果类型和一些用例吗?构建JSON更好吗?@franzgleichman它来自一个提供程序,因此不相关:。事实上,如果我们假设属性名都是整数,我认为来自的转换器ListToDictionaryConverter可能适合您,因为它的ReadJson检查传入的JSON是数组还是对象。您的JSON格式不正确。第二个propertyNames值需要用{and}而不是[and]分隔。但如果我解决了这个问题,那么[JsonConvertertypeofListToDictionaryConverter]可以工作,请参阅。标记为重复?你能添加反序列化的结果类型和一些用例吗?构建JSON更好吗?@franzgleichman它来自一个提供商,所以不相关:。事实上,如果我们假设属性名都是整数,我认为来自的转换器ListToDictionaryConverter可能适合您,因为它的ReadJson检查传入的JSON是数组还是对象。您的JSON格式不正确。第二个propertyNames值需要用{and}而不是[and]分隔。但如果我解决了这个问题,那么[JsonConvertertypeofListToDictionaryConverter]可以工作,请参阅。标记为重复?这是一个很好且更通用的答案。碰巧dbc的答案已经可以使用了,这是一个很好的更通用的答案。dbc的答案正好可以使用。