I am trying to consume API receiving JSON objects. The problem is my API sends these objects nested in square brackets, which makes me deseralize it as a List instead of a single object.
I am declaring this variable as an array of this instance of the class.
SomeModel[] variable = new SomeModel[1];
using (var httpClient = new HttpClient())
{
using (var response = await httpClient.GetAsync("https://someurl.dev.local/getInfo/" + id))
{
if (response.StatusCode == System.Net.HttpStatusCode.OK)
{
string apiResponse = await response.Content.ReadAsStringAsync();
variable = JsonConvert.DeserializeObject<SomeModel[]>(apiResponse);
}
else
ViewBag.StatusCode = response.StatusCode;
}
}
Thiis is a sample of a JSON object I should be receiving, which I tested using Postman:
[
{
"pri_key": "7005210446", //concatenation of this_nbr & that_nbr
"dl_load_date": "2021-11-25T00:00:00Z",
"this_nbr": 7005210,
"that_nbr": 446,
"Passtest": "Eligible"
}
]
...And this is SomeModel class:
namespace ThisSolution.Models
{
public partial class SomeModel
{
public DateTime? DlLoadDate { get; set; }
public int? ThisNbr{ get; set; }
public int? ThatNbr { get; set; }
public string Passtest { get; set; }
public string PriKey { get; set; }
}
}
I am getting is this error:
JsonReaderException: Unexpected character encountered while parsing value: <. Path '', line 0, position 0.
How can I deserialize or is something wrong in my code?
You need to fix your model
public partial class SomeModel
{
[JsonProperty("pri_key")]
public string PriKey { get; set; }
[JsonProperty("dl_load_date")]
public DateTimeOffset DlLoadDate { get; set; }
[JsonProperty("this_nbr")]
public int? ThisNbr { get; set; }
[JsonProperty("that_nbr")]
public int? ThatNbr { get; set; }
[JsonProperty("Passtest")]
public string Passtest { get; set; }
}
Related
I'm trying and failing to write a program that will make an API call and then turn the returned items into objects that fit my model. Specifically I can't make it deserealize, and I suspect it has something to do with how the json is return compared to what my model looks like.
The data I'm trying to get looks like this;
https://api.nasa.gov/planetary/apod?start_date=2022-03-01&end_date=2022-03-08&api_key=DEMO_KEY
As you can see, it consists of an array of items, but there is no name for the array items. When I paste this into the Get-model with Paste JSON as Classes, I get this;
public class GetApodItemsResult
{
public Class1[] Property1 { get; set; }
}
public class Class1
{
public string copyright { get; set; }
public string date { get; set; }
public string explanation { get; set; }
public string hdurl { get; set; }
public string media_type { get; set; }
public string service_version { get; set; }
public string title { get; set; }
public string url { get; set; }
}
My entire code works just fine up until I need to serialize the JSON with this line:
var responseObject = await response.Content.ReadFromJsonAsync<GetApodItemsResult>();
, where I get this message;
System.Text.Json.JsonException: 'The JSON value could not be converted to UnnamedSpaceProject.Models.GetApodItemsResult.
Interestingly I know that the code works on a spotify api call, so the code really should work largely the same, which leads me to believe that the problem is with how the JSON is formatted.
How do I get around that? Because I don't see a way to have the root object contain an unnamed array.
Your GetApodItemsResult class is not a valid class to deserialize the content you get from server, the correct deserialization type will be List<Class1> or Class1[]
var responseObject = await response.Content.ReadFromJsonAsync<List<Class1>>();
I recommend you to use more meaningful name instead of Class1 you can name it Apod (acronym for Astronomy Picture of the Day)
Full working code:
using System.Text.Json;
using System.Text.Json.Serialization;
HttpClient client = new HttpClient();
const string BaseUrl = #"https://api.nasa.gov/";
var response = await client.GetAsync($"{BaseUrl}planetary/apod?start_date=2022-03-01&end_date=2022-03-08&api_key=DEMO_KEY");
if ((response.StatusCode != System.Net.HttpStatusCode.OK))
{
Console.Error.WriteLine("field to fetch data from server");
}
var responseBody = await response.Content.ReadAsStringAsync();
var pictuersList = JsonSerializer.Deserialize<List<Apod>>(responseBody);
Console.WriteLine($"there is {pictuersList?.Count} apod downloaded successflly");
Console.WriteLine("done");
public class Apod
{
[JsonPropertyName("copyright")]
public string Copyright { get; set; } = "";
[JsonPropertyName("date")]
public string Date { get; set; } = "";
[JsonPropertyName("explanation")]
public string Explanation { get; set; } = "";
[JsonPropertyName("hdurl")]
public string Hdurl { get; set; } = "";
[JsonPropertyName("media_type")]
public string MediaType { get; set; } = "";
[JsonPropertyName("service_version")]
public string ServiceVersion { get; set; } = "";
[JsonPropertyName("title")]
public string Title { get; set; } = "";
[JsonPropertyName("url")]
public string Url { get; set; } = "";
}
The object your JSON containing is not some container with the array in it, it IS the array. So, the correct code would be like this:
var responseObject = await response.Content.ReadFromJsonAsync<Class1[]>();
The correct JSON for your code would look like this:
{
"Property1": [{
"copyright": "Jeff DaiTWAN",
"date": "2022-03-01",
"url": "https://apod.nasa.gov/apod/image/2203/DuelingBands_Dai_960.jpg"
}]
}
how to convert list obj to client.PostAsJsonAsync
Class model
public class CheckStatusModel
{
public int OBJID { get; set; }
public string SUPID { get; set; }
public string STATUSPTC { get; set; }
public int DATEACTIVESUP { get; set; }
}
public class CheckStatus
{
public CheckStatusModel Data { get; set; }
public string StatusCode { get; set; }
}
Sending request to find web api REST service resource using
HttpClient**
using (var client = new HttpClient())
{
client.BaseAddress = new Uri(Baseurl);
client.DefaultRequestHeaders.Clear();
client.DefaultRequestHeaders.Accept.Add(new
MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.PostAsJsonAsync("api/RPDeployment/BIL_CFP_BOX_CHECK_STATUSPTC", checkStatusParam);
if(response.IsSuccessStatusCode)
{
var EmpResponse = response.Content.ReadAsStringAsync().Result;
ListStatusPTC = JsonConvert.DeserializeObject<List<CheckStatus>>(EmpResponse);// not convert ????
}
}
EmpResponse
{
"data": [**
{
"OBJID": 1012540462,
"SUPID": 1041252952,
"STATUSPTC": 1,
"DATEACTIVESUP": 0
}
**],
"StatusCode": 200
}
help me please ??
Oh I see. You're trying to deserialize an object (denoted by { and }) into a list (in JSON, denoted by [ and ]).
You need to change your CheckStatus class as follows:
public class CheckStatus
{
public List<CheckStatusModel> Data { get; set; } // data is an array so this needs to be some kind of collection
public string StatusCode { get; set; }
}
And deserialize like so:
ListStatusPTC = JsonConvert.DeserializeObject<CheckStatus>(EmpResponse); // the JSON contains an object, so this needs to deserialize to an object. you can't deserialize to a list.
I am able to handle simple JSON serialization and deserialization but this API response seems little complicated, and I am seeking an advice as to what would be ideal approach to tackle this.
I'm trying to call an API for MVC application.
Goal is to map API data to model.
API endpoint is
https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=1min&apikey=MyAPIKey
Troubles here are:
JSON data keys have white space in them.
When I tried doing paste special in Visual studio, It gave me a long
list of classes for each date entry separately, because this API
call returns a separate set of information for date.
To solve problem explained in point 1, I used [JsonProperty("1. Information")] in class. And in my code..
public async Task TSI()
{
HttpClient client = new HttpClient();
//Uri uri = new Uri("http://date.jsontest.com/");
Uri uri = new Uri("https://www.alphavantage.co/query?function=TIME_SERIES_INTRADAY&symbol=MSFT&interval=5min&apikey=demo");
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(uri);
if (response.IsSuccessStatusCode)
{
dynamic result = await response.Content.ReadAsAsync<object>();
IEnumerable<dynamic> dObj = JsonConvert.DeserializeObject<dynamic>(result.ToString());
IEnumerable<dynamic> t1 = dObj.FirstOrDefault();
IEnumerable<dynamic> t2 = dObj.LastOrDefault();
dynamic MetaData = t1.FirstOrDefault();
Rootobject ro = new Rootobject();
ro.MetaData = MetaData;
}
PS: I'm relatively new to make API calls and handling them.
I was able to make a call to
date.jsontest.com
and map the API data to model (which I had created using paste special)
//API response
{
"time": "12:53:22 PM",
"milliseconds_since_epoch": 1504875202754,
"date": "09-08-2017"
}
//C# code to map to API data
public class sampleObject
{
public string time { get; set; }
public long milliseconds_since_epoch { get; set; }
public string date { get; set; }
}
My RootObject looks like this:
public class Rootobject
{
[JsonProperty("Meta Data")]
public MetaData MetaData { get; set; }
[JsonProperty("Time Series (1min)")]
public TimeSeries1Min TimeSeries1min { get; set; }
}
public class MetaData
{
[JsonProperty("1. Information")]
public string _1Information { get; set; }
[JsonProperty("2. Symbol")]
public string _2Symbol { get; set; }
[JsonProperty("3. Last Refreshed")]
public string _3LastRefreshed { get; set; }
[JsonProperty("4. Interval")]
public string _4Interval { get; set; }
[JsonProperty("5. Output Size")]
public string _5OutputSize { get; set; }
[JsonProperty("6. Time Zone")]
public string _6TimeZone { get; set; }
}
// I have so many of these sub-classes for dates, which again is an issue
public class TimeSeries1Min
{
public _20170907160000 _20170907160000 { get; set; }
public _20170907155900 _20170907155900 { get; set; }
....
....}
public class _20170907160000
{
public string _1open { get; set; }
public string _2high { get; set; }
public string _3low { get; set; }
public string _4close { get; set; }
public string _5volume { get; set; }
}
public class _20170907155900
{
public string _1open { get; set; }
public string _2high { get; set; }
public string _3low { get; set; }
public string _4close { get; set; }
public string _5volume { get; set; }
}
It is hard to create a model from this json, but you can convert those data to dictionary
var jObj = JObject.Parse(json);
var metadata = jObj["Meta Data"].ToObject<Dictionary<string, string>>();
var timeseries = jObj["Time Series (1min)"].ToObject<Dictionary<string, Dictionary<string, string>>>();
The following code should do what you want
if (response.IsSuccessStatusCode)
{
var result = await response.Content.ReadAsStringAsync();
var obj = JsonConvert.DeserializeObject<Rootobject>(result);
//No idea what you want to do with this line as there is no MetaData property on the root object
obj.MetaData = MetaData;
}
Im having with the content. it is auto increment.
the result is static but the content is dynamic.
I'm using a hardcoded array in catching the return string from the web. Can anyone json decoder in converting the returned string to c# object
This is the returned string from web:
{
"result":{
"count":"3"
},
"content_1":{
"message_id":"23",
"originator":"09973206870",
"message":"Hello",
"timestamp":"2016-09-14 13:59:47"
},
"content_2":{
"message_id":"24",
"originator":"09973206870",
"message":"Test again.",
"timestamp":"2016-09-14 14:49:14"
},
"content_3":{
"message_id":"25",
"originator":"09973206870",
"message":"Another message",
"timestamp":"2016-09-14 14:49:20"
}
}
On site json2csharp.com you can generate classes for JSON data.
Generated classes needs some improvements and can look like:
public class Result
{
public string count { get; set; }
}
public class Content
{
public string message_id { get; set; }
public string originator { get; set; }
public string message { get; set; }
public string timestamp { get; set; }
}
public class RootObject
{
public Result result { get; set; }
public Content content_1 { get; set; }
public Content content_2 { get; set; }
public Content content_3 { get; set; }
}
And using JSON.NET you can deserialize it:
public class Program
{
static public void Main()
{
string json = "{ \"result\":{ \"count\":\"3\" }, \"content_1\":{ \"message_id\":\"23\", \"originator\":\"09973206870\", \"message\":\"Hello\", \"timestamp\":\"2016-09-14 13:59:47\" }, \"content_2\":{ \"message_id\":\"24\", \"originator\":\"09973206870\", \"message\":\"Test again.\", \"timestamp\":\"2016-09-14 14:49:14\" }, \"content_3\":{ \"message_id\":\"25\", \"originator\":\"09973206870\", \"message\":\"Another message\", \"timestamp\":\"2016-09-14 14:49:20\" } }";
RootObject ro = JsonConvert.DeserializeObject<RootObject>(json);
Console.WriteLine(ro.content_1.message_id);
Console.WriteLine(ro.content_2.message_id);
}
}
JSON String
[{"Program":"eBay
US","Date":"/Date(1384108200000)/","TimePlus":"/Date(-62135596800000)/","Campaign":"cwsi12","Clicks":0,"EPC":3.3799,"Earnings":6.7599,"CampaignID":"5337412363","Impression":"0","Status":"Duplicate
in Database"},{"Program":"eBay
US","Date":"/Date(1384108200000)/","TimePlus":"/Date(-62135596800000)/","Campaign":"cwsi12","Clicks":0,"EPC":3.3799,"Earnings":6.7599,"CampaignID":"5337412363","Impression":"0","Status":"Duplicate
in Database"},{"Program":"eBay
US","Date":"/Date(1384108200000)/","TimePlus":"/Date(-62135596800000)/","Campaign":"cwsi12","Clicks":0,"EPC":3.3799,"Earnings":6.7599,"CampaignID":"5337412363","Impression":"0","Status":"Duplicate
in Database"},{"Program":"eBay
US","Date":"/Date(1384108200000)/","TimePlus":"/Date(-62135596800000)/","Campaign":"cwsi12","Clicks":0,"EPC":3.3799,"Earnings":6.7599,"CampaignID":"5337412363","Impression":"0","Status":"Duplicate
in Database"}]
View Model
public class EbayEarnings_Temp
{
public String Program { get; set; }
public DateTime Date { get; set; }
public DateTime TimePlus { get; set; }
public String Campaign { get; set; }
public int Clicks { get; set; }
public decimal EPC { get; set; }
public decimal Earnings { get; set; }
public String CampaignID { get; set; }
public String Impression { get; set; }
public string Status { get; set; }
}
var serializer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(EbayEarnings_Temp));
var c = (EbayEarnings_Temp)serializer.ReadObject(jsonString);
I am getting this error
Unexpected character encountered while parsing value: S. Path '', line 0, position 0.
Message is json object not list. You must have integrated serializer or serialize json object in action manually.
I think it must look like this:
public ActionResult action(Object Message)
{
// deserialise if Object Message is a string
var serializer = new JavaScriptSerializer();
var c = serializer.Deserialize<YourClass>(Message);
// deserialise if Object Message is a JsonObject
var serializer = new DataContractJsonSerializer(typeof(YourClass));
var c = (YourClass)serializer.ReadObject(Message);
return PartialView(Message);
}
or another solution:
I use library Newtonsoft.Json. If you're going to use it in your case it would look like:
...
MyClass m = JsonConvert.DeserializeObject<Message>(message.ToString());
var status = m.Status; //...and so on