甲JsonConverter
不能設置在父對象中的屬性的名稱。當調用轉換器的WriteJson
方法時,屬性名稱已被寫入JSON;作者只希望有一點值得指出。這就是你遇到錯誤的原因。爲了使這個工作,自定義轉換器將不得不爲父對象。該轉換器將負責編寫其子項的屬性名稱和值。
後續
這是可以寫入,使得施加給它的JSON屬性仍然尊重對父對象的轉換器,同時還實現你想要的結果。我將概述下面的方法。
首先,稍微設置一下。既然你沒有說你的班級被稱爲什麼,我將假設這個例子叫做Document
。我們只需要對其進行實質性更改,即從DocTypeIdentifier
屬性中刪除[JsonConverter]
屬性。因此,我們有:
[JsonObject(MemberSerialization.OptIn)]
class Document
{
[JsonProperty("title", Required = Required.Always, Order = 1)]
public string Title { get; set; }
[JsonProperty("date", Order = 3)]
[JsonConverter(typeof(IsoDateTimeConverter))]
public DateTime Date { get; set; }
[JsonProperty(Order = 2)]
public TypeIdentifier DocTypeIdentifier { get; set; }
public string OtherStuff { get; set; }
}
您還沒有表現出對TypeIdentifier
類的代碼,所以我就假設它看起來像這樣,例如緣故
class TypeIdentifier
{
public string Value { get; set; }
public string ParameterName { get; set; }
}
有了這樣的方式,我們可以製造轉換器。這種方法非常簡單:我們將Document
加載到JObject
中,利用它尊重所應用的屬性的優點,然後返回並修復DocTypeIdentifier
的序列化,因爲它需要特殊處理。一旦我們有了,我們將JObject
寫入JsonWriter
。下面是代碼:
class DocumentConverter : JsonConverter
{
public override bool CanConvert(Type objectType)
{
return (objectType == typeof(Document));
}
public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
{
Document doc = (Document)value;
// Create a JObject from the document, respecting existing JSON attribs
JObject jo = JObject.FromObject(value);
// At this point the DocTypeIdentifier is not serialized correctly.
// Fix it by replacing the property with the correct name and value.
JProperty prop = jo.Children<JProperty>()
.Where(p => p.Name == "DocTypeIdentifier")
.First();
prop.AddAfterSelf(new JProperty(doc.DocTypeIdentifier.ParameterName,
doc.DocTypeIdentifier.Value));
prop.Remove();
// Write out the JSON
jo.WriteTo(writer);
}
public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
{
throw new NotImplementedException();
}
}
現在我們有轉換器,但美中不足的是,我們不能簡單地用[JsonConverter]
屬性裝飾Document
類才能使用它。如果我們這樣做了,那麼當我們將文檔加載到JObject
時,轉換器會嘗試使用它自己,最終會產生遞歸循環。相反,我們需要創建一個轉換器的實例並通過設置將它傳遞給序列化器。轉換器的CanConvert
方法確保它在正確的類上使用。 JObject.FromObject
方法在內部使用不同的串行器實例,因此它看不到DocumentConverter
,因此不會出現問題。
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new DocumentConverter());
string json = JsonConvert.SerializeObject(doc, settings);
這裏是在運行中的轉換器演示:
class Program
{
static void Main(string[] args)
{
Document doc = new Document
{
Title = "How to write a JSON converter",
Date = DateTime.Today,
DocTypeIdentifier = new TypeIdentifier
{
ParameterName = "type_id",
Value = "26"
},
OtherStuff = "this should not appear in the JSON"
};
JsonSerializerSettings settings = new JsonSerializerSettings();
settings.Converters.Add(new DocumentConverter());
settings.Formatting = Formatting.Indented;
string json = JsonConvert.SerializeObject(doc, settings);
Console.WriteLine(json);
}
}
這裏是從上面的輸出:
{
"title": "How to write a JSON converter",
"type_id": "26",
"date": "2014-03-28T00:00:00-05:00"
}
你有對象上的[Serializable]屬性? – Robert
@Robert使用JSON.NET不是內置的.NET序列化,意思是那些被忽略。不過,我確實有爲該類設置的[JsonObject(MemberSerialization.OptIn)]屬性。 – JNYRanger