I am struggling with how to convert the following price quote JSON data into a C#
object:
{"MyFeed":
{"#Provider":"SomeProvider","MMM":
{"#name":"3M Corp","low":"194.80","high":"136.78","change":"2.80","pctchange":"0.22","ask":"135.15","bid_time":"20161104131845","bid":"134.80"}
}}
I created a C# class like so:
public class Quote
{
public string Provider { get; set; }
public Data Info { get; set; }
}
public class Data
{
public string name { get; set; }
public decimal low { get; set; }
public decimal high { get; set; }
public decimal change { get; set; }
public decimal pctchange { get; set; }
public decimal ask { get; set; }
public DateTime bid_time { get; set; }
public decimal bid { get; set; }
}
Then, in code, I am fetching the data using an HttpWebRequest, which runs just fine. But the step to deserialize the JSON data doesn't work.. It doesn't throw an error, it just has no data. That code is:
var request = HttpWebRequest.Create(new Uri("<request URL here>")) as HttpWebRequest;
request.Method = "POST";
var response = request.GetResponse();
using (Stream stream = response.GetResponseStream())
{
using (var reader = new StreamReader(stream))
{
Quote quote = JsonConvert.DeserializeObject<Quote>(reader.ReadToEnd());
lblPrice.Text = string.Format("{0:c}", quote.Data.ask);
}
}
I stepped through the code, so I know the web request is working and returning a JSON string. I just don't know how to structure the C# class to accept the deserialized data. Help would be appreciated!
You should define the properties like this.
[JsonProperty(PropertyName = "#Provider")]
public string Provider { get; set; }
And
[JsonProperty(PropertyName = "#name")]
public string name { get; set; }
You have dozens other problems, like your fields are not decimal in the json, wrong class structure. Here how your class should look like:
public class MyFeed
{
[JsonProperty(PropertyName = "#Provider")]
public string Provider { get; set; }
public MMM MMM { get; set; }
}
public class RootJsonObject
{
public MyFeed MyFeed { get; set; }
}
public class MMM
{
[JsonProperty(PropertyName = "#name")]
public string name { get; set; }
public string provider { get; set; }
public string low { get; set; }
public string high { get; set; }
public string change { get; set; }
public string pctchange { get; set; }
public string ask { get; set; }
public string bid_time { get; set; }
public string bid { get; set; }
}
How you make the conversion:
RootJsonObject quote = JsonConvert.DeserializeObject<RootJsonObject>(json);
have you tried to use this json2csharp
Use JsonProperty to specify the names in the serialized string.
You need to wrap the whole Quote type in a different type as you are passing in an object that contains the object you are interested in.
You need to specify how the DateTime types are serialized.
Here is a complete and working solution with your json.
class JsonTester
{
public void Test()
{
const string json = "{\"MyFeed\":{\"#Provider\":\"SomeProvider\",\"MMM\":{\"#name\":\"3M Corp\",\"low\":\"194.80\",\"high\":\"136.78\",\"change\":\"2.80\",\"pctchange\":\"0.22\",\"ask\":\"135.15\",\"bid_time\":\"20161104131845\",\"bid\":\"134.80\"}}}";
var settings = new JsonSerializerSettings()
{
DateFormatString = "yyyyMMddHHmmss"
};
var quoteWrapper = JsonConvert.DeserializeObject<MyFeed>(json, settings);
var quote = quoteWrapper.Quote;
}
}
public class MyFeed
{
[JsonProperty("MyFeed")]
public Quote Quote { get; set; }
}
public class Quote
{
[JsonProperty("#Provider")]
public string Provider { get; set; }
[JsonProperty(PropertyName = "MMM")]
public Data Info { get; set; }
}
public class Data
{
[JsonProperty("#name")]
public string name { get; set; }
public decimal low { get; set; }
public decimal high { get; set; }
public decimal change { get; set; }
public decimal pctchange { get; set; }
public decimal ask { get; set; }
public DateTime bid_time { get; set; }
public decimal bid { get; set; }
}
Your Quote class should be Serializable. Either add Serializable attribute to it or DataContract attribute to it with DataMembers.
Related
I am trying to consume a REST API via a C# Console Application and I've got as far as getting the webservice to return the JSON file, with the format:
{"status":200,"result":{"postcode":"SW1W0DT","quality":1,"eastings":528813,"northings":178953,"country":"England","nhs_ha":"London","longitude":-0.145828,"latitude":51.494853,"european_electoral_region":"London","primary_care_trust":"Westminster","region":"London","lsoa":"Westminster 023E","msoa":"Westminster 023","incode":"0DT","outcode":"SW1W","parliamentary_constituency":"Cities of London and Westminster","admin_district":"Westminster","parish":"Westminster, unparished area","admin_county":null,"admin_ward":"Warwick","ccg":"NHS Central London (Westminster)","nuts":"Westminster","codes":{"admin_district":"E09000033","admin_county":"E99999999","admin_ward":"E05000647","parish":"E43000236","parliamentary_constituency":"E14000639","ccg":"E38000031","nuts":"UKI32"}}}
I have created a class AddressInfo which is as follows:
public class AddressInfo {
public string postcode { get; set; }
public int quality { get; set; }
public int eastings { get; set; }
public int northings { get; set; }
public string country { get; set; }
public string nhs_ha { get; set; }
public string admin_county { get; set; }
public string admin_district { get; set; }
public string admin_ward { get; set; }
public double longitude { get; set; }
public double latitude { get; set; }
public string parliamentary_constituency { get; set; }
public string european_electoral_region { get; set; }
public string primary_care_trust { get; set; }
public string region { get; set; }
public string parish { get; set; }
public string lsoa { get; set; }
public string msoa { get; set; }
public string ccg { get; set; }
public string nuts { get; set; }
public object codes { get; set; }
}
The code to call the API and get the values is:
string strJSON = string.Empty;
strJSON = rClient.makeRequest();
Console.Write(strJSON);
AddressInfo AI = new AddressInfo();
AI = Newtonsoft.Json.JsonConvert.DeserializeObject<AddressInfo>(strJSON);
However, when I debug, AI is returning the values as "NULL".
Thanks
Notice that your JSON has a nested structure. The AddressInfo is contained within its result property, it isn't at the top level.
Your actual class structure to deserialize the entire JSON response should look something like this (I've called the class JsonResponse but you can name it whatever you want):
class JsonResponse{
public int status { get; set; }
public AddressInfo result { get; set; }
}
Then deserialize it like this:
JsonResponse res = JsonConvert.DeserializeObject<JsonResponse>(strJSON);
AddressInfo addressInfo = res.result;
You're missing the fact that you need an outer class that has the properties int status and AdressInfo result.
You don't need to create a separate class to deserialize the entire response, this can be done dynamically to achieve desired result:
var source = "(your JSON");
dynamic data = JObject.Parse(source);
var d = JsonConvert.SerializeObject(data.result);
AddressInfo account = JsonConvert.DeserializeObject<AddressInfo>(d);
Your JSON is nested. The result is a nested object. That's why you are experiencing this issue.
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
I have read some articles but didnt fix my problem , i have a problem with JSON string when deserialize, here the string
{"table":"sy_version","effected":2,"data":[{"mod_id":"CS","sub_mod":"sbm_sl.exe","version":"2015.11.07.1","upload_date ":"2015-11-10 11:34:13"},{"mod_id":"FA","sub_mod":"sbm_fa.exe","version":"2015.11.09","upload_date ":"2015-11-10 11:34:13"}]}
And this is my class
public class Datum
{
public string mod_id { get; set; }
public string sub_mod { get; set; }
public string version { get; set; }
public DateTime upload_date { get; set; }
}
public class sy_periode
{
public string table { get; set; }
public int effected { get; set; }
public IList<Datum> datas { get; set; }
}
public static void test(string str) {
// dynamic sy_periode = JsonConvert.DeserializeObject(str);
var sy_periode = JsonConvert.DeserializeObject<sy_periode>(str);
foreach (var data in sy_periode.datas)
{
Console.WriteLine(data.sub_mod);
}
}
When I executed, string table and effected have value, but datas is null, this is the error message
Object reference not set to an instance of an object.
It shouldn't be datas, it should have the same name as JSON object: data.
Here is the correct classes structure:
public class Datum
{
public string mod_id { get; set; }
public string sub_mod { get; set; }
public string version { get; set; }
public DateTime upload_date { get; set; }
}
public class sy_periode
{
public string table { get; set; }
public int effected { get; set; }
public IList<Datum> data { get; set; }
}
Also, note that in JSON your upload_date properties have an odd whitespace in the end: upload_date. It may be a typo. However, if it is an actual input and since C# member name cannot contain spaces, you can try to specify the name in order to serialize it:
[JsonProperty(PropertyName = "upload_date ")]
public DateTime upload_date { get; set; }
I am not quite sure that it will work, but I see no reasons of why it shouldn't.
I am trying to parse a whois json response but when I try parse it I get null values.
string html;
string whoisUrl = "https://whois.apitruck.com/:google.com";
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(whoisUrl);
using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
{
using (StreamReader reader = new StreamReader(response.GetResponseStream(), Encoding.ASCII))
{
html = reader.ReadToEnd();
}
}
Class1 m = JsonConvert.DeserializeObject<Class1>(html);
MessageBox.Show(m.created);
Object
class Class1
{
public string created { get; set; }
}
can anyone please point what I am doing wrong here ?
Your Class1 doesn't get the value since "created" is part of the "response" and not the root level of the JSON reponse.
You'll either need to use dynamic or create a hierarchy for the classes for a simple fix.
class Class1
{
public Response Response { get; set; }
}
class Response
{
public string created { get; set; }
}
Then you can use this:
Class1 m = JsonConvert.DeserializeObject<Class1>(html);
MessageBox.Show(m.Response.created);
UPDATE
Also, here's an example of how to use the dynamic:
var m = JsonConvert.DeserializeObject<dynamic>(html);
DateTime created = (DateTime)m.response.created;
There is nice app to convert json to .net class:
public class Registrar
{
public string id { get; set; }
public string name { get; set; }
public object email { get; set; }
public string url { get; set; }
}
public class Response
{
public string name { get; set; }
public string idnName { get; set; }
public List<string> status { get; set; }
public List<string> nameserver { get; set; }
public object ips { get; set; }
public string created { get; set; }
public string changed { get; set; }
public string expires { get; set; }
public bool registered { get; set; }
public bool dnssec { get; set; }
public string whoisserver { get; set; }
public List<object> contacts { get; set; }
public Registrar registrar { get; set; }
public List<string> rawdata { get; set; }
public object network { get; set; }
public object exception { get; set; }
public bool parsedContacts { get; set; }
}
public class RootObject
{
public int error { get; set; }
public Response response { get; set; }
}
...
RootObject result = JsonConvert.DeserializeObject<RootObject>(html);
var created = result.response.created;
I'm trying to check if a twitch.tv stream is online or not via c#. Currently I have:
private bool checkStream(String chan)
{
using (var w = new WebClient()) {
String json_data = w.DownloadString("https://api.twitch.tv/kraken/streams/" + chan);
JObject stream = JObject.Parse(json_data);
print(json_data); //just for testing purposes
if (stream["stream"] != null)
{
print("YIPPEE");
}
}
return false;
}
Here's the twitch JSON API for what I'm downloading: https://github.com/justintv/Twitch-API/blob/master/v2_resources/streams.md#get-streamschannel
As you can see, if a stream is currently offline, the stream field just says null. But obviously, it's still there, so my if(stream["stream"]!=null) check doesn't work. Never used JSON or Newtonsoft's json.net before, so I'm kind of at a loss for what to do. Thanks in advance for any help!
You need to create a class that you can de-serialize the json to. For instance, if you receive json that looks like this
MyJson = {
Prop1 : "Property1",
Prop2 : "Property2"
}
then you'll need to create a class that acts as a contract between your program and the JSON stream.
public class MyJsonClass{
public string Prop1;
public string Prop2;
public MyJsonClass(){
}
}
Now, you can deserialize the json to your C# class and check it for any null values:
// Create a MyJson class instance by deserializing your json string
string myJsonString = ...//get your json string
MyJsonClass deserialized = JsonConvert.DeserializeObject<MyJsonClass>(myJsonString);
if ( deserialized.Prop1 == null )
//etc etc etc
Here's a full processor for that Json response (Disclaimer: I used http://json2csharp.com/ for this code ) :
public class Links
{
public string channel { get; set; }
public string self { get; set; }
}
public class Links2
{
public string self { get; set; }
}
public class Links3
{
public string stream_key { get; set; }
public string editors { get; set; }
public string subscriptions { get; set; }
public string commercial { get; set; }
public string videos { get; set; }
public string follows { get; set; }
public string self { get; set; }
public string chat { get; set; }
public string features { get; set; }
}
public class Channel
{
public string display_name { get; set; }
public Links3 _links { get; set; }
public List<object> teams { get; set; }
public string status { get; set; }
public string created_at { get; set; }
public string logo { get; set; }
public string updated_at { get; set; }
public object mature { get; set; }
public object video_banner { get; set; }
public int _id { get; set; }
public string background { get; set; }
public string banner { get; set; }
public string name { get; set; }
public string url { get; set; }
public string game { get; set; }
}
public class Stream
{
public Links2 _links { get; set; }
public string broadcaster { get; set; }
public string preview { get; set; }
public long _id { get; set; }
public int viewers { get; set; }
public Channel channel { get; set; }
public string name { get; set; }
public string game { get; set; }
}
public class RootObject
{
public Links _links { get; set; }
public Stream stream { get; set; }
}
and here's how to use it :
bool StreamOnline = false;
using (var w = new WebClient())
{
var jsonData = w.DownloadData("https://api.twitch.tv/kraken/streams/" + + chan);
var s = new DataContractJsonSerializer(typeof(RootObject));
using (var ms = new MemoryStream(jsonData))
{
var obj = (RootObject)s.ReadObject(ms);
StreamOnline = obj.stream == null;
}
}
return StreamOnline;
Please note that you need to reference System.Runtime.Serialization and add using System.Runtime.Serialization.Json; to use DataContractJsonSerializer. If you don't need every detail just make the stream property of type object (in the RootObject class) and check whether it's null or not.
Have you tried this. The HasValues is a bool property that checks if there are child tokens, if its value is null there will not be any child tokens.
if (stream["stream"].HasValues)
{
print("YIPPEE");
}else
{
print("No Stream");
}