I have the following working code that fetches a JSON data from Azure API:
@code {
string responseBody;
protected override async Task OnInitializedAsync()
{
var personalaccesstoken = "*******";
var uri = "https://dev.azure.com/*****";
using (HttpClient client = new HttpClient())
{
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(System.Text.ASCIIEncoding.ASCII.GetBytes(string.Format("{0}:{1}", "", personalaccesstoken))));
HttpResponseMessage response = client.GetAsync(uri).Result;
response.EnsureSuccessStatusCode();
responseBody = await response.Content.ReadAsStringAsync();
System.Diagnostics.Debug.Print(">>> responseBody" responseBody);
}
}
}
I can see the JSON object in the console, so there is no issue with the above code. For reference, this is the a portion of the output I see.
{
"count": 50,
"value": [
{
"_links": {
"self": {
"href": "https://dev.azure.com/****"
}
}
....
}
}
Unfortunately, in C# it is not possible to do foreach on this response so after reading a little I realized I need to make a class for the response object in order to loop through it.
@code {
public class BuildItem
{
public string count { get; set; }
public List<Build> builds { get; set; }
}
public class Build
{
public int id { get; set; }
public string _links { get; set; }
public string tags { get; set; }
public string plans { get; set; }
public string queueTime { get; set; }
}
Next, I added added this line to bottom of the @code{}
block
BuildItem data = JsonConvert.DeserializeObject<BuildItem>(responseBody);
foreach (var res in data.builds)
{
Console.WriteLine($"Id: {res._links}");
}
I am expecting to see each link or at list only the _links
part of the JSON, but instead I get this error:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
MyBuilds.Components.Builds.BuildItem.builds.get returned null.
Thanks for the help
**Update: Full JSON object **
The only ones I need are _links
, id
, buildNumber
and status
{
"count":2,
"value":[
{
"_links":{
"self":{
"href":"****"
},
"web":{
"href":"****"
},
"sourceVersionDisplayUri":{
"href":"****"
},
"timeline":{
"href":"****"
},
"badge":{
"href":"****"
}
},
"properties":{
},
"tags":[
],
"validationResults":[
],
"plans":[
{
"planId":"****"
}
],
"triggerInfo":{
"pr.number":"11244",
"pr.isFork":"False",
"pr.triggerRepository":"****",
"pr.triggerRepository.Type":"TfsGit"
},
"id":106479,
"buildNumber":"****",
"status":"****",
"result":"****",
"queueTime":"****",
"startTime":"****",
"finishTime":"****",
"url":"****",
"definition":{
"drafts":[
],
"id":554,
"name":"****",
"url":"****",
"uri":"****",
"path":"****",
"type":"****",
"queueStatus":"****",
"revision":7,
"project":{
"id":"****",
"name":"****",
"url":"****",
"state":"****",
"revision":****,
"visibility":"****",
"lastUpdateTime":"****"
}
},
"buildNumberRevision":5,
"project":{
"id":"****",
"name":"****",
"url":"****",
"state":"wellFormed",
"revision":749,
"visibility":"private",
"lastUpdateTime":"****"
},
"uri":"****",
"sourceBranch":"****",
"sourceVersion":"****",
"queue":{
"id":313,
"name":"Azure Pipelines",
"pool":{
"id":36,
"name":"Azure Pipelines",
"isHosted":true
}
},
"priority":"normal",
"reason":"pullRequest",
"requestedFor":{
"displayName":"****",
"url":"****",
"_links":{
"avatar":{
"href":"****"
}
},
"id":"****",
"uniqueName":"****",
"imageUrl":"****",
"descriptor":"****"
},
"requestedBy":{
"displayName":"****",
"url":"****",
"_links":{
"avatar":{
"href":"****"
}
},
"id":"****",
"uniqueName":"****",
"imageUrl":"****",
"descriptor":"****"
},
"lastChangedDate":"****",
"lastChangedBy":{
"displayName":"****",
"url":"****",
"_links":{
"avatar":{
"href":"****"
}
},
"id":"****",
"uniqueName":"****",
"imageUrl":"****",
"descriptor":"****"
},
"parameters":"{}",
"orchestrationPlan":{
"planId":"****"
},
"logs":{
"id":0,
"type":"Container",
"url":"****"
},
"repository":{
"id":"****",
"type":"****",
"clean":null,
"checkoutSubmodules":false
},
"keepForever":true,
"retainedByRelease":false,
"triggeredByBuild":null
}
]
}
Thanks a lot
CodePudding user response:
try below:
your JSON string has value
as array/list but your properties' name is builds that you have created try changing the builds
to value
@code {
public class BuildItem
{
public string count { get; set; }
public List<Build> value{ get; set; }
}
public class Build
{
public int Id { get; set; }
public Links _links { get; set; }
public string Tags { get; set; }
public string Plans { get; set; }
public string QueueTime { get; set; }
public string Status { get; set; }
public string BuildNumber{get;set;}
}
also for the _links, so _links is also a object and you have created it string, so you need create a class for the _links as well with the properties in it. then also self
property is also a objec, so you need to create class with property for that as well
class Links {
public SelfModel Self{get;set;}
public WebModel Web{get;set;}
}
class SelfModel{
public string Href{get;set;}
}
class WebModel{
public string Href{get;set;}
}
be careful while creating model for JSON string in C#. C# model will follow the camel case property name.
CodePudding user response:
Instead of
public class BuildItem
{
public string count { get; set; }
public List<Build> value{ get; set; }
}
Try doing
public class BuildItem
{
public string count { get; set; }
public List<Build> value{ get; set; } = New List<Build>();
}
CodePudding user response:
Your models:
public class Self
{
public string href { get; set; }
}
public class Web
{
public string href { get; set; }
}
public class SourceVersionDisplayUri
{
public string href { get; set; }
}
public class Timeline
{
public string href { get; set; }
}
public class Badge
{
public string href { get; set; }
}
public class Links
{
public Self self { get; set; }
public Web web { get; set; }
public SourceVersionDisplayUri sourceVersionDisplayUri { get; set; }
public Timeline timeline { get; set; }
public Badge badge { get; set; }
}
public class Value
{
public Links _links { get; set; }
public int id { get; set; }
public string buildNumber { get; set; }
public string status { get; set; }
}
public class Root
{
public int count { get; set; }
public List<Value> value { get; set; }
}
After requesting:
string responseBody = await response.Content.ReadAsStringAsync();
if(responseBody is {Length: > 0})
{
var result= JsonSerializer.Deserialize<Root>(responseBody);
};
CodePudding user response:
Step one when dealing with Json objects is to make sure you are correctly mapping between your C# object structure and nomenclature and your Json object structure and nomenclature.
Here's your original simpler json and the objects set used to deserialize it put into a test page. One way to figure out your mappings is to make an instance of object and serialize it so you can compare the two. You can see this is the code.
Once you have your C# object you can do whatever iterations you want.
@page "/"
@using System.Text.Json;
@using System.Text.Json.Serialization;
<h2>Test Page</h2>
<code>
Test JSON : @jsonExample
</code>
@code {
private string jsonData = @"
{
""count"": 2,
""value"": [
{
""_links"": {
""self"": {
""href"": ""https://dev.azure.com/****""
}
}
},
{
""_links"": {
""self"": {
""href"": ""https://dev.azure.com/****""
}
}
}
]
}
";
private string jsonExample = string.Empty;
protected override void OnInitialized()
{
var z = new LinkData { href = "http://www.me.com" };
var l = new Link { self = z };
var ls = new LinkValue { _links = l };
var y = new Data() { count = 2 };
y.value.Add(ls);
jsonExample = JsonSerializer.Serialize<Data>(y);
var x = JsonSerializer.Deserialize<Data>(jsonData);
var g = true;
}
public class Data
{
public int count { get; set; }
public List<LinkValue> value { get; set; } = new List<LinkValue>();
}
public class LinkValue
{
public Link _links { get; set; } = new Link();
}
public class Link
{
public LinkData? self { get; set; }
}
public class LinkData
{
public string? href { get; set; }
}
}