甲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