问题描述
我有一个与此班相似的班:
I have a class similar to this one:
public class Values
{
public int BestValue { get; set; }
public List<string> AllValues { get; set; }
}
该类可能(由于历史原因)存储为
This class could be (because of history) be stored either as
"MyFirstValue" /* if only one value */
或
{ "BestValue" : 0, "AllValues" : ["DefaultValue", "OtherValue"] }
如何使用JsonConverter
自动反序列化? (或任何其他解决方案.)
How can I deserialize this automatically using a JsonConverter
? (Or any other solution.)
推荐答案
您将需要创建为此定制JsonConverter
:
You will need to create a custom JsonConverter
for this purpose:
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;
}
}
}
然后按如下所示将其应用于您的类型:
Then apply it to your type as follows:
[JsonConverter(typeof(ValuesConverter))]
public class Values
{
public int BestValue { get; set; }
public List<string> AllValues { get; set; }
}
或者将其添加到 JsonSerializerSettings.Converters
,然后修改您的设置,如 JsonSerializerSettings和Asp.Net Core 所示.
Or, add it to JsonSerializerSettings.Converters
then modify your settings as shown in JsonSerializerSettings and Asp.Net Core.
注释-
-
通过将
CanWrite
设置为假写入JSON时可以使用默认序列化.
By setting
CanWrite
to false one can use default serialization when writing to JSON.
当JSON值不是字符串时, JsonSerializer.Populate()
用于通过默认反序列化来填充Values
的内容.
When the JSON value is not a string, JsonSerializer.Populate()
is used to fill in the contents of Values
via default deserialization.
通过使用 ContractResolver.ResolveContract(objectType).DefaultCreator()
来构建Values
对象,可以支持对Values
的子类(如果有)进行反序列化.
By using ContractResolver.ResolveContract(objectType).DefaultCreator()
to construct the Values
object, deserialization of subclasses of Values
(if any) can be supported.
工作示例.Net小提琴此处.
Working sample .Net fiddle here.
这篇关于用Json.Net反序列化以两种不同方式序列化的值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!