尝试通过序列化为JSON打印对象时,为什么有些成员丢失?

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

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

  • https://stackoverflow.com/a/26181763/2125837建议使用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 list = new List(); 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(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; 
  2. 然后用[JsonProperty]标记:

     [JsonProperty] int A; [JsonProperty] int b; 
  3. 使用[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,那会有点麻烦但很有用。

  4. 使用[JsonObject(MemberSerialization = MemberSerialization.Fields)]标记您的对象:

     [JsonObject(MemberSerialization = MemberSerialization.Fields)] public class Test { // Remainder as before... }; 

    正如MemberSerialization 文档中MemberSerializationMemberSerialization.Fields确保了这一点

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

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

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

    JSON.Net上显示了几个:强制序列化所有私有字段和子类中的所有字段,这些字段序列化公共或私有属性和字段。

    另一个来自c#Serialize的DeclaredFieldContractResolverinheritance了私有字段 ,只通过自动假设所有对象都用MemberSerialization.Fields标记来序列化公共或私有字段。 你会像这样使用它:

     var settings = new JsonSerializerSettings { ContractResolver = DeclaredFieldContractResolver.Instance }; var json = JsonConvert.SerializeObject(t1, Formatting.Indented, settings); 
  6. 创建一个自定义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可能是最佳选择。