C# JSON Deserialization JIRA

SSinhg 316 Reputation points
2022-10-08T11:53:23.86+00:00

Hi - Its a related question.
Thanks @Bruce (SqlWork.com) & @Jack J Jun for their earlier help.

I'm using this to generate the response classes to desearlize but not able to loop through.
Is there a way I can desearlise this response so that i can iterate through all the properties?
All my response is null - i think its not serializing

My Json sample

{  
  "expand": "projects",  
  "projects": [  
    {  
      "expand": "issuetypes",  
      "self": "https://someJiraSite.atlassian.net/rest/api/3/project/10006",  
      "id": "10006",  
      "key": "IMDB",  
      "name": "IMDB",  
      "issuetypes": [  
        {  
          "self": "https://someJiraSite.atlassian.net/rest/api/3/issuetype/10035",  
          "id": "10035",  
          "description": "Comedy",  
          "iconUrl": "https://someJiraSite.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10304?size=medium",  
          "name": "Comedy",  
          "untranslatedName": "Comedy",  
          "subtask": false,  
          "expand": "fields",  
          "fields": {  
            "issuetype": {  
              "required": true,  
              "schema": {  
                "type": "issuetype",  
                "system": "issuetype"  
              },  
              "name": "Issue Type",  
              "key": "issuetype",  
              "hasDefaultValue": false,  
              "operations": [],  
              "allowedValues": [  
                {  
                  "self": "https://someJiraSite.atlassian.net/rest/api/3/issuetype/10035",  
                  "id": "10035",  
                  "description": "Non fictional",  
                  "iconUrl": "https://someJiraSite.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10304?size=medium",  
                  "name": "NC (Non fictional)",  
                  "subtask": false,  
                  "avatarId": 10304,  
                  "hierarchyLevel": 0  
                }  
              ]  
            },  
            "customfield_10191": {  
              "required": false,  
              "schema": {  
                "type": "string",  
                "custom": "com.atlassian.jira.plugin.system.customfieldtypes:textarea",  
                "customId": 10191  
              },  
              "name": "Movie Comment",  
              "key": "customfield_10191",  
              "hasDefaultValue": false,  
              "operations": [  
                "set"  
              ]  
            },  
            "customfield_10071": {  
              "required": false,  
              "schema": {  
                "type": "string",  
                "custom": "com.atlassian.jira.plugin.system.customfieldtypes:textfield",  
                "customId": 10071  
              },  
              "name": "Award",  
              "key": "customfield_10071",  
              "hasDefaultValue": false,  
              "operations": [  
                "set"  
              ]  
            },  
            "customfield_10072": {  
              "required": false,  
              "schema": {  
                "type": "option",  
                "custom": "com.atlassian.jira.plugin.system.customfieldtypes:radiobuttons",  
                "customId": 10072  
              },  
              "name": "CoC",  
              "key": "customfield_10072",  
              "hasDefaultValue": true,  
              "operations": [  
                "set"  
              ],  
              "allowedValues": [  
                {  
                  "self": "https://someJiraSite.atlassian.net/rest/api/3/customFieldOption/10115",  
                  "value": "Yes",  
                  "id": "10115"  
                },  
                {  
                  "self": "https://someJiraSite.atlassian.net/rest/api/3/customFieldOption/10116",  
                  "value": "No",  
                  "id": "10116"  
                }  
              ],  
              "defaultValue": {  
                "self": "https://someJiraSite.atlassian.net/rest/api/3/customFieldOption/10116",  
                "value": "No",  
                "id": "10116"  
              }  
            }  
          }  
        },  
        {  
          "self": "https://someJiraSite.atlassian.net/rest/api/3/issuetype/10035",  
          "id": "10035",  
          "description": "Action",  
          "iconUrl": "https://someJiraSite.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10304?size=medium",  
          "name": "Action",  
          "untranslatedName": "Action",  
          "subtask": false,  
          "expand": "fields",  
          "fields": {  
            "issuetype": {  
              "required": true,  
              "schema": {  
                "type": "issuetype",  
                "system": "issuetype"  
              },  
              "name": "Issue Type",  
              "key": "issuetype",  
              "hasDefaultValue": false,  
              "operations": [],  
              "allowedValues": [  
                {  
                  "self": "https://someJiraSite.atlassian.net/rest/api/3/issuetype/10035",  
                  "id": "10035",  
                  "description": "Action",  
                  "iconUrl": "https://someJiraSite.atlassian.net/rest/api/2/universal_avatar/view/type/issuetype/avatar/10304?size=medium",  
                  "name": "Action",  
                  "subtask": false,  
                  "avatarId": 10304,  
                  "hierarchyLevel": 0  
                }  
              ]  
            },  
            "customfield_10191": {  
              "required": false,  
              "schema": {  
                "type": "string",  
                "custom": "com.atlassian.jira.plugin.system.customfieldtypes:textarea",  
                "customId": 10191  
              },  
              "name": "Movie Comment",  
              "key": "customfield_10191",  
              "hasDefaultValue": false,  
              "operations": [  
                "set"  
              ]  
            },  
            "customfield_10071": {  
              "required": false,  
              "schema": {  
                "type": "string",  
                "custom": "com.atlassian.jira.plugin.system.customfieldtypes:textfield",  
                "customId": 10071  
              },  
              "name": "Award",  
              "key": "customfield_10071",  
              "hasDefaultValue": false,  
              "operations": [  
                "set"  
              ]  
            },  
            "customfield_10072": {  
              "required": false,  
              "schema": {  
                "type": "option",  
                "custom": "com.atlassian.jira.plugin.system.customfieldtypes:radiobuttons",  
                "customId": 10072  
              },  
              "name": "CoC",  
              "key": "customfield_10072",  
              "hasDefaultValue": true,  
              "operations": [  
                "set"  
              ],  
              "allowedValues": [  
                {  
                  "self": "https://someJiraSite.atlassian.net/rest/api/3/customFieldOption/10115",  
                  "value": "Yes",  
                  "id": "10115"  
                },  
                {  
                  "self": "https://someJiraSite.atlassian.net/rest/api/3/customFieldOption/10116",  
                  "value": "No",  
                  "id": "10116"  
                }  
              ],  
              "defaultValue": {  
                "self": "https://someJiraSite.atlassian.net/rest/api/3/customFieldOption/10116",  
                "value": "No",  
                "id": "10116"  
              }  
            }  
          }  
        }  
      ]  
    }  
  ]  
}  

