2

how to Deserialize JSON with nested List in C#, my Activities are always null. please help me. Not able to get where I am going wrong. Any help would be really appreciated.

I am trying to deserialize the code, but not getting Activities . My Project is:

using System;
using System.Collections.Generic;
using Newtonsoft.Json;
using System.ComponentModel.DataAnnotations;

public class Program
{
    public static void Main()
    {
        string json = @"
            {
  ""Title"": ""test"",
  ""Id"": ""SR21576"",
  ""CreatedDate"": ""2016-12-10T09:21:06+03:30"",
  ""DisplayName"": ""SR21576 : test"",
  ""Description"": ""10"",
  ""AlternateContactMethod"": null,
  ""AffectedUser"": null,
  ""AssignedToUser"": ""XXX\\BB Team"",
  ""CustomerCode"": ""00000000-0000-0000-0000-000000000000"",
  ""CustomerName"": null,
  ""ContractId"": ""00000000-0000-0000-0000-000000000000"",
  ""ContractTitle"": null,
  ""ContractDetailsId"": ""00000000-0000-0000-0000-000000000000"",
  ""ContractDetailsTitle"": null,
  ""CRMLink"": null,
  ""LeadId"": ""00000000-0000-0000-0000-000000000000"",
  ""LeadTitle"": null,
  ""Urgency"": ""b02d9277-a9fe-86f1-e95e-0ba8cd4fd075"",
  ""Priority"": ""1e070214-693f-4a19-82bb-b88ee6362d98"",
  ""Source"": ""57e11419-ac27-a6fa-97f1-0ec2a9722807"",
  ""Area"": ""3c5e6037-b057-5745-4d89-e95f67d3236b"",
  ""SupportGroup"": ""ae536997-8124-85e7-496e-225b7991a450"",
  ""Attachments"": [ ],
  ""Activities"": [
    {
      ""<Id>k__BackingField"": ""ffe60a69-f3c8-adbe-9bbd-4050d766cc81"",
      ""<ActivityID>k__BackingField"": ""MA21578"",
      ""<Title>k__BackingField"": ""a"",
      ""<Status>k__BackingField"": ""Ready"",
      ""<TypeOfActivity>k__BackingField"": 1
    },
    {
      ""<Id>k__BackingField"": ""91286e74-6a39-964f-040f-5daf99e84792"",
      ""<ActivityID>k__BackingField"": ""RA21579"",
      ""<Title>k__BackingField"": ""b"",
      ""<Status>k__BackingField"": ""Ready"",
      ""<TypeOfActivity>k__BackingField"": 0
    },
    {
      ""<Id>k__BackingField"": ""9754f1a1-d37b-265a-087a-f6688808dbeb"",
      ""<ActivityID>k__BackingField"": ""MA21577"",
      ""<Title>k__BackingField"": ""c"",
      ""<Status>k__BackingField"": ""Active"",
      ""<TypeOfActivity>k__BackingField"": 1
    },
    {
      ""<Id>k__BackingField"": ""d959cac5-cb78-a3fb-09e2-76da1b5381b2"",
      ""<ActivityID>k__BackingField"": ""MA21580"",
      ""<Title>k__BackingField"": ""d"",
      ""<Status>k__BackingField"": ""Ready"",
      ""<TypeOfActivity>k__BackingField"": 1
    }
  ],
  ""Status"": ""InProgress""
}";


        ServiceRequest items = JsonConvert.DeserializeObject<ServiceRequest>(json);

        Console.WriteLine("Area: " + items.Area);
        Console.WriteLine("CRMLink: " + items.CRMLink);

        Console.WriteLine("Number of Activities: " + items.Activities.Count);

        int i = 0;
        //Activities are null why???????
        foreach (var type in items.Activities)
        {
            i++;
            Console.WriteLine("Activities item number " + i);
            Console.WriteLine("ActivityID: " + type.ActivityID);
            Console.WriteLine("Id: " + type.Id);
            Console.WriteLine("Status: " + type.Status);
            Console.WriteLine("Title: " + type.Title);
            Console.WriteLine("TypeOfActivity: " + type.TypeOfActivity);
            Console.WriteLine();
        }
    }
}

[Serializable]
public class Activity
{
    public Guid Id { get; set; }
    public String ActivityID { get; set; }
    public String Title { get; set; }
    public String Status { get; set; }

    public ActivityType TypeOfActivity { get; set; }
}

[Serializable]
public enum ActivityType
{
    ReviewActvity,
    ManualActivity
}

[Serializable]
public class Attachment
{
    [Required]
    public string FileName { get; set; }
    [Required]
    public string ServerFileName { get; set; }
    public bool ToRemove { get; set; }
    [Required]
    public string AttachedByUser { get; set; }

}

[Serializable]
public class ServiceRequest
{
    [Required]
    public string Title { get; set; }
    public String Id { get; set; }
    public DateTime CreatedDate { get; set; }
    public string DisplayName { get; set; }
    [Required]
    public string Description { get; set; }
    public string AlternateContactMethod { get; set; }
    public string AffectedUser { get; set; }
    public string AssignedToUser { get; set; }
    public Guid CustomerCode { get; set; }
    public string CustomerName { get; set; }
    public Guid ContractId { get; set; }
    public string ContractTitle { get; set; }
    public Guid ContractDetailsId { get; set; }
    public string ContractDetailsTitle { get; set; }
    public string CRMLink { get; set; }
    public Guid LeadId { get; set; }
    public string LeadTitle { get; set; }
    public Guid Urgency { get; set; }
    public Guid Priority { get; set; }
    public Guid Source { get; set; }
    public Guid Area { get; set; }
    public Guid SupportGroup { get; set; }
    public List<Attachment> Attachments { get; set; }
    public List<Activity> Activities { get; set; }
    public string Status { get; set; }
}
arioamir
  • 43
  • 5
  • Why is the JSON actually double-quoted? At present, your string is not valid JSON. – Geoff James Dec 10 '16 at 09:11
  • Is it real json: ""k__BackingField"": ""ffe60a69-f3c8-adbe-9bbd-4050d766cc81" ? This "k__BackingField" instead of id is reason, becasue you couldn't deserialize it. – Maksim Simkin Dec 10 '16 at 09:13
  • Does it properly deserialize if you remove the `k__BackingField` marker (e.g. `k__BackingField` to `Id`)? That's being generated by the default context resolver. You may want to set `IgnoreSerializableAttribute = true` otherwise. – OnoSendai Dec 10 '16 at 09:13
  • @dbc - Ah, my bad - didn't notice the `@` prefix, whoops! Thanks. Still, it won't deserialize properly with the `k__BackingField` stuffs. Is this JSON generated by an API? It should just be `"Id" : "..."` – Geoff James Dec 10 '16 at 09:16
  • hi Geoff James, actually my josn isn't double-quoted. this is in c# string and we should use double-quoted. everything is ok but Activity Class return null. – arioamir Dec 10 '16 at 09:19
  • 1
    @GeoffJames that's how the `DataContractJsonSerializer` Class handles auto-implemented properties. (edit) ref: https://conficient.wordpress.com/2014/05/22/getting-rid-of-k__backingfield-in-serialization/ – OnoSendai Dec 10 '16 at 09:19
  • @OnoSendai - That is true, but 1) `ServiceRequest` is also marked with `[Serializable]` but its properties are included in the JSON, not its fields. 2) OP is using Json.NET. – dbc Dec 10 '16 at 09:28
  • @dbc Oh, nice point - didn't noticed the attribute on `ServiceRequest`. – OnoSendai Dec 10 '16 at 09:31

2 Answers2

5

Whoever originally generated the JSON for your Activities collection chose to serialize the fields of the objects. And since the class consists entirely of auto-implemented properties, you're getting the secret backing fields.

To force Json.NET to deserialize the public and private fields of Activity rather than its properties, mark the type with [JsonObject(MemberSerialization.Fields)]:

[Serializable]
[JsonObject(MemberSerialization.Fields)]
public class Activity
{
    public Guid Id { get; set; }
    public String ActivityID { get; set; }
    public String Title { get; set; }
    public String Status { get; set; }

    public ActivityType TypeOfActivity { get; set; }
}

Or, fix the code that originally generated the JSON to serialize the properties in preference to the fields. This seems to have been a conscious choice since the root type ServiceRequest has its properties serialized, not its fields.

Sample fiddle.

dbc
  • 104,963
  • 20
  • 228
  • 340
0

Method 1: remove the [Serializable] attribute from the Activity class.

If not strictly necessary, the removal will prevent the default DataContractJsonSerializer from generating the extra markers.

Method 2: Configure the serializer to ignore the [Serializable] attribute:

config.Formatters.JsonFormatter.SerializerSettings.ContractResolver =
new DefaultContractResolver { IgnoreSerializableAttribute = true };

Reference.

Community
  • 1
  • 1
OnoSendai
  • 3,960
  • 2
  • 22
  • 46