I am new to stack overflow and I am a beginner programmer.
I wanted to make an application that is about League of Legends but I have a problem. I just can't figure out how to deserialize the json into an object.
This is what I've tried
public class LOL
{
public User user { get; set; }
}
public class User
{
public int id { get; set; }
public string name { get; set; }
public int profileIconId { get; set; }
public long revisionDate { get; set; }
public int summonerLevel { get; set; }
}
These are the classes I created using the website http://json2csharp.com/ .
I've just changed the name of these classes to something I like
This is my other class where I call the API
public class LOLFacade
{
private const string APIKey = "secret :D";
public async static Task<LOL> ConnectToRiot(string user)
{
var http = new HttpClient();
string riotURL = String.Format("https://eune.api.pvp.net/api/lol/eune/v1.4/summoner/by-name/{0}?api_key={1}", user, APIKey);
var response = await http.GetAsync(riotURL);
var result = await response.Content.ReadAsStringAsync();
return JsonConvert.DeserializeObject<LOL>(result);
}
}
This is the place I use the API
private async void GetUserInfo_Click(object sender, RoutedEventArgs e)
{
LOL user = await LOLFacade.ConnectToRiot("gigaxel");
string name = user.user.name;
int level = user.user.summonerLevel;
InfoTextBlock.Text = name + " is level " + level;
}
And I always get this error when I execute my code :( :
Object reference not set to an instance of an object.
Here is the Json:
{"gigaxel": {
"id": 36588106,
"name": "Gigaxel",
"profileIconId": 713,
"revisionDate": 1451494377000,
"summonerLevel": 30
}}
Please if anyone can help me I would really appreciate it. I just started and I think that I made a lot of mistakes in this code but if you could help me I would really appreciate it :D
Your LOL model doesn't match with JSON that you received.
Look my answer in this question: Deserialize JSON into Object C#
The correct model is that
public class LOL
{
public Gigaxel gigaxel { get; set; }
}
public class Gigaxel
{
public int id { get; set; }
public string name { get; set; }
public int profileIconId { get; set; }
public long revisionDate { get; set; }
public int summonerLevel { get; set; }
}
try the following class instead of your LOL class
public class LOL
{
public User gigaxel { get; set; }
}
Apart from the issues pointed by the other users, your error is due to the fact that you are trying to deserialize the JSON into an object that you never instantiated. You have to create the object before deserializing:
LOL LOLObj = new LOL { user = new User() };
return JsonConvert.DeserializeObject<LOLObj>(result);
Related
I'm calling an API that returns a standard response structure for all actions. I deserialise the response using Newtonsoft.Json and JsonConvert.DeserializeObject<Response>
public class Response
{
public int Code { get; set; }
public string Message { get; set; }
public object Result { get; set; }
public DateTime ResponseDateTime { get; set; }
}
The Result object changes depending on the request action that has been requested and if there was an error or not (Code + Message describe errors). I know the structure of the Result objects and have created classes for each Result I require.
How do i go about casting the Result object to a typed variable such as a Detail[]? I know i can serialize the Result object and deserialise it again but surely there is a more elegant solution.
public class Detail
{
public int Id { get; set; }
public string DetailOne { get; set; }
public string DetailTwo { get; set; }
}
If you always know what kind of Result you'll get, I'd suggest making Response generic:
public class Response<TResult>
{
public int Code { get; set; }
public string Message { get; set; }
public T Result { get; set; }
public DateTime ResponseDateTime { get; set; }
}
Then you can just deserialize to a Response<Detail[]> and Json.NET should handle everything fine.
This is assuming that if there's an error, you won't end up with a Result that could be problematic. Alternatively, you could still deserialize to a Response class, but with a JToken property type:
public class Response
{
public int Code { get; set; }
public string Message { get; set; }
public JToken Result { get; set; }
public DateTime ResponseDateTime { get; set; }
}
Then use:
Response response = JsonConvert.DeserializeObject<Response>(json);
if (response.Code == 200) // Or whatever
{
Detail[] details = response.Result.ToObject<Detail[]>();
}
You could potentially wrap that into a generic method. I'd at least try the generic response class first though.
If you change your object model to this:
public class Response<T>
{
public int Code { get; set; }
public string Message { get; set; }
public T Result { get; set; }
public DateTime ResponseDateTime { get; set; }
}
public class Detail
{
public int Id { get; set; }
public string DetailOne { get; set; }
public string DetailTwo { get; set; }
}
Then you can do this:
var original = new Response<Detail>()
{
Code = 42,
Message = "OK",
Result = new Detail()
{
Id = 1701,
DetailOne = "Don't",
DetailTwo = "Panic",
},
ResponseDateTime = DateTime.Now,
};
var json = JsonConvert.SerializeObject(original, Newtonsoft.Json.Formatting.Indented);
var response = JsonConvert.DeserializeObject<Response<Newtonsoft.Json.Linq.JToken>>(json);
if (response.Code == 42)
{
Detail detail = response.Result.ToObject<Detail>();
/* Do something with `Detail`. */
}
That seems a fairly nice way to get to the underlying Detail object.
The key technique is to serialize a Response<Detail> and deserialize as a Response<JToken>. Simple.
Of course, if you really wanted to create a Response<Detail> instance you could make a fairly straightforward way of converting from Response<JToken> to Response<Detail> by doing a straight field-to-field mapping.
Here is the Response<Detail[]> version of the code:
var original = new Response<Detail[]>()
{
Code = 42,
Message = "OK",
Result = new Detail[]
{
new Detail()
{
Id = 1701,
DetailOne = "Don't",
DetailTwo = "Panic",
},
new Detail()
{
Id = 360,
DetailOne = "Microsoft",
DetailTwo = "Xbox",
}
},
ResponseDateTime = DateTime.Now,
};
var json = JsonConvert.SerializeObject(original, Newtonsoft.Json.Formatting.Indented);
var response = JsonConvert.DeserializeObject<Response<Newtonsoft.Json.Linq.JToken>>(json);
if (response.Code == 42)
{
Detail[] detail = response.Result.ToObject<Detail[]>();
/* Do something with `Detail[]`. */
}
I am trying to access a simple REST Api, https://api.cryptonator.com/api/ticker/btc-usd
The result of the same is like this format:
{"ticker":{"base":"BTC","target":"USD","price":"9969.76308171","volume":"127575.47420967","change":"-197.36472278"},"timestamp":1517410741,"success":true,"error":""}
Now, when I am trying to get result from it, I find ticker objet of json null, timestamp and error objects are getting filled.
So, I suspect there might be the problem datamembers are not matching with json text. My Modeldto looks like this:
public class CurtoUsd
{
public ticker tick { get; set; }
public Single timestamp { get; set; }
public bool success { get; set; }
public string error { get; set; }
}
public class ticker
{
public string _base { get; set; }
public string target { get; set; }
public string price { get; set; }
public string volume { get; set; }
public string change { get; set; }
}
Please have a look, I was suppose to use base as variable but it is the keyword, so instead i used _base.
And I am using httpclient to in asp.net core 2.0 webapi and the code looks like this:
HttpClient client = new HttpClient();
if (client.BaseAddress == null)
{
client.BaseAddress = new Uri("https://api.cryptonator.com/");
}
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(baseUrl);
CurtoUsd usdrate = new CurtoUsd();
if (response.IsSuccessStatusCode)
{
usdrate = await response.Content.ReadAsJsonAsync<CurtoUsd>();
}
return CommonFunctions.ConvertDouble(usdrate.tick.price);
Detail
of function:
public static class HttpContentExtensions
{
public static async Task<T> ReadAsJsonAsync<T>(this HttpContent content)
{
string json = await content.ReadAsStringAsync();
T value = JsonConvert.DeserializeObject<T>(json);
return value;
}
}
May I know what's wrong I am doing? Is the point I have pointed out correct, is there any solution if it is so.
Please help.
You can use # in C# to use keywords as identifiers, e.g. foo.#base.#class.
So your DTO becomes:
public class Ticker
{
public string #base { get; set; } // Escape the `base` keyword with `#`
public string target { get; set; }
public string price { get; set; }
public string volume { get; set; }
public string change { get; set; }
}
Note that you should use PascalCase for type identifiers n C#/.NET (so class Ticker instead of class ticker), and for public members too.
Note that Newtonsoft.Json is actually case-insensitive for member names by default (unless you specifically configure it otherwise) so you can use PascalCase for the properties, this also stops them from being C# keywords too, and it will still work:
public class Ticker
{
public string Base { get; set; } // `Base` is not a keyword
public string Target { get; set; }
public string Price { get; set; }
public string Volume { get; set; }
public string Change { get; set; }
}
I'm trying to replicate the functionality in one of MoshHamedani's course on Xamarin Forms.
Here's my code (with a valid, working _url, that returns a json object with escape characters):
public partial class PartnersListPage : ContentPage
{
private const string _url = "xyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyzxyz";
private HttpClient _httpClient = new HttpClient();
private ObservableCollection<Partner> _partners;
public PartnersListPage()
{
InitializeComponent();
}
protected override async void OnAppearing()
{
var jsonObject = await _httpClient.GetStringAsync(_url);
var dotNetObject = JsonConvert.DeserializeObject<List<Partner>>(jsonObject);
_partners = new ObservableCollection<Partner>(dotNetObject);
partnersListView.ItemsSource = _partners;
base.OnAppearing();
}
Partner.cs looks like this:
public class Partner
{
//public int Id { get; set; }
//public string Name { get; set; }
public string ImageUrl { get; set; }
public string WebUrl { get; set; }
}
Postman returns the following:
{
"partners": [
{
"imageUrl": "http://www.abcdefgh.xy//media/1007/3.jpg",
"webUrl": "http://www.abcdefgh.xy/"
},
{
"imageUrl": "http://www.ijklmnop.xy//media/1009/5.jpg",
"webUrl": "https://www.ijklmnop.xy/xy"
},
{
"imageUrl": "http://www.qrstuvxy.xy//media/2623/slsp.svg",
"webUrl": "https://www.qrstuvxy.xy/"
}
]
}
When I hit the JsonConvert.DeserializeObject line, I get the following:
An unhandled exception occured. Why is it not working?
You are deserializing with incorrect type (List<Partner>)
I'm using Json to c# converter in order to determine the class I need - just paste in your json text/data and in will generate the classes for you. For the example for your json text/data you need:
public class Partner
{
public string imageUrl { get; set; }
public string webUrl { get; set; }
}
public class RootObject
{
public List<Partner> partners { get; set; }
}
........
var result = JsonConvert.DeserializeObject<RootObject>(jsonObject);
controller returning single object but you are trying to array deserialize
public class Partner
{
//public int Id { get; set; }
//public string Name { get; set; }
public string ImageUrl { get; set; }
public string WebUrl { get; set; }
}
public class ApiResult
{
List<Partner> Partners {get;set;}
}
and..
var dotNetObject = JsonConvert.DeserializeObject<ApiResult>(jsonObject);
I have a web api that returns a complex object that looks like this:
public class CanDeleteRumsaAttributeResponse
{
public CanDeleteRumsaAttributeResponse()
{
}
public CanDeleteRumsaAttributeResponse(int attributeId)
{
RumsaAttributeId = attributeId;
}
public int RumsaAttributeId { get; set; }
public bool AttributeFound { get; set; }
public List<RumsaRoom> AffectedRumsaRooms { get; set; } = new List<RumsaRoom>();
public List<RumsaAttribute> AffectedLinkedRumsaAttributes { get; set; } = new List<RumsaAttribute>();
[JsonIgnore]
public bool CanDelete
{
get
{
return AffectedRumsaRooms.Count == 0&&AttributeFound&&AffectedLinkedRumsaAttributes.Count==0;
}
}
}
When I debug it I can see that the controller return that object and that the list AffectedLinkedRumsaAttributes has several objects in the list
When the client receives the list all but the first object are null.
I've tried returning the object as Ok(CanDeleteRumsaAttributeResponse) and I've tried serializing it like this:
RoomAttributesUtils utils = new RoomAttributesUtils(db);
string json = JsonConvert.SerializeObject(utils.GetCanDeleteColor(id));
var response = this.Request.CreateResponse(HttpStatusCode.OK);
response.Content = new StringContent(json, Encoding.UTF8, "application/json");
return response;
In the second case I can search the json string and find the missing data.
So its being serialized in the second case.
I've checked fiddler to see what is being sent and I can see that something is not right in the json-data.
The missing objects gets values like $ref: "4" and so on, but nothing else.
Here is the json-string I'm afraid I dont know how to format it properly for Stackoverflow, but I think that the information is there as well, but when I look at it using a viewer, its not and it sure doesnt deserialize to the correct objects.
The other list in the object can have any number of objects and they all return fine. Also, other endpoints are returning lists of the same type perfectly fine.
The three objects have unique values on the Code property and they are V30, V31 and V12 (if you want to identify them in the json string).
Any ideas?
Here is the json string
{"RumsaAttributeId":4797,"AttributeFound":true,"AffectedRumsaRooms":[{"$id":"1","RoomName":"STÄD","RoomNumber":"U12102-1150","Building":"U1","PartOfBuilding":"21","Plan":"02","Number":"1150","RoomDescriptions":[],"IsDeleted":false,"PMs":[],"IDNR":"175D_40","Exclude":false,"Department":"VN40 Lokalvård","Comments":"","Area":"23.19","HygeneClass":null,"CeilingHeight":"","UniqueRoomId":"d00e5325-7918-4d01-b273-813a770b46ca-010591d3","SolviegHasOpenedThis":true,"LastSynchedFromRevit":"1900-01-01T00:00:00","LastUpdatedFromRevit":"1900-01-01T00:00:00","Id":25772}],"AffectedLinkedRumsaAttributes":[{"$id":"2","AMACode":"KBC.3211","Malning":"56-03510","AvaliableColors":[{"$id":"3","AvaliableMaterials":[{"$ref":"2"},{"$id":"4","AMACode":"MBE.221","Malning":"-","AvaliableColors":[{"$ref":"3"}],"RoomDescriptions":[],"Code":"V30","ShortDescription":"Kakel, vattenavvisande beklädnad","LongDescription":"-","Comment":"-","PartOfRoom":null,"PartOfRoomId":960,"Id":1438},{"$id":"5","AMACode":"MBE.222","Malning":"-","AvaliableColors":[{"$ref":"3"}],"RoomDescriptions":[],"Code":"V31","ShortDescription":"Kakel, vattentät beklädnad","LongDescription":"-","Comment":"-","PartOfRoom":null,"PartOfRoomId":960,"Id":1439}],"RoomDescriptions":[],"Code":"V31_01","ShortDescription":"Kakel, vattentät beklädnad","LongDescription":"Marazzi SistemC Arch ME83, kulör Bianco(vit)200x200x5 mm. Fog Mapei Ultracolor Plus kulör 111 Silver Grey","Comment":"På 1 fondvägg","PartOfRoom":null,"PartOfRoomId":960,"Id":4797}],"RoomDescriptions":[],"Code":"V12","ShortDescription":"Gipsskivor, hygienklass 2","LongDescription":"Hög standard, hygienklass 2\n","Comment":"-","PartOfRoom":null,"PartOfRoomId":960,"Id":1425},{"$ref":"4"},{"$ref":"5"}]}
I had a similar situation in which I found that due to circular references, the serialization was not completed.
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogForeignKey { get; set; }
[ForeignKey("BlogForeignKey")]
public Blog Blog {get;set;}
}
I just deleted the child to parent relationship and included the foreingkey anotation to the entity set.
public class Blog
{
public int BlogId { get; set; }
public string Url { get; set; }
[ForeignKey("BlogForeignKey")]
public List<Post> Posts { get; set; }
}
public class Post
{
public int PostId { get; set; }
public string Title { get; set; }
public string Content { get; set; }
public int BlogForeignKey { get; set; }
}
Also consider LoopReferenceHandling
I am developing an application in c# that gets the players backpack value on a game called TF2 using Backpack.tf's api.
At the moment the code is:
(MAIN CLASS)
JsonConvert.DeserializeObject<Json1>(json);
(END OF MAIN CLASS)
public class Json1 {
public static List<Json2> response { get; set; }
}
public class Json2
{
public static int success { get; set; }
public static int current_time { get; set; }
public static IEnumerable<Json4> players { get; set; }
}
public class Json4 {
public static int steamid { get; set; }
public static int success { get; set; }
public static double backpack_value { get; set; }
public static string name { get; set; }
}
I've cut out all the other crap out of the main class etc but suffice it to say that yes i've got the json code into the json string ready for deserializing (Tested it with Console.Writeline)
The problem is. Whenever I use things like Json4.name (when writing to console)
it always returns 0.
Sorry if I've made a stupid mistake but I think I've tried things like removing static, changing variable types etc but I still can't get it to work. Please note this is my first attemopt at deserializing Json code and I wrote the classes at bottom myself because some reason http://json2csharp.com/ didn't work. Heres the Json I am trying to deserialize:
{
"response":{
"success":1,
"current_time":1365261392,
"players":{
"0":{
"steamid":"76561198045802942",
"success":1,
"backpack_value":12893.93,
"backpack_update":1365261284,
"name":"Brad Pitt",
"stats_tf_reputation":2257,
"stats_tf_supporter":1,
"notifications":0
},
"1":{
"steamid":"76561197960435530",
"success":1,
"backpack_value":4544.56,
"backpack_update":1365254794,
"name":"Robin",
"notifications":0
}
}
}
}
(formatting messed up a bit. Also please excuse some spelling mistakes :) )
You have several problems with your code:
a) All your fields are static. Remove static; you need them to be instance members.
b) The response property in Json1 should be just a single instance, not a list.
c) Players needs to be a dictionary (or custom type), not an IEnumerable, since it is not an array in the JSON.
d) StreamId has really big numbers that will not fit into an int; change this to long (or string).
public class Json1
{
public Json2 response { get; set; }
}
public class Json2
{
public int success { get; set; }
public int current_time { get; set; }
public IDictionary<int, Json4> players { get; set; }
}
public class Json4
{
public long steamid { get; set; }
public int success { get; set; }
public double backpack_value { get; set; }
public string name { get; set; }
}