JSON.NET序列化空JSON [英] JSON.NET Serializes Empty JSON

查看:93
本文介绍了JSON.NET序列化空JSON的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I am using MetadataType to define Json.NET attributes for the following type, then serializing it using Json.NET inside its ToString() method:

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();
        }
    }
}

我的问题是Plant.ToString()将返回'{}'.这是为什么?以前在工作.我所做的唯一更改是在PlantMetadata中,我将MemberSerialization更改为OptIn而不是OptOut,因为我希望包含的属性少于保留的属性.

My problem is that Plant.ToString() will return '{}'. Why is that? It was working before. The only change I made was in PlantMetadata where I altered the MemberSerialization to OptIn instead of OptOut, as I had less properties I wanted included than left out.

推荐答案

Newtonsoft在 MetadataTypeAttribute 属性实际上受Json.NET支持.但是,似乎Json.NET要求 MetadataClassType 成员必须是属性,而当相应真实"成员是字段时,则必须是字段.因此,如果我如下定义您的Plant类型,具有两个属性和一个要序列化的字段:

As stated by Newtonsoft in this issue, MetadataTypeAttribute attributes are in fact supported by Json.NET. However, it appears that Json.NET requires that the MetadataClassType members must be properties when the corresponding "real" members are properties, and fields when the corresponding "real" members are fields. Thus, if I define your Plant type as follows, with two properties and one field to be serialized:

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.

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

Then the PlantMetadata must also have two properties and one field for them to be serialized successfully:

//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;
    }
}

如果我将CellsGenericName设置为字段,或者将FieldIWantSerialized设置为属性,则不会选择序列化.

If I make Cells or GenericName be fields, or FieldIWantSerialized be a property, then they do not get opted into serialization.

示例工作 .Net Fiddle .

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

Note that, in addition, I have found that the MetadataClassType properties apparently must have the same return type as the real properties. If I change your PlantMetadata as follows:

[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 显示此行为.这可能是Newtonsoft的问题;如Microsoft文档:

Then only FieldIWantSerialized is serialized, not the properties. .Net Fiddle #2 showing this behavior. This may be a Newtonsoft issue; as stated in the Microsoft documentation Defining Attributes in Metadata Classes:

这些属性的实际类型并不重要,将被忽略 由编译器.公认的方法是将它们全部声明为 键入对象.

The actual type of these properties is not important, and is ignored by the compiler. The accepted approach is to declare them all as of type Object.

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

If it matters, you could report an issue about the return type restriction to Newtonsoft - or report an issue asking that details of their support for MetadataTypeAttribute be more fully documented.

这篇关于JSON.NET序列化空JSON的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