Cor*_*rey 2 c# json json.net mimekit
我有一些问题反序列化mimeKit.mimeMessage,我将其序列化为JSON字符串并存储在redis键值缓存中.
我能够使用json.NET或Jil成功地序列化和存储mimeMessage,但是当我去反序列化时,会抛出以下错误.
由json.NET抛出
无法找到用于MimeKit.Header类型的构造函数.一个类应该有一个默认的构造函数,一个带参数的构造函数或一个用JsonConstructor属性标记的构造函数.路径'标题[0].偏移',第1行,第22位.
我使用StackExchange.Redis方法stringGet获取序列化对象,然后将RedisValue传递给Json.Net; 下面的代码片段:
RedisValue result = db.StringGet(key);
MimeMessage message = new MimeMessage();
message = JsonConvert.DeserializeObject<MimeMessage>(result);
Run Code Online (Sandbox Code Playgroud)
我的理解是总是创建一个默认构造函数,这使得我很难理解,默认构造函数是否已被指定为私有,如果是这样,为什么?
我还检查了返回的JSON字符串的格式,它是正确的.
谢谢你的帮助.
首先,澄清一些事情:
我的理解是总是创建一个默认构造函数,这使得我很难理解,默认构造函数是否已被指定为私有,如果是这样,为什么?
这不是真的.当您定义一个没有构造函数的类时,会为您生成一个默认的no-args构造函数.如果提供构造函数,则不再生成此默认构造函数.换句话说,类可能没有默认构造函数.
考虑到这一点,MimeKit.Header该类提供了6个构造函数,其中没有一个不带参数.因此,JSON.NET不知道如何实例化这个类,这就是异常发生的原因.
由于您无法控制MimeKit.Header该类,因此让JSON.NET知道如何构造Header实例的一种方法是使用自定义转换器:
public class MimeHeaderConverter : JsonConverter
{
public override object ReadJson(
JsonReader reader,
Type objectType,
object existingValue,
JsonSerializer serializer)
{
JObject obj = serializer.Deserialize<JObject>(reader);
HeaderId headerId = obj["Id"].ToObject<HeaderId>();
Header header = new Header(headerId, obj["Value"].ToObject<string>());
return header;
}
public override void WriteJson(
JsonWriter writer,
object value,
JsonSerializer serializer)
{
throw new NotImplementedException();
}
public override bool CanConvert(Type t)
{
return typeof(Header).IsAssignableFrom(t);
}
public override bool CanRead { get { return true; } }
public override bool CanWrite { get { return false; } }
}
Run Code Online (Sandbox Code Playgroud)
在这里,我们将Header类反序列化为JObject第一个.然后,我们挑选HeaderId和Value出的是JObject为了创建一个Header实例.
这里有一个注释:我对这个库不太了解.这可能不是实例化a的最佳方式Header,我可能会意外丢弃某些信息.我只做了一些非常基本的测试.
一旦你解决了这个问题,你将遇到另一个与不接受null值的属性设置器有关的问题.
具体来说,如果你提供的话,ResentMessageId和MimeVersion属性在setter中有逻辑.这是一个问题,因为在实例化时这些值可以为null .ArgumentExceptionnullMimeMessage
一种解决方法是创建一个ContractResolver排除这些属性:
public class MimeMessageContractResolver : DefaultContractResolver
{
private static HashSet<string> excludedMembers = new HashSet<string>
{
"ResentMessageId",
"MimeVersion"
};
protected override List<MemberInfo> GetSerializableMembers(Type objectType)
{
var baseMembers = base.GetSerializableMembers(objectType);
if (typeof(MimeMessage).IsAssignableFrom(objectType))
{
baseMembers.RemoveAll(m => excludedMembers.Contains(m.Name));
}
return baseMembers;
}
}
Run Code Online (Sandbox Code Playgroud)
这样,我们永远不会意外地传递null给其中一个属性的setter.
这里还有一个注意事项:我注意到即使我忽略了它MimeVersion,ResentMessageId如果标题包含一个MimeVersion和/或ResentMessageId标题,它们仍然会被设置.我猜这已经融入了MimeMessage某个地方,但同样,我并不完全熟悉这个库.
因此,要使用上面的类(仅在反序列化时),您可以这样做:
string someJsonString = "{ ... }";
MimeMessage deserialized = JsonConvert.DeserializeObject<MimeMessage>(
someJsonString, new JsonSerializerSettings
{
ContractResolver = new MimeMessageContractResolver(),
Converters = new JsonConverter[]
{
new MimeHeaderConverter()
}
});
Run Code Online (Sandbox Code Playgroud)
通过一些基本测试,这似乎工作正常.您可能最终在实际使用中遇到更多问题,因此无法保证.
希望这至少可以让你开始.
| 归档时间: |
|
| 查看次数: |
1215 次 |
| 最近记录: |