Classes that got generated for ref

// Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);  
    public class AllowedValue  
    {  
        public string self { get; set; }  
        public string id { get; set; }  
        public string description { get; set; }  
        public string iconUrl { get; set; }  
        public string name { get; set; }  
        public bool subtask { get; set; }  
        public int avatarId { get; set; }  
        public int hierarchyLevel { get; set; }  
        public string value { get; set; }  
    }  
  
    public class AvatarUrls  
    {  
        public string _48x48 { get; set; }  
        public string _24x24 { get; set; }  
        public string _16x16 { get; set; }  
        public string _32x32 { get; set; }  
    }  
  
    public class Customfield10071  
    {  
        public bool required { get; set; }  
        public Schema schema { get; set; }  
        public string name { get; set; }  
        public string key { get; set; }  
        public bool hasDefaultValue { get; set; }  
        public List<string> operations { get; set; }  
    }  
  
    public class Customfield10072  
    {  
        public bool required { get; set; }  
        public Schema schema { get; set; }  
        public string name { get; set; }  
        public string key { get; set; }  
        public bool hasDefaultValue { get; set; }  
        public List<string> operations { get; set; }  
        public List<AllowedValue> allowedValues { get; set; }  
        public DefaultValue defaultValue { get; set; }  
    }  
  
    public class Customfield10191  
    {  
        public bool required { get; set; }  
        public Schema schema { get; set; }  
        public string name { get; set; }  
        public string key { get; set; }  
        public bool hasDefaultValue { get; set; }  
        public List<string> operations { get; set; }  
    }  
  
    public class DefaultValue  
    {  
        public string self { get; set; }  
        public string value { get; set; }  
        public string id { get; set; }  
    }  
  
    public class Fields  
    {  
        public Issuetype issuetype { get; set; }  
        public Customfield10191 customfield_10191 { get; set; }  
        public Customfield10071 customfield_10071 { get; set; }  
        public Customfield10072 customfield_10072 { get; set; }  
    }  
  
    public class Issuetype  
    {  
        public string self { get; set; }  
        public string id { get; set; }  
        public string description { get; set; }  
        public string iconUrl { get; set; }  
        public string name { get; set; }  
        public string untranslatedName { get; set; }  
        public bool subtask { get; set; }  
        public string expand { get; set; }  
        public Fields fields { get; set; }  
    }  
  
    public class Issuetype2  
    {  
        public bool required { get; set; }  
        public Schema schema { get; set; }  
        public string name { get; set; }  
        public string key { get; set; }  
        public bool hasDefaultValue { get; set; }  
        public List<object> operations { get; set; }  
        public List<AllowedValue> allowedValues { get; set; }  
    }  
  
    public class Project  
    {  
        public string expand { get; set; }  
        public string self { get; set; }  
        public string id { get; set; }  
        public string key { get; set; }  
        public string name { get; set; }  
        public AvatarUrls avatarUrls { get; set; }  
        public List<Issuetype> issuetypes { get; set; }  
    }  
  
    public class Root  
    {  
        public string expand { get; set; }  
        public List<Project> projects { get; set; }  
    }  
  
    public class Schema  
    {  
        public string type { get; set; }  
        public string system { get; set; }  
        public string custom { get; set; }  
        public int customId { get; set; }  
    }  

