JSON.Net:强制序列化所有私有字段和子类中的所有字段



我有一个类,它有几个不同的类,我把这些类中的信息发送给客户端,但我不想把它们都发送出去,所以有些是私有的,有些是[JsonObject(MemberSerialization.OptIn)]标志等。

然而,现在当我需要关闭服务器并且每12小时(我不想使用数据库)时,我想要对所有这些对象进行备份,所以我想要做的(如果可能的话)是强制JSON。. Net序列化器转换对象和属于该对象的所有对象。

例如:

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);

应该可以:

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;
    }
}

@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;
    }
}

太棒了,谢谢@ 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
  }
}

这是先前接受的答案的修改版本,这也将是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;
    }
}

相关内容

  • 没有找到相关文章

最新更新