JSON.NET序列化空JSON

我使用MetadataType为以下类型定义Json.NET属性,然后在其ToString()方法中使用Json.NET对其进行序列化:

 namespace ConsoleApp1 { public interface ICell { int Id { get; } } public interface IEukaryote { System.Collections.Generic.IEnumerable Cells { get; } string GenericName { get; } } public sealed partial class PlantCell : ICell { public int Id => 12324; } public sealed partial class Plant : IEukaryote { private readonly System.Collections.Generic.IDictionary _valuesDict; public Plant() { _valuesDict = new System.Collections.Generic.Dictionary(); var cells = new System.Collections.Generic.List(); cells.Add(new PlantCell()); _valuesDict["Cells"] = cells; _valuesDict["GenericName"] = "HousePlant"; } public System.Collections.Generic.IEnumerable Cells => _valuesDict["Cells"] as System.Collections.Generic.IEnumerable; public string GenericName => _valuesDict["GenericName"] as string; public int SomethingIDoNotWantSerialized => 99999; public override string ToString() { return Newtonsoft.Json.JsonConvert.SerializeObject(this, new Newtonsoft.Json.JsonSerializerSettings() { ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver() } ); } } [System.ComponentModel.DataAnnotations.MetadataType(typeof(PlantMetadata))] public sealed partial class Plant { [Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)] internal sealed class PlantMetadata { [Newtonsoft.Json.JsonProperty] public System.Collections.Generic.IEnumerable Cells; [Newtonsoft.Json.JsonProperty] public string GenericName; //... } } class Program { static void Main(string[] args) { var plant = new Plant(); System.Console.WriteLine(System.String.Format("Output is {0}", plant.ToString())); System.Console.ReadKey(); } } } 

我的问题是Plant.ToString()将返回'{}’。 这是为什么? 它以前工作过。 我做的唯一改变是在PlantMetadata ,我将MemberSerialization改为OptIn而不是OptOut,因为我想要包含的属性少于遗漏。

正如Newtonsoft在本期中所述 , MetadataTypeAttribute属性实际上是由Json.NET支持的。 但是,当相应的“真实”成员是属性时,Json.NET似乎要求MetadataClassType成员必须是属性,而当相应的“真实”成员是字段时,Json.NET要求必须是属性。 因此,如果我按如下方式定义Plant类型,则需要序列化两个属性和一个字段:

 public sealed partial class Plant : IEukaryote { public System.Collections.Generic.IEnumerable Cells { get { return (_valuesDict["Cells"] as System.Collections.IEnumerable).Cast(); } } public string GenericName { get { return _valuesDict["GenericName"] as string; } } public string FieldIWantSerialized; public int SomethingIDoNotWantSerialized { get { return 99999; } } // Remainder as before. 

然后, PlantMetadata还必须具有两个属性和一个字段才能成功序列化:

 //Metadata.cs [System.ComponentModel.DataAnnotations.MetadataType(typeof(PlantMetadata))] public sealed partial class Plant { [JsonObject(MemberSerialization.OptIn)] internal sealed class PlantMetadata { [JsonProperty] public IEnumerable Cells { get; set; } [JsonProperty] public string GenericName { get; set; } [JsonProperty] public string FieldIWantSerialized; } } 

如果我将CellsGenericName设为字段,或者FieldIWantSerialized是一个属性,那么它们不会选择序列化。

样品工作.Net小提琴 。

请注意,此外,我发现MetadataClassType属性显然必须具有与真实属性相同的返回类型 。 如果我按如下方式更改PlantMetadata

 [JsonObject(MemberSerialization.OptIn)] internal sealed class PlantMetadata { [JsonProperty] public object Cells { get; set; } [JsonProperty] public object GenericName { get; set; } [JsonProperty] public object FieldIWantSerialized; } 

然后只序列化FieldIWantSerialized ,而不是属性。 .Net小提琴#2显示了这种行为。 这可能是牛顿问题; 如Microsoft文档中定义元数据类中的属性 :

这些属性的实际类型并不重要,编译器会忽略它们。 接受的方法是将它们全部声明为Object类型。

如果重要,您可以向Newtonsoft 报告有关返回类型限制的问题 – 或者报告一个问题,要求更详细地记录他们对MetadataTypeAttribute的支持的详细信息。