当前位置: 首页 > 面试题库 >

JSON.NET序列化空JSON

鞠修雅
2023-03-14
问题内容

我正在使用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();
        }
    }
}

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


问题答案:

如Newtonsoft在本期中所述,MetadataTypeAttributeJson.NET实际上支持属性。但是,MetadataClassType当相应的“真实”成员是属性时,似乎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.

然后,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;
    }
}

如果我创建CellsGenericName成为字段,或者FieldIWantSerialized成为属性,则它们不会选择序列化。

示例工作 .Net Fiddle。

请注意,此外,我发现这些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显示此行为。这可能是Newtonsoft的问题;如Microsoft文档在元数据类中定义属性中所述:

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

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



 类似资料:
  • 问题内容: 是否可以使用Json.NET 序列化为NDJSON(换行分隔的JSON)?Elasticsearch API使用NDJSON进行批量操作,我找不到任何暗示 任何 .NET库都支持此格式的信息。 这个答案提供指导反序列化NDJSON,并有人指出,一个能够独立序列每一行和新行加入,但我不一定会调用 支持 。 问题答案: false`](http://www.newtonsoft.com/j

  • 问题内容: 我目前有一个处理程序,该处理程序获取excel文件的文件路径和标签名,将文件处理为数据表,然后将表序列化为json字符串以返回。在尝试处理大文件之前,此方法一直有效,然后出现内存不足异常。 我在想,如果不先将所有内容加载到数据表中,而是直接加载到json字符串中,它将减少内存使用。但是,我一直找不到如何执行此操作的任何示例。 我可以直接从OleDbConnection序列化为字符串吗?

  • 问题内容: 我正在尝试对a进行序列化/反序列化,如果对象是简单类型,这似乎很好,但是当对象更复杂时,它不起作用。 我有这个课: 在我的字典中,我添加了一个带有“重定向链”键的键和一些带有“状态”,“网址”,“父网址”键的简单字符串。我从JSON.Net返回的字符串如下所示: 我用来序列化的代码如下: 反序列化我正在做的事情: 字典恢复正常,所有字符串恢复正常,但是列表未正确反序列化。它只是作为 当

  • 问题内容: 将对象反序列化为()时,嵌套对象反序列化为s。是否可以强制将嵌套对象反序列化为s? 问题答案: 我找到了一种通过提供实现将所有嵌套对象转换为的方法: 文档: Json.NET的CustomCreationConverter

  • 问题内容: 我正在反序列化使用的对象,该对象包含Guid类型的私有字段和该字段的公共属性。当我的json中的my的值为null时,我想分配给我的字段。 但是想要访问私有字段,导致在尝试反序列化时出现此错误: 将值{null}转换为类型’System.Guid’时出错。路径“ [0]。属性”,第6行,位置26。 如何使其忽略私有字段,而使用公共属性? 问题答案: Json.NET拒绝为a 设置值,因

  • Json.net有没有办法只指定你想要序列化的属性?或者根据绑定标志序列化某些属性,比如只声明? 现在我正在使用< code > JObject。FromObject(MainObj。SubObj);要获取SubObj的所有属性,SubObj是遵循ISubObject接口的类的实例: 如果是,它将序列化A和B,但如果是,它将仅序列化B和C并忽略父属性