如何在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时,我的所有类成员都会丢失?
答案 0 :(得分:7)
默认情况下,Json.NET只会序列化公共属性和字段。您的字段A
和b
私有。要使非公共(私有或内部)成员通过Json.NET序列化,您可以:
公开宣传:
public int A;
public int b;
然后用[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.Fields
中所述,DeclaredFieldContractResolver
确保
所有公共和私人字段都是序列化的。可以使用JsonIgnoreAttribute或NonSerializedAttribute排除成员。也可以通过使用SerializableAttribute标记类并将DefaultContractResolver上的IgnoreSerializableAttribute设置为false来设置此成员序列化模式。
当然这只会导致非公共字段被序列化,而不是非公共属性,但如果您的目的是打印任意变量进行调试,这可能就是您想要的目的
使用序列化所有公共和非公共字段的documentation。
custom contract resolver 显示了几个,它们序列化了公共或私有的属性和字段。
另一个来自 JSON.Net: Force serialization of all private fields and all fields in sub-classes 的MemberSerialization.Fields
,仅通过自动假设所有对象都标有var settings = new JsonSerializerSettings
{
ContractResolver = DeclaredFieldContractResolver.Instance
};
var json = JsonConvert.SerializeObject(t1, Formatting.Indented, settings);
来序列化公共字段或私有字段。你可以这样使用它:
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
}
创建一个序列化必要字段的c# Serialize with JSON.NET inherited private fields。由于字段是私有的,因此需要custom JsonConverter
:
var json = JsonConvert.SerializeObject(t1, Formatting.Indented, new Test.TestJsonConverter());
并使用它:
if (mViewPager.getAdapter() != null)
mViewPager.setAdapter(null);
mViewPager.setAdapter(mPagerAdapter);
mViewPager.setCurrentItem(desiredPos);
虽然这样做有效,但由于类型是嵌套的,你的模型仍然依赖于Json.NET,这使得选项#2成为更好的选择。
如果您只是为了调试目的而转储对象,那么#5可能是最佳选择。