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

为什么在尝试通过序列化为JSON打印对象时缺少某些成员?

张逸清
2023-03-14
问题内容

如何在C#中打印任意变量以打印所有成员?

我用相同的技术找到了三个答案:

  • 建议在其他答案中使用Json.NET进行序列化,以及
  • https://tech.io/playgrounds/2098/how-to-dump-objects-in-c/using-json-and-yaml-serializers,
  • https://www.codeproject.com/Articles/1194980/How-to-Dump-Object-for-Debugging-Purposes-in-Cshar

但是,当我尝试使用以下代码进行测试时,

    using System;
    using System.Collections.Generic;

    using Newtonsoft.Json;

    public static class Program
    {
        public static void Main()
        {
            Test t1 = new Test(1, 2);
            {
                string json = JsonConvert.SerializeObject(t1, Formatting.Indented);
                Console.WriteLine(json);
            }
            Dump(t1);

            // Add 3 objects to a List.
            List<Test> list = new List<Test>();
            list.Add(new Test(1, 2));
            list.Add(new Test(3, 4));
            list.Add(new Test(5, 6));

            Console.WriteLine(list.ToString());
            {
                string json = JsonConvert.SerializeObject(list, Formatting.Indented);
                Console.WriteLine(json);
            }
        }

        public class Test
        {
            int A;
            int b;
            public Test(int _a, int _b)
            {
                A = _a;
                b = _b;
            }
        };

        public static void Dump<T>(this T x)
        {
            string json = JsonConvert.SerializeObject(x, Formatting.Indented);
            Console.WriteLine(json);
        }
    }

我得到的只是空Test输出:

    {}
    {}
    System.Collections.Generic.List`1[Program+Test]
    [
      {},
      {},
      {}
    ]

使用Json.NET序列化为JSON时,为什么所有类成员都丢失了?


问题答案:

默认情况下,Json.NET将仅序列化 公共 属性和字段。您的字段Ab私有的
。要使非公共(私有或内部)成员被Json.NET序列化,您可以:

  1. 公开它们:
        public int A;
    public int b;

但是,从风格上讲,如果要使其公开,最好将它们转换为属性:

        public class Test
    {
        public int A { get; private set; }
        public int b { get; private set; }
        public Test(int a, int b)
        {
            this.A = a;
            this.b = b;
        }
    };

对于Json.NET,只有获取器需要公开才能序列化它们。

  1. 然后用标记[JsonProperty]
        [JsonProperty]
    int A;
    [JsonProperty]
    int b;

这也适用于非公共财产。

  1. 用标记您的对象,[DataContract]并用标记您的字段[DataMember]
        [DataContract]
    public class Test
    {
        [DataMember]
        int A;
        [DataMember]
        int b;
        public Test(int _a, int _b)
        {
            A = _a;
            b = _b;
        }
    };

请注意,数据合同序列化是可选的,因此您需要使用标记 每个
要序列化的成员[DataMember]。有点麻烦,但如果您不希望c#模型依赖于Json.NET,则很有用。

这也适用于非公共财产。

  1. 用以下标记您的对象[JsonObject(MemberSerialization = MemberSerialization.Fields)]
        [JsonObject(MemberSerialization = MemberSerialization.Fields)]
    public class Test
    {
        // Remainder as before...
    };

由于在解释文件的MemberSerializationMemberSerialization.Fields可确保

所有公共和私有字段都已序列化。可以使用JsonIgnoreAttribute或NonSerializedAttribute排除成员。也可以通过使用SerializableAttribute标记该类并将DefaultContractResolver上的IgnoreSerializableAttribute设置为false来设置此成员序列化模式。

当然,这只会导致非公共 字段 被序列化,而不是非公共属性,但是如果您的目的是出于调试目的而 打印任意变量 ,则可能需要这样做。

  1. 使用可序列化所有公共和非公共字段的自定义合同解析器。

将属性和公共或私有字段进行序列化。

另一个方法是
使用JSON.NET继承的私有字段DeclaredFieldContractResolver从_C#序列化开始,通过自动假定所有对象都标记为,仅序列化公共字段或私有字段MemberSerialization.Fields`。您可以这样使用它:

    var settings = new JsonSerializerSettings
{
    ContractResolver = DeclaredFieldContractResolver.Instance
};
var json = JsonConvert.SerializeObject(t1, Formatting.Indented, settings);
  1. 创建一个序列化必要字段和属性的自定义JsonConverter。由于字段是私有的,因此需要为嵌套类型:
    public class Test
    

    {
    public class TestJsonConverter : JsonConverter
    {
    public override bool CanConvert(Type objectType)
    {
    return typeof(Test).IsAssignableFrom(objectType);
    }

        public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
        {
            var test = (Test)value;
    
            writer.WriteStartObject();
            writer.WritePropertyName(nameof(Test.A));
            serializer.Serialize(writer, test.A);
            writer.WritePropertyName(nameof(Test.b));
            serializer.Serialize(writer, test.b);
            writer.WriteEndObject();
        }
    
        public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
        {
            throw new NotImplementedException();
        }
    }
    // Remainder as before
    

    }

