[英]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:或者,如果您希望您的
propertyNames
为Dictionary<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.