我在序列化为 JSON 时加密某些字段并在反序列化为特定 C# 类期间解密这些字段的任务失败。
我把问题归结为最基本的问题,就是无法通过操作 value 来自定义特定字段的反序列化,也不知道是什么原因。我正在为每个字段使用自定义合同解析器和自定义值提供程序。我可以看到该GetValue
函数已执行,但SetValue
从未执行。
代码示例:
class Program
{
static void Main(string[] args)
{
var text = "This is text";
var number = 1;
var anotherText = "This is another text";
var anotherNumber = 2;
var sampleInner = new SampleInner(anotherText, anotherNumber);
var sample = new SampleMessage(text, number, sampleInner);
var myCustomContractResolver = new MyCustomContractResolver();
var jsonSettings = GetJsonSettings(myCustomContractResolver);
Console.WriteLine("Serializing..");
var json = JsonConvert.SerializeObject(sample, jsonSettings);
Console.WriteLine(json);
Console.WriteLine("Deserializing..");
var sampleDeserialized = JsonConvert.DeserializeObject(json, typeof(SampleMessage), jsonSettings);
Console.WriteLine(sampleDeserialized);
Console.ReadLine();
}
private static JsonSerializerSettings GetJsonSettings(IContractResolver contractResolver)
{
var jsonSettings =
new JsonSerializerSettings
{
ContractResolver = contractResolver
};
return jsonSettings;
}
}
自定义合同解析器:
public class MyCustomContractResolver
: DefaultContractResolver
{
public MyCustomContractResolver()
{
NamingStrategy = new CamelCaseNamingStrategy();
}
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var jsonProperties = base.CreateProperties(type, memberSerialization);
foreach (var jsonProperty in jsonProperties)
{
var propertyInfo = type.GetProperty(jsonProperty.UnderlyingName);
var defaultValueProvider = jsonProperty.ValueProvider;
jsonProperty.ValueProvider = new MyValueProvider(defaultValueProvider);
}
return jsonProperties;
}
}
SetValue
以及在反序列化期间从不执行的自定义值提供程序:
public class MyValueProvider
: IValueProvider
{
private readonly IValueProvider _valueProvider;
public MyValueProvider(IValueProvider valueProvider)
{
_valueProvider = valueProvider;
}
public void SetValue(object target, object value)
{
//This is not executed during deserialization. Why?
_valueProvider.SetValue(target, value);
Console.WriteLine($"Value set: {value}");
}
public object GetValue(object target)
{
var value = _valueProvider.GetValue(target);
Console.WriteLine($"Value get: {value}");
return value;
}
}
希望有人可以让我知道我错过了什么:)
更新 1:我序列化/反序列化的对象是不可变的(没有公共设置器),这是一个要求,因为我需要支持这些对象。正如评论指出的那样,没有SetValue
执行是有道理的
更新 2:感谢@dbc 的精彩回答,不,我知道反序列化为不可变对象的好方法。接受答案后的最终版本代码。
更新 3:考虑到问题,选择的答案是绝对正确的。然而,在进一步调查之后,我决定采用一种稍微不同的方法,该方法适用于不可变类和可变类,以防有人处于类似情况。我现在使用合同解析器和 json 转换器的组合,而不是使用值提供程序,以便使用合同解析器我可以根据类型决定如何序列化/反序列化,并且使用 json 转换器我可以在序列化/反序列化期间访问值并进行操作如预期的。
基本上,在我的合同解析器上,我重写了创建属性的方法(我可以在其中访问我的原始 Type 属性)并有选择地指定要使用的 json 转换器。
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var jsonProperties = base.CreateProperties(type, memberSerialization);
//Filter here based on type, attribute or whatever and if want to customize a specific property type:
foreach (var jsonProperty in jsonProperties)
{
jsonProperty.Converter = new MyJsonConverter();
}
return jsonProperties;
}
在 MyJsonConverter 中,我们可以选择写入 json 或读取 json 时要执行的操作:
public class MyJsonConverter
: JsonConverter
{
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
//I can do whatever with value
var finalValue = $"{value}-edited";
writer.WriteValue(finalValue);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
// I can do whatever with the value
var value = (string)reader.Value;
var newValue = "whatever";
return newValue;
}
public override bool CanWrite => true;
public override bool CanRead => true;
public override bool CanConvert(Type objectType)
{
return true;
}
}