并像这样使用它:

    var json = JsonConvert.SerializeObject(t1, Formatting.Indented, new Test.TestJsonConverter());

在这种情况下,由于类型是嵌套的,因此您的模型仍将依赖于Json.NET,这使选项#2成为更好的选择。

如果仅出于调试目的转储对象,则#5可能是最佳选择。



 类似资料:
  • 我有一个大的嵌套对象。我想在JSON字符串中序列化这个对象,但是我只需要包含某些字段。这里的问题是字段可能会非常频繁地更改,我希望以一种可以帮助我轻松包含或排除用于序列化的字段的方式来构建它。 我知道我可以编写很多代码来提取某些字段并“手动”构建JSON。但我想知道,除了指定一个必填字段列表之外,是否还有其他优雅的方法可以实现类似的结果? 例如,我希望在响应中只包含和以下对象结构: Json:

  • 问题内容: 我已经从Khalid Mughal SCJP复制了以下程序片段,但是我无法 理解输出。 上面的程序为第一个print语句提供了输出true,但是应该给出false,因为它是==关系运算符的引用比较。但是第三张印刷品是假的,我不理解这种不一致。 解释非常感谢! 问题答案: 在第一种情况下,两个和都指向相同的缓存对象。默认情况下,-128和127之间的范围作为对象缓存。我们可以使用

  • 问题内容: 如何在JavaScript中将对象序列化为JSON? 问题答案: 您正在寻找。

  • 问题内容: 因此,当我偶然发现新的JsonSerializable Interface 时,我在php.net上四处徘徊,以获取有关将PHP对象序列化为JSON的信息。它只是 PHP > = 5.4,而我正在5.3.x环境中运行。 PHP <5.4如何实现这种功能? 我还没有使用JSON进行很多工作,但是我试图在应用程序中支持API层,并且将数据对象( 否则将发送到视图 )转储到JSON中将是完美

  • 我使用avro工具从avsc文件生成java类,使用: 然后,我试图通过ObjectMapper将这些对象序列化为json,但总是得到一个JsonMappingException,上面写着“不是枚举”或“不是联合”。在我的测试中,我使用其生成器或构造函数创建生成的对象。我对不同类的对象有这样的例外。。。 示例代码: 我还使用:serializer尝试了许多配置。配置(…)但还是失败了。版本:Jav

  • 让我们假设有一个福克斯类,它有名字、颜色和年龄。假设我有一份狐狸的名单,我想打印出那些狐狸的名字,它们的颜色是绿色的。我想使用流来这样做。 字段: 名称:私有字符串 颜色:专用字符串 年龄:私有整数 我写了以下代码来做过滤和Sysout: 但是,我的代码中存在一些语法问题。 到底是什么问题?我该怎么整理?