I tried the previous suggestion but the field list is empty

    public class Issuetype  
    {  
        public string self { get; set; }  
        public string id { get; set; }  
        public string description { get; set; }  
        public string iconUrl { get; set; }  
        public string name { get; set; }  
        public string untranslatedName { get; set; }  
        public bool subtask { get; set; }  
        public string expand { get; set; }  
          
        //public Fields fields { get; set; }  
        public Dictionary<string, Fields> fields { get; set; }  
    }  

My Sample code

       var dynamicjiraFieldResponse = JsonConvert.DeserializeObject<Root>(strJsonResponse, new JsonSerializerSettings  
                    {  
                        MaxDepth = 2000  
                    }  
                        );  
                    if (dynamicjiraFieldResponse!= null)  
                    {                         
                        for (int i = 0; i < dynamicjiraFieldResponse.projects[0].issuetypes.Count; i++)  
                        {  
                            var IssueTypeName = dynamicjiraFieldResponse.projects[0].issuetypes[i].name;  
                            var IssueTypeId = dynamicjiraFieldResponse.projects[0].issuetypes[i].id;  
                            var jrfields = dynamicjiraFieldResponse.projects[0].issuetypes[i].fields;  
  
                            PropertyInfo[] properties = typeof(Fields).GetProperties();  
                            foreach (PropertyInfo property in properties)  
                            {  
                                string jrFieldName = property.Name;  
                                //LookupType lookupType;  
  
                                //Here I want to loop through the response  
                          }  
                   }  
 }  
Developer technologies C#
0 comments No comments
{count} votes

2 answers

Sort by: Most helpful
  1. Bruce (SqlWork.com) 77,686 Reputation points Volunteer Moderator
    2022-10-08T16:33:38.823+00:00

    You issue is fields should be defined as a Dictionary<string,Field> where Fields is the superset of the fields properties.

    The paste as json does not support mapped objects, you need to manually do the conversion.

    1 person found this answer helpful.

  2. AgaveJoe 30,126 Reputation points
    2022-10-08T14:11:35.527+00:00

    The problem you are trying to fix is not clear. The code to deserialize the JSON is very basic.

    static void Main(string[] args)  
    {  
        ProjetModel model = new ProjectModel();  
      
        using (StreamReader r = new StreamReader("data.json"))  
        {  
            string json = r.ReadToEnd();  
            model = JsonSerializer.Deserialize<ProjectModel>(json);  
        }  
      
        foreach(var project in model.projects)  
        {  
            Console.WriteLine($"{project.id}");  
            foreach(var issuetype in project.issuetypes)  
            {  
                Console.WriteLine($"\t{issuetype.id}");  
                Console.WriteLine($"\t{issuetype.name}");  
            }  
                      
        }  
    }  
    

    The results.

    10006  
            10035  
            Comedy  
            10035  
            Action  
    

    I used Visual Studio to generate the classes.

    using System;  
    using System.Collections.Generic;  
    using System.Linq;  
    using System.Text;  
    using System.Threading.Tasks;  
      
    namespace ConsoleAppCS  
    {  
      
        public class ProjectModel  
        {  
            public string expand { get; set; }  
            public Project[] projects { get; set; }  
        }  
      
        public class Project  
        {  
            public string expand { get; set; }  
            public string self { get; set; }  
            public string id { get; set; }  
            public string key { get; set; }  
            public string name { get; set; }  
            public Issuetype[] issuetypes { get; set; }  
        }  
      
        public class Issuetype  
        {  
            public string self { get; set; }  
            public string id { get; set; }  
            public string description { get; set; }  
            public string iconUrl { get; set; }  
            public string name { get; set; }  
            public string untranslatedName { get; set; }  
            public bool subtask { get; set; }  
            public string expand { get; set; }  
            public Fields fields { get; set; }  
        }  
      
        public class Fields  
        {  
            public Issuetype1 issuetype { get; set; }  
            public Customfield_10191 customfield_10191 { get; set; }  
            public Customfield_10071 customfield_10071 { get; set; }  
            public Customfield_10072 customfield_10072 { get; set; }  
        }  
      
        public class Issuetype1  
        {  
            public bool required { get; set; }  
            public Schema schema { get; set; }  
            public string name { get; set; }  
            public string key { get; set; }  
            public bool hasDefaultValue { get; set; }  
            public object[] operations { get; set; }  
            public Allowedvalue[] allowedValues { get; set; }  
        }  
      
        public class Schema  
        {  
            public string type { get; set; }  
            public string system { get; set; }  
        }  
      
        public class Allowedvalue  
        {  
            public string self { get; set; }  
            public string id { get; set; }  
            public string description { get; set; }  
            public string iconUrl { get; set; }  
            public string name { get; set; }  
            public bool subtask { get; set; }  
            public int avatarId { get; set; }  
            public int hierarchyLevel { get; set; }  
        }  
      
        public class Customfield_10191  
        {  
            public bool required { get; set; }  
            public Schema1 schema { get; set; }  
            public string name { get; set; }  
            public string key { get; set; }  
            public bool hasDefaultValue { get; set; }  
            public string[] operations { get; set; }  
        }  
      
        public class Schema1  
        {  
            public string type { get; set; }  
            public string custom { get; set; }  
            public int customId { get; set; }  
        }  
      
        public class Customfield_10071  
        {  
            public bool required { get; set; }  
            public Schema2 schema { get; set; }  
            public string name { get; set; }  
            public string key { get; set; }  
            public bool hasDefaultValue { get; set; }  
            public string[] operations { get; set; }  
        }  
      
        public class Schema2  
        {  
            public string type { get; set; }  
            public string custom { get; set; }  
            public int customId { get; set; }  
        }  
      
        public class Customfield_10072  
        {  
            public bool required { get; set; }  
            public Schema3 schema { get; set; }  
            public string name { get; set; }  
            public string key { get; set; }  
            public bool hasDefaultValue { get; set; }  
            public string[] operations { get; set; }  
            public Allowedvalue1[] allowedValues { get; set; }  
            public Defaultvalue defaultValue { get; set; }  
        }  
      
        public class Schema3  
        {  
            public string type { get; set; }  
            public string custom { get; set; }  
            public int customId { get; set; }  
        }  
      
        public class Defaultvalue  
        {  
            public string self { get; set; }  
            public string value { get; set; }  
            public string id { get; set; }  
        }  
      
        public class Allowedvalue1  
        {  
            public string self { get; set; }  
            public string value { get; set; }  
            public string id { get; set; }  
        }  
      
    }  
    
      
    

    All my response is null - i think its not serializing

    You did not share this code! The example I used above returns a file stream which is no different then reading an HTTP response. If the problem is your REST service is not returning JSON then debug your service.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.