C# 反序列化JSON时如何将ObjectCreationHandling.Replace应用于选定属性?
我有一个类,它包含一个C# 反序列化JSON时如何将ObjectCreationHandling.Replace应用于选定属性?,c#,json,serialization,json.net,C#,Json,Serialization,Json.net,我有一个类,它包含一个List属性,其默认构造函数分配列表并用一些默认值填充列表,例如: public class Configuration { public List<Tuple<int, int, int>> MyThreeTuple { get; set; } public Configuration() { MyThreeTuple = new List<Tuple<int, int, int>>
List
属性,其默认构造函数分配列表并用一些默认值填充列表,例如:
public class Configuration
{
public List<Tuple<int, int, int>> MyThreeTuple { get; set; }
public Configuration()
{
MyThreeTuple = new List<Tuple<int, int, int>>();
MyThreeTuple.Add(new Tuple<int, int, int>(-100, 20, 501));
MyThreeTuple.Add(new Tuple<int, int, int>(100, 20, 864));
MyThreeTuple.Add(new Tuple<int, int, int>(500, 20, 1286));
}
}
如何应用
对象创建处理。有选择地替换对象图中的某些属性,而不是其他属性?您有几种方法可以强制替换列表,而不是重复使用列表:
您可以向列表属性中添加,以指示应替换而不是重复使用该属性:
public class Configuration
{
[JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<Tuple<int, int, int>> MyThreeTuple { get; set; }
}
然后将其与以下内容一起使用:
如果希望替换而不是重复使用所有列表属性,可以进行自定义,以执行以下操作:
public class ListReplacementContractResolver : DefaultContractResolver
{
// As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons.
// http://www.newtonsoft.com/json/help/html/ContractResolver.htm
// http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm
// "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance."
static readonly ListReplacementContractResolver instance;
// Using a static constructor enables fairly lazy initialization. http://csharpindepth.com/Articles/General/Singleton.aspx
static ListReplacementContractResolver() { instance = new ListReplacementContractResolver(); }
public static ListReplacementContractResolver Instance { get { return instance; } }
protected ListReplacementContractResolver() : base() { }
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var jsonProperty = base.CreateProperty(member, memberSerialization);
if (jsonProperty.ObjectCreationHandling == null && jsonProperty.PropertyType.GetListType() != null)
jsonProperty.ObjectCreationHandling = ObjectCreationHandling.Replace;
return jsonProperty;
}
}
public static class TypeExtensions
{
public static Type GetListType(this Type type)
{
while (type != null)
{
if (type.IsGenericType)
{
var genType = type.GetGenericTypeDefinition();
if (genType == typeof(List<>))
return type.GetGenericArguments()[0];
}
type = type.BaseType;
}
return null;
}
}
如果集合是get only(本例中不是),请参阅
您有几种替代方法可以强制替换列表,而不是重复使用:
您可以向列表属性中添加,以指示应替换而不是重复使用该属性:
public class Configuration
{
[JsonProperty(ObjectCreationHandling = ObjectCreationHandling.Replace)]
public List<Tuple<int, int, int>> MyThreeTuple { get; set; }
}
然后将其与以下内容一起使用:
如果希望替换而不是重复使用所有列表属性,可以进行自定义,以执行以下操作:
public class ListReplacementContractResolver : DefaultContractResolver
{
// As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons.
// http://www.newtonsoft.com/json/help/html/ContractResolver.htm
// http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm
// "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance."
static readonly ListReplacementContractResolver instance;
// Using a static constructor enables fairly lazy initialization. http://csharpindepth.com/Articles/General/Singleton.aspx
static ListReplacementContractResolver() { instance = new ListReplacementContractResolver(); }
public static ListReplacementContractResolver Instance { get { return instance; } }
protected ListReplacementContractResolver() : base() { }
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var jsonProperty = base.CreateProperty(member, memberSerialization);
if (jsonProperty.ObjectCreationHandling == null && jsonProperty.PropertyType.GetListType() != null)
jsonProperty.ObjectCreationHandling = ObjectCreationHandling.Replace;
return jsonProperty;
}
}
public static class TypeExtensions
{
public static Type GetListType(this Type type)
{
while (type != null)
{
if (type.IsGenericType)
{
var genType = type.GetGenericTypeDefinition();
if (genType == typeof(List<>))
return type.GetGenericArguments()[0];
}
type = type.BaseType;
}
return null;
}
}
如果集合是get only(本例中不是),请参阅
请发表你的问题,这将极大地帮助我们帮助你。dbc,这是我所见过的最漂亮的编辑。请发表你的问题,这将极大地帮助我们帮助你。dbc,这是我所见过的最漂亮的编辑。太棒了!谢谢@dbc,这正是我需要的。我的问题是System.Net.Mail.MailAddress,因此添加属性从来都不是一个选项。我选择了解决方案4,一个定制的合同解析程序。再次感谢!明亮的谢谢@dbc,这正是我需要的。我的问题是System.Net.Mail.MailAddress,因此添加属性从来都不是一个选项。我选择了解决方案4,一个定制的合同解析程序。再次感谢!
public class ConfigurationConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return typeof(Configuration).IsAssignableFrom(objectType);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
var config = (existingValue as Configuration ?? (Configuration)serializer.ContractResolver.ResolveContract(objectType).DefaultCreator());
if (config.MyThreeTuple != null)
config.MyThreeTuple.Clear();
serializer.Populate(reader, config);
return config;
}
public override bool CanWrite { get { return false; } }
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
var settings = new JsonSerializerSettings { Converters = new JsonConverter[] { new ConfigurationConverter() } };
public class ListReplacementContractResolver : DefaultContractResolver
{
// As of 7.0.1, Json.NET suggests using a static instance for "stateless" contract resolvers, for performance reasons.
// http://www.newtonsoft.com/json/help/html/ContractResolver.htm
// http://www.newtonsoft.com/json/help/html/M_Newtonsoft_Json_Serialization_DefaultContractResolver__ctor_1.htm
// "Use the parameterless constructor and cache instances of the contract resolver within your application for optimal performance."
static readonly ListReplacementContractResolver instance;
// Using a static constructor enables fairly lazy initialization. http://csharpindepth.com/Articles/General/Singleton.aspx
static ListReplacementContractResolver() { instance = new ListReplacementContractResolver(); }
public static ListReplacementContractResolver Instance { get { return instance; } }
protected ListReplacementContractResolver() : base() { }
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var jsonProperty = base.CreateProperty(member, memberSerialization);
if (jsonProperty.ObjectCreationHandling == null && jsonProperty.PropertyType.GetListType() != null)
jsonProperty.ObjectCreationHandling = ObjectCreationHandling.Replace;
return jsonProperty;
}
}
public static class TypeExtensions
{
public static Type GetListType(this Type type)
{
while (type != null)
{
if (type.IsGenericType)
{
var genType = type.GetGenericTypeDefinition();
if (genType == typeof(List<>))
return type.GetGenericArguments()[0];
}
type = type.BaseType;
}
return null;
}
}
var settings = new JsonSerializerSettings { ContractResolver = ListReplacementContractResolver.Instance };