{"balances-and-info":{"on_hold":[],"available": {"USD":0.93033384},"usd_volume":"243.18","fee_bracket": {"maker":"0.00","taker":"0.60"},"global_usd_volume":"0.09942900"}}
I have this JSON response, and I'm trying to store it in an object, however as you can see "balances-and-info" cannot be used as a variable name. The method I have been using is:
RestClient client = new RestClient("http://currency-api.appspot.com/api/");
RestRequest request = new RestRequest(url);
var response = client.Execute<Currency>(request);
Currency obj = response.Data;
Where obviously the class is a lot easier
public class Currency
{
public string rate { get; set; }
}
So how can I handle this?
String.replace() balances-and-info with balances_and_info
in your code
YourObject deserialized = parseResponse(obj.replace("balances-and-info", "balances_and_info"));
YourObject parseResponse(string response) {
try
{
// https://www.nuget.org/packages/Newtonsoft.Json/
// Json.NET
YourObject ret = JsonConvert.DeserializeObject<YourObject>(response);
return ret;
}
catch (JsonSerializationException)
{
// do something
}
return null;
}
YourObject
Use http://json2csharp.com/ and generate your object (copy response string, replace balances-and-info with balances_and_info and generate)
public class Available
{
public double USD { get; set; }
}
public class FeeBracket
{
public string maker { get; set; }
public string taker { get; set; }
}
public class BalancesAndInfo
{
public List<object> on_hold { get; set; }
public Available available { get; set; }
public string usd_volume { get; set; }
public FeeBracket fee_bracket { get; set; }
public string global_usd_volume { get; set; }
}
public class YourObject
{
public BalancesAndInfo balances_and_info { get; set; }
}
Related
I don't know if there is an existing name for that case, but I'm trying to retrieve data from NASA API (https://api.nasa.gov/) and I have a simple challenge to catch a list of objects near earth. Here is the JSON response I have from the GET request I do to "https://api.nasa.gov/neo/rest/v1/feed?...."
{
"links": {
"next": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-04&end_date=2021-07-04&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym",
"prev": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-02&end_date=2021-07-02&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym",
"self": "http://www.neowsapp.com/rest/v1/feed?start_date=2021-07-03&end_date=2021-07-03&detailed=false&api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym"
},
"element_count": 6,
"near_earth_objects": {
"2021-07-03": [
{
"links": {
"self": "http://www.neowsapp.com/rest/v1/neo/3701710?api_key=NjgpxgSbYHXyFSBI3HaOhRowtjMZgAKv2t4DMRym"
},
"id": "3701710",
"neo_reference_id": "3701710",
"name": "(2014 WF497)",
"nasa_jpl_url": "http://ssd.jpl.nasa.gov/sbdb.cgi?sstr=3701710",
"absolute_magnitude_h": 20.23,
"estimated_diameter": {
"kilometers": {
}
And that's the way it is built in Visual Studio (using the Special Paste option for JSON)
public class NearEarthObject
{
public Links links { get; set; }
public int element_count { get; set; }
public Near_Earth_Objects near_earth_objects { get; set; }
}
public class Links
{
public string next { get; set; }
public string prev { get; set; }
public string self { get; set; }
}
public class Near_Earth_Objects
{
public _20210703[] _20210703 { get; set; }
}
public class _20210703
{
public Links1 links { get; set; }
public string id { get; set; }
public string neo_reference_id { get; set; }
public string name { get; set; }
public string nasa_jpl_url { get; set; }
public float absolute_magnitude_h { get; set; }
public Estimated_Diameter estimated_diameter { get; set; }
public bool is_potentially_hazardous_asteroid { get; set; }
public Close_Approach_Data[] close_approach_data { get; set; }
public bool is_sentry_object { get; set; }
}
The question is, inside of the element "near_earth_objects", there is an element called "2021-07-03" (the date of the data I requested), the problem is that I am trying to include it into a DataGridView made in .NET C# (Windows Forms, but that doesn't matters here, I think) and the user wants to get the information by date. So, "2021-07-03" is a valid member just for one day, and the user should be able to get data from multiple days.
So, is there a way in C# to get all child objects inside of near_earth_objects without knowing their names since there will be the option to search for asteroids from date X to Y in my application?
Using System.Text.Json
The API response will map to the following classes
public class Neo
{
public Links Links { get; set; }
public int ElementCount { get; set; }
public Dictionary<string, List<NearEarthObject>> NearEarthObjects { get; set; }
}
public class Links
{
public string Next { get; set; }
public string Prev { get; set; }
public string Self { get; set; }
}
public class NearEarthObject
{
public Links Links { get; set; }
public string Id { get; set; }
public string Name { get; set; }
// Other properties
}
The NearEarthObjects is simply a Dictionary, where the key is the formatted date and value is a List containing NearEarthObject
The PropertyNamingPolicy will allow us to support the API's underscore property naming convention.
public class UnderscoreNamingPolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
return name.Underscore();
}
}
Example usage
// using using System.Text.Json;
var response = await new HttpClient().GetStringAsync(url);
var neo = JsonSerializer.Deserialize<Neo>(response, new JsonSerializerOptions
{
PropertyNamingPolicy = new UnderscoreNamingPolicy()
});
foreach(var neos in neo.NearEarthObjects)
{
Console.WriteLine(neos.Key);
}
use System.Text.Json, JsonNamingPolicy
demo code
public class DynamicNamePolicy : JsonNamingPolicy
{
public override string ConvertName(string name)
{
var today = DateTime.Today.ToString("yyyy-MM-dd");
if (name.Equals("DateData")) //model property name
return today; //convert to json string property name
return name;
}
}
//data deserialize
string data = ""; //json string
var obj = JsonSerializer.Deserialize<NearEarthObject>(data, new JsonSerializerOptions
{
PropertyNamingPolicy = new DynamicNamePolicy(),
});
Im trying to parse JSON into ListView, but its giving me deserialization error.
This is my model - it's same as api's keys:
public class Currency
{
public string Drzava { get; set; }
public int Sifra_valute { get; set; }
public string Drzava_iso { get; set; }
public int Jedinica { get; set; }
public double Kupovni_tecaj { get; set; }
public double Srednji_tecaj { get; set; }
public double Prodajni_tecaj { get; set; }
}
This is my list of Currencies:
public class CurrencyTable
{
public List<Currency> Results { get; set; }
}
Class for binding with Listview:
public class ShowCurrency
{
static ShowCurrency() {
using (var webClient = new WebClient())
{
String rawJSON =
webClient.DownloadString("http://api.hnb.hr/tecajn/v2/");
CurrencyTable currencyTable =
JsonConvert.DeserializeObject<CurrencyTable>(rawJSON);
}
}
private static List<Currency> currencies;
public static List<Currency> Currencies { get; set; }
public static List<Currency> GetCurrencies() {
return Currencies;
}
}
And i get error at: CurrencyTable currencyTable =
JsonConvert.DeserializeObject(rawJSON);
this is how api looks like:
http://api.hnb.hr/tecajn/v2
The web-service response body starts with this text:
[{"broj_tecajnice":"85","datum_primjene":"2019-05-...
Note how it starts with [ which means it's returning a JSON array directly as its root object and that it is not returning an object with a member named Results (i.e. it is not returning { Results: [ {"broj_tecajnice"... }, { ... } ] }.
Change your code to this:
List<Currency> list = JsonConvert.DeserializeObject<List<Currency>>( rawJSON );
CurrencyTable currencyTable = new CurrencyTable()
{
Results = list
};
i´m in the middle of a project and i just got stuck. My problem is parsing the Json string to my class. This is my Json:
{
"ReturnCode": 0,
"CampaignId": 155087586,
"TotalSMSSent": 1,
"TotalSMSwithError": 0,
"MSISDNwithErrorList": {
}
}
and this is my class
public class RootObject
{
public int ReturnCode { get; set; }
public int CampaignId { get; set; }
public int TotalSMSSent { get; set; }
public int TotalSMSwithError { get; set; }
public List<MSISDNwithErrorList> MSISDNwithErrorList { get; set; }
}
public class MSISDNwithErrorList
{
}
this is my code to get the json string
HttpClient client = new HttpClient();
var response = client.GetAsync("http://evolus.ddns.net/Q4Evolution/php/phpCategoria/BOPesquisaEmp.php").Result;
if (response.IsSuccessStatusCode)
{
string output = JsonConvert.SerializeObject(response.Content.ReadAsStringAsync().Result);
JsonConvert.DeserializeObject<RootObject>(output);
}
And the error is this...
Newtonsoft.Json.JsonSerializationException: Error converting value "{"ReturnCode":0,"CampaignId":155087586,"TotalSMSSent":1,"TotalSMSwithError":0,"MSISDNwithErrorList":{}}" to type 'AppTeste.RootObject'. Path '', line 1, position 115.
MSISDNwithErrorList member seems only object as per the json structure
public class RootObject
{
public int ReturnCode { get; set; }
public int CampaignId { get; set; }
public int TotalSMSSent { get; set; }
public int TotalSMSwithError { get; set; }
//Change from List to Object
public MSISDNwithErrorList MSISDNwithErrorList { get; set; }
}
Rest of Code should be like ...
HttpClient client = new HttpClient();
var response =client.GetAsync("http://evolus.ddns.net/Q4Evolution/php/phpCategoria/BOPesquisa
Emp.php").Result;
if (response.IsSuccessStatusCode)
{
//Here Result already gives you a valid json, you do not need to serialize again
string output =response.Content.ReadAsStringAsync().Result;
//obj is your desired c# object
var obj =JsonConvert.DeserializeObject<RootObject>(output);
}
You can check your working code on https://dotnetfiddle.net/CeXDNA
I'm calling an API that returns a standard response structure for all actions. I deserialise the response using Newtonsoft.Json and JsonConvert.DeserializeObject<Response>
public class Response
{
public int Code { get; set; }
public string Message { get; set; }
public object Result { get; set; }
public DateTime ResponseDateTime { get; set; }
}
The Result object changes depending on the request action that has been requested and if there was an error or not (Code + Message describe errors). I know the structure of the Result objects and have created classes for each Result I require.
How do i go about casting the Result object to a typed variable such as a Detail[]? I know i can serialize the Result object and deserialise it again but surely there is a more elegant solution.
public class Detail
{
public int Id { get; set; }
public string DetailOne { get; set; }
public string DetailTwo { get; set; }
}
If you always know what kind of Result you'll get, I'd suggest making Response generic:
public class Response<TResult>
{
public int Code { get; set; }
public string Message { get; set; }
public T Result { get; set; }
public DateTime ResponseDateTime { get; set; }
}
Then you can just deserialize to a Response<Detail[]> and Json.NET should handle everything fine.
This is assuming that if there's an error, you won't end up with a Result that could be problematic. Alternatively, you could still deserialize to a Response class, but with a JToken property type:
public class Response
{
public int Code { get; set; }
public string Message { get; set; }
public JToken Result { get; set; }
public DateTime ResponseDateTime { get; set; }
}
Then use:
Response response = JsonConvert.DeserializeObject<Response>(json);
if (response.Code == 200) // Or whatever
{
Detail[] details = response.Result.ToObject<Detail[]>();
}
You could potentially wrap that into a generic method. I'd at least try the generic response class first though.
If you change your object model to this:
public class Response<T>
{
public int Code { get; set; }
public string Message { get; set; }
public T Result { get; set; }
public DateTime ResponseDateTime { get; set; }
}
public class Detail
{
public int Id { get; set; }
public string DetailOne { get; set; }
public string DetailTwo { get; set; }
}
Then you can do this:
var original = new Response<Detail>()
{
Code = 42,
Message = "OK",
Result = new Detail()
{
Id = 1701,
DetailOne = "Don't",
DetailTwo = "Panic",
},
ResponseDateTime = DateTime.Now,
};
var json = JsonConvert.SerializeObject(original, Newtonsoft.Json.Formatting.Indented);
var response = JsonConvert.DeserializeObject<Response<Newtonsoft.Json.Linq.JToken>>(json);
if (response.Code == 42)
{
Detail detail = response.Result.ToObject<Detail>();
/* Do something with `Detail`. */
}
That seems a fairly nice way to get to the underlying Detail object.
The key technique is to serialize a Response<Detail> and deserialize as a Response<JToken>. Simple.
Of course, if you really wanted to create a Response<Detail> instance you could make a fairly straightforward way of converting from Response<JToken> to Response<Detail> by doing a straight field-to-field mapping.
Here is the Response<Detail[]> version of the code:
var original = new Response<Detail[]>()
{
Code = 42,
Message = "OK",
Result = new Detail[]
{
new Detail()
{
Id = 1701,
DetailOne = "Don't",
DetailTwo = "Panic",
},
new Detail()
{
Id = 360,
DetailOne = "Microsoft",
DetailTwo = "Xbox",
}
},
ResponseDateTime = DateTime.Now,
};
var json = JsonConvert.SerializeObject(original, Newtonsoft.Json.Formatting.Indented);
var response = JsonConvert.DeserializeObject<Response<Newtonsoft.Json.Linq.JToken>>(json);
if (response.Code == 42)
{
Detail[] detail = response.Result.ToObject<Detail[]>();
/* Do something with `Detail[]`. */
}
I have an issue with my JSON to XML code. It's not assigning the values to the Object and I cannot figure out why. Please let me know what I am doing wrong.
My C# code:
using Newtonsoft.Json;
using System.Xml;
namespace JSONTest
{
public class Program
{
static void Main(string[] args)
{
string fileName = "C:\\Code\\JSONTest\\data\\response.xml";
// Convert XML Data into JSON Data
XmlDocument xmlFile = new XmlDocument();
xmlFile.Load(fileName);
string jsonData = JsonConvert.SerializeXmlNode(xmlFile);
// Convert JSON Data into Object
RootObject root = JsonConvert.DeserializeObject<RootObject>(jsonData);
var data = root.RESPONSE_GROUP;
Console.ReadLine();
}
}
public class RootObject
{
public RESPONSEGROUP RESPONSE_GROUP { get; set; }
}
public class RESPONSEGROUP
{
public string MISMOVersionID { get; set; }
public object RESPONDING_PARTY { get; set; }
public object RESPOND_TO_PARTY { get; set; }
public RESPONSE RESPONSE { get; set; }
}
public class RESPONSE
{
public string ResponseDateTime { get; set; }
public KEY KEY { get; set; }
public STATUS STATUS { get; set; }
}
public class KEY
{
public string _Name { get; set; }
public string _Value { get; set; }
}
public class STATUS
{
public string _Code { get; set; }
public string _Condition { get; set; }
public string _Description { get; set; }
public string _Name { get; set; }
}
}
XML
<RESPONSE_GROUP MISMOVersionID="2.4">
<RESPONDING_PARTY/>
<RESPOND_TO_PARTY/>
<RESPONSE ResponseDateTime="2015-02-19T10:32:11-06:00">
<KEY _Name="LOSClientID" _Value="3000799866"/>
<STATUS _Code="S0010" _Condition="Success" _Description="TEST DESC" _Name="Complete"/>
</RESPONSE>
</RESPONSE_GROUP>
My "JSONData" string:
{"RESPONSE_GROUP":{"#MISMOVersionID":"2.4","RESPONDING_PARTY":null,"RESPOND_TO_PARTY":null,"RESPONSE":{"#ResponseDateTime":"2015-02-19T10:32:11-06:00","KEY":{"#_Name":"LOSClientID","#_Value":"3000799866"},"STATUS":{"#_Code":"S0010","#_Condition":"Success","#_Description":"THIS IS THE DESCRIPTION.","#_Name":"Complete"}}}}
The value of: root.RESPONSE_GROUP.MISMOVersionID is NULL as well as any other values that should have been populated. I know I'm doing something wrong here, but I cannot figure out what it is.
Please help! Thanks in advance.
The problem is that your JSON contains # signs in front of some property names. For example:
"#MISMOVersionID":"2.4"
There are two options here:
Fix the JSON to not have that, e.g. "#MISMOVersionID":"2.4"
Use JsonPropertyAttribute to tell Json.NET which property name to expect in the JSON, e.g.
[JsonProperty("#MISMOVersionID")]
public string MISMOVersionID { get; set; }