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

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

问题描述

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

命名空间 ConsoleApp1{公共接口 ICell{int ID { 获取;}}公共接口 IEukaryote{System.Collections.Generic.IEnumerable细胞{得到;}字符串通用名称 { 获取;}}公共密封部分类 PlantCell: ICell{公共 int Id =>12324;}公共密封部分类植物: IE核生物{私有只读 System.Collections.Generic.IDictionary_valuesDict;公共工厂(){_valuesDict = new System.Collections.Generic.Dictionary();var cell = new System.Collections.Generic.List();细胞.添加(新植物细胞());_valuesDict["单元格"] = 单元格;_valuesDict["GenericName"] = "HousePlant";}公共 System.Collections.Generic.IEnumerable细胞=>_valuesDict["Cells"] 作为 System.Collections.Generic.IEnumerable;公共字符串 GenericName =>_valuesDict["GenericName"] 作为字符串;public int SomethingIDoNotWantSerialized =>99999;公共覆盖字符串 ToS​​tring(){返回 Newtonsoft.Json.JsonConvert.SerializeObject(this,新 Newtonsoft.Json.JsonSerializerSettings(){ContractResolver = new Newtonsoft.Json.Serialization.CamelCasePropertyNamesContractResolver()});}}[System.ComponentModel.DataAnnotations.MetadataType(typeof(PlantMetadata))]公共密封部分类植物{[Newtonsoft.Json.JsonObject(Newtonsoft.Json.MemberSerialization.OptIn)]内部密封类 PlantMetadata{[Newtonsoft.Json.JsonProperty]公共 System.Collections.Generic.IEnumerable细胞;[Newtonsoft.Json.JsonProperty]公共字符串通用名称;//...}}课程计划{静态无效主(字符串 [] args){var 植物 = 新植物();System.Console.WriteLine(System.String.Format("输出为 {0}", plant.ToString()));System.Console.ReadKey();}}}

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

解决方案

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

公共密封部分类植物:IEukaryote{公共 System.Collections.Generic.IEnumerable单元格 { get { return (_valuesDict["Cells"] as System.Collections.IEnumerable).Cast();} }public string GenericName { get { return _valuesDict["GenericName"] 作为字符串;} }公共字符串 FieldIWantSerialized;公共 intSomethingIDoNotWantSerialized { 获取 { 返回 99999;} }//剩下的和以前一样.

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

//元数据.cs[System.ComponentModel.DataAnnotations.MetadataType(typeof(PlantMetadata))]公共密封部分类植物{[JsonObject(MemberSerialization.OptIn)]内部密封类 PlantMetadata{[Json属性]公共 IEnumerable细胞{得到;放;}[Json属性]公共字符串 GenericName { 获取;放;}[Json属性]公共字符串 FieldIWantSerialized;}}

如果我将 CellsGenericName 设为字段,或将 FieldIWantSerialized 设为属性,则它们不会被选择进行序列化.

工作示例 .Net Fiddle.

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

[JsonObject(MemberSerialization.OptIn)]内部密封类 PlantMetadata{[Json属性]公共对象细胞{得到;放;}[Json属性]公共对象 GenericName { 获取;放;}[Json属性]公共对象 FieldIWantSerialized;}

然后只有 FieldIWantSerialized 被序列化,而不是属性..Net Fiddle #2 显示了这种行为.这可能是 Newtonsoft 的问题;如 Microsoft 文档中所述 在元数据类中定义属性:

<块引用>

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

如果有关系,您可以报告有关返回类型限制的问题Newtonsoft - 或报告一个问题,要求更完整地记录他们对 MetadataTypeAttribute 的支持细节.

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

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.

解决方案

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.

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

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

Sample working .Net Fiddle.

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

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.

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天全站免登陆