你的基本问题是你的CustomContractResolver
仅改变PropertyName https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_JsonProperty_PropertyName.htm and PropertyType https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_JsonProperty_PropertyType.htm归来的JsonProperty https://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_Serialization_JsonProperty.htm,然而底层的PropertyInfo https://learn.microsoft.com/en-us/dotnet/api/system.reflection.propertyinfo?view=netframework-4.8它的创造来源仍然是公共替代财产,而不是私人内部“真实”财产。就这样ValueProvider https://www.newtonsoft.com/json/help/html/P_Newtonsoft_Json_Serialization_JsonProperty_ValueProvider.htm,除其他外,仍然是错误的。
你需要做的是生成一个JsonProperty
对于内部属性,更正其名称和可访问性,然后返回代替 the JsonProperty
为了公共财产。这将确保序列化程序将序列化和反序列化内部属性而不是其公共代理。
以下合同解析器完成这项工作:
public class CustomContractResolver : DefaultContractResolver
{
const string InternalSuffix = "Internal";
protected override JsonProperty CreateProperty(MemberInfo member, MemberSerialization memberSerialization)
{
var property = member as PropertyInfo;
var jProperty = base.CreateProperty(member, memberSerialization);
if (property != null && jProperty != null && memberSerialization != MemberSerialization.Fields && !jProperty.HasMemberAttribute)
{
var replacementName = jProperty.UnderlyingName + InternalSuffix;
// Check for replacement property.
var replacementProperty = jProperty.DeclaringType.GetProperty(replacementName, BindingFlags.Instance | BindingFlags.NonPublic);
if (replacementProperty != null
&& replacementProperty.GetGetMethod(true) != null && replacementProperty.GetSetMethod(true) != null
&& ReplacementTypeCompatible(property, replacementProperty.PropertyType)
)
{
var replacementJProperty = base.CreateProperty(replacementProperty, memberSerialization);
replacementJProperty.PropertyName = jProperty.PropertyName;
if (!replacementJProperty.Readable && replacementProperty.GetGetMethod(true) != null)
replacementJProperty.Readable = true;
if (!replacementJProperty.Writable && replacementProperty.GetSetMethod(true) != null)
replacementJProperty.Writable = true;
return replacementJProperty;
}
// Check for replacement field.
var replacementField = jProperty.DeclaringType.GetField(replacementName, BindingFlags.Instance | BindingFlags.NonPublic);
if (replacementField != null
&& ReplacementTypeCompatible(property, replacementField.FieldType)
)
{
var replacementJProperty = base.CreateProperty(replacementField, memberSerialization);
replacementJProperty.PropertyName = jProperty.PropertyName;
replacementJProperty.Readable = true;
replacementJProperty.Writable = true;
return replacementJProperty;
}
}
return jProperty;
}
static bool ReplacementTypeCompatible(PropertyInfo property, Type replacementType)
{
// Add here whatever restrictions you need
if (property.PropertyType.IsGenericType && typeof(IReadOnlyList<>).IsAssignableFrom(property.PropertyType.GetGenericTypeDefinition())
&& replacementType.IsGenericType && typeof(List<>).IsAssignableFrom(replacementType.GetGenericTypeDefinition())
&& replacementType.GetGenericArguments().SequenceEqual(property.PropertyType.GetGenericArguments()))
return true;
return false;
}
}
要使用它,请将解析器的实例缓存在某处表现 https://www.newtonsoft.com/json/help/html/Performance.htm#ReuseContractResolver:
static IContractResolver customContractResolver = new CustomContractResolver();
并像这样反序列化:
var settings = new JsonSerializerSettings
{
ContractResolver = customContractResolver,
};
var root = JsonConvert.DeserializeObject<Nbgv>(json, settings);
Notes: