Getting an error saying
JsonReaderException: Unexpected character encountered while parsing value: M. Path ', line 0, position 0.
when try to parse JSON response (not entire, but first few items, I changed in the xxxxxx's for anonymity):
{
"total_count": 1091,
"items": [
{
"hap": "retry_limit_reached",
"message": "Retry limit reached. Dropped: [email protected] \u2192 [email protected] 'REMINDER - Pattison Stampede BBQ (Jul 11, 2018)' No MX for crscranessystems.com Server response: 498 No MX for crscranessystems.com",
"type": "error",
"created_at": "Thu, 05 Jul 2018 06:45:48 GMT",
"message_id": "[email protected]"
},
{
"hap": "tempfailed",
"message": "Will retry in 14400 seconds: [email protected] \u2192 [email protected] 'REMINDER - Pattison Stampede BBQ (Jul 11, 2018)' No MX for greexxxxxxxy.org Server response: 498 No MX for grexxxxxxy.org",
"type": "warn",
"created_at": "Thu, 05 Jul 2018 06:45:17 GMT",
"message_id": "[email protected]"
},
{
"hap": "opened",
"message": "Opened: [email protected]",
"type": "info",
"created_at": "Thu, 05 Jul 2018 06:45:15 GMT",
"message_id": "[email protected]"
},
{
"hap": "tempfailed",
"message": "Will retry in 14400 seconds: [email protected] \u2192 [email protected] 'SUBJECT' No MX for step-eps.com Server response: 498 No MX for stxxxxxx.com",
"type": "warn",
"created_at": "Thu, 05 Jul 2018 06:45:14 GMT",
"message_id": "[email protected]"
},
//...
Here is part of my code:
if(response.IsSuccessStatusCode)
{
ViewBag.Msg = "Success";
var stresult = await response.Content.ReadAsStringAsync();
var flogs = JsonConvert.DeserializeObject<List<EmailLog>>(stresult);
logs = flogs.ToList();
}
Here is the emaillog model:
public class EmailLog
{
public string hap { get; set; }
public string message { get; set; }
public string type { get; set; }
public string created_at { get; set; }
public string message_id { get; set; }
}
This is the first time I have ever used RESTful API and JSON, so I might be missing something easy.
EDIT:
This is my full controller code which makes the API request:
HttpClient client = new HttpClient();
client.BaseAddress = new Uri("https://api:[email protected]/v3");
List<EmailLog> logs = new List<EmailLog>();
HttpResponseMessage response = await client.GetAsync("/mg.xxxxx.ca/log");
if (response.IsSuccessStatusCode)
{
// var stresult = await response.Content.ReadAsStringAsync();
// var flogs = JsonConvert.DeserializeObject<List<EmailLog>>(stresult);
// logs = flogs.ToList();
var json = await response.Content.ReadAsStringAsync();
var jObject = JObject.Parse(json);
if (jObject.ContainsKey("items"))
{
ViewBag.Msg = "Success";
logs = jObject["items"].ToObject<List<EmailLog>>();
}
//var logs = JsonConvert.DeserializeObject<ApiResponse>(json);
}
else { ViewBag.Msg = "Fail"; }
return View(logs);
2 Answers 2
The problem is trying to get a list of EmailLog objects directly because they are enclosed within the "items" element of your json response.
You can solve it by using a wrapper class, for example:
public class ApiResponse
{
[JsonProperty(PropertyName = "total_count")]
public int TotalCount { get; set; }
[JsonProperty(PropertyName = "items")]
public List<EmailLog> Items { get; set; }
}
And then you don't need to use a list to deserialize:
var flogs = JsonConvert.DeserializeObject<ApiResponse>(json);
Comments
Here is an alternative to creating a root object as already explained in another answer
This approach takes advantage of the Linq To JSON provided by the Json.Net, which is being used to deserialize the JSON.
if(response.IsSuccessStatusCode) {
ViewBag.Msg = "Success";
var json = await response.Content.ReadAsStringAsync();
var jObject = JObject.Parse(json);
if (jObject.ContainsKey("items"))
logs = jObject["items"].ToObject<List<EmailLog>>();
}
The JSON is parsed and only the desired key is extracted.
This assumes that value of "total_count" was not needed so only extracts the items value.
If the entire object is wanted then defining a root object and deserializing to that would be the easier approach, as demonstrated in @Isma's answer
UPDATE:
Based on discussion you indicated that the service is currently returning
"Mailgun Magnificent API"
which would match the invalid character exception being thrown trying to parse M, as it is clearly not well formatted JSON.
After reviewing the Mailgun documentation it looks like the URL you are using will only work in a browser and was not meant to be used the HttpClient class.
The documentation explains that the request should be made using BASIC authorization
For example.
var myMailgunDomain = "https://api.mailgun.net/v3/mg.xxxxx.ca/";
var client = new HttpClient() {
BaseAddress = new Uri(myMailgunDomain)
};
var apiKey = "api:key-xxxxxxxxxxxxxxxxxxxxxxxxxxxx";
var parameter = Convert.ToBase64String(Encoding.ASCII.GetBytes(apiKey));
client.DefaultRequestHeaders
.Authorization = new AuthenticationHeaderValue("Basic", parameter);
HttpResponseMessage response = await client.GetAsync("log");
//...
11 Comments
HttpClient and that response is a HttpResponseMessageExplore related questions
See similar questions with these tags.