簡體   English   中英

為什么嘗試通過序列化為JSON打印對象時缺少某些成員?

[英]Why are some members missing when trying to print an object by serializing to JSON?

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

我用相同的技術找到了三個答案:

但是,當我嘗試使用以下代碼進行測試時,

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,只有獲取器需要公開才能序列化它們。

  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#中的另一個DeclaredFieldContractResolver帶有JSON.NET繼承的私有字段 ,通過自動假定所有對象都標記有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可能是最佳選擇。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM