C# 如何将非类型值的多态字典的值反序列化到传统的.Net数组中?
我有一个具有属性的类C# 如何将非类型值的多态字典的值反序列化到传统的.Net数组中?,c#,json,json.net,C#,Json,Json.net,我有一个具有属性的类 public Dictionary<string, object> Attributes { get; set; } 公共字典属性{get;set;} 属性值只能是字符串、数字、字符串数组和数字数组 我现在有一个JSON字符串(没有类型信息),并希望将其反序列化为该类的对象。问题是作为数组的属性值被反序列化为JArray对象,而不是string[]或long[] 如何执行反序列化以使属性“Attribute”的结果字典值都是string、long、strin
public Dictionary<string, object> Attributes { get; set; }
公共字典属性{get;set;}
属性值只能是字符串、数字、字符串数组和数字数组
我现在有一个JSON字符串(没有类型信息),并希望将其反序列化为该类的对象。问题是作为数组的属性值被反序列化为JArray
对象,而不是string[]
或long[]
如何执行反序列化以使属性“Attribute”的结果字典值都是
string
、long
、string[]
或long[]
(或者包含字符串和long的对象[]
)?一种解决方案是创建一个for字典,该字典将逻辑从调整到,以返回所需的特定类型的数组,而不仅仅是列表
集合
首先,定义以下转换器和扩展方法:
public class ObjectDictionaryConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(Dictionary<string, object>);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var tokenType = reader.SkipComments().TokenType;
if (tokenType == JsonToken.Null)
return null;
var tempDictionary = new Dictionary<string, object>();
var old = reader.DateParseHandling;
try
{
// Disable recognition of date strings
reader.DateParseHandling = DateParseHandling.None;
serializer.Populate(reader, tempDictionary);
}
finally
{
reader.DateParseHandling = old;
}
var dictionary = existingValue as IDictionary<string, object> ?? (IDictionary<string, object>)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
foreach (var pair in tempDictionary)
dictionary.Add(pair.Key, pair.Value.ToObject());
return dictionary;
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
public static partial class JsonExtensions
{
public static JsonReader SkipComments(this JsonReader reader)
{
while (reader.TokenType == JsonToken.Comment && reader.Read())
;
return reader;
}
public static object ToObject(this object obj)
{
return ToObject(obj as JToken) ?? obj;
}
public static object ToObject(this JToken token)
{
// Adapts the logic from https://stackoverflow.com/a/19140420/3744182)
// to https://stackoverflow.com/q/5546142/3744182
// By [Brian Rogers](https://stackoverflow.com/users/10263/brian-rogers)
if (token == null)
return null;
switch (token.Type)
{
case JTokenType.Null:
return null;
case JTokenType.Object:
return token.Children<JProperty>()
.ToDictionary(prop => prop.Name,
prop => ToObject(prop.Value));
case JTokenType.Array:
{
var list = token.Select(t => ToObject(t)).ToList();
if (list.All(i => i is long))
return list.Cast<long>().ToArray();
else if (list.All(i => i is string))
return list.Cast<string>().ToArray();
else return list.ToArray();
}
default:
return ((JValue)token).Value;
}
}
}
注:
- 因为您知道字典值应该是字符串而不是
DateTime
值,所以我禁用了Json.NET的自动日期识别。有关日期识别的详细信息,请参阅
演示小提琴。相关:。也相关:。
var settings = new JsonSerializerSettings
{
Converters = { new ObjectDictionaryConverter() },
};
var deserializedObj = JsonConvert.DeserializeObject<AttributeObject>(jsonString, settings);