JSON.NET序列化嵌套复杂字典对象

时间:2017-05-16 04:18:17

标签: c# json.net

我有一个多级别的类(vpc / subnet / instance)。他们是一对多的关系。

  • 一个vpc可能有多个子网。
  • 一个子网可以有多个实例

每个对象都是一个独立的类,我使用字典保持子对象。所以字典是Dictionary <string, child object>

子对象可以是不同的类型,但它们都来自相同的基类。我在课堂上使用泛型。

以下是vpc类的代码:

public class CEVpcBase : CECloudVpcBase
{
    [JsonProperty("CESubnetCache")]
    public CESubnetCache CESubnetCache { get; set; }
    public CESnapshotCache CESnapshotCache { get; set; }
    public List<CEVpcGroup> CEVpcGroups { get; set; }
    public BrokerAuthenticationBase BrokerAuthentication;
    protected DynamoDBHelper dynamoDbHelper;

    public CEVpcBase(DynamoDBHelper dynamoDbHelper)
    {
        this.dynamoDbHelper = dynamoDbHelper;
        //we can's init subnet/snapshot cache here because, we need the cloud account
        //the cloud account is not init until the base class init
        this.CEVpcGroups = new List<CEVpcGroup>();
    }
...
}

以下是子对象的代码:

public class CESubnetCache : CECacheBase<CESubnetBase>
{
    [JsonIgnore]
    public CEVpcBase ParentVpc { get; }
    [JsonConstructor]
    public CESubnetCache()
    {

    }
    public CESubnetCache(CEVpcBase vpc, DynamoDBHelper dbHelper) : base(dbHelper)
    {
        this.ParentVpc = vpc;
        this.ec2Client = CloudClientFactory.GetCloudClient(ParentVpc.CloudAccount, CloudClientType.AwsEC2) as AmazonEC2Client;
        this.CreatedOn = DateTime.Now;
        log.InfoFormat("ParentVpc:{0}**{1} subnet cache created", ParentVpc.ObjectId, ParentVpc.ObjectName);
    }
}

字典在基类中。

[JsonObject(MemberSerialization.OptIn)]
public abstract class CECacheBase<T>
{
    [JsonIgnore]
    protected AmazonEC2Client ec2Client;
    [JsonIgnore]
    protected log4net.ILog log = log4net.LogManager.GetLogger(typeof(CECacheBase<T>));
    protected ConcurrentDictionary<string, T> items = new ConcurrentDictionary<string, T>();
    protected DateTime CreatedOn;
    protected DateTime UpdatedOn;
    public string test = "test";
    public virtual async Task Load() { }
    public virtual async Task Load(object o) { }
    public virtual async Task<ConcurrentDictionary<string, T>> Load(string id, string name) { return null; }
    protected bool isInitialized = false;
    protected object lockObject = new object();
    [JsonIgnore]
    protected DynamoDBHelper dynamoDBhandler;
    [JsonConstructor]
    public CECacheBase()
    {

    }
}

以下是CESubnetBase的代码:

public class CESubnetBase : CECloudSubnetBase
{
    [JsonIgnore]
    public CEVpcBase ParentVpc { get; set; }
    [JsonProperty("CEInstanceCache")]
    public CEInstanceCache CEInstanceCache { get; set; }
    [JsonConstructor]
    public CESubnetBase()
    {

    }
}

我尝试了所有不同类型的json.net属性。但是在序列化的json文件中,CESubnetCache显示为空对象{}。在我的代码中,如上所示,CESubnetCache类有一个items字典。我希望字典会被序列化。

"vpc-68c3090c": {
"BrokerAuthentication": null,
"CESubnetCache": {},
"CESnapshotCache": {},
"CEVpcGroups": [],
"VpcCidr": "10.1.0.0/16",
"InstanceStatic": null,
"StackId": "arn:aws-cn:cloudformation:cn-north-1:663242140710:stack/MYCloud-2017-3-18-10-28-6/93f37bc0-0bc5-11e7-8d6d-50fa18a0d262",
"StackName": "MYCloud-2017-3-18-10-28-6",
"AdNatStatus": null,
"StackStatus": null,
"VpcSummary": {
  "LanSgId": null,
  "DmzSgId": null,
  "GatewayIP": "54.223.239.78",
  "ADInstanceId": "i-0be9a18f05927dea2",
  "VpcType": null,
  "AuthenticationType": "AD",
  "DomainName": "MYCloud.local",
  "IsSoftDeleted": false
},
"VpcMetadata": {
  "CloudAccountId": "AWS-663242140710-CNNorth1",
  "VpcDns": "MYCloud",
  "AdAmiId": null,
  "NatAmiId": null
},

以下是我如何序列化它:

var json = JsonConvert.SerializeObject(input, Formatting.Indented);

如何让Json.Net序列化词典?

1 个答案:

答案 0 :(得分:0)

从你的评论中你说CESubnetCache被序列化为一个空对象,你期望它里面的字典会被序列化。字典未被序列化的原因是因为基类使用了opt-in语义,如其上的[JsonObject(MemberSerialization.OptIn)]属性所示。这意味着除非您使用[JsonProperty]属性标记它们,否则不会序列化该类的任何成员。

尝试将[JsonProperty("Items")]添加到字典成员中,这应解决问题:

[JsonObject(MemberSerialization.OptIn)]
public abstract class CECacheBase<T>
{
    ...
    [JsonProperty("Items")]
    protected ConcurrentDictionary<string, T> items = new ConcurrentDictionary<string, T>();
    ...
}

我还应该提一下,如果您要从类中删除 [JsonObject(MemberSerialization.OptIn)]属性,那么在没有{{1}的情况下,字典仍然将无法序列化在这种情况下属性,因为它是[JsonProperty]而不是protected。 Json.Net默认只序列化公共成员。因此,无论哪种方式,您都需要public属性。

相关问题