[英]Json.NET - Default deserialization behavior for a single property in CustomCreationConverter
在下面的场景中,当遇到我反序列化的类型中存在的JSON属性时,如何让CrazyItemConverter
像往常一样继续?
我有一些看起来像这样的JSON:
{
"Item":{
"Name":"Apple",
"Id":null,
"Size":5,
"Quality":2
}
}
JSON被反序列化为一个看起来像这样的类:
[JsonConverter(typeof(CrazyItemConverter))]
public class Item
{
[JsonConverter(typeof(CrazyStringConverter))]
public string Name { get; set; }
public Guid? Id { get; set; }
[JsonIgnore]
public Dictionary<string, object> CustomFields
{
get
{
if (_customFields == null)
_customFields = new Dictionary<string, object>();
return _customFields;
}
}
...
}
CrazyItemConverter
填充已知属性的值,并将未知属性放在CustomFields中。 其中的ReadJson
看起来像这样:
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var outputObject = Create(objectType);
var objProps = objectType.GetProperties().Select(p => p.Name).ToArray();
while (reader.Read())
{
if (reader.TokenType == JsonToken.PropertyName)
{
string propertyName = reader.Value.ToString();
if (reader.Read())
{
if (objProps.Contains(propertyName))
{
// No idea :(
// serializer.Populate(reader, outputObject);
}
else
{
outputObject.AddProperty(propertyName, reader.Value);
}
}
}
}
return outputObject;
}
在反序列化期间,当CrazyItemConverter
遇到已知属性时,我希望它像通常那样运行。 意思是,尊重[JsonConverter(typeof(CrazyStringConverter))]
的Name
。
我用下面的代码来设置已知的特性,但它引发的nullables例外,不尊重我的其他JsonConverters。
PropertyInfo pi = outputObject.GetType().GetProperty(readerValue, BindingFlags.IgnoreCase | BindingFlags.Public | BindingFlags.Instance);
var convertedValue = Convert.ChangeType(reader.Value, pi.PropertyType);
pi.SetValue(outputObject, convertedValue, null);
有任何想法吗?
更新:我已经学会了serializer.Populate(reader, outputObject);
是如何反序列化整个事情,但如果你想要逐个属性的默认功能似乎不起作用。
如果我正确理解,您的CrazyItemConverter
存在,以便您可以将JSON中的已知属性反序列化为强类型属性,同时仍然保留可能在JSON中的“额外”字段到字典中。
事实证明,Json.Net已经内置了此功能(自5.0版本5开始),因此您不需要疯狂的转换器。 相反,您只需要使用[JsonExtensionData]
属性标记字典。 (有关更多信息,请参阅作者的博客 。)
所以你的Item类看起来像这样:
public class Item
{
[JsonConverter(typeof(CrazyStringConverter))]
public string Name { get; set; }
public Guid? Id { get; set; }
[JsonExtensionData]
public Dictionary<string, object> CustomFields
{
get
{
if (_customFields == null)
_customFields = new Dictionary<string, object>();
return _customFields;
}
private set
{
_customFields = value;
}
}
private Dictionary<string, object> _customFields;
}
然后你可以正常反序列化它。 演示:
class Program
{
static void Main(string[] args)
{
string json = @"
{
""Item"":
{
""Name"":""Apple"",
""Id"":""4b7e9f9f-7a30-4f79-8e47-8b50ea26ddac"",
""Size"":5,
""Quality"":2
}
}";
Item item = JsonConvert.DeserializeObject<Wrapper>(json).Item;
Console.WriteLine("Name: " + item.Name);
Console.WriteLine("Id: " + item.Id);
foreach (KeyValuePair<string, object> kvp in item.CustomFields)
{
Console.WriteLine(kvp.Key + ": " + kvp.Value);
}
}
}
public class Wrapper
{
public Item Item { get; set; }
}
class CrazyStringConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return objectType == typeof(string);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
JToken token = JToken.Load(reader);
// Reverse the string just for fun
return new string(token.ToString().Reverse().ToArray());
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
输出:
Name: elppA
Id: 4b7e9f9f-7a30-4f79-8e47-8b50ea26ddac
Size: 5
Quality: 2
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.