I am trying to loop through some JSON to create some variables using a dictionary.
Here are the definitions that I am using:
public class Customfield10002
{
public string name { get; set; }
}
public class Fields
{
public string summary { get; set; }
public List<Customfield10002> customfield_10002 { get; set; }
}
public class Issue
{
public string id { get; set; }
public string key { get; set; }
public Fields fields { get; set; }
}
public class Root
{
public List<Issue> issues { get; set; }
}
The following code validates fine.
Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(response.Content);
foreach (var issue in myDeserializedClass.issues)
{
string id = issue.id.ToString();
string key = issue.key.ToString();
string summary = issue.fields.summary.ToString();
{
But when I include the following string field, it fails validation
string creatoremail = issue.fields.customfield_10002.name.ToString();
The error is:
'List<ITSDWorklogs.Customfield10002' does not contain a definition for 'name' and no extension method 'name' accepting a first argument of type"
'List<ITSDWorklogs.Customfield10002' could be found (are you missing a using directive or an assembly reference?)
How can I access the value from this nested list?
Any help greatly appreciated.
UPDATED with JSON
{
"expand": "names,schema",
"startAt": 0,
"maxResults": 1,
"total": 151,
"issues": [
{
"expand": "operations,versionedRepresentations,editmeta,changelog,renderedFields",
"id": "10210",
"self": "https://xxxxxxxxxx.atlassian.net/rest/api/3/issue/10210",
"key": "ITSD-202",
"fields": {
"statuscategorychangedate": "2021-01-25T20:12:11.922+0000",
"issuetype": {
"self": "https://xxxxxxxxxx.atlassian.net/rest/api/3/issuetype/10003",
"id": "10003",
"description": "For customer support issues. Created by Jira Service Desk.",
"iconUrl": "https://xxxxxxxxxx.atlassian.net/secure/viewavatar?size=medium&avatarId=10308&avatarType=issuetype",
"name": "Support",
"subtask": false,
"avatarId": 10308
},
"timespent": null,
"customfield_10030": null,
"customfield_10031": {
"id": "1",
"name": "Time to resolution",
"_links": {
"self": "https://xxxxxxxxxx.atlassian.net/rest/servicedeskapi/request/10210/sla/1"
},
"completedCycles": [],
"ongoingCycle": {
"startTime": {
"iso8601": "2021-01-25T20:12:11+0000",
"jira": "2021-01-25T20:12:11.592+0000",
"friendly": "Yesterday 08:12",
"epochMillis": 1611605531592
},
"breachTime": {
"iso8601": "2021-02-11T14:30:00+0000",
"jira": "2021-02-11T14:30:00.000+0000",
"friendly": "11/Feb/21 02:30",
"epochMillis": 1613053800000
},
"breached": false,
"paused": false,
"withinCalendarHours": false,
"goalDuration": {
"millis": 432000000,
"friendly": "120h"
},
"elapsedTime": {
"millis": 0,
"friendly": "0m"
},
"remainingTime": {
"millis": 432000000,
"friendly": "120h"
}
}
},
"project": {
"self": "https://xxxxxxxxxx.atlassian.net/rest/api/3/project/10000",
"id": "10000",
"key": "ITSD",
"name": "Customer Service Desk",
"projectTypeKey": "service_desk",
"simplified": false,
"avatarUrls": {
"48x48": "https://xxxxxxxxxx.atlassian.net/secure/projectavatar?pid=10000&avatarId=10412",
"24x24": "https://xxxxxxxxxx.atlassian.net/secure/projectavatar?size=small&s=small&pid=10000&avatarId=10412",
"16x16": "https://xxxxxxxxxx.atlassian.net/secure/projectavatar?size=xsmall&s=xsmall&pid=10000&avatarId=10412",
"32x32": "https://xxxxxxxxxx.atlassian.net/secure/projectavatar?size=medium&s=medium&pid=10000&avatarId=10412"
}
},
"customfield_10032": {
"id": "2",
"name": "Time to first response",
"_links": {
"self": "https://xxxxxxxxxx.atlassian.net/rest/servicedeskapi/request/10210/sla/2"
},
"completedCycles": [],
"ongoingCycle": {
"startTime": {
"iso8601": "2021-01-25T20:12:11+0000",
"jira": "2021-01-25T20:12:11.592+0000",
"friendly": "Yesterday 08:12",
"epochMillis": 1611605531592
},
"breachTime": {
"iso8601": "2021-01-26T12:30:00+0000",
"jira": "2021-01-26T12:30:00.000+0000",
"friendly": "Today 12:30",
"epochMillis": 1611664200000
},
"breached": false,
"paused": false,
"withinCalendarHours": false,
"goalDuration": {
"millis": 14400000,
"friendly": "4h"
},
"elapsedTime": {
"millis": 0,
"friendly": "0m"
},
"remainingTime": {
"millis": 14400000,
"friendly": "4h"
}
}
},
"fixVersions": [],
"customfield_10034": {
"languageCode": "en",
"displayName": "English"
},
"resolution": null,
"customfield_10037": null,
"customfield_10027": null,
"customfield_10028": null,
"customfield_10029": null,
"resolutiondate": null,
"workratio": -1,
"lastViewed": "2021-01-25T20:12:11.936+0000",
"watches": {
"self": "https://xxxxxxxxxx.atlassian.net/rest/api/3/issue/ITSD-202/watchers",
"watchCount": 1,
"isWatching": true
},
"created": "2021-01-25T20:12:11.592+0000",
"customfield_10020": null,
"customfield_10021": null,
"customfield_10022": null,
"customfield_10023": null,
"priority": {
"self": "https://xxxxxxxxxx.atlassian.net/rest/api/3/priority/3",
"iconUrl": "https://xxxxxxxxxx.atlassian.net/images/icons/priorities/medium.svg",
"name": "Medium",
"id": "3"
},
"customfield_10024": null,
"customfield_10025": null,
"labels": [],
"customfield_10026": [],
"customfield_10016": null,
"customfield_10017": null,
"customfield_10018": {
"hasEpicLinkFieldDependency": false,
"showField": false,
"nonEditableReason": {
"reason": "PLUGIN_LICENSE_ERROR",
"message": "The Parent Link is only available to Jira Premium users."
}
},
"customfield_10019": "0|i0013b:",
"timeestimate": null,
"versions": [],
"assignee": {
"self": "https://xxxxxxxxxx.atlassian.net/rest/api/3/user?accountId=12345678912345678912345",
"accountId": "12345678912345678912345",
"emailAddress": "first.last#xxxxxxxxxx.co.uk",
"avatarUrls": {
"48x48": "https://secure.gravatar.com/avatar/2758e009bbe7f2348bfdf52d653b6a2b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBE-1.png",
"24x24": "https://secure.gravatar.com/avatar/2758e009bbe7f2348bfdf52d653b6a2b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBE-1.png",
"16x16": "https://secure.gravatar.com/avatar/2758e009bbe7f2348bfdf52d653b6a2b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBE-1.png",
"32x32": "https://secure.gravatar.com/avatar/2758e009bbe7f2348bfdf52d653b6a2b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBE-1.png"
},
"displayName": "First Last",
"active": true,
"timeZone": "Europe/London",
"accountType": "atlassian"
},
"updated": "2021-01-25T20:12:14.321+0000",
"status": {
"self": "https://xxxxxxxxxx.atlassian.net/rest/api/3/status/10001",
"description": "This was auto-generated by Jira Service Desk during workflow import",
"iconUrl": "https://xxxxxxxxxx.atlassian.net/images/icons/status_generic.gif",
"name": "Waiting for support",
"id": "10001",
"statusCategory": {
"self": "https://xxxxxxxxxx.atlassian.net/rest/api/3/statuscategory/4",
"id": 4,
"key": "indeterminate",
"colorName": "yellow",
"name": "In Progress"
}
},
"components": [],
"customfield_10050": null,
"customfield_10051": null,
"timeoriginalestimate": null,
"customfield_10052": null,
"customfield_10053": null,
"description": null,
"customfield_10010": null,
"customfield_10014": null,
"customfield_10015": null,
"customfield_10005": null,
"customfield_10049": null,
"customfield_10006": null,
"customfield_10007": null,
"security": null,
"customfield_10008": null,
"customfield_10009": null,
"summary": "Barry Test",
"creator": {
"self": "https://xxxxxxxxxx.atlassian.net/rest/api/3/user?accountId=12345678912345678912345",
"accountId": "12345678912345678912345",
"emailAddress": "first.last#xxxxxxxxxx.co.uk",
"avatarUrls": {
"48x48": "https://secure.gravatar.com/avatar/2758e009bbe7f2348bfdf52d653b6a2b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBE-1.png",
"24x24": "https://secure.gravatar.com/avatar/2758e009bbe7f2348bfdf52d653b6a2b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBE-1.png",
"16x16": "https://secure.gravatar.com/avatar/2758e009bbe7f2348bfdf52d653b6a2b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBE-1.png",
"32x32": "https://secure.gravatar.com/avatar/2758e009bbe7f2348bfdf52d653b6a2b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBE-1.png"
},
"displayName": "First Last",
"active": true,
"timeZone": "Europe/London",
"accountType": "atlassian"
},
"customfield_10040": null,
"customfield_10041": null,
"customfield_10042": null,
"customfield_10043": null,
"reporter": {
"self": "https://xxxxxxxxxx.atlassian.net/rest/api/3/user?accountId=12345678912345678912345",
"accountId": "12345678912345678912345",
"emailAddress": "first.last#xxxxxxxxxx.co.uk",
"avatarUrls": {
"48x48": "https://secure.gravatar.com/avatar/2758e009bbe7f2348bfdf52d653b6a2b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBE-1.png",
"24x24": "https://secure.gravatar.com/avatar/2758e009bbe7f2348bfdf52d653b6a2b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBE-1.png",
"16x16": "https://secure.gravatar.com/avatar/2758e009bbe7f2348bfdf52d653b6a2b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBE-1.png",
"32x32": "https://secure.gravatar.com/avatar/2758e009bbe7f2348bfdf52d653b6a2b?d=https%3A%2F%2Favatar-management--avatars.us-west-2.prod.public.atl-paas.net%2Finitials%2FBE-1.png"
},
"displayName": "First Last",
"active": true,
"timeZone": "Europe/London",
"accountType": "atlassian"
},
"customfield_10044": null,
"customfield_10000": "{}",
"customfield_10001": null,
"customfield_10045": null,
"customfield_10046": null,
"customfield_10002": [
{
"id": "4",
"name": "xxxxxxxxxx.co.uk",
"_links": {
"self": "https://xxxxxxxxxx.atlassian.net/rest/servicedeskapi/organization/4"
}
}
],
"customfield_10003": null,
"customfield_10047": null,
"customfield_10048": null,
"customfield_10004": null,
"customfield_10038": null,
"customfield_10039": null,
"environment": null,
"duedate": null,
"progress": {
"progress": 0,
"total": 0
}
}
}
]
}
you can use LINQ for enumerate over Customfield10002 list:
var createOrEmail = issue.fields.customfield_10002.Select(c=>c.name).DefaultIfEmpty("").Aggregate((s, s1) => $"{s}, {s1}");
This should work as suggested by #gunr2171
string creatoremail = "";
foreach (var names in issue.fields.customfield_10002)
{
creatoremail = names.name.ToString();
}
or by Sajid
string creatoremail = issue.fields.customfield_10002.FirstOrDefault().name.ToString();
Regards
Related
In the json response the property "data" is used as a List and in other places in the Json it is used as a string.. when its used in the List the property has some value when its using as a string the value is coming as null..
How to include both scenario here when I am deserialzing and serializing the json.. without running in to exception A member with the name 'data' already exists. Use the JsonPropertyAttribute to specify another name
public class Example
{
[JsonProperty("data", NullValueHandling = NullValueHandling.Ignore)]
public List<Datum> Data { get; set; }
[JsonProperty("data", NullValueHandling = NullValueHandling.Include)]
public string Data { get; set; }
}
Here is what I tried to use a private property but not able to resolve the issue
[JsonProperty("data", NullValueHandling = NullValueHandling.Ignore)]
public List<Datum> Data { get; set; }
[JsonProperty("data2", NullValueHandling = NullValueHandling.Include)]
private List<Datum> Data2 { set { Data = value; } }
Here is the Json
{
"adRoots": null,
"allowedTagTypes": [
0,
1,
4
],
"canEdit": true,
"filterConfigData": {
"config": [{
"extraData": null,
"id": "Endpoints.ID.SearchInProgress",
"title": "Search in Progress",
"type": 5
},
{
"data": null,
"extraData": null,
"id": "Endpoints.ID.Policies",
"source": {
"definition": "dbo",
"displayColumn": "Name",
"keyColumn": "Id",
"name": "Policies",
"type": 1
},
"title": "Policies",
"type": 3
},
{
"extraData": null,
"id": "Endpoints.ID.MACs",
"title": "MAC Addresses",
"type": 1
},
{
"data": [{
"name": "Endpoint Closed",
"value": 11
},
{
"name": "Endpoint Completed",
"value": 15
},
{
"name": "Endpoint Opened",
"value": 10
}
],
"extraData": null,
"id": "Endpoints.ID.ClientActivityState",
"source": {
"definition": "State",
"displayColumn": "Name",
"keyColumn": "Id",
"name": "ClientActivityState",
"type": 2
},
"title": "Client Activity State",
"type": 3
},
{
"data": [{
"name": "System Alarm",
"value": 3
},
{
"name": "System Audit",
"value": 2
}
],
"extraData": null,
"id": "Endpoints.ID.AceType",
"source": {
"definition": "AceType",
"displayColumn": "Name",
"keyColumn": "Id",
"name": "AceType",
"type": 2
},
"title": "ACL: ACE Type",
"type": 3
},
{
"extraData": null,
"id": "Endpoints.ID.AceWho",
"title": "ACL: Trustee",
"type": 1
},
{
"data": [{
"name": "Append Data",
"value": 4
},
{
"name": "Delete",
"value": 65536
},
{
"name": "Execute",
"value": 32
}
],
"extraData": null,
"id": "Endpoints.ID.AceRights",
"source": {
"definition": "AceRights",
"displayColumn": "Name",
"editor": "ViewModel",
"keyColumn": "Id",
"name": "AceRights",
"type": 2
},
"title": "ACL: Authorization",
"type": 3
},
{
"extraData": null,
"id": "Endpoints.ID.FilterTagName",
"title": "Tag Name",
"type": 1
},
{
"data": null,
"extraData": null,
"id": "Endpoints.ID.FilterTags",
"source": {
"definition": "dbo",
"displayColumn": "Name",
"keyColumn": "Id",
"name": "Tags",
"type": 1
},
"title": "Tags",
"type": 3
},
{
"extraData": null,
"id": "Endpoints.Name.EndpointName",
"title": "Endpoint Name",
"type": 1
},
{
"data": null,
"extraData": null,
"id": "Endpoints.Version.Version",
"title": "Endpoint Version",
"type": 1
},
{
"extraData": null,
"id": "Endpoints.Platform.Platform",
"title": "Endpoint Platform",
"type": 1
},
{
"data": [{
"name": "Desktop",
"value": 1
},
{
"name": "Server",
"value": 2
},
{
"name": "Unknown",
"value": 0
}
],
"extraData": null,
"id": "ELPlatformType",
"source": {
"displayColumn": "Name",
"keyColumn": "Id",
"name": "PlatformType",
"type": 2
},
"title": "Platform Type",
"type": 3
},
{
"extraData": null,
"id": "Endpoints.LastPoll.LastPoll",
"title": "Last Poll Time",
"type": 2
}
],
"pagedListItems": null
},
"forests": null,
"item": {
"disallowed": false,
"editPermissions": 0,
"endpointsCount": 0,
"filter": null,
"id": 404,
"ldapPaths": null,
"name": "tag",
"query": null,
"type": 0
}
}
This question already has an answer here:
Map category parent id self referencing table structure to EF Core entity
(1 answer)
Closed 2 years ago.
I have an issue on cleaning querying my parent child without repeating the children at its own root of the list.
Object
public class Office
{
public int Id { get; set; }
[Required]
public string Name { get; set; }
public bool Inactive { get; set; }
public int? ParentId { get; set; }
[ForeignKey("ParentId")]
public Office Parent { get; set; }
[InverseProperty("Parent")]
public virtual ICollection<Office> Children { get; set; }
}
}
The Query
public async Task<IEnumerable<Office>> GetOffices()
{
return await _context.Offices.Where(os => !os.Inactive)
.Include(o => o.Parent)
.Include(o => o.Children).ToListAsync();
}
And the result
{
"id": 5,
"name": "AA",
"inactive": false,
"parentId": null,
"parent": null,
"children": []
},
{
"id": 10,
"name": "BAA",
"inactive": false,
"parentId": 2,
"parent": {
"id": 2,
"name": "BA",
"inactive": false,
"parentId": null,
"parent": null,
"children": []
},
"children": [
{
"id": 1011,
"name": "BAAA",
"inactive": false,
"parentId": 10,
"children": []
}
]
},
{
"id": 1011,
"name": "BAAA",
"inactive": false,
"parentId": 10,
"parent": {
"id": 10,
"name": "BAA",
"inactive": false,
"parentId": 2,
"parent": {
"id": 2,
"name": "BA",
"inactive": false,
"parentId": null,
"parent": null,
"children": []
},
"children": []
},
"children": []
},
,
{
"id": 2,
"name": "BA",
"inactive": false,
"parentId": null,
"parent": null,
"children": [
{
"id": 10,
"name": "BAA",
"inactive": false,
"parentId": 2,
"children": [
{
"id": 1011,
"name": "BAAA",
"inactive": false,
"parentId": 10,
"children": []
}
]
}
]
}
This also has child objects at the root level so I tried this
public async Task<IEnumerable<Office>> GetOffices()
{
return await _context.Offices.Where(os => !os.Inactive && !os.ParentId.HasValue).Include(o => o.Parent).Include(o => o.Children).ToListAsync();
}
And this is the result of the other query
{
"id": 5,
"name": "AA",
"inactive": false,
"parentId": null,
"parent": null,
"children": []
},
{
"id": 2,
"name": "BA",
"inactive": false,
"parentId": null,
"parent": null,
"children": [
{
"id": 10,
"name": "BAA",
"inactive": false,
"parentId": 2,
"children": null
}
]
}
This leaves out id 1010 BAAA child object. Idealy I would like to have it come out as
{
"id": 5,
"name": "AA",
"inactive": false,
"parentId": null,
"parent": null,
"children": []
},
{
"id": 2,
"name": "BA",
"inactive": false,
"parentId": null,
"parent": null,
"children": [
{
"id": 10,
"name": "BAA",
"inactive": false,
"parentId": 2,
"children": [
{
"id": 1011,
"name": "BAAA",
"inactive": false,
"parentId": 10,
"children": []
}
]
}
]
}
No matter how I stack the query I can't seem to get this to display this way. Is there a way to adjust the query to allow this or an easy post query command to trim only the root level objects that are a child?
If you want limited number of child levels (2 in this example) fetched you can try:
await _context.Offices
.Where(os => !os.Inactive && !os.ParentId.HasValue)
.Include(o => o.Parent)
.Include(o => o.Children)
.ThenInclude(o => o.Children)
.ToListAsync()
So I am trying to return a couple of ListItems from a sharepoint list. I get the content back just fine, but when it Deserializes the content, the calculated column returns a null value. I just do not get it since the value is there in the content.
string geturl = "https://graph.microsoft.com/v1.0/sites/XXXXX.sharepoint.com,495435b4-60c3-49b7-8f6e-1d262a120ae5,0fad9f67-35a8-4c0b-892e-113084058c0a/lists/18a725ac-83ef-48fb-a5cb-950ca2378fd0/items/9?expand=fields(select=SerialNumber,id)";
public async Task<string> GetDataWithTokenAsync(string url, string token, string listitem)
{
var httpClient = new System.Net.Http.HttpClient();
System.Net.Http.HttpResponseMessage response;
try
{
var request = new System.Net.Http.HttpRequestMessage(System.Net.Http.HttpMethod.Get, url);
//Add the token in Authorization header
request.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
response = await httpClient.SendAsync(request);
var content = await response.Content.ReadAsStringAsync();
var result = JsonConvert.DeserializeObject<SharePointListItems.RootObject>(content);
if (listitem == "id")
{
return result.fields.Id;
}
else
{
return result.fields.SerialNumber;
}
}
catch (Exception ex)
{
return ex.ToString();
}
}
Here is the class (shortened):
public class SharePointListItems
{
public class Fields
{
[JsonProperty("#odata.etag")]
public string ODataETag { get; set; }
//General Parameters
...
public string SerialNumber { get; set; } // Calculated field in Sharepoint
public string Id { get; set; }
...
}
public class RootObject
{
[JsonProperty("#odata.context")]
public string ODataContext { get; set; }
[JsonProperty("#odata.etag")]
public string ODataETag { get; set; }
[JsonProperty("fields#odata.context")]
public string FieldsODataContext { get; set; }
public Fields fields { get; set; }
}
}
The content that is returned with my GET is:
"{\"#odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items/$entity\",\"#odata.etag\":\"\\\"a69b1840-239d-42ed-9b20-8789761fb06a,3\\\"\",\"createdDateTime\":\"2018-08-25T22:44:16Z\",\"eTag\":\"\\\"a69b1840-239d-42ed-9b20-8789761fb06a,3\\\"\",\"id\":\"9\",\"lastModifiedDateTime\":\"2018-08-25T22:44:16Z\",\"webUrl\":\"https://XXXXX.sharepoint.com/sites/GeneratorApp/Lists/GenApp/9_.000\",\"createdBy\":{\"user\":{\"email\":\"XXXXX#XXXXX.com\",\"id\":\"b0465821-e891-4f44-9e18-27e875f1b75d\",\"displayName\":\"XXXXX\"}},\"lastModifiedBy\":{\"user\":{\"email\":\"XXXXX#XXXXX.com\",\"id\":\"b0465821-e891-4f44-9e18-27e875f1b75d\",\"displayName\":\"XXXXX\"}},\"parentReference\":{},\"contentType\":{\"id\":\"0x0100E19591A4ECA81542AEA41A6AAFED6781\"},\"fields#odata.context\":\"https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items('9')/fields/$entity\",\"fields\":{\"#odata.etag\":\"\\\"a69b1840-239d-42ed-9b20-8789761fb06a,3\\\"\",\"SerialNumber\":\"20180824-1353-DC6-Generator-A\",\"id\":\"9\"}}"
If I add a line
Jobject json = Jobject.Parse(content);
I get the following response (changed endpoint to get multiple ListItems):
{{
"#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items",
"value": [
{
"#odata.etag": "\"a69b1840-239d-42ed-9b20-8789761fb06a,3\"",
"createdDateTime": "2018-08-25T22:44:16Z",
"eTag": "\"a69b1840-239d-42ed-9b20-8789761fb06a,3\"",
"id": "9",
"lastModifiedDateTime": "2018-08-25T22:44:16Z",
"webUrl": "https://XXXXX.sharepoint.com/sites/GeneratorApp/Lists/GenApp/9_.000",
"createdBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"lastModifiedBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"parentReference": {},
"contentType": {
"id": "0x0100E19591A4ECA81542AEA41A6AAFED6781"
},
"fields#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items('9')/fields/$entity",
"fields": {
"#odata.etag": "\"a69b1840-239d-42ed-9b20-8789761fb06a,3\"",
"SerialNumber": "20180824-1353-DC6-Generator-A",
"id": "9"
}
},
{
"#odata.etag": "\"13f60f9e-1bf2-4803-93b9-c45234963d47,3\"",
"createdDateTime": "2018-08-25T22:45:55Z",
"eTag": "\"13f60f9e-1bf2-4803-93b9-c45234963d47,3\"",
"id": "10",
"lastModifiedDateTime": "2018-08-25T22:45:55Z",
"webUrl": "https://XXXXX.sharepoint.com/sites/GeneratorApp/Lists/GenApp/10_.000",
"createdBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"lastModifiedBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"parentReference": {},
"contentType": {
"id": "0x0100E19591A4ECA81542AEA41A6AAFED6781"
},
"fields#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items('10')/fields/$entity",
"fields": {
"#odata.etag": "\"13f60f9e-1bf2-4803-93b9-c45234963d47,3\"",
"SerialNumber": "20180824-1416-DC6-Generator-B",
"id": "10"
}
},
{
"#odata.etag": "\"00024848-0d4e-4ee8-b018-f1653af2a577,3\"",
"createdDateTime": "2018-08-25T22:47:30Z",
"eTag": "\"00024848-0d4e-4ee8-b018-f1653af2a577,3\"",
"id": "11",
"lastModifiedDateTime": "2018-08-25T22:47:30Z",
"webUrl": "https://XXXXX.sharepoint.com/sites/GeneratorApp/Lists/GenApp/11_.000",
"createdBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"lastModifiedBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"parentReference": {},
"contentType": {
"id": "0x0100E19591A4ECA81542AEA41A6AAFED6781"
},
"fields#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items('11')/fields/$entity",
"fields": {
"#odata.etag": "\"00024848-0d4e-4ee8-b018-f1653af2a577,3\"",
"SerialNumber": "20180824-1438-DC6-Generator-R",
"id": "11"
}
},
{
"#odata.etag": "\"7c8e80ed-6fea-408a-9594-2b7b13e3691b,3\"",
"createdDateTime": "2018-08-25T23:02:43Z",
"eTag": "\"7c8e80ed-6fea-408a-9594-2b7b13e3691b,3\"",
"id": "12",
"lastModifiedDateTime": "2018-08-25T23:02:43Z",
"webUrl": "https://XXXXX.sharepoint.com/sites/GeneratorApp/Lists/GenApp/12_.000",
"createdBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"lastModifiedBy": {
"user": {
"email": "XXXXX#XXXXX.com",
"id": "b0465821-e891-4f44-9e18-27e875f1b75d",
"displayName": "XXXXX"
}
},
"parentReference": {},
"contentType": {
"id": "0x0100E19591A4ECA81542AEA41A6AAFED6781"
},
"fields#odata.context": "https://graph.microsoft.com/v1.0/$metadata#sites('XXXXX.sharepoint.com%2C495435b4-60c3-49b7-8f6e-1d262a120ae5%2C0fad9f67-35a8-4c0b-892e-113084058c0a')/lists('18a725ac-83ef-48fb-a5cb-950ca2378fd0')/items('12')/fields/$entity",
"fields": {
"#odata.etag": "\"7c8e80ed-6fea-408a-9594-2b7b13e3691b,3\"",
"SerialNumber": "20180824-1456-DC6-Generator-C",
"id": "12"
}
}
]
}}
It just seems like I am going round in circles now.
What I want to end up is with a List of id & SerialNumber.
[Code updated to reflect my comment]
Since I really answered the question of the topic the 2nd thing I was asking was a totally separate issue.
So what happened was that I was looking at the wrong data. There happened to also be an 'id' field also in the area I was looking at, so it was showing that 'id' and not the one I was really looking for. When I setup the appropriate entry point, I was able to work down to the appropriate field.
In the Zendesk Developer Blog i found a helpfull Entry(https://developer.zendesk.com/blog/getting-and-creating-tickets-with-.net).
I used the Code from the Article in an C# ConsoleApp for testing:
using System;
using ConsoleApplication1.Properties;
using Newtonsoft.Json.Linq;
using RestSharp;
using RestSharp.Authenticators;
namespace ConsoleApplication1
{
public class Ticket
{
public int id { get; set; }
public string url { get; set; }
public string external_id { get; set; }
public string type { get; set; }
public string subject { get; set; }
public string description { get; set; }
public string priority { get; set; }
public string status { get; set; }
public string recipient { get; set; }
public int requester_id { get; set; }
public int submitter_id { get; set; }
public int assignee_id { get; set; }
public int organization_id { get; set; }
public int group_id { get; set; }
}
internal class Program
{
private static readonly string requestUri = "https://xxx.zendesk.com/";
private static readonly string username = Settings.Default.Username;
private static readonly string password = Settings.Default.Password;
private static void Main(string[] args)
{
var client = new RestClient(requestUri);
client.Authenticator = new HttpBasicAuthenticator(username, password);
var request = new RestRequest("/api/v2/tickets.json", Method.GET);
client.AddDefaultHeader("Accept", "application/json");
var response = client.Execute(request);
var content = response.Content;
var ticket = JObject.Parse(content);
foreach (var pair in ticket)
{
Console.WriteLine("{0}: {1}", pair.Key, pair.Value);
}
}
}
}
It works, and i receive the following Data:
tickets: [
{
"url": "xxx.zendesk.com/api/v2/tickets/1.json",
"id": 1,
"external_id": null,
"via": {
"channel": "sample_ticket",
"source": {
"from": {},
"to": {},
"rel": null
}
},
"created_at": "2015-10-12T12:08:25Z",
"updated_at": "2015-10-12T18:15:13Z",
"type": "incident",
"subject": "Beispielticket: erster Blick auf das Ticket",
"raw_subject": "Beispielticket: erster Blick auf das Ticket",
"description": "Hallo xxx,\n\nE-Mails, Chats, Voicemails und Tweets werden in Zendesk in Form von Tickets erfasst. Geben Sie oben Ihre Antwort
ein und klicken Sie dann auf "Einreichen", um sie zu senden. Um auszuprobieren, wie eine E-Mail zu einem Ticket wird, senden Sie eine Nachricht an sup
port#xxx.zendesk.com.\n",
"priority": "normal",
"status": "open",
"recipient": null,
"requester_id": 1371652071,
"submitter_id": 1371651941,
"assignee_id": null,
"organization_id": null,
"group_id": 24976891,
"collaborator_ids": [],
"forum_topic_id": null,
"problem_id": null,
"has_incidents": false,
"due_at": null,
"tags": [
"zendesk-beispiel"
],
"custom_fields": [
{
"id": 28089621,
"value": null
},
{
"id": 28087191,
"value": null
},
{
"id": 28087201,
"value": null
}
],
"satisfaction_rating": null,
"sharing_agreement_ids": [],
"fields": [
{
"id": 28089621,
"value": null
},
{
"id": 28087191,
"value": null
},
{
"id": 28087201,
"value": null
}
],
"brand_id": 782281
},
{
"url": "xxx.zendesk.com/api/v2/tickets/2.json",
"id": 2,
"external_id": null,
"via": {
"channel": "web",
"source": {
"from": {},
"to": {},
"rel": null
}
},
"created_at": "2015-10-12T20:26:13Z",
"updated_at": "2015-10-12T20:26:13Z",
"type": "question",
"subject": "test",
"raw_subject": "test",
"description": "test 1234",
"priority": "normal",
"status": "open",
"recipient": null,
"requester_id": 1371651941,
"submitter_id": 1371651941,
"assignee_id": 1371651941,
"organization_id": 157600651,
"group_id": 24976891,
"collaborator_ids": [],
"forum_topic_id": null,
"problem_id": null,
"has_incidents": false,
"due_at": null,
"tags": [
"jpa"
],
"custom_fields": [
{
"id": 28089621,
"value": "jpa"
},
{
"id": 28087191,
"value": null
},
{
"id": 28087201,
"value": null
}
],
"satisfaction_rating": null,
"sharing_agreement_ids": [],
"fields": [
{
"id": 28089621,
"value": "jpa"
},
{
"id": 28087191,
"value": null
},
{
"id": 28087201,
"value": null
}
],
"brand_id": 782281
}
]
next_page:
previous_page:
count: 2
But now i did not know how to load the received data in Ticket Objects.
I Need something like that:
foreach(Ticket t in [Received Data])
{
... do something
}
to replace the "Console.WriteLine("{0}: {1}", pair.Key, pair.Value);" part.
These are my first steps in JSON, some how-to or first step link could be helpfull too.
(tried to get hints on http://www.newtonsoft.com/json but without sucess)
Update 1:
After the Comment from dbc (thx, for the very helpful Link) i testet a Little bit more. The variable "content":
var content = response.Content;
contains a Valid JSON string:
{
"tickets": [
{
"url": "https://xxx.zendesk.com/api/v2/tickets/2.json",
"id": 2,
"external_id": null,
"via": {
"channel": "web",
"source": {
"from": {},
"to": {},
"rel": null
}
},
"created_at": "2015-10-12T20:26:13Z",
"updated_at": "2015-10-12T20:26:13Z",
"type": "question",
"subject": "test",
"raw_subject": "test",
"description": "test 1234",
"priority": "normal",
"status": "open",
"recipient": null,
"requester_id": 1371651941,
"submitter_id": 1371651941,
"assignee_id": 1371651941,
"organization_id": 157600651,
"group_id": 24976891,
"collaborator_ids": [],
"forum_topic_id": null,
"problem_id": null,
"has_incidents": false,
"due_at": null,
"tags": [
"jpa"
],
"custom_fields": [
{
"id": 28089621,
"value": "jpa"
},
{
"id": 28087191,
"value": null
},
{
"id": 28087201,
"value": null
}
],
"satisfaction_rating": null,
"sharing_agreement_ids": [],
"fields": [
{
"id": 28089621,
"value": "jpa"
},
{
"id": 28087191,
"value": null
},
{
"id": 28087201,
"value": null
}
],
"brand_id": 782281
},
{
"url": "https://xxx.zendesk.com/api/v2/tickets/3.json",
"id": 3,
"external_id": null,
"via": {
"channel": "web",
"source": {
"from": {},
"to": {},
"rel": null
}
},
"created_at": "2015-10-13T12:22:39Z",
"updated_at": "2015-10-13T12:22:39Z",
"type": null,
"subject": "Test 2",
"raw_subject": "Test 2",
"description": "test content",
"priority": null,
"status": "open",
"recipient": null,
"requester_id": 1371651941,
"submitter_id": 1371651941,
"assignee_id": 1371651941,
"organization_id": 157600651,
"group_id": 24976891,
"collaborator_ids": [],
"forum_topic_id": null,
"problem_id": null,
"has_incidents": false,
"due_at": null,
"tags": [],
"custom_fields": [
{
"id": 28089621,
"value": ""
},
{
"id": 28087191,
"value": null
},
{
"id": 28087201,
"value": null
}
],
"satisfaction_rating": null,
"sharing_agreement_ids": [],
"fields": [
{
"id": 28089621,
"value": ""
},
{
"id": 28087191,
"value": null
},
{
"id": 28087201,
"value": null
}
],
"brand_id": 782281
}
],
"next_page": null,
"previous_page": null,
"count": 2
}
but, only if there is NO double Quotation mark in the description (and i think in other fields too). Seems that Zendesk API does no escaping for the Quotation Marks !?!
But anyway i have valid JSON now, how can i load the JSON string in the Ticket object?
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://92logics.zendesk.com/");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("Authorization", "Bearer your_api_key"); // or your basic authentication
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
string path = "api/v2/tickets.json?page=1";
ZenDeskTickets list = null;
HttpResponseMessage response = await client.GetAsync(path);
if (response.IsSuccessStatusCode)
{
long SkippedId = 1;
string SkippedUrl = "";
list = await response.Content.ReadAsAsync<ZenDeskTickets>();
}
You need to add namespace System.Net.Http to access ReadAsAsync.
It is available as dll and also as web api package files
Here is ZenDeskTickets Calls for you.
public class ZenDeskTickets
{
[JsonProperty("tickets")]
public Ticket[] Tickets { get; set; }
[JsonProperty("next_page")]
public object NextPage { get; set; }
[JsonProperty("previous_page")]
public object PreviousPage { get; set; }
[JsonProperty("count")]
public int Count { get; set; }
}
Same way you can define Ticket Class.
Each property/column will map automatically to right location and data will be filled.
I have a nested json format like given below,I need to read all the nodes till the last node to get the node name, node value, attribute name, parent node. I tried using a recursive function to read data but its not working correctly. Please help with a simple solution to read data. (precisely a dynamic one which can handle any number of nodes and attributes)
Required Output format
name | Value | IsNode | Parent
------------------------------------------------
updated 2014-01-01 false record
position ambassador true record/person
first_name Eliyahu true record/person/names
alias Eli true record/person/names/aliases
country ISRAEL true record/details/countries
category DIPLOMAT false record
Json Input format
{
"Node": "record",
"NodeValue": null,
"ParentNode": "records",
"Nodes": [
{
"Node": "person",
"NodeValue": null,
"ParentNode": "record",
"Nodes": [
{
"Node": "title",
"NodeValue": "Dr",
"ParentNode": "person",
"Nodes": [
],
"Attributes": [
]
},
{
"Node": "position",
"NodeValue": "Ambassador",
"ParentNode": "person",
"Nodes": [
],
"Attributes": [
]
},
{
"Node": "names",
"NodeValue": null,
"ParentNode": "person",
"Nodes": [
{
"Node": "first_name",
"NodeValue": "Eliyahu",
"ParentNode": "names",
"Nodes": [
],
"Attributes": [
]
},
{
"Node": "last_name",
"NodeValue": "BEN TURA",
"ParentNode": "names",
"Nodes": [
],
"Attributes": [
]
},
{
"Node": "aliases",
"NodeValue": null,
"ParentNode": "names",
"Nodes": [
{
"Node": "alias",
"NodeValue": "BEN TURA,Eli",
"ParentNode": "aliases",
"Nodes": [
],
"Attributes": [
]
}
],
"Attributes": [
]
},
{
"Node": "alternative_spelling",
"NodeValue": null,
"ParentNode": "names",
"Nodes": [
],
"Attributes": [
{
"Key": "{http://www.w3.org/2001/XMLSchema-instance}nil",
"Value": "true"
}
]
}
],
"Attributes": [
]
},
{
"Node": "agedata",
"NodeValue": null,
"ParentNode": "person",
"Nodes": [
{
"Node": "age",
"NodeValue": null,
"ParentNode": "agedata",
"Nodes": [
],
"Attributes": [
{
"Key": "{http://www.w3.org/2001/XMLSchema-instance}nil",
"Value": "true"
}
]
},
{
"Node": "as_of_date",
"NodeValue": null,
"ParentNode": "agedata",
"Nodes": [
],
"Attributes": [
{
"Key": "{http://www.w3.org/2001/XMLSchema-instance}nil",
"Value": "true"
}
]
},
{
"Node": "dob",
"NodeValue": null,
"ParentNode": "agedata",
"Nodes": [
],
"Attributes": [
{
"Key": "{http://www.w3.org/2001/XMLSchema-instance}nil",
"Value": "true"
}
]
},
{
"Node": "deceased",
"NodeValue": null,
"ParentNode": "agedata",
"Nodes": [
],
"Attributes": [
{
"Key": "{http://www.w3.org/2001/XMLSchema-instance}nil",
"Value": "true"
}
]
}
],
"Attributes": [
]
}
],
"Attributes": [
{
"Key": "ssn",
"Value": ""
},
{
"Key": "e-i",
"Value": "M"
}
]
},
{
"Node": "details",
"NodeValue": null,
"ParentNode": "record",
"Nodes": [
{
"Node": "passports",
"NodeValue": null,
"ParentNode": "details",
"Nodes": [
{
"Node": "passport",
"NodeValue": null,
"ParentNode": "passports",
"Nodes": [
],
"Attributes": [
{
"Key": "country",
"Value": ""
},
{
"Key": "{http://www.w3.org/2001/XMLSchema-instance}nil",
"Value": "true"
}
]
}
],
"Attributes": [
]
},
{
"Node": "place_of_birth",
"NodeValue": null,
"ParentNode": "details",
"Nodes": [
],
"Attributes": [
{
"Key": "{http://www.w3.org/2001/XMLSchema-instance}nil",
"Value": "true"
}
]
},
{
"Node": "locations",
"NodeValue": null,
"ParentNode": "details",
"Nodes": [
{
"Node": "location",
"NodeValue": null,
"ParentNode": "locations",
"Nodes": [
],
"Attributes": [
{
"Key": "country",
"Value": "SENEGAL"
},
{
"Key": "city",
"Value": "Dakar"
},
{
"Key": "state",
"Value": "Dakar"
},
{
"Key": "{http://www.w3.org/2001/XMLSchema-instance}nil",
"Value": "true"
}
]
}
],
"Attributes": [
]
},
{
"Node": "countries",
"NodeValue": null,
"ParentNode": "details",
"Nodes": [
{
"Node": "country",
"NodeValue": "ISRAEL",
"ParentNode": "countries",
"Nodes": [
],
"Attributes": [
]
}
],
"Attributes": [
]
},
{
"Node": "companies",
"NodeValue": null,
"ParentNode": "details",
"Nodes": [
{
"Node": "company",
"NodeValue": null,
"ParentNode": "companies",
"Nodes": [
],
"Attributes": [
{
"Key": "{http://www.w3.org/2001/XMLSchema-instance}nil",
"Value": "true"
}
]
}
],
"Attributes": [
]
},
{
"Node": "keywords",
"NodeValue": null,
"ParentNode": "details",
"Nodes": [
{
"Node": "keyword",
"NodeValue": null,
"ParentNode": "keywords",
"Nodes": [
],
"Attributes": [
{
"Key": "{http://www.w3.org/2001/XMLSchema-instance}nil",
"Value": "true"
}
]
}
],
"Attributes": [
]
}
],
"Attributes": [
]
}
],
"Attributes": [
{
"Key": "category",
"Value": "DIPLOMAT"
},
{
"Key": "editor",
"Value": ""
},
{
"Key": "entered",
"Value": "2010-11-19"
},
{
"Key": "sub-category",
"Value": "PEP"
},
{
"Key": "uid",
"Value": "1389120"
},
{
"Key": "updated",
"Value": "2014-01-01"
}
]
}
You can use Json.NET to deserialize the JSON into the following class:
public class JsonNodes
{
public string Node { get; set; }
public string NodeValue { get; set; }
public string ParentNode { get; set; }
public List<JsonNodes> Nodes { get; set; }
public List<JsonNodesAttribute> Attributes { get; set; }
}
public class JsonNodesAttribute
{
public string Key { get; set; }
public string Value { get; set; }
}
and you can use this method to print all the values in the required output format using a console application:
private static void PrintValues(JsonNodes nodes, string parent)
{
Console.WriteLine(string.Format("Name: {0}", nodes.Node));
Console.WriteLine(string.Format("Value: {0}", nodes.NodeValue));
Console.WriteLine("IsNode: true");
Console.WriteLine(string.Format("Parent: {0}", parent));
Console.WriteLine();
if (parent == string.Empty)
{
parent += nodes.Node;
}
else
{
parent += string.Format("/{0}", nodes.Node);
}
foreach (JsonNodesAttribute attribute in nodes.Attributes)
{
Console.WriteLine(string.Format("Name: {0}", attribute.Key));
Console.WriteLine(string.Format("Value: {0}", attribute.Value));
Console.WriteLine("IsNode: false");
Console.WriteLine(string.Format("Parent: {0}", parent));
}
Console.WriteLine();
foreach (JsonNodes childNode in nodes.Nodes)
{
PrintValues(childNode, parent);
}
}
Let's say you put the JSON to a string variable named jsonInput, here's how you deserialize and print all of its values:
string jsonInput = ...; // put the above json here
JsonNodes nodes = JsonConvert.DeserializeObject<JsonNodes>(jsonInput);
PrintValues(nodes, string.Empty);
Console.ReadLine();
Use the following method to enumerate your JSON string using Json.NET:
void JsonVisitor(JToken node, int indent = 0)
{
var indentString = new String(' ', indent * 4);
Console.WriteLine("{0}+{1}: {2}", indentString, node["Node"], node["NodeValue"]);
foreach (var attribute in node["Attributes"])
{
Console.WriteLine("{0} {1}: {2}", indentString, attribute["Key"], attribute["Value"]);
}
foreach (var subNode in node["Nodes"])
{
JsonVisitor(subNode, indent + 1);
}
}
You can call it like this (if jsonString is your input):
var jsonObject = JObject.Parse(jsonString);
JsonVisitor(jsonObject.Root);