Retrieving data from Random User API with C# - c#

I am trying to receive data from the Random User API (https://api.randomuser.me/) with C# (which I am new to). I have a React front end and am able to successfully retrieve and render gender of a person, location of a person. However, I am struggling when it comes to the details that are further nested, such as the first name of a person. My backend code at the moment is:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net.Http;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Newtonsoft.Json;
namespace RandomPersonGenerator.Controllers
{
[Route("api/[controller]")]
public class GeneratorController : Controller
{
[HttpGet("[action]")]
public async Task<IActionResult> Generate()
{
using (var client = new HttpClient())
{
try
{
client.BaseAddress = new Uri("https://api.randomuser.me");
var response = await client.GetAsync("https://api.randomuser.me");
response.EnsureSuccessStatusCode();
var stringResult = await response.Content.ReadAsStringAsync();
var rawData = JsonConvert.DeserializeObject<PersonAPIResponse>(stringResult);
return Ok(new
{
Gender = rawData.Results.Select(x => x.Gender)
});
}
catch (HttpRequestException httpRequestException)
{
return BadRequest($"Error generating person: {httpRequestException.Message}");
}
}
}
}
public class PersonAPIResponse
{
public IEnumerable<PersonDescription> Results { get; set; }
}
public class PersonDescription
{
public string Gender { get; set; }
}
}
I have tried to retrieve the first name of a person by adding:
Name = rawData.Results.Select(x => x.Name) and Name = rawData.Results.Select(x => x.Name.First) but this is not retrieving the data. Is anyone able to help me select the first name from the Random User API JSON?
Thank you!

Your problem is that you need to change this line:
var rawData = JsonConvert.DeserializeObject<PersonAPIResponse>(stringResult);
to
RootObject person = JsonConvert.DeserializeObject<RootObject>(stringResult);
You should create a new return type class and map into that, what you want to return.. assigning from person:
public class PersonAPIResponse
{
//.... your own properties
}
Return
return Ok(new PersonAPIResponse
{
Gender = person.results[0].gender, //first result
});
You also need to include the following classes for deserializing the string:
public class Name
{
public string title { get; set; }
public string first { get; set; }
public string last { get; set; }
}
public class Coordinates
{
public string latitude { get; set; }
public string longitude { get; set; }
}
public class Timezone
{
public string offset { get; set; }
public string description { get; set; }
}
public class Location
{
public string street { get; set; }
public string city { get; set; }
public string state { get; set; }
public int postcode { get; set; }
public Coordinates coordinates { get; set; }
public Timezone timezone { get; set; }
}
public class Login
{
public string uuid { get; set; }
public string username { get; set; }
public string password { get; set; }
public string salt { get; set; }
public string md5 { get; set; }
public string sha1 { get; set; }
public string sha256 { get; set; }
}
public class Dob
{
public DateTime date { get; set; }
public int age { get; set; }
}
public class Registered
{
public DateTime date { get; set; }
public int age { get; set; }
}
public class Id
{
public string name { get; set; }
public object value { get; set; }
}
public class Picture
{
public string large { get; set; }
public string medium { get; set; }
public string thumbnail { get; set; }
}
public class Result
{
public string gender { get; set; }
public Name name { get; set; }
public Location location { get; set; }
public string email { get; set; }
public Login login { get; set; }
public Dob dob { get; set; }
public Registered registered { get; set; }
public string phone { get; set; }
public string cell { get; set; }
public Id id { get; set; }
public Picture picture { get; set; }
public string nat { get; set; }
}
public class Info
{
public string seed { get; set; }
public int results { get; set; }
public int page { get; set; }
public string version { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
public Info info { get; set; }
}

{
public class Name
{
public string Title { get; set; }
public string First { get; set; }
public string Last { get; set; }
}
public class Result
{
public Name Name { get; set; }
}
public class Person
{
public List<Result> Results { get; set; }
}
public async Task<Name> GetPersonAsync()
{
HttpClient client = new HttpClient
{
BaseAddress = new Uri("https://api.randomuser.me")
};
HttpResponseMessage response = await client.GetAsync("https://randomuser.me/api/");
response.EnsureSuccessStatusCode();
var stringResult = await response.Content.ReadAsStringAsync();
Person root = JsonConvert.DeserializeObject<Person>(stringResult);
Console.WriteLine(root.Results[0].Name.Last);
return root.Results[0].Name;
}
}

Related

Convert JSON Request to C# object and send Response back in different JSON format

I am making a call to a webservice and getting following Json Request
{"handler":{"name":"abc"},"intent":{"name":"actions.intent.MAIN","params":{},"query":"Mit Google sprechen"},"scene":{"name":"actions.scene.START_CONVERSATION","slotFillingStatus":"UNSPECIFIED","slots":{},"next":{"name":"Start_Frage"}},"session":{"id":"ABwppHHVumDrliLJaLSikS6KnIlN7yYv6Z4XJCOYzEZt8Fr08RH6r0wtM2-E0v40lS2p1YosTDfpSCd5Lw","params":{},"typeOverrides":[],"languageCode":""},"user":{"locale":"de-DE","params":{},"accountLinkingStatus":"ACCOUNT_LINKING_STATUS_UNSPECIFIED","verificationStatus":"VERIFIED","packageEntitlements":[],"gaiamint":"","permissions":[],"lastSeenTime":"2021-04-01T10:06:59Z"},"home":{"params":{}},"device":{"capabilities":["SPEECH","RICH_RESPONSE","LONG_FORM_AUDIO"]}}
I used https://json2csharp.com/ to convert my Json String to C# Classes
public class Handler
{
public string name { get; set; }
}
public class Params
{
}
public class Intent
{
public string name { get; set; }
public Params #params { get; set; }
public string query { get; set; }
}
public class Slots
{
}
public class Next
{
public string name { get; set; }
}
public class Scene
{
public string name { get; set; }
public string slotFillingStatus { get; set; }
public Slots slots { get; set; }
public Next next { get; set; }
}
public class Session
{
public string id { get; set; }
public Params #params { get; set; }
public List<object> typeOverrides { get; set; }
public string languageCode { get; set; }
}
public class User
{
public string locale { get; set; }
public Params #params { get; set; }
public string accountLinkingStatus { get; set; }
public string verificationStatus { get; set; }
public List<object> packageEntitlements { get; set; }
public string gaiamint { get; set; }
public List<object> permissions { get; set; }
public DateTime lastSeenTime { get; set; }
}
public class Home
{
public Params #params { get; set; }
}
public class Device
{
public List<string> capabilities { get; set; }
}
public class RequestJson
{
public Handler handler { get; set; }
public Intent intent { get; set; }
public Scene scene { get; set; }
public Session session { get; set; }
public User user { get; set; }
public Home home { get; set; }
public Device device { get; set; }
}
I need to send back a JSON Respond that is formatted that way
{"responseJson": {"session": {"id": "ABwppHF4mhTR8RAjnFSt7me_NFR1hRKHY5N6X0kfONIcz_VVPUOmR8VddWVJ3GM3G8ix3OR3O1Ew2wbldc5cRziYebVA","params": {},"languageCode": ""},"prompt": {"override": false,"firstSimple": {"speech": "Stellen Sie eine Frage","text": ""}}}}
https://json2csharp.com/ that results into this object structure
public class Params
{
}
public class Session
{
public string id { get; set; }
public Params #params { get; set; }
public string languageCode { get; set; }
}
public class FirstSimple
{
public string speech { get; set; }
public string text { get; set; }
}
public class Prompt
{
public bool #override { get; set; }
public FirstSimple firstSimple { get; set; }
}
public class ResponseJson
{
public Session session { get; set; }
public Prompt prompt { get; set; }
}
}
My current code looks like this:
I get an nullreferenceexception if i do it that way. I cant set any Values in the RespondJson object. I am new to programming. I would be very grateful for help
[HttpPost]
public async Task<IActionResult> PostWebHook([FromBody] RequestJson request)
{
ResponseJson response = new ResponseJson();
string body;
using (var reader = new StreamReader(Request.Body))
{
body = await reader.ReadToEndAsync();
// => doesnt work that way I get a nullreferenceexception
response.session.id = request.session.id; //nullreferenceexception
response.prompt.#override = false;
response.prompt.firstSimple.speech = "Test123";
//
}
return Ok(response);
}
}
How would i do that?
In short: I receive a request in JSON,but later on I need to send a response back in another JSON format.
The best way it is have two separate models. One pre request and second per response. Ofcourse you can reuse some classes anuse in Both models. In your json you can reuse the session object and then you have to create new class which will be represent prompt object.
Example of your Response object:
public class Params
{
}
public class Session
{
[JsonPropertyName("id")]
public string Id { get; set; }
[JsonPropertyName("params")]
public Params Params { get; set; }
[JsonPropertyName("languageCode")]
public string LanguageCode { get; set; }
}
public class FirstSimple
{
[JsonPropertyName("speech")]
public string Speech { get; set; }
[JsonPropertyName("text")]
public string Text { get; set; }
}
public class Prompt
{
[JsonPropertyName("override")]
public bool Override { get; set; }
[JsonPropertyName("firstSimple")]
public FirstSimple FirstSimple { get; set; }
}
public class ResponseJson
{
[JsonPropertyName("session")]
public Session Session { get; set; }
[JsonPropertyName("prompt")]
public Prompt Prompt { get; set; }
}
public class Response
{
[JsonPropertyName("responseJson")]
public ResponseJson ResponseJson { get; set; }
}

The class the virtual method refers to, returns null ASP.Net Core MVC

I am coming with question.
Why my class returns null value?
As You can see on this picture, class is returning null, but fields inside are not null.
This is Post model where I place virtual method to class Category, and the class is null
Why is that happening?
I checked every reference, and it's all good.
This may be caused by Windows Update or IIS/VisualStudio?
Please help
Post Model
using System;
using System.Collections.Generic;
namespace collector_forum.Data.Models
{
public class Post
{
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public DateTime Created { get; set; }
public virtual ApplicationUser User { get; set; }
public virtual Category Category { get; set; }
public virtual IEnumerable<PostReply> Replies { get; set; }
}
}
Category Model:
using System;
using System.Collections.Generic;
namespace collector_forum.Data.Models
{
public class Category
{
public int Id { get; set; }
public string Title { get; set; }
public string Description { get; set; }
public DateTime Created { get; set; }
public string ImageUrl { get; set; }
public virtual IEnumerable<Post> Posts { get; set; }
}
}
Index and BuildHomeIndex methods from HomeController:
public IActionResult Index()
{
var model = BuildHomeIndexModel();
return View(model);
}
public HomeIndexModel BuildHomeIndexModel()
{
var latestPosts = _postService.GetLatestPosts(10);
var posts = latestPosts.Select(post => new PostListingModel
{
Id = post.Id,
Title = post.Title,
AuthorId = post.User.Id,
AuthorName = post.User.UserName,
AuthorRating = post.User.Rating,
DatePosted = post.Created.ToString(),
RepliesCount = post.Replies.Count(),
Category = GetCategoryListingForPost(post)
});
return new HomeIndexModel
{
LatestPosts = posts,
SearchQuery = ""
};
}
PostListingModel if needed:
using collector_forum.Models.Category;
namespace collector_forum.Models.Post
{
public class PostListingModel
{
public CategoryListingModel Category { get; set; }
public int Id { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public string AuthorName { get; set; }
public int AuthorRating { get; set; }
public string AuthorId { get; set; }
public string DatePosted { get; set; }
public int CategoryId { get; set; }
public string CategoryName { get; set; }
public string CategoryImageUrl { get; set; }
public int RepliesCount { get; set; }
}
}
CategoryListingModel if needed too:
using collector_forum.Models.Post;
using System.Collections.Generic;
namespace collector_forum.Models.Category
{
public class CategoryListingModel
{
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
public string ImageUrl { get; set; }
public int NumberOfPosts { get; set; }
public int NumberOfUsers { get; set; }
public bool HasRecentPost { get; set; }
public PostListingModel Latest { get; set; }
}
}

How to read sections of JSON document?

I have a JSON document and I want to access the details of the STATUS SECTION but it keeps returning null.
JSON Data is as shown:
{
"results":[
{
"messageId":"15712480583306574",
"to":"",
"from":"TestServer",
"sentAt":"2019-10-16T17:47:38.368+0000",
"doneAt":"2019-10-16T17:47:38.370+0000",
"smsCount":1,
"mccMnc":"null",
"price":{
"pricePerMessage":0.0,
"currency":"USD"
},
"status":{
"groupId":5,
"groupName":"REJECTED",
"id":8,
"name":"REJECTED_PREFIX_MISSING",
"description":"Number prefix missing"
},
"error":{
"groupId":0,
"groupName":"OK",
"id":0,
"name":"NO_ERROR",
"description":"No Error",
"permanent":false
}
}
]
}
C# Code is:
string JsonData = response.Content.ToString();
dynamic results = JsonConvert.DeserializeObject<dynamic>(JsonData);
var statuses = results.status;
foreach(var stat in statuses) {
string groupname = stat.groupName.Value;
string name = stat.name.Value;
string description = stat.description.Value;
}
It keeps returning null, How can I access these members? I am using Newtonsoft.
If you want to access the status object property you need to rewrite your whole code.
string JsonData = response.Content.ToString();
var input = JObject.Parse(str);
var results = input["results"].Children();
var status = results.First()["status"];
string groupname = status["groupName"].ToString();
string name = status["name"].ToString();
string description = status["description"].ToString();
Console.WriteLine(groupname);
Console.WriteLine(name);
Console.WriteLine(description);
The result in Console
REJECTED
REJECTED_PREFIX_MISSING
Number prefix missing
But I would rather use concrete class. You need to create multiple classes. Here is good example.
public class Envelope
{
public List<Item> Results { get; set; }
}
public class Item
{
public Status Status { get; set; }
}
public class Status
{
public int GroupId { get; set; }
public string GroupName { get; set; }
public int Id { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}
After that the usage is much simpler.
string JsonData = response.Content.ToString();
MyEnvelope envelope = JsonConvert.DeserializeObject<MyEnvelope>(JsonData);
var status = envelope.results[0].status;
Console.WriteLine(status.GroupName);
Console.WriteLine(status.Name);
Console.WriteLine(status.Description);
Finest Option: Create A model for the JSON.
public class Price
{
public double pricePerMessage { get; set; }
public string currency { get; set; }
}
public class Status
{
public int groupId { get; set; }
public string groupName { get; set; }
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
}
public class Error
{
public int groupId { get; set; }
public string groupName { get; set; }
public int id { get; set; }
public string name { get; set; }
public string description { get; set; }
public bool permanent { get; set; }
}
public class Result
{
public string messageId { get; set; }
public string to { get; set; }
public string from { get; set; }
public DateTime sentAt { get; set; }
public DateTime doneAt { get; set; }
public int smsCount { get; set; }
public string mccMnc { get; set; }
public Price price { get; set; }
public Status status { get; set; }
public Error error { get; set; }
}
public class RootObject
{
public List<Result> results { get; set; }
}
Then do RootObject results = JsonConvert.DeserializeObject<RootObject>(JsonData);
Fair Option: Get the exact JToken you want.
using System;
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using Newtonsoft.Json.Linq;
public class Program
{
public static void Main()
{
string jsonData = "{\"results\":[{\"messageId\":\"15712480583306574\",\"to\":\"\",\"from\":\"TestServer\",\"sentAt\":\"2019-10-16T17:47:38.368+0000\",\"doneAt\":\"2019-10-16T17:47:38.370+0000\",\"smsCount\":1,\"mccMnc\":\"null\",\"price\":{\"pricePerMessage\":0.0,\"currency\":\"USD\"},\"status\":{\"groupId\":5,\"groupName\":\"REJECTED\",\"id\":8,\"name\":\"REJECTED_PREFIX_MISSING\",\"description\":\"Number prefix missing\"},\"error\":{\"groupId\":0,\"groupName\":\"OK\",\"id\":0,\"name\":\"NO_ERROR\",\"description\":\"No Error\",\"permanent\":false}}]}";
JObject jObject = JObject.Parse(jsonData);
Console.WriteLine(jObject.SelectToken("results[0].status"));
}
}

Getting a JsonSerializationException when trying to deserialize PlayerStats

I want to insert into my class data from JSON but I got a Newtonsoft.Json.JsonSerializationException.
My PlayerStats class is good, I think, and I don't know why it's not working.
I can download and print JSON to the console but my code stops working at the point when I try to deserialize. I tried to add settings to deserialize but it's still not working.
Here is my code:
using Newtonsoft.Json;
using Newtonsoft.Json.Serialization;
using System;
using System.Net;
namespace DiscordBot
{
class Osu
{
public string _nickname;
private string _key = "key";
public class PlayerStats
{
[JsonProperty("user_id")]
public int UserId { get; set; }
[JsonProperty("username")]
public string UserName { get; set; }
[JsonProperty("count300")]
public int Count300 { get; set; }
[JsonProperty("count100")]
public int Count100 { get; set; }
[JsonProperty("count50")]
public int Count50 { get; set; }
[JsonProperty("playcount")]
public int PlayCount { get; set; }
[JsonProperty("ranked_score")]
public long RankedScore { get; set; }
[JsonProperty("total_score")]
public long TotalScore { get; set; }
[JsonProperty("pp_rank")]
public int PpRank { get; set; }
[JsonProperty("level")]
public double Level { get; set; }
[JsonProperty("pp_raw")]
public double RawPp { get; set; }
[JsonProperty("accuracy")]
public double Accuracy { get; set; }
[JsonProperty("count_rank_ss")]
public int CountRankSs { get; set; }
[JsonProperty("count_rank_ssh")]
public int CoundRankSsh { get; set; }
[JsonProperty("count_rank_s")]
public int CountRankS { get; set; }
[JsonProperty("count_rank_sh")]
public int CountRankSh { get; set; }
[JsonProperty("count_rank_a")]
public int CountRankA { get; set; }
[JsonProperty("country")]
public string Country { get; set; }
[JsonProperty("pp_country_rank")]
public int PpCountryRank { get; set; }
}
public PlayerStats GetUserStats()
{
string json = string.Empty;
var result = JsonConvert.DeserializeObject<PlayerStats>(json);
try
{
string url = #"https://osu.ppy.sh/api/get_user";
using (WebClient wc = new WebClient())
{
wc.QueryString.Add("k", _key);
wc.QueryString.Add("u", _nickname);
wc.QueryString.Add("m", "0");
json = wc.DownloadString(url);
Console.WriteLine(json);
result = JsonConvert.DeserializeObject<PlayerStats>(json);
return result;
}
}
catch (WebException ex)
{
Console.WriteLine("Osu Error: " + ex.Status);
}
return result;
}
}
}
JSON:
[
{
"user_id":"10415972"
,"username":"iGruby"
,"count300":"851431"
,"count100":"15449 6"
,"count50":"19825"
,"playcount":"7129"
,"ranked_score":"453511877"
,"total_score" :"2735863526"
,"pp_rank":"147461"
,"level":"74.5611"
,"pp_raw":"1642.73"
,"accuracy" :"94.46521759033203"
,"count_rank_ss":"13"
,"count_rank_ssh":"2"
,"count_rank_s":"3 6"
,"count_rank_sh":"13"
,"count_rank_a":"65"
,"country":"PL"
,"pp_country_rank":"77 20"
,"events":[]
}
]
Refer this Tested Answer from the file I have loaded your json and DeserializeObject check my model also and how I am DeserializeObject
namespace ConsoleApplication3
{
class Program
{
static void Main(string[] args)
{
string data = File.ReadAllText("D://readjson.txt");
var obj = JsonConvert.DeserializeObject<List<RootObject>>(data);
}
}
public class RootObject
{
public string user_id { get; set; }
public string username { get; set; }
public string count300 { get; set; }
public string count100 { get; set; }
public string count50 { get; set; }
public string playcount { get; set; }
public string ranked_score { get; set; }
public string total_score { get; set; }
public string pp_rank { get; set; }
public string level { get; set; }
public string pp_raw { get; set; }
public string accuracy { get; set; }
public string count_rank_ss { get; set; }
public string count_rank_ssh { get; set; }
public string count_rank_s { get; set; }
public string count_rank_sh { get; set; }
public string count_rank_a { get; set; }
public string country { get; set; }
public string pp_country_rank { get; set; }
[JsonProperty(NullValueHandling = NullValueHandling.Ignore)]
public List<object> events { get; set; }
}
}
Pp_country_rank and count_rank_s contains a space. This is trying to be parsed to an integer.
"count_rank_s":"3 6"
,"count_rank_sh":"13"
,"count_rank_a":"65"
,"country":"PL"
,"pp_country_rank":"77 20"

JsonConvert.DeserializeObject not working sometimes

I'm trying to Deserialize some json using JsonConver.DeserializeObject. however it's not working on some json from the api I'm using. here is a link that does not work: https://api.pokemontcg.io/v1/cards?setCode=smp
and here is a link that does work. https://api.pokemontcg.io/v1/cards?setCode=sm2
I'm not sure why it sometimes works and sometimes not. The data that comes out of it is very similar to each other, just different cards.
Here is the code:
public static async Task<T> GetDataAsync<T>(this HttpClient client, string address, string querystring)
where T : class
{
var uri = address;
if (!string.IsNullOrEmpty(querystring))
{
uri += querystring;
}
var httpMessage = await client.GetStringAsync(uri);
var jsonObject = JsonConvert.DeserializeObject<T>(httpMessage);
return jsonObject;
}
Now my card class
namespace CardAppReal.Lib.Models
{
public class Card
{
public string id { get; set; }
public string name { get; set; }
public string imageUrl { get; set; }
public string imageUrlHiRes { get; set; }
public string supertype { get; set; } // if pokemon, trainer or energy
public string setcode { get; set; }
public int number { get; set; }
public string set { get; set; }
}
}
With a root
using System.Collections.Generic;
using CardAppReal.Lib.Models;
namespace CardAppReal.Lib.Entities
{
public class RootCard
{
public List<Card> cards { get; set; }
}
}
If u could help me out I would find it amazing.
I have tested your json.
this is the Model
namespace Test
{
public class Attack
{
public List<string> cost { get; set; }
public string name { get; set; }
public string text { get; set; }
public string damage { get; set; }
public int convertedEnergyCost { get; set; }
}
public class Weakness
{
public string type { get; set; }
public string value { get; set; }
}
public class Resistance
{
public string type { get; set; }
public string value { get; set; }
}
public class Ability
{
public string name { get; set; }
public string text { get; set; }
public string type { get; set; }
}
public class Card
{
public string id { get; set; }
public string name { get; set; }
public int nationalPokedexNumber { get; set; }
public string imageUrl { get; set; }
public string imageUrlHiRes { get; set; }
public string subtype { get; set; }
public string supertype { get; set; }
public string hp { get; set; }
public List<string> retreatCost { get; set; }
public string number { get; set; }
public string artist { get; set; }
public string rarity { get; set; }
public string series { get; set; }
public string set { get; set; }
public string setCode { get; set; }
public List<string> types { get; set; }
public List<Attack> attacks { get; set; }
public List<Weakness> weaknesses { get; set; }
public List<Resistance> resistances { get; set; }
public string evolvesFrom { get; set; }
public Ability ability { get; set; }
public List<string> text { get; set; }
}
public class RootObject
{
public List<Card> cards { get; set; }
}
}
And this is how I call the Deserialize
RootObject root = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(RootObject.WRONG_JSON);
(NB WRONG_JSON is your json string...)

Categories

Resources