I am currently doing a project related to a formula 1 API but sadly I cannot figure out how to serialize my xml content into an object.
The XML I am trying to serialize : https://pastebin.com/nkt9EA1k
My API request and the attempt to serialize it.
client = new HttpClient();
HttpResponseMessage response = client.GetAsync("http://ergast.com/api/f1/2022").Result;
HttpContent responseContent = response.Content;
XmlSerializer serializer = new XmlSerializer(typeof(Wrapper));
Wrapper wrapper2;
string result = File.ReadAllText("temp.txt");//hc.ReadAsStringAsync().Result;
using (TextReader reader = new StringReader(result))
{
wrapper2 = (Wrapper)serializer.Deserialize(reader);
}
if(wrapper2 != null)
{
SecondWrapper wrapper = wrapper2.MRData;
string outPut = wrapper.Season;
foreach (Race r in wrapper.RaceTable)
{
outPut += $"\n{r.RaceName}\t{r.Date}\t{r.Circuit.CircuitName}";
}
File.WriteAllText("Output.txt", outPut);
}
My Wrapper class :
public class Wrapper
{
public SecondWrapper MRData;
}
My SecondWrapper Class :
public class SecondWrapper
{
public string Season;
public Race[] RaceTable;
}
My Race class :
public class Race
{
public string RaceName { set; get; }
public Circuit Circuit { set; get; }
public string Date;
public string Time;
public StepDateTime FirstPractice { set; get; }
public StepDateTime SecondPractice { set; get; }
public StepDateTime ThirdPractice { set; get; }
public StepDateTime Qualifying { set; get; }
public StepDateTime Sprint { set; get; }
}
My Circuit class :
public class Circuit
{
public string CircuitName { set; get; }
public Location Location { set; get; }
}
My Location class :
public class Location
{
public double lat { set; get; }
[XmlAttribute("long")]
public double Long { set; get; }
public string Locality { set; get; }
public string Country { set; get; }
}
My StepDateTime class :
public class StepDateTime
{
public string Date { set; get; }
public string Time { set; get; }
}
I tried to make a text file where I deleted the first 2 lines of the XML answer hoping it would fix the issue but it didn't.
PS : I know I'm not using propreties and I am not respecting the c# conventions for the classes but it is temporary just so I can find a way to fix the issue. It is also my first time working with xml answers so I might have done some obvious errors.
Thanks for the help.
I'm trying to implement MusixMatch API, I must admit, when I debug I'm unable to see what's in the ObservableCollection after the API call because the debugger jumps to another thread (I have zero expertise in thread management), however I can see what's the from the API response, Visual Studio says is not Json formatted:
HttpClient httpClient = new HttpClient();
var response = await httpClient.GetStringAsync($"https://api.musixmatch.com/ws/1.1/artist.search?format=jsonp&callback=callback&q_artist=queen&page=1&page_size=5&apikey={apikey}");
RootObject testList= JsonConvert.DeserializeObject<RootObject>(response);
return testList;
I have a model with this structure:
public class Header
{
public int status_code { get; set; }
public double execute_time { get; set; }
public int available { get; set; }
}
public class ArtistNameTranslation
{
public string language { get; set; }
public string translation { get; set; }
}
public class ArtistNameTranslationList
{
public ArtistNameTranslation artist_name_translation { get; set; }
}
public class ArtistAliasList
{
public string artist_alias { get; set; }
}
public class ArtistCredits
{
public List<object> artist_list { get; set; }
}
public class Artist
{
public int artist_id { get; set; }
public string artist_name { get; set; }
public List<ArtistNameTranslationList> artist_name_translation_list { get; set; }
public string artist_comment { get; set; }
public string artist_country { get; set; }
public List<ArtistAliasList> artist_alias_list { get; set; }
public int artist_rating { get; set; }
public string artist_twitter_url { get; set; }
public ArtistCredits artist_credits { get; set; }
public int restricted { get; set; }
public DateTime updated_time { get; set; }
}
public class ArtistList
{
public Artist artist { get; set; }
}
public class Body
{
public List<ArtistList> artist_list { get; set; }
}
public class Message
{
public Header header { get; set; }
public Body body { get; set; }
}
public class RootObject
{
public Message message { get; set; }
}
}
As I said I was able to see what's in the response from the API, you can look at the complete response:
callback({"message":{"header": {"status_code":200,"execute_time":0.043232917785645,"available":6936},"body":{"artist_list":[{"artist":{"artist_id":118,"artist_name":"Queen","artist_name_translation_list":[{"artist_name_translation":{"language":"JA","translation":"\u30af\u30a4\u30fc\u30f3"}}],"artist_comment":"","artist_country":"","artist_alias_list":[{"artist_alias":"\u30af\u30a4\u30fc\u30f3"},{"artist_alias":"Queen + Adam Lambert"}],"artist_rating":99,"artist_twitter_url":"","artist_credits":{"artist_list":[]},"restricted":0,"updated_time":"2015-12-16T15:50:53Z"}},{"artist":{"artist_id":13755603,"artist_name":"Queen with David Bowie","artist_name_translation_list":[{"artist_name_translation":{"language":"EN","translation":"Queen"}}],"artist_comment":"","artist_country":"","artist_alias_list":[{"artist_alias":"Queen"}],"artist_rating":38,"artist_twitter_url":"","artist_credits":{"artist_list":[{"artist":{"artist_id":118,"artist_name":"Queen","artist_name_translation_list":[{"artist_name_translation":{"language":"JA","translation":"\u30af\u30a4\u30fc\u30f3"}}],"artist_comment":"","artist_country":"","artist_alias_list":[{"artist_alias":"\u30af\u30a4\u30fc\u30f3"},{"artist_alias":"Queen + Adam Lambert"}],"artist_rating":99,"artist_twitter_url":"","artist_credits":{"artist_list":[]},"restricted":0,"updated_time":"2015-12-16T15:50:53Z"}},{"artist":{"artist_id":431,"artist_name":"David Bowie","artist_name_translation_list":[{"artist_name_translation":{"language":"JA","translation":"\u30c7\u30f4\u30a3\u30c3\u30c9\u30fb\u30dc\u30a6\u30a4"}}],"artist_comment":"","artist_country":"GB","artist_alias_list":[{"artist_alias":"\u30c7\u30f4\u30a3\u30c3\u30c9\u30fb\u30dc\u30a6\u30a4"},{"artist_alias":"David Robert Jones"},{"artist_alias":"David Jones"},{"artist_alias":"Ziggy Stardust"},{"artist_alias":"\ub370\uc774\ube44\ub4dc \ubcf4\uc704"},{"artist_alias":"\u0414\u044d\u0432\u0438\u0434 \u0411\u043e\u0443\u0438"},{"artist_alias":"Davis Bowie"},{"artist_alias":"Bowie"},{"artist_alias":"\u30c7\u30d3\u30c3\u30c9\u30fb\u30dc\u30a6\u30a4"},{"artist_alias":"David Bowie"},{"artist_alias":"Davie Bowie"},{"artist_alias":"The Thin White Duke"}],"artist_rating":85,"artist_twitter_url":"","artist_credits":{"artist_list":[]},"restricted":0,"updated_time":"2018-10-20T16:37:59Z"}}]},"restricted":0,"updated_time":"2015-12-01T18:35:35Z"}},{"artist":{"artist_id":17057,"artist_name":"Queen Latifah","artist_name_translation_list":[{"artist_name_translation":{"language":"JA","translation":"\u30af\u30a4\u30fc\u30f3\u30fb\u30e9\u30c6\u30a3\u30d5\u30a1"}}],"artist_comment":"","artist_country":"US","artist_alias_list":[{"artist_alias":"\u30af\u30a4\u30fc\u30f3\u30fb\u30e9\u30c6\u30a3\u30d5\u30a1"},{"artist_alias":"Queen Latifa"},{"artist_alias":"Dana Owens"}],"artist_rating":46,"artist_twitter_url":"","artist_credits":{"artist_list":[]},"restricted":0,"updated_time":"2013-11-05T11:25:25Z"}},{"artist":{"artist_id":7321,"artist_name":"Queens of the Stone Age","artist_name_translation_list":[{"artist_name_translation":{"language":"RU","translation":"Queens Of The Stone Age"}}],"artist_comment":"","artist_country":"US","artist_alias_list":[{"artist_alias":"\u30af\u30a4\u30fc\u30f3\u30ba\u30aa\u30d6\u30b6\u30b9\u30c8\u30fc\u30f3\u30a8\u30a4\u30b8"},{"artist_alias":"Queens Of The Stone Age"},{"artist_alias":"shiqishidaihuanghou"},{"artist_alias":"Queen Of Stoneage"},{"artist_alias":"Queens Of The Stoneage"},{"artist_alias":"QOTSA"}],"artist_rating":76,"artist_twitter_url":"https:\/\/twitter.com\/qotsa","artist_credits":{"artist_list":[]},"restricted":0,"updated_time":"2015-12-09T18:04:11Z"}},{"artist":{"artist_id":26029011,"artist_name":"\u5973\u738b\u8702","artist_name_translation_list":[{"artist_name_translation":{"language":"EN","translation":"Queen Bee"}}],"artist_comment":"","artist_country":"JP","artist_alias_list":[{"artist_alias":"Queen Bee"}],"artist_rating":48,"artist_twitter_url":"","artist_credits":{"artist_list":[]},"restricted":0,"updated_time":"2019-07-15T13:55:16Z"}}]}}});
(https://drive.google.com/file/d/1RH9qxrCfKOXdX16eKy74iWhtbnfT46mD/view?usp=sharing)
As I said, Visual Studio is telling me that the response is not in Json>
(https://drive.google.com/file/d/1MoZlKEIbh8Epp_CC9gukWYtMBwp5oXwy/view?usp=sharing)
Looks like you are passing a parameter format=jsonp in the URL. JSONP is a format where JSON data is wrapped in a callback function. It is intended to be used from within <script> tags in HTML pages. If you want plain JSON, try changing that parameter to format=json and removing the corresponding callback parameter. Or you could try removing both format and callback parameters, assuming that JSON is the default format.
If that doesn't work, then the other alternative is to strip off the callback() function wrapper from the response string prior to trying to parse it as JSON. You can do that with a helper method like this:
public static string ExtractJson(string text)
{
int i = text.IndexOf('(');
int j = text.LastIndexOf(')');
return i > -1 && j > i ? text.Substring(i + 1, j - i - 1) : null;
}
You need to update your code to:
var response = await httpClient.GetStringAsync($"https://api.musixmatch.com/ws/1.1/artist.search?format=jsonp&callback=callback&q_artist=queen&page=1&page_size=5&apikey={apikey}");
var contents = await response.Content.ReadAsStringAsync();
RootObject testList= JsonConvert.DeserializeObject<RootObject>(contents);
return testList;
I have a code REST API response which is json, and parsing to JObject and pulling a value from it. But i am getting the error when parsing to JObject.
Error: "Unexpected character encountered while parsing value: S. Path '', line 0, position 0."
Is there any other way to convert Json string to C# object.
I have the following code:
using Newtonsoft.Json;
using (HttpResponseMessage message = httpclient.GetAsync(folderIdURL).Result)
{
if(message.IsSuccessStatusCode)
{
var dataobjects = message.Content.ReadAsStringAsync();
//dataobjects = "{"id":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/","title":"DQL query results","author":[{"name":"EMC Documentum"}],"updated":"2019-05-02T15:19:52.508+00:00","page":1,"items-per-page":100,"links":[{"rel":"self","href":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/?dql=SELECT%20r_object_id%2cobject_name%20FROM%20dm_sysobject%20WHERE%20FOLDER%20(%27%2fgbc%2fUS%2fOSA-ATTACHMENT%2f2019%27)"}],"entries":[{"id":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/?dql=SELECT%20r_object_id%2cobject_name%20FROM%20dm_sysobject%20WHERE%20FOLDER%20(%27%2fgbc%2fUS%2fOSA-ATTACHMENT%2f2019%27)&index=0","title":"0b0111738011c114","updated":"2019-05-02T15:19:52.508+00:00","published":"2019-05-02T15:19:52.508+00:00","links":[{"rel":"edit","href":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/objects/0b0111738011c114"}],"content":{"json-root":"query-result","definition":"https://gbc-dev5.cloud.wc.com/DctmRest/repositori es/dmgbsap_crt/types/dm_sysobject","properties":{"r_object_id":"0b0111738011c114","object_name":"04"},"links":[{"rel":"self","href":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/objects/0b0111738011c114"}]}},{"id":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/?dql=SELECT%20r_object_id%2cobject_name%20FROM%20dm_sysobject%20WHERE%20FOLDER%20(%27%2fgbc%2fUS%2fOSA-ATTACHMENT%2f2019%27)&index=1","title":"0b0111738011c115","updated":"2019-05-02T15:19:52.509+00:00","published":"2019-05-02T15:19:52.509+00:00","links":[{"rel":"edit","href":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/objects/0b0111738011c115"}],"content":{"json-root":"query-result","definition":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/types/dm_sysobject","properties":{"r_object_id":"0b0111738011c115","object_name":"05"},"links":[{"rel":"self","href":"https://gbc-dev5.cloud.wc.com/DctmRest/repositories/dmgbsap_crt/objects/0b0111738011c115"}]}}]}"
JObject responseObj = JObject.Parse(dataobjects.ToString());
String id = (String)responseObj["entries" -->"content"-->"properties"-->"object_name"];
}
}
}
I am expecting the value from (String)responseObject["enteries"]["content"][" properties"]["object_name"]
JObjects are a pain. You could get a sample of the JSON response and paste it into a converter like json2csharp.com. It will generate a class for you which you can then use like so:
Generated Class:
public class MyClass
{
public string SomeProperty { get; set; }
public string AnotherProperty { get; set; }
}
Usage:
if (message.IsSuccessStatusCode)
{
var deserializedObject = JsonConvert.DeserializeObject<MyClass>(response.Content.ReadAsStringAsync().Result);
Console.WriteLine(deserializedObject.SomeProperty);
}
I would suggest to follow those steps:
You need to check that your json is actually a json, because an error says it is not. You can use online tools like this
If possible, avoid JObject and generate real classes. It is not that hard if you know the structure, and you can use another online tools
Modify your code to use classes
so you will have something like:
using System;
using Newtonsoft.Json;
namespace ConsoleApp11
{
class Program
{
public class Message
{
public Enteries enteries { get; set; }
}
public class Enteries
{
public Content content { get; set; }
}
public class Content
{
public Properties properties { get; set; }
}
public class Properties
{
public string object_name { get; set; }
}
static void Main(string[] args)
{
var input = "{\"enteries\":{\"content\":{ \"properties\":{ \"object_name\":\"your value string\"}}}}";
Message msg = JsonConvert.DeserializeObject<Message>(input);
Console.WriteLine(msg?.enteries?.content?.properties?.object_name ?? "no value");
Console.ReadKey();
}
}
}
I hope it helps 😊
Thank you so much for all the help and trips. Finally i am able to get the required value from JSON string.
Here is the Final code json2csharp.com
public class Author
{
public string name { get; set; }
}
public class Link
{
public string rel { get; set; }
public string href { get; set; }
}
public class Link2
{
public string rel { get; set; }
public string href { get; set; }
}
public class Properties
{
public string r_object_id { get; set; }
public string object_name { get; set; }
}
public class Link3
{
public string rel { get; set; }
public string href { get; set; }
}
public class Content
{
public string json_root { get; set; }
public string definition { get; set; }
public Properties properties { get; set; }
public List<Link3> links { get; set; }
}
public class Entry
{
public string id { get; set; }
public string title { get; set; }
public DateTime updated { get; set; }
public DateTime published { get; set; }
public List<Link2> links { get; set; }
public Content content { get; set; }
}
public class RootObject
{
public string id { get; set; }
public string title { get; set; }
public List<Author> author { get; set; }
public DateTime updated { get; set; }
public int page { get; set; }
public int items_per_page { get; set; }
public List<Link> links { get; set; }
public List<Entry> entries { get; set; }
}
Using Newtonsoft.Json
First get the list of entries from the responseObj. Then loop each entries and use LINQ to JSON to get values by property name or index.
You can use Item[Object] index on JObject/JArray and then cast the returned JValue to the type you want
JObject responseObj = JObject.Parse(dataobjects.ToString());
// get JSON result objects into a list
IList<JToken> entries = responseObj ["entries"].Children().ToList();
foreach(JToken entry in entries)
{
string object_name = (string) entry["content"]["properties"]["object_name"];
}
I am trying to make a simple app with Xamarin and the Riot Games API. I have trouble accessing summoner information. It works only with my username due to the way that my deserialization is done I think.
This is my code:
public async void GetSummonerInformation()
{
using (var client = new HttpClient())
{
var result = await client.GetStringAsync(url);
var res = JsonConvert.DeserializeObject<RootObject>(result);
sumName = res.psychoal3x.name;
}
}
public class Psychoal3x
{
public int id { get; set; }
public string name { get; set; }
public int profileIconId { get; set; }
public int summonerLevel { get; set; }
public long revisionDate { get; set; }
}
public class RootObject
{
public Psychoal3x psychoal3x { get; set; }
}
The problem is that if I change my username to something else then it won't work since it will search for psychoal3x in the RootObject class. Anyone know how to fix this?
EDIT
Ok so i changed the code a bit and this is how it looks like
This is the modified code
try
{
using (var httpClient = new HttpClient())
{
HttpResponseMessage response = httpClient.GetAsync(url).Result;
response.EnsureSuccessStatusCode();
string result = response.Content.ReadAsStringAsync().Result;
var data = JsonConvert.DeserializeObject<Dictionary<string, SummonerDto>>(result);
var name1 = data.First().Value.name;
var id = data.First().Value.id;
var profileIconId1 = data.First().Value.profileIconId;
var revisionDate1 = data.First().Value.revisionDate;
sumId = id;
sumProfileIconId = profileIconId1;
sumRevisionDate = revisionDate1;
System.Diagnostics.Debug.WriteLine("{0} this is the {1}", data.First().Value.name, data.First().Value.profileIconId);
}
}catch(Exception ex)
{ System.Diagnostics.Debug.WriteLine(ex.Message); }
public class SummonerDto
{
public int id { get; set; }
public string name { get; set; }
public int profileIconId { get; set; }
public int summonerLevel { get; set; }
public long revisionDate { get; set; }
}
where sumName is the account name that is changed when the api is called.
You're close, but don't hardcode the username into your model classes. Assuming the API you are calling is this one, I'd recommend a structure like this:
public class SummonerDto
{
public int Id { get; set; }
public string Name { get; set; }
public int ProfileIconId { get; set; }
public int SummonerLevel { get; set; }
public long RevisionDate { get; set; }
}
According to the API docs, the return type is Dictionary<string, SummonerDto>. You can use JSON.NET to deserialize this easily:
var data = JsonConvert.DeserializeObject<Dictionary<string, SummonerDto>>(result);
That means that there will be a key-value pair with the key "psychoal3x" and a SummonerDto object as the value. You can get the first returned value by using First():
var summoner = data.First().Value;
From there, you can access all the properties, such as Name.
Here's a working fiddle based on the JSON data you posted in the comments: https://dotnetfiddle.net/xEUXa6
First time working with JSON and related, I'm trying to get distance/duration of all possible routes from this request: https://maps.googleapis.com/maps/api/directions/json?origin=41.2091585,-8.5763016&destination=41.258913,-8.636942&mode=driving&alternatives=true&avoid=tolls&language=pt-PT&key=AIzaSyDuhdvLAny3MpraXKX-bahkXZJolm7KLbE
I got the following classes using "Paste JSON as Classes" and create one Class for each of the following ones:
public class Rootobject
{
public Geocoded_Waypoints[] geocoded_waypoints { get; set; }
public Route[] routes { get; set; }
public string status { get; set; }
}
public class Route
{
public Bounds bounds { get; set; }
public string copyrights { get; set; }
public Leg[] legs { get; set; }
public Overview_Polyline overview_polyline { get; set; }
public string summary { get; set; }
public object[] warnings { get; set; }
public object[] waypoint_order { get; set; }
}
public class Leg
{
public Distance distance { get; set; }
public Duration duration { get; set; }
public string end_address { get; set; }
public End_Location end_location { get; set; }
public string start_address { get; set; }
public Start_Location start_location { get; set; }
public Step[] steps { get; set; }
public object[] traffic_speed_entry { get; set; }
public Via_Waypoint[] via_waypoint { get; set; }
}
public class Distance
{
public string text { get; set; }
public int value { get; set; }
}
public class Duration
{
public string text { get; set; }
public int value { get; set; }
}
For the query mentioned above I have 3 different routes (aka "legs") and I want to get the distance/duration of each one.
I came up with the following but it's not working.
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(query);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
using (var streamReader = new StreamReader(response.GetResponseStream()))
{
var result = streamReader.ReadToEnd();
if (!string.IsNullOrEmpty(result))
{
Distance t = JsonConvert.DeserializeObject<Distance>(result);
string distance1_Value = t.value;
string distance1_Text = t.text;
Duration d = JsonConvert.DeserializeObject<Duration>(result);
string duration1_Value = d.value;
string duration1_Value = d.text;
}
}
Any help?
PS: If anyone can show me how to iterate throw each "legs" that would be great.
EDIT: Forgot to mention I'm using Newtonsoft.
I found the solution a few days ago...
First, i do the same of you, but still not working for me, so i take a look deep inside the classes auto generated by this tool and notice that some classes was missing the 's' at the end of its names..
Step, where correct name 'Steps'
Leg. correct name 'Legs'
Route. correct name 'Routes'
Do you have to fix this at entire document.
After this, you can convert directly...
Take a look at correct answer: [1]: http://pastie.org/10935748#9