嵌套列表属性在C#中反序列化时引起问题

时间:2018-11-30 21:59:10

标签: c# json json.net deserialization

我整天都在引用大量帖子,并尝试了各种不同的技术来解决此问题,但无济于事。我的失败可能是缺乏了解的结果,但是我之前从未经历过这种问题,所以陷入了僵局。

将以下JSON作为从WebService请求接收的字符串给出...

{
    "contacts": [{
        "identities": [{
            "vid": 40451,
            "identity": [{
                "value": "bsmith@aol.com",
                "type": "EMAIL",
                "timestamp": 4556668881236,
                "isPrimary": true
            },
            {
                "value": "a2c53333-3333-3333-3333-34bc21723333",
                "type": "LEAD_GUID",
                "timestamp": 4556668881236
            }],
            "linkedVid": []
        }],
        "properties": [{
            "name": "firstname",
            "value": "Bob",
            "sourceVid": []
        },
        {
            "name": "lastmodifieddate",
            "value": "151512112212",
            "sourceVid": []
        },
        {
            "name": "lastname",
            "value": "Smith",
            "sourceVid": []
        }],
        "formSubmissions": [],
        "listMembership": [],
        "vid": 44444,
        "portalId": 4444444,
        "isContact": true,
        "vids": [],
        "imports": [],
        "publicToken": "kshdfkjhsdsdjfjkdhshjksd",
        "canonicalVid": 44444,
        "mergeAudit": [],
        "mergedVids": [],
        "campaigns": [],
        "stateChanges": []
    }, {
        ... 
    }, {
        ... 
    }]
}

当我尝试反序列化联系人列表时...

String jsonString = obj.GetJson();
var response = Newtonsoft.Json.JsonConvert.DeserializeObject<HSContactListResult>(
    jsonString,
    new Newtonsoft.Json.JsonSerializerSettings
    {
        TypeNameHandling = Newtonsoft.Json.TypeNameHandling.All,
        NullValueHandling = Newtonsoft.Json.NullValueHandling.Ignore
    });

我收到错误消息...

Newtonsoft.Json.JsonSerializationException: Cannot deserialize the current JSON array (e.g. [1,2,3]) into type 'HSContactIdentityProfile' because the type requires a JSON object (e.g. {"name":"value"}) to deserialize correctly.
To fix this error either change the JSON to a JSON object (e.g. {"name":"value"}) or change the deserialized type to an array or a type that implements a collection interface (e.g. ICollection, IList) like List<T> that can be deserialized from a JSON array. JsonArrayAttribute can also be added to the type to force it to deserialize from a JSON array.
Path 'contacts[0].identities', line 1, position 28

以下类表示将JSON反序列化为...的类

[Serializable]
[DataContract]
public class HSContactListResult 
{
    [DataMember(Name ="hasMore")]
    public bool HasMore { get; set; }

    [DataMember(Name = "vidOffset")]
    public long Offset { get; set; }


    [DataMember(Name = "contacts")]
    public List<Companies.Models.HSContact> Contacts{ get; set; }


    public Int32 Count { get { return this.Contacts.Count; } }


    public HSContactListResult()
    {
        this.Contacts = new List<Companies.Models.HSContact>().ToList();
    }

}


[Serializable]
[DataContract]
public class HSContact
{
    [DataMember(Name = "vid")]
    public long ContactId { get; set;  }

    [DataMember(Name = "portalId")]
    public long PortalId { get; set; }

    [DataMember(Name = "isContact")]
    public bool IsContact { get; set; }

    [DataMember(Name = "properties")]
    public Companies.Models.HSContactProperties Properties { get; set; }

    [DataMember(Name = "identities")]
    public Companies.Models.HSContactIdentityProfile IdentityProfiles { get; }

    public HSCompany Company { get; set; }

    #region c-tor
    public HSContact()
    {
        this.Properties = new Companies.Models.HSContactProperties();
        this.IdentityProfiles = new Companies.Models.HSContactIdentityProfile();
    }
    #endregion c-tor
}


[Serializable]
[DataContract]
public class HSContactProperties: IHSContactProperties
{
    [DataMember(Name ="firstname")]
    public HSProperty FirstName { get; set; }

    [DataMember(Name = "lastname")]
    public HSProperty LastName { get; set; }

    [DataMember(Name = "company")]
    public HSProperty CompanyName { get; set; }
}


[Serializable]
[DataContract]
public class HSContactIdentityProfile 
{
    [DataMember(Name = "vid")]
    public Int64 ContactID { get; set; }


    [DataMember(Name = "identity")]
    public List<Companies.Models.HSContactIdentity> Identities { get; set; }


    [DataMember(Name = "saved-at-timestamp")]
    public Int64 saved_at_timestamp { get; set; }

    [DataMember(Name = "deleted-changed-timestamp")]
    public Int64 deleted_changed_timestamp { get; set; }


    public HSContactIdentityProfile()
    {
        this.Identities = new List<Companies.Models.HSContactIdentity>().ToList();
    }
}


[Serializable]
[DataContract]
public class HSContactIdentity : IHSContactIdentity
{

    [DataMember(Name = "type")]
    public string Type { get; set; }

    [DataMember(Name = "value")]
    public string Value { get; set; }

    [DataMember(Name = "timestamp")]
    public long Timestamp { get; set; }

    [DataMember(Name = "isPrimary")]
    public bool IsPrimary { get; set; }
}

问题似乎是Newtonsoft想要将HSContactIdentityProfile实例反序列化为一个Array,即使它实际上是一个对象。属性“ Identities”是一个数组,由于似乎已被剔除,因此我假设这会干扰反序列化过程。但是,我不明白为什么它没有将列表反序列化为HSContactIdentityProfile对象的属性。

我尝试了自定义转换器,但可能做错了(第一次使用)。我不确定还有什么尝试。 在尝试实施其他潜在重复帖子中显示的“修复”中的5个或6个之后,我无法解决该问题。

1 个答案:

答案 0 :(得分:-1)

根据错误消息:

go.sum

应为列表或数组:

[DataMember(Name = "identities")]
public Companies.Models.HSContactIdentityProfile IdentityProfiles { get; }

如果原始JSON是,您的原始代码将起作用:

[DataMember(Name = "identities")] public List<Companies.Models.HSContactIdentityProfile> IdentityProfiles { get; }

但是可惜的是"contacts": { "identities"

(额外的"contacts": [{ "identities"表示涉及JSON数组)