繁体   English   中英

Newtonsoft.json 或 System.Text.Json 仅序列化属性的定义类型而不是继承值

[英]Newtonsoft.json or System.Text.Json Serialize only the property's defined type not inherited values

考虑你有:

class ContentRef {
  SomeProperty
}

class Content : ContentRef {
   SomeOtherProperty
}

class C  {
   ContentRef someProperty;
   List<ContentRef> someList;
}

var someObject = new C { someProperty = new Content(), someList = new List<ContentRef>({new Content()})};

默认情况下,Newtonsoft 和 System.Text.Json 都会序列化 someObject 中 Content 的所有属性。 但很明显,C 的定义说两者都是 A 类型。我想确保在直接属性 A 和 List 的情况下,即使您将 B 分配给它,唯一被序列化的是 A 的属性。

This happens all of the time in document databases when you have a Ref class for a property that you're setting and you set it to the full class that inherits from the ref class for the rest of the data. 您只希望文档数据库存储 ref 类的数据,而不是所有完整的 class 因为当它被反序列化时,您只关心定义的 Ref class。

我有这个:

public class StrictTypeContractResolver : DefaultContractResolver
{
    private readonly FieldInfo _IsSealedField = typeof(JsonContract).GetField("IsSealed", BindingFlags.Instance | BindingFlags.NonPublic)!;

    public override JsonContract ResolveContract(Type type)
    {
        var resolveContract = base.ResolveContract(type);
        _IsSealedField.SetValue(resolveContract, true);
        return resolveContract;
    }
}

它适用于直接属性情况,仅序列化实际定义的类型。 但是,我不知道如何让它在 List 类型(哈希集、IList 或 IEnumerable)上工作。 它序列化整个事物,而不是像它应该的那样序列化列表。

https://dotnetfiddle.net/CCbOFf

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using static Newtonsoft.Json.JsonConvert;

class Ref { public int a {get;set;} public string b {get;set;} public DateTime c {get;set;} }
class DerivedRef : Ref { public bool d {get;set;} public long e {get;set;} }

class Ref2 { public int a {get;set;} public string b {get;set;} public DateTime c {get;set;} }
class DerivedRef2 : Ref2 { public bool d {get;set;} public long e {get;set;} }

public class StrictTypeContractResolver<T>: DefaultContractResolver
{
    
    protected override IList<JsonProperty> CreateProperties(Type type, MemberSerialization memberSerialization)
    {
        if(type.IsSubclassOf(typeof(T)))
        {           
            return base.CreateProperties(typeof(T), memberSerialization);
        }
        
        return base.CreateProperties(type, memberSerialization);
    }
    
}

public class Program
{
    public static void Main()
    {       
        var list = new Ref[]{
            new Ref{a=1,b="2",c=DateTime.Now}
            ,new DerivedRef{a=1,b="2",c=DateTime.Now,d=true,e=999}
        };

        Console.WriteLine(PerformSerialization(list));
            
        var list2 = new Ref2[]{
            new Ref2{a=1,b="2",c=DateTime.Now}
            ,new DerivedRef2{a=1,b="2",c=DateTime.Now,d=true,e=999}
        };

        Console.WriteLine(PerformSerialization(list2));
    }
    
    public static string PerformSerialization<T>(IList<T> list)
    {
        var settings = new JsonSerializerSettings { ContractResolver = new StrictTypeContractResolver<T>(), Formatting = Formatting.Indented  };
        return SerializeObject(list, settings);
    }
    
    
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM