我有一个班级有几个不同的班级,我把这些课程中的信息发送给客户,但我不想把它们全部发送出去,所以有些是私人的,有些有[JsonObject(MemberSerialization.OptIn)]
标志等
但是,现在我想在需要关闭服务器时每12小时(我不想使用数据库)对所有这些对象进行备份,这样我想做什么(如果可能的话)是强制JSON.Net Serializer转换对象和属于该对象的所有对象。
例如:
class Foo
{
public int Number;
private string name;
private PrivateObject po = new PrivateObject();
public string ToJSON()
{ /* Serialize my public field, my property and the object PrivateObject */ }
}
我尝试了这段代码(即使它已经过时了),但它并没有序列化与我的对象相关的对象:
Newtonsoft.Json.JsonSerializerSettings jss = new Newtonsoft.Json.JsonSerializerSettings();
Newtonsoft.Json.Serialization.DefaultContractResolver dcr = new Newtonsoft.Json.Serialization.DefaultContractResolver();
dcr.DefaultMembersSearchFlags |= System.Reflection.BindingFlags.NonPublic;
jss.ContractResolver = dcr;
return Newtonsoft.Json.JsonConvert.SerializeObject(this, jss);
答案 0 :(得分:52)
这应该有效:
var settings = new JsonSerializerSettings() { ContractResolver = new MyContractResolver() };
var json = JsonConvert.SerializeObject(obj, settings);
public class MyContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
{
var props = type.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(p => base.CreateProperty(p, memberSerialization))
.Union(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(f => base.CreateProperty(f, memberSerialization)))
.ToList();
props.ForEach(p => { p.Writable = true; p.Readable = true; });
return props;
}
}
答案 1 :(得分:5)
@ L.B的答案很棒。但是......它需要.NET 3.5或更高版本。
对于我们这些坚持使用2.0的人......
public class ForceJSONSerializePrivatesResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
protected override IList<Newtonsoft.Json.Serialization.JsonProperty> CreateProperties(System.Type type, MemberSerialization memberSerialization)
{
var props = type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance);
List<Newtonsoft.Json.Serialization.JsonProperty> jsonProps = new List<Newtonsoft.Json.Serialization.JsonProperty>();
foreach( var prop in props )
{
jsonProps.Add( base.CreateProperty(prop, memberSerialization));
}
foreach( var field in type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance) )
{
jsonProps.Add ( base.CreateProperty( field, memberSerialization ) );
}
jsonProps.ForEach(p => { p.Writable = true; p.Readable = true; });
return jsonProps;
}
}
......似乎有效。
答案 2 :(得分:1)
非常感谢@ L.B.这是在.linq脚本中的完整实现,以防任何人想要使用私有子类进行测试 - 例如参见A有私有子类B。
void Main()
{
var a = A.Test();
SerialiseAllFields.Dump(a);
}
class A
{
private int PrivField1;
private int PrivProp1 { get; set; }
private B PrivSubClassField1;
public static A Test()
{
return new A { PrivField1 = 1, PrivProp1 = 2, PrivSubClassField1 = B.Test() };
}
}
class B
{
private int PrivField1;
private int PrivProp1 { get; set; }
public static B Test()
{
return new B { PrivField1 = 3, PrivProp1 = 4 };
}
}
// Define other methods and classes here
public static class SerialiseAllFields
{
public static void Dump(object o, bool indented = true)
{
var settings = new Newtonsoft.Json.JsonSerializerSettings() { ContractResolver = new AllFieldsContractResolver() };
if (indented)
{
settings.Formatting = Newtonsoft.Json.Formatting.Indented;
}
Newtonsoft.Json.JsonConvert.SerializeObject(o, settings).Dump();
}
}
public class AllFieldsContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
protected override IList<Newtonsoft.Json.Serialization.JsonProperty> CreateProperties(Type type, Newtonsoft.Json.MemberSerialization memberSerialization)
{
var props = type
.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(p => base.CreateProperty(p, memberSerialization))
.Union(type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)
.Select(f => base.CreateProperty(f, memberSerialization)))
.ToList();
props.ForEach(p => { p.Writable = true; p.Readable = true; });
return props;
}
}
有趣的是,属性的支持字段也是序列化的,即输出为:
{
"PrivProp1": 2,
"PrivField1": 1,
"<PrivProp1>k__BackingField": 2,
"PrivSubClassField1": {
"PrivProp1": 4,
"PrivField1": 3,
"<PrivProp1>k__BackingField": 4
}
}
答案 3 :(得分:0)
这是先前接受的答案的修改版本,这也将serialize private fields/properties
。性能略有提升。 (没有 BinaryFormatter 的序列化有点慢)
public class CloneContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
protected override IList<JsonProperty> CreateProperties(Type type,
MemberSerialization memberSerialization)
{
List<MemberInfo> members = GetSerializableMembers(type);
if (members == null)
throw new JsonSerializationException("Null collection of serializable members returned.");
members.AddRange(type.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(f => !f.CustomAttributes.Any(x => x.AttributeType
== typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute))));
members.AddRange(type.GetFields(BindingFlags.NonPublic | BindingFlags.Instance)
.Where(f => !f.CustomAttributes.Any(x => x.AttributeType
== typeof(System.Runtime.CompilerServices.CompilerGeneratedAttribute))));
JsonPropertyCollection properties = new JsonPropertyCollection(type);
members.ForEach(member =>
{
JsonProperty property = CreateProperty(member, memberSerialization);
property.Writable = true;
property.Readable = true;
properties.AddProperty(property);
});
return properties;
}
}
在我看来,这种方法会使用更多的内存
public static class CloneHelper
{
private readonly static JsonSerializerSettings clone_settings = new JsonSerializerSettings() { ContractResolver = new CloneContractResolver() };
public static T Clone<T>(this object source)
{
T entity = JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source, clone_settings), clone_settings);
return entity;
}
}