JSON.NET序列化空JSON

Dan*_* L. 4 c# serialization json json.net

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

namespace ConsoleApp1
{
    public interface ICell
    {
        int Id { get; }
    }
    public interface IEukaryote
    {
        System.Collections.Generic.IEnumerable<ICell> 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<string, object> _valuesDict;
        public Plant()
        {
            _valuesDict = new System.Collections.Generic.Dictionary<string, object>();
            var cells = new System.Collections.Generic.List<PlantCell>();
            cells.Add(new PlantCell());
            _valuesDict["Cells"] = cells;
            _valuesDict["GenericName"] = "HousePlant";
        }
        public System.Collections.Generic.IEnumerable<ICell> Cells => _valuesDict["Cells"] as System.Collections.Generic.IEnumerable<ICell>;
        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<ICell> 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();
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

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

dbc*_*dbc 5

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

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

    // Remainder as before.
Run Code Online (Sandbox Code Playgroud)

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

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

        [JsonProperty]
        public string GenericName { get; set; }

        [JsonProperty]
        public string FieldIWantSerialized;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我制作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;
} 
Run Code Online (Sandbox Code Playgroud)

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

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

如果重要,您可以向Newtonsoft 报告有关退货类型限制的问题 - 或者报告一个问题,要求MetadataTypeAttribute更全面地记录其支持的详细信息.