I have at times made it my life's work to avoid API's at all costs (that's a debate for another day) but the time is arriving for this to change, a few months ago I got started on creating an API for my applications, and thanks to this very website, it's worked a charm.
So now I'm creating a simple Windows Console Application, it should do nothing more than get API Data then submit to a database for the primary application to use at a later date.
So far so good or so I thought.
This is what I came up with:
static void Main(string[] args)
{
string pair = "xxx/xxx";
string apiUrl = "http://someURL" + pair;
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(apiUrl);
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
Stream responseStream = response.GetResponseStream();
StreamReader readerStream = new StreamReader(responseStream, System.Text.Encoding.GetEncoding("utf-8"));
string json = readerStream.ReadToEnd();
readerStream.Close();
var jo = JObject.Parse(json);
Console.WriteLine("Pair : " + (string)jo["pair"]);
Console.WriteLine("Open : " + (string)jo["openPrice"]);
Console.WriteLine("Close : " + (string)jo["closePrice"]);
Console.WriteLine("Vol : " + (string)jo["vol"]);
Console.ReadKey();
}
Now this works FANTASTIC for the primary source, but when I change the source (eventually it will be multi source) it fails to work.
After some investigation, it seems the slightly different responses are the culprit.
API Return looks like this
{
"ip":"1.1.1.1","country_code":"AU","country_name":"Australia",
"region_code":"VIC","region_name":"Victoria","city":"Research",
"zip_code":"3095","time_zone":"Australia/Melbourne","latitude":-37.7,
"longitude":145.1833,"metro_code":0
}
The return for an alternative source looks like this
{
"success":true,"message":"",
"result":[
{"MarketName":"BITCNY-BTC","High":8000.00000001,"Low":7000.00000000,
"Volume":0.02672075, "Last":7000.00000000,"BaseVolume":213.34995000,
"TimeStamp":"2017-02-09T08:38:22.62","Bid":7000.00000001,"Ask":9999.99999999,
"OpenBuyOrders":14,
"OpenSellOrders":20,"PrevDay":8000.00000001,"Created":"2015-12-11T06:31:40.653"
}
]
}
As we can see the second return is structured differently, and for this feed I've been unable to work this out, clearly my code works, kind of, and clearly it doesn't.
I've looked about on the net and am still no closer to a solution, partly I don't know what I'm really asking and secondly google only wants to talk webAPI.
If there is someone who can point me in the right direction, I don't want the work done for me per say that solves nothing, I have got to learn to do this one way or another.
As mentioned in the comments, your strings are unrelated. You won't be able to perform the same actions on both JSON strings because they're different.
Your best bet is to work with Deserialization to objects, which is converting a JSON string into an object and working with properties instead of JObject literals.
Putting your first JSON string into Json2Csharp.com, this class structure was produced:
public class RootObject
{
public string ip { get; set; }
public string country_code { get; set; }
public string country_name { get; set; }
public string region_code { get; set; }
public string region_name { get; set; }
public string city { get; set; }
public string zip_code { get; set; }
public string time_zone { get; set; }
public double latitude { get; set; }
public double longitude { get; set; }
public int metro_code { get; set; }
}
You could then make some adjustments to your code to extract the HTTP request functionality, assuming that you'll only be working with JSON strings in this instance, and then simply deserialized the JSON to an object.
An example of a WebRequest() method would be:
private static string WebRequest(string UrlToQuery)
{
using(WebClient client = new WebClient)
{
return client.DownloadString(UrlToQuery);
}
}
(Make sure you catch any errors and deal with unexpected responses, I'll leave that up to you!)
You can then call this method like so:
string JsonResponse = WebRequest(apiUrl);
and deserialize to an object of type RootObject like so:
RootObject deserializedString = JsonConvert.Deserialize<RootObject>(JsonResponse);
You'll then be able to perform something like:
Console.WriteLine($"Country name: {deserializedString.country_name}");
Which will print the value of the country_name property of your deserializedString object.
I am trying to make a simple program that can automate price checking using data from json, however I haven't used json before and I'm not quite sure what I need to do get get the desired result.
Effectively I'm trying to convert this PHP into c#. (http://www.sourcecodester.com/tutorials/php/8042/api-json-parsing-php.html)
<?php
$src = file_get_contents('https://www.g2a.com/marketplace/product/auctions/?id=256');
$json = json_decode($src, true);
foreach ($json as $k=>$v) {
if (is_array($v)) {
foreach($v as $key=>$value) {
if (is_array($value)) {
foreach($value as $arKey => $arValue) {
if ($arKey == 'p') {
echo $arValue . '<br/>';
}
}
}
}
}
}
?>
I've tried a few things such as JsonConvert.DeserializeObject(webJson) and JObject.Parse(webJson), but I'm just not sure where I should be looking or how to go about doing it.
I have the first part:
internal static string GetWebContent(string #ID)
{
var wc = new WebClient();
string response = wc.DownloadString(#"https://www.g2a.com/marketplace/product/auctions/?id=" + #ID);
return response;
}
A response looks like this: (https://www.g2a.com/marketplace/product/auctions/?id=27446)
{"a":{"k_709942":{"c":"pl","tr":3451,"f":"\u00a324.71","fb":"\u00a327.18","ci":"565784","cname":"Marketplace User","p":"24.7098173","pb":"27.18431394","ep":"35.15","epb":"38.67","a":"709942","it":"game","t":"1","sl":"0","l":null,"lt":null,"x":0,"v":"all","so":0,"r":99},"k_763218":{"c":"pl","tr":1120,"f":"\u00a324.74","fb":"\u00a327.22","ci":"6533797","cname":"User #f36726dcd","p":"24.7449664","pb":"27.21946304","ep":"35.20","epb":"38.72","a":"763218","it":"game","t":"0","sl":"0","l":null,"lt":"0","x":0,"v":"all","so":0,"r":92},"k_799750":{"c":"pl","tr":559,"f":"\u00a324.78","fb":"\u00a327.26","ci":"6115711","cname":"Marketplace User","p":"24.7801155","pb":"27.26164196","ep":"35.25","epb":"38.78","a":"799750","it":"game","t":null,"sl":"0","l":null,"lt":null,"x":0,"v":"retail","so":0,"r":98},"k_722082":{"c":"gb","tr":49066,"f":"\u00a324.96","fb":"\u00a327.45","ci":"1047917","cname":"Marketplace User","p":"24.955861","pb":"27.4514471","ep":"35.50","epb":"39.05","a":"722082","it":"game","t":"1","sl":"0","l":null,"lt":"0","x":0,"v":"all","so":0,"r":98},"k_718113":{"c":"pl","tr":5852,"f":"\u00a324.96","fb":"\u00a327.45","ci":"226876","cname":"Marketplace User","p":"24.955861","pb":"27.4514471","ep":"35.50","epb":"39.05","a":"718113","it":"game","t":"1","sl":"0","l":null,"lt":"0","x":0,"v":"all","so":0,"r":98},"k_739155":{"c":"pl","tr":1208,"f":"\u00a325.43","fb":"\u00a327.98","ci":"6540559","cname":"User #1f948a6a66249","p":"25.43316468854","pb":"27.976481157394","ep":"35.30","epb":"38.83","a":"739155","it":"game","t":"0","sl":"0","l":null,"lt":"0","x":0,"v":"all","so":0,"r":89},"k_795049":{"c":"pl","tr":50420,"f":"\u00a325.86","fb":"\u00a328.45","ci":"2498689","cname":"Marketplace User","p":"25.86270778","pb":"28.44968154","ep":"36.79","epb":"40.47","a":"795049","it":"game","t":"1","sl":"0","l":null,"lt":"0","x":0,"v":"all","so":0,"r":99},"k_816132":{"c":"pl","tr":22,"f":"\u00a326.00","fb":"\u00a328.60","ci":"6208533","cname":"Marketplace User","p":"25.99627436","pb":"28.59730776","ep":"36.98","epb":"40.68","a":"816132","it":"game","t":"0","sl":"0","l":null,"lt":"0","x":0,"v":"retail","so":0,"r":0},"k_809925":{"c":"pl","tr":81021,"f":"\u00a326.00","fb":"\u00a328.60","ci":"407513","cname":"Marketplace User","p":"26.00330418","pb":"28.60433758","ep":"36.99","epb":"40.69","a":"809925","it":"game","t":"1","sl":"0","l":null,"lt":"0","x":0,"v":"retail","so":0,"r":100},"k_815898":{"c":"cl","tr":1,"f":"\u00a326.01","fb":"\u00a328.61","ci":"7524623","cname":"Marketplace User","p":"26.010334","pb":"28.6113674","ep":"37.00","epb":"40.70","a":"815898","it":"game","t":null,"sl":"0","l":null,"lt":null,"x":0,"v":"retail","so":0,"r":0},"k_711901":{"c":"pl","tr":12194,"f":"\u00a326.51","fb":"\u00a329.16","ci":"286793","cname":"Marketplace User","p":"26.506689203722","pb":"29.158078610346","ep":"36.79","epb":"40.47","a":"711901","it":"game","t":"1","sl":"0","l":null,"lt":null,"x":0,"v":"all","so":0,"r":99},"k_748710":{"c":"pt","tr":66460,"f":"\u00a326.65","fb":"\u00a329.32","ci":"440288","cname":"Marketplace User","p":"26.650786454082","pb":"29.316585585742","ep":"36.99","epb":"40.69","a":"748710","it":"game","t":"1","sl":"0","l":null,"lt":"0","x":0,"v":"all","so":0,"r":100},"k_709464":{"c":"pl","tr":121341,"f":"\u00a327.02","fb":"\u00a329.72","ci":"1072530","cname":"User #3285e5f8dfcb2","p":"27.0182344425","pb":"29.72005788675","ep":"37.50","epb":"41.25","a":"709464","it":"game","t":"1","sl":"0","l":null,"lt":"0","x":0,"v":"retail","so":0,"r":100},"k_709805":{"c":"pl","tr":11708,"f":"\u00a328.09","fb":"\u00a330.90","ci":"1043113","cname":"User #ca1965d0354a","p":"28.091758957682","pb":"30.901655339702","ep":"38.99","epb":"42.89","a":"709805","it":"game","t":"1","sl":"0","l":null,"lt":null,"x":0,"v":"retail","so":0,"r":100},"k_725839":{"c":"es","tr":1,"f":"\u00a331.99","fb":"\u00a335.18","ci":"7023396","cname":"Marketplace User","p":"31.985681","pb":"35.1842491","ep":"45.50","epb":"50.05","a":"725839","it":"game","t":null,"sl":"0","l":null,"lt":null,"x":0,"v":"retail","so":0,"r":0},"k_0":{"f":"\u00a332.33","fb":"\u00a335.56","p":"32.33014218","pb":"35.563156398","ep":"45.99","epb":"50.59","a":0,"c":"","rc":"","r":"","tr":0,"t":1,"so":0,"x":0,"n":"G2A.com"}},"w":0}
Any help with will greatly appreciated.
Thanks in advace
So Json is a way for two languages to pass objects to each other. It's just a way to encode an object, so the first part would be to create an object that matches the Json encoding. I was unable to see your example, so I will give you one of my own.
{"Aggregates": [{"ColumnName": "Some Value", "AggregateFunction": "Some Other Value"}], "GroupBy": true}
I would then create a class like this one.
public class JsonAggregates
{
public List<Aggregate> Aggregates { get; set; }
public string GroupBy { get; set; }
}
public class Aggregate
{
public string ColumnName {get; set;}
public string AggregateFunction {get; set;}
}
You can then encode the Json to this new data type with the following code.
using (Stream s = GenerateStreamFromString(json))
{
DataContractJsonSerializer serializer = new DataContractJsonSerializer(typeof(JsonAggregates));
JsonAggregates aggregate = (JsonAggregates)serializer.ReadObject(s);
}
Does anyone know how to convert a string which contains json into a C# array. I have this which reads the text/json from a webBrowser and stores it into a string.
string docText = webBrowser1.Document.Body.InnerText;
Just need to somehow change that json string into an array. Been looking at Json.NET but I'm not sure if that's what I need, as I don't want to change an array into json; but the other way around. Thanks for the help!
just take the string and use the JavaScriptSerializer to deserialize it into a native object. For example, having this json:
string json = "[{Name:'John Simith',Age:35},{Name:'Pablo Perez',Age:34}]";
You'd need to create a C# class called, for example, Person defined as so:
public class Person
{
public int Age {get;set;}
public string Name {get;set;}
}
You can now deserialize the JSON string into an array of Person by doing:
JavaScriptSerializer js = new JavaScriptSerializer();
Person [] persons = js.Deserialize<Person[]>(json);
Here's a link to JavaScriptSerializer documentation.
Note: my code above was not tested but that's the idea Tested it. Unless you are doing something "exotic", you should be fine using the JavascriptSerializer.
using Newtonsoft.Json;
Install this class in package console
This class works fine in all .NET Versions, for example in my project: I have DNX 4.5.1 and DNX CORE 5.0 and everything works.
Firstly before JSON deserialization, you need to declare a class to read normally and store some data somewhere
This is my class:
public class ToDoItem
{
public string text { get; set; }
public string complete { get; set; }
public string delete { get; set; }
public string username { get; set; }
public string user_password { get; set; }
public string eventID { get; set; }
}
In HttpContent section where you requesting data by GET request
for example:
HttpContent content = response.Content;
string mycontent = await content.ReadAsStringAsync();
//deserialization in items
ToDoItem[] items = JsonConvert.DeserializeObject<ToDoItem[]>(mycontent);
Yes, Json.Net is what you need. You basically want to deserialize a Json string into an array of objects.
See their examples:
string myJsonString = #"{
"Name": "Apple",
"Expiry": "\/Date(1230375600000+1300)\/",
"Price": 3.99,
"Sizes": [
"Small",
"Medium",
"Large"
]
}";
// Deserializes the string into a Product object
Product myProduct = JsonConvert.DeserializeObject<Product>(myJsonString);
Old question but worth adding an answer if using .NET Core 3.0 or later. JSON serialization/deserialization is built into the framework (System.Text.Json), so you don't have to use third party libraries any more. Here's an example based off the top answer given by #Icarus
using System;
using System.Collections.Generic;
namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
var json = "[{\"Name\":\"John Smith\", \"Age\":35}, {\"Name\":\"Pablo Perez\", \"Age\":34}]";
// use the built in Json deserializer to convert the string to a list of Person objects
var people = System.Text.Json.JsonSerializer.Deserialize<List<Person>>(json);
foreach (var person in people)
{
Console.WriteLine(person.Name + " is " + person.Age + " years old.");
}
}
public class Person
{
public int Age { get; set; }
public string Name { get; set; }
}
}
}
One Situation that wasn't covered in the other responses is when you don't know the type of what the JSON object contains. That was my case as I needed to be able to NOT type it and leave it dynamic.
var objectWithFields = js.Deserialize<dynamic[]>(json);
Note: it is definitely preferred to have a type, in some cases, it is not possible, that's why I added this answer.