Search code examples
c#jsonjson.net

Deserialize JSON Object to User Defined Type


I have a JSON Object which is like

[
    {
        "attributes": {
            "type": "M2O_ProductOptions__c",
            "url": ""
        },
        "Id": "aAP8A0000004ZkiWAE",
        "ExternalId__c": "123456_ABCDEFG",
        "Product__r": {
            "attributes": {
                "type": "Product2",
                "url": "/services/data/v51.0/sobjects/Product2"
            },
            "ProductCode": "123456"
        },
        "Option__r": {
            "attributes": {
                "type": "Product2",
                "url": "/services/data/v51.0/sobjects/"
            },
            "ProductCode": "23456"
        }
    }
]

And I have classes

public class SF_M20_ProductOptions
{
    public string Id { get; set; }
    public string ExternalId__c { get; set; }
    public Product__r Product__r { get; set; }
    public Option__r Option__r { get; set; }
}

public class Product__r
{
    public string ProductCode { get; set; }
}

public class Option__r
{
    public string ProductCode { get; set; }
}

I am trying to deserialize the JSON string to the type SF_M20_ProductOptions, but I am getting an error.

Unable to convert type string to SF_M20_ProductOptions

Note: "attributes":{} element is not part of the type SF_M20_ProductOptions. Somehow I need to avoid it during deserialization.

I am trying like this


List<SF_M20_ProductOptions> obj = JsonConvert.DeserializeObject<List<SF_M20_ProductOptions>>(doc);

Exact value of doc (doc.toString()) is

"\"[{\\\"attributes\\\":{\\\"type\\\":\\\"M2O_ProductOptions__c\\\",\\\"url\\\":\\\"/services/data/v51.0/sobjects/M2O_ProductOptions__c/aAP8A0000004ZkiWAE\\\"},\\\"Id\\\":\\\"aAP8A0000004ZkiWAE\\\",\\\"ExternalId__c\\\":\\\"722137_NCVB641\\\",\\\"Product__r\\\":{\\\"attributes\\\":{\\\"type\\\":\\\"Product2\\\",\\\"url\\\":\\\"/services/data/v51.0/sobjects/Product2/01t8A000005vdmtQAA\\\"},\\\"ProductCode\\\":\\\"722137\\\"},\\\"Option__r\\\":{\\\"attributes\\\":{\\\"type\\\":\\\"Product2\\\",\\\"url\\\":\\\"/services/data/v51.0/sobjects/Product2/01t8A000004f9FtQAI\\\"},\\\"ProductCode\\\":\\\"NCVB641\\\"}}]\""

Solution

  • your json is a collection, so you have to deseialize it to collection

    using Newtonsoft.Json;
    
    SF_M20_ProductOptions options = JsonConvert
                          .DeserializeObject<List<SF_M20_ProductOptions>>(json)[0];
    

    or

    using System.Text.Json;
    
    SF_M20_ProductOptions options = System.Text.Json.JsonSerializer
                                .Deserialize<List<SF_M20_ProductOptions>>(json)[0];
    

    and fix Option__r property, you can use [JsonProperty] attribute if you want to have different c# property name

    public class SF_M20_ProductOptions
    {
        public string Id { get; set; }
        public string ExternalId__c { get; set; }
        public Product__r Product__r { get; set; }
        
        [JsonProperty("Option__r")]  // using Newtonsoft.Json
        [JsonPropertyName("Option__r")] //using System.Text.Json
        public Option__r OptionR { get; set; }
    }
    

    Update

    your second json was twice serialized, it is better to fix the source, otherwise

    using Newtonsoft.Json;
    
    var json2="\"[{\\\"attributes\\\":{\\\"type\\\":\\\"M2O_ProductOptions__c\\\",\\\"url\\\":\\\"/services/data/v51.0/sobjects/M2O_ProductOptions__c/aAP8A0000004ZkiWAE\\\"},\\\"Id\\\":\\\"aAP8A0000004ZkiWAE\\\",\\\"ExternalId__c\\\":\\\"722137_NCVB641\\\",\\\"Product__r\\\":{\\\"attributes\\\":{\\\"type\\\":\\\"Product2\\\",\\\"url\\\":\\\"/services/data/v51.0/sobjects/Product2/01t8A000005vdmtQAA\\\"},\\\"ProductCode\\\":\\\"722137\\\"},\\\"Option__r\\\":{\\\"attributes\\\":{\\\"type\\\":\\\"Product2\\\",\\\"url\\\":\\\"/services/data/v51.0/sobjects/Product2/01t8A000004f9FtQAI\\\"},\\\"ProductCode\\\":\\\"NCVB641\\\"}}]\"";
    json2 = Regex.Unescape(json2);
    json2 = json2.Substring(1,json2.Length-2);
    
    SF_M20_ProductOptions options = JsonConvert
                          .DeserializeObject<List<SF_M20_ProductOptions>>(json2)[0];