我有一个类似于这个的课程:
public class Values
{
public int BestValue { get; set; }
public List<string> AllValues { get; set; }
}
这个类可以(因为历史记录)存储为</ p>
"MyFirstValue" /* if only one value */
或
{ "BestValue" : 0, "AllValues" : ["DefaultValue", "OtherValue"] }
如何使用JsonConverter
自动反序列化? (或任何其他解决方案。)
答案 0 :(得分:2)
您需要为此目的创建custom JsonConverter
:
internal class ValuesConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(Values).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var tokenType = reader.SkipComments().TokenType;
if (tokenType == JsonToken.Null)
return null;
var value = existingValue as Values ?? (Values)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator();
if (tokenType == JsonToken.Date)
{
// Avoid annoying bug that converts date strings to local format described in
// https://stackoverflow.com/questions/35166060/json-net-get-specific-json-date-value
value.AllValues = new List<string> { JToken.Load(reader).ToString(Formatting.None).Trim('"') };
}
else if (tokenType.IsPrimitive())
{
value.AllValues = new List<string> { (string)JToken.Load(reader) };
}
else
{
serializer.Populate(reader, value);
}
return value;
}
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 bool IsPrimitive(this JsonToken tokenType)
{
switch (tokenType)
{
case JsonToken.Integer:
case JsonToken.Float:
case JsonToken.String:
case JsonToken.Boolean:
case JsonToken.Undefined:
case JsonToken.Null:
case JsonToken.Date:
case JsonToken.Bytes:
return true;
default:
return false;
}
}
}
然后将其应用于您的类型,如下所示:
[JsonConverter(typeof(ValuesConverter))]
public class Values
{
public int BestValue { get; set; }
public List<string> AllValues { get; set; }
}
或者,将其添加到JsonSerializerSettings.Converters
,然后修改您的设置,如 JsonSerializerSettings and Asp.Net Core 所示。
备注 -
通过将CanWrite
设置为false,可以在写入JSON时使用默认序列化。
当JSON值不是字符串时,JsonSerializer.Populate()
用于通过默认反序列化填充Values
的内容。
通过使用ContractResolver.ResolveContract(objectType).DefaultCreator()
构造Values
对象,可以支持对Values
(如果有)的子类进行反序列化。
工作样本.Net小提琴here。