简体   繁体   English

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

[英]Deserialize a property name that can have different types

I receive data from a provider and it can look like:我从提供者那里收到数据,它看起来像:

{
    "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"
        }
    ]
}

So effectively, propertyNames can be the following types:如此有效, propertyNames可以是以下类型:

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

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

How can I deserialize this?我怎样才能反序列化这个?

There are multiple choices really how you can approach this.确实有多种选择可以解决这个问题。

For example you can use JObject as a type例如,您可以使用JObject作为类型

[JsonProperty("propertyNames")]
JObject PropertyNames {get;set;}

Unfortunately you would have to write down complex logic to parse information out of that.不幸的是,您必须写下复杂的逻辑才能从中解析出信息。

You can also create custom JsonConverter您还可以创建自定义JsonConverter

public class DynamicTypeConverter: JsonConverter<DynamicType>
{
    public override void WriteJson(JsonWriter writer, Version value, JsonSerializer serializer)
    {
    }

    public override DynamicType ReadJson(JsonReader reader, Type objectType, Version existingValue, bool hasExistingValue, JsonSerializer serializer)
    {
        var obj = new DynamicType();
        // Least fun part, compute & assign values to properties
        // Logic depends if you are going to use JObject.Load(reader) or reader.Read() with reader.Value and TokenType
        return obj;
    }
}

public class DynamicType
{
  Dictionary<string, MyObject> PropertyNamesDict {get;set;}
  List<MyObject> PropertyNamesList {get;set;}
}

Assuming that the property names inside the "propertyNames" object are all integers, you can define your data model as follows, using ListToDictionaryConverter<T> from this answer to Display JSON object array in datagridview : Assuming that the property names inside the "propertyNames" object are all integers, you can define your data model as follows, using ListToDictionaryConverter<T> from this answer to Display JSON object array in datagridview :

The data model:数据 model:

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; }
}

The converter is copied as-is with no modification.转换器按原样复制,不做任何修改。 It transforms the JSON object它转换 JSON object

{
   "1":{
      "a":"a1",
      "b":"b1",
      "z":"z1"
   },
   "2":{
      "a":"a2",
      "b":"b2",
      "z":"z2"
   }
}

into a List<MyObject> with values at indices 1 and 2, and null at index zero.进入一个List<MyObject> ,其值位于索引 1 和 2 处, null位于索引 0 处。

Demo fiddle #1 here .演示小提琴#1在这里

Alternatively , if you would prefer your propertyNames to be of type Dictionary<int, MyObject> , you can modify the model and converter as follows:或者,如果您希望您的propertyNamesDictionary<int, MyObject>类型,您可以修改 model 和转换器,如下所示:

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();
    }
}

Demo fiddle #2 here .演示小提琴#2在这里

If the property names aren't always integers you can modify the converter slightly to deserialize to a Dictionary<string, T> .如果属性名称不总是整数,您可以稍微修改转换器以反序列化为Dictionary<string, T>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用2个不同类型的相同xml元素和属性名称反序列化xml? - How can I deserialize xml with 2 different types of the same xml element and property name? 反序列化具有不同名称的属性? - Deserialize property with a different name? 如何使用 Json.NET 反序列化可以是两种不同数据类型的 JSON 属性 - How to deserialize a JSON property that can be two different data types using Json.NET 在C#中将不同的元素类型反序列化为一个对象属性? - Deserialize different element types into one object Property in C#? XAML:如何将元素绑定到Property的名称是动态的,可以在不同位置使用不同的名称 - XAML: How to bind element to Property the name of is dynamic, can have different name in different places 如何在.Net中反序列化包含不同类型的JSON数组? - How can you deserialize a JSON array containing different types in .Net? 当一个属性可以具有不同的类型时,如何序列化DataContract的Member? - How to serialize a DataContract's Members when one property can have different types? 使用具有相同属性但具有不同类型的属性查询 CosmosDB 集合 - Querying CosmosDB Collection with property that have the same property but with different types 使用不同类型反序列化JSON数组 - Deserialize JSON array with different types 使用不同的propertyValue类型反序列化json - deserialize json with different propertyValue types
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM