i´m in the middle of a project and i just got stuck. My problem is parsing the Json string to my class. This is my Json:
{
"ReturnCode": 0,
"CampaignId": 155087586,
"TotalSMSSent": 1,
"TotalSMSwithError": 0,
"MSISDNwithErrorList": {
}
}
and this is my class
public class RootObject
{
public int ReturnCode { get; set; }
public int CampaignId { get; set; }
public int TotalSMSSent { get; set; }
public int TotalSMSwithError { get; set; }
public List<MSISDNwithErrorList> MSISDNwithErrorList { get; set; }
}
public class MSISDNwithErrorList
{
}
this is my code to get the json string
HttpClient client = new HttpClient();
var response = client.GetAsync("http://evolus.ddns.net/Q4Evolution/php/phpCategoria/BOPesquisaEmp.php").Result;
if (response.IsSuccessStatusCode)
{
string output = JsonConvert.SerializeObject(response.Content.ReadAsStringAsync().Result);
JsonConvert.DeserializeObject<RootObject>(output);
}
And the error is this...
Newtonsoft.Json.JsonSerializationException: Error converting value "{"ReturnCode":0,"CampaignId":155087586,"TotalSMSSent":1,"TotalSMSwithError":0,"MSISDNwithErrorList":{}}" to type 'AppTeste.RootObject'. Path '', line 1, position 115.
MSISDNwithErrorList member seems only object as per the json structure
public class RootObject
{
public int ReturnCode { get; set; }
public int CampaignId { get; set; }
public int TotalSMSSent { get; set; }
public int TotalSMSwithError { get; set; }
//Change from List to Object
public MSISDNwithErrorList MSISDNwithErrorList { get; set; }
}
Rest of Code should be like ...
HttpClient client = new HttpClient();
var response =client.GetAsync("http://evolus.ddns.net/Q4Evolution/php/phpCategoria/BOPesquisa
Emp.php").Result;
if (response.IsSuccessStatusCode)
{
//Here Result already gives you a valid json, you do not need to serialize again
string output =response.Content.ReadAsStringAsync().Result;
//obj is your desired c# object
var obj =JsonConvert.DeserializeObject<RootObject>(output);
}
You can check your working code on https://dotnetfiddle.net/CeXDNA
Related
I am trying to get use the rawg api and get games from their api, i have created the game entity class to parse the data to
//game entity
public class Game
{
public int Id { get; set; }
public string Slug { get; set; }
public string Name { get; set; }
public string Released { get; set; }
public string Background_Image { get; set; }
public int Rating { get; set; }
public int Playtime { get; set; }
}
now i need to get the games from the api, and i made this method
public static async Task<List<Game>> ApiRawgGamesRequest()
{
var gamesList = new List<Game>();
for (int i = 1; i < 250; i++)
{
using (var msg = new HttpRequestMessage(HttpMethod.Get, new Uri($"https://api.rawg.io/api/games?page_size=40&page={i}")))
using (var response = await _client.SendAsync(msg))
{
response.EnsureSuccessStatusCode();
var gamesResponse = await response.Content.ReadAsAsync<Game[]>();
gamesList.AddRange(gamesResponse);
}
}
return gamesList;
}
i am trying not to add all the games at once so i used a for loop to continously add the games into a list to potentially reduce the stress.
but i get an error
// error
Unhandled exception. System.AggregateException: One or more errors occurred. (Cannot deserialize the current JSON object (e.g. {"name":"value"}) into type 'Domain.Game[]' because the t
ype requires a JSON array (e.g. [1,2,3]) to deserialize correctly.
To fix this error either change the JSON to a JSON array (e.g. [1,2,3]) or change the deserialized type so that it is a normal .NET type (e.g. not a primitive type like integer, not a
collection type like an array or List<T>) that can be deserialized from a JSON object. JsonObjectAttribute can also be added to the type to force it to deserialize from a JSON object.
Path 'count', line 1, position 9.)
the response from the rawg api looks like this -- the results part is the game data i am trying to collect
// api response
{
"count": 454988,
"next": "https://api.rawg.io/api/games?page=2&page_size=40",
"previous": null,
"results": [
{
"id": 3498,
"slug": "grand-theft-auto-v",
"name": "Grand Theft Auto V",
"released": "2013-09-17",
"tba": false,
"background_image": "https://media.rawg.io/media/games/84d/84da2ac3fdfc6507807a1808595afb12.jpg",
"rating": 4.48,
},
{
"id": 4200,
"slug": "portal-2",
"name": "Portal 2",
"released": "2011-04-18",
"tba": false,
"background_image": "https://media.rawg.io/media/games/328/3283617cb7d75d67257fc58339188742.jpg",
"rating": 4.62
}
]
}
is there a better way to do this?
Your exception is resulting from a wrong JSON parsed object.
In your code you are calling:
var gamesResponse = await response.Content.ReadAsAsync<Game[]>();
But the response is the object (from your example JSON):
public class GameResponse
{
public int Count { get; set; }
public string Next{ get; set; }
public string Previous { get; set; }
public IEnumerable<Game> Results { get; set; }
}
If you change it to:
var gamesResponse = await response.Content.ReadAsAsync<GameResponse>();
You will be successful in parsing the response and access the games via:
gamesResponse.Results
So, you are trying to deserialize only the "results" part of the json, you have to build a class with all the items from the response json.
// Root myDeserializedClass = JsonConvert.DeserializeObject<Root>(myJsonResponse);
public class Result {
public int id { get; set; }
public string slug { get; set; }
public string name { get; set; }
public string released { get; set; }
public bool tba { get; set; }
public string background_image { get; set; }
public double rating { get; set; }
}
public class Root {
public int count { get; set; }
public string next { get; set; }
public object previous { get; set; }
public List<Result> results { get; set; }
}
You can always use some kind of Json>class generator online, used this for this anwser: https://json2csharp.com/
There are a couple of good answers addressing the issue of not having the correct structure. The only thing I am adding here as a good practice and for better control of your variable names are the annotations. Note, DataContract and DataMember are part of the framework but work well with Json.Net even though Json.Net comes with their own set of annotations.
[DataContract]
public class Payload
{
[DataMember(Name = "count")]
public int Count { get; set; }
[DataMember(Name = "next")]
public string Next { get; set; }
[DataMember(Name = "previous")]
public string Previous { get; set; }
[DataMember(Name = "results")]
public List<GameData> Results { get; set; }
}
[DataContract]
public class GameData
{
[DataMember(Name = "id")]
public long Id { get; set; }
[DataMember(Name = "slug")]
public string Slug { get; set; }
[DataMember(Name = "name")]
public string Name { get; set; }
[DataMember(Name = "rating")]
public float Rating { get; set; }
[DataMember(Name = "rating_top")]
public float Rating_top { get; set; }
}
public static async Task<IEnumerable<Payload>> GetGameDatasAsync(int page = 1, int pageSize = 40, bool followNext = false, CancellationToken cancellationToken = default)
{
cancellationToken.ThrowIfCancellationRequested();
string next = $"https://api.rawg.io/api/games?page_size={pageSize}&page={page}";
var results = new List<Payload>();
using (var client = new HttpClient())
do
{
var result = await client.GetAsync(next, cancellationToken);
next = string.Empty;
if (result.IsSuccessStatusCode)
{
var json = await result.Content.ReadAsStringAsync();
if (!string.IsNullOrWhiteSpace(json))
{
var payload = JsonConvert.DeserializeObject<Payload>(json);
next = payload.Next;
results.Add(payload);
}
}
} while (!string.IsNullOrWhiteSpace(next) && followNext);
return results;
}
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'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);
{"balances-and-info":{"on_hold":[],"available": {"USD":0.93033384},"usd_volume":"243.18","fee_bracket": {"maker":"0.00","taker":"0.60"},"global_usd_volume":"0.09942900"}}
I have this JSON response, and I'm trying to store it in an object, however as you can see "balances-and-info" cannot be used as a variable name. The method I have been using is:
RestClient client = new RestClient("http://currency-api.appspot.com/api/");
RestRequest request = new RestRequest(url);
var response = client.Execute<Currency>(request);
Currency obj = response.Data;
Where obviously the class is a lot easier
public class Currency
{
public string rate { get; set; }
}
So how can I handle this?
String.replace() balances-and-info with balances_and_info
in your code
YourObject deserialized = parseResponse(obj.replace("balances-and-info", "balances_and_info"));
YourObject parseResponse(string response) {
try
{
// https://www.nuget.org/packages/Newtonsoft.Json/
// Json.NET
YourObject ret = JsonConvert.DeserializeObject<YourObject>(response);
return ret;
}
catch (JsonSerializationException)
{
// do something
}
return null;
}
YourObject
Use http://json2csharp.com/ and generate your object (copy response string, replace balances-and-info with balances_and_info and generate)
public class Available
{
public double USD { get; set; }
}
public class FeeBracket
{
public string maker { get; set; }
public string taker { get; set; }
}
public class BalancesAndInfo
{
public List<object> on_hold { get; set; }
public Available available { get; set; }
public string usd_volume { get; set; }
public FeeBracket fee_bracket { get; set; }
public string global_usd_volume { get; set; }
}
public class YourObject
{
public BalancesAndInfo balances_and_info { get; set; }
}
I'm attempting to serialize an object as Json. The error returned by the code below is "An instance of type string cannot be assigned to a variable of type JsonResult". Can someone explain what I've done wrong? I thought serialize() accepts an object and that's what I am passing it.
public class SummaryStats
{
public int rating_number { get; set; }
public string rating_label { get; set; }
public string rating_view { get; set; }
public int max_stars { get; set; }
public int star_1_rating { get; set; }
public int star_2_rating { get; set; }
public int star_3_rating { get; set; }
public int star_4_rating { get; set; }
public int star_5_rating { get; set; }
}
public JsonResult GetSummaryStats()
{
SummaryStats stats = new SummaryStats();
stats.star_1_rating = 1;
stats.star_2_rating = 1;
stats.star_3_rating = 1;
stats.star_4_rating = 11;
stats.star_5_rating = 20;
JavaScriptSerializer json = new JavaScriptSerializer();
JsonResult output = json.Serialize(stats);
return output;
}
Assuming this is within a Controller derivative, just do:
return Json(stats);
The rest is handled for you.
Try Serializing your class :
[Serializable()]
public class SummaryStats
{
...
}