[英]Deserialising mimekit.MimeMessage Object
我在反序列化mimeKit.mimeMessage時遇到一些問題,該序列已序列化為JSON字符串並存儲在redis鍵值緩存中。
我能夠使用json.NET或Jil成功地序列化並存儲mimeMessage,但是當我進行反序列化時,會引發以下錯誤。
由json.NET拋出
找不到用於MimeKit.Header類型的構造函數。 一個類應該具有一個默認構造函數,一個帶有參數的構造函數或一個標有JsonConstructor屬性的構造函數。 路徑“ Headers [0] .Offset”,第1行,位置22。
我正在使用StackExchange.Redis方法stringGet來獲取序列化的對象,然后將RedisValue傳遞到Json.Net。 下面的代碼段:
RedisValue result = db.StringGet(key);
MimeMessage message = new MimeMessage();
message = JsonConvert.DeserializeObject<MimeMessage>(result);
據我了解,總是會創建一個默認的構造函數,這使我有點難以理解,是否可以將默認的構造函數指定為私有,如果可以,為什么?
我還檢查了返回的JSON字符串的格式,它是正確的。
謝謝你的幫助。
首先,要清理一下:
據我了解,總是會創建一個默認的構造函數,這使我有點難以理解,是否可以將默認的構造函數指定為私有,如果可以,為什么?
這不是真的。 當您定義沒有構造函數的類時,將為您生成一個默認的無參數構造函數。 如果提供構造函數,則不再生成此默認構造函數。 換句話說,一個類可能沒有默認的構造函數。
考慮到這一點, MimeKit.Header
類提供了6個構造函數,這些構造函數都不帶任何參數。 因此,JSON.NET不知道如何實例化此類,這就是發生異常的原因。
由於您對MimeKit.Header
類沒有任何控制權, 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; } }
}
在這里,我們首先將Header
類反序列化為JObject
。 然后,我們從該JObject
中選擇HeaderId
和Value
以便創建Header
實例。
這里的注釋 :我對該庫了解不多。 這可能不是實例化Header
的最佳方法,而且我可能會不小心丟棄一些信息。 我只做了一些非常基本的測試。
一旦解決了這個問題,就會遇到另一種與不接受null
值的屬性設置器有關的問題。
具體來說,如果您提供null
,則ResentMessageId
和MimeVersion
屬性在設置器中具有引發ArgumentException
的邏輯。 這是一個問題,因為在實例化MimeMessage
時,這些值可以為null。
一種解決方法是創建一個不包含那些屬性的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;
}
}
這樣,我們絕不會意外地將null
傳遞給這些屬性之一的設置器。
這里也要注意 :我注意到,即使當我忽略MimeVersion
和ResentMessageId
,如果標頭包含MimeVersion
和/或ResentMessageId
標頭,它們仍然會被設置。 我猜想它已經被MimeMessage
到MimeMessage
某個地方,但是同樣,我對這個庫並不完全熟悉。
因此,要使用上述類(僅在反序列化時),您可以這樣做:
string someJsonString = "{ ... }";
MimeMessage deserialized = JsonConvert.DeserializeObject<MimeMessage>(
someJsonString, new JsonSerializerSettings
{
ContractResolver = new MimeMessageContractResolver(),
Converters = new JsonConverter[]
{
new MimeHeaderConverter()
}
});
通過一些基本測試,這似乎可以正常工作。 您最終可能會在實際使用中遇到更多問題,因此無法保證。
希望這至少可以幫助您入門。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.