[英]ServiceStack JsonSerializer not serializing object members when inheritance
[英]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將僅序列化公共屬性和字段。 您的字段A
和b
是私有的 。 要使非公共(私有或內部)成員被Json.NET序列化,您可以:
公開它們:
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,只有獲取器需要公開才能序列化它們。
然后用[JsonProperty]
標記:
[JsonProperty] int A; [JsonProperty] int b;
這也適用於非公共財產。
用[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,則很有用。
這也適用於非公共財產。
用[JsonObject(MemberSerialization = MemberSerialization.Fields)]
標記您的對象:
[JsonObject(MemberSerialization = MemberSerialization.Fields)] public class Test { // Remainder as before... };
如MemberSerialization
文檔中MemberSerialization
, MemberSerialization.Fields
確保
所有公共和私有字段都已序列化。 可以使用JsonIgnoreAttribute或NonSerializedAttribute排除成員。 也可以通過用SerializableAttribute標記該類並將DefaultContractResolver上的IgnoreSerializableAttribute設置為false來設置此成員序列化模式。
當然,這只會導致非公共字段被序列化,而不是非公共屬性被序列化,但是如果您的目的是出於調試目的打印任意變量 ,則可能需要這樣做。
使用可序列化所有公共和非公共字段的自定義合同解析器 。
JSON.Net中顯示了幾個:強制序列化所有私有字段以及子類中的所有字段,這些子類將屬性以及公共或私有字段進行序列化。
C#中的另一個DeclaredFieldContractResolver
, 帶有JSON.NET繼承的私有字段 ,通過自動假定所有對象都標記有MemberSerialization.Fields
,僅序列化公共字段或私有字段。 您可以這樣使用它:
var settings = new JsonSerializerSettings { ContractResolver = DeclaredFieldContractResolver.Instance }; var json = JsonConvert.SerializeObject(t1, Formatting.Indented, settings);
創建一個自定義的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.