Trying to create a new item in list in c# - c#

I'm having a hard time to bind one particular field called url in a List.
This is my json format:
{
id: 'someID',
name: 'someName.pdf',
url: {
download: 'https://mydomain/api_binary/v1/document/mcipv7sgq11c9e6e42upqapc7k '
}
}
This is my model
public class CantoItem
{
public string id { get; set; }
public string name { get; set; }
[JsonProperty("default")]
public DefaultNest Default { get; set; }
[JsonProperty("url")]
public ResultUrl Url { get; set; }
[JsonProperty("tag")]
public object Tag { get; set; }
}
public partial class ResultUrl
{
[JsonProperty("preview")]
public Uri Preview { get; set; }
[JsonProperty("download")]
public Uri Download { get; set; }
}
[JsonProperty("tag")]
public List<string> Tag { get; set; }
}
Then for adding the value I have:
var cantoAssetMetadata = new List<CantoItem>();
foreach (JValue item in collection)
{
try
{
var collectionjObj = JObject.Parse(item.ToString());
cantoAssetMetadata.Add(new CantoItem()
{
id = collectionjObj["id"].ToString(),
name = collectionjObj["name"].ToString(),
Url = collectionjObj["url"].ToString(),
Tag = collectionjObj["tag"].ToString(),
});
}
catch (Exception ex)
{
Console.WriteLine($"Exeption: {ex}, {item}");
}
}
Other fields are set correctly just the URL is not, I canĀ“t figure out how I can set the value correctly. Any help will be appreciated

The following wouldn't work:
Url = collectionjObj["url"].ToString()
You will need to initialize the Url and set the related property:
name = collectionjObj["name"].ToString(),
Url = new ResultUrl()
{
Download = new System.Uri(collectionjObj["url"].ToString())
},
Tag = collectionjObj["tag"].ToString(),

Why not try
var cantoAssetMetadata = new List<CantoItem>();
foreach (JValue item in collection)
{
try
{
cantoAssetMetadata.Add(item.ToObject<CantoItem>());
}
catch (Exception ex)
{
Console.WriteLine($"Exeption: {ex}, {item}");
}
}

You are calling .ToString() on a class object - Url = collectionjObj["url"].ToString(), Url is a partial class called ResultUrl. Convert the JToken to the appropriate class which it deserializes to
//Convert to the proper class object type
Url = collectionjObj["url"].ToObject<ResultUrl>;

Related

How to loop attributes in a JSON string post converting it into C# object?

I have a below json, I want to loop the items inside the attribute CheckingUrls.
{
"Root": {
"Urls": {
"CheckingUrls": [
{
"API Management": {
"url": ".azure-api.net",
"displayurl": "*.azure-api.net"
},
"Log Analytics": {
"url": "1.ods.opinsights.azure.com",
"displayurl": "*.ods.opinsights.azure.com"
}
}
]
}
}
}
Here are the C# class
public class Root
{
Urls Urls { get; set; }
}
public class Urls
{
public List<CheckingUrls> CheckingUrls { get; set; }
}
public class CheckingUrls
{
[JsonProperty("API Management")]
public UrlDetails APIManagement { get; set; }
[JsonProperty("Log Analytics")]
public UrlDetails LogAnalytics { get; set; }
}
public class UrlDetails
{
[JsonProperty("url")]
public string url { get; set; }
[JsonProperty("displayurl")]
public string displayurl { get; set; }
}
I am trying to convert it into c# object using the below code
var content = File.ReadAllText(jsonstring);
var settings = JsonConvert.DeserializeObject<Root>(content);
I am getting APIManagement and LogAnalytics as properties in the result. Is it possible to get these as List, so that I can loop the contents without hardcoding the properties in code.
Why I need solution: We might add new child to CheckingUrls and we do not want to change the c# code everytime when we change JSON.
Use a C# Dictionary when you want to convert a JSON Object to C# when you don't have a concrete type. CheckingUrls is already an array, so you end up with
public List<Dictionary<string, UrlDetails>> CheckingUrls { get; set; }
The key of a Dictionary entry is the property name in the array element (like "API Management"), and the value is the object that contains the url and displayurl properties.
This eliminates the need for the CheckingUrls C# class.
If you want a List, you can create a CheckingUrls class
List<CheckingUrls> checkingUrlsList = JObject.Parse(json)
.SelectToken("Root.Urls.CheckingUrls")
.SelectMany(jo => ((JObject)jo).Properties()
.Select(p => new CheckingUrls
{
UrlName = p.Name,
UrlDetails = new UrlDetails
{
url = (string)p.Value["url"],
displayurl = (string)p.Value["displayurl"]
}
}
)).ToList();
public class CheckingUrls
{
public string UrlName { get; set; }
public UrlDetails UrlDetails { get; set; }
}
public class UrlDetails
{
public string url { get; set; }
public string displayurl { get; set; }
}
output ( in a json format)
[
{
"UrlName": "API Management",
"UrlDetails": {
"url": ".azure-api.net",
"displayurl": "*.azure-api.net"
}
},
{
"UrlName": "Log Analytics",
"UrlDetails": {
"url": "1.ods.opinsights.azure.com",
"displayurl": "*.ods.opinsights.azure.com"
}
}
]
but if you changed your mind to a Dictionary
Dictionary<string, UrlDetails> checkingUrlsDict = JObject.Parse(json)
.SelectToken("Root.Urls.CheckingUrls")
.Select(jo => jo.ToObject<Dictionary<string, UrlDetails>>())
.FirstOrDefault();

Restsharp error on deserialzation when nested value is null

I'm running into an error when a nested value is null. If the value is not null everything works as expected. This does not happen if the value is not nested.
The error is:
InvalidCastException: Unable to cast object of type 'System.String' to type 'System.Collections.Generic.IDictionary`2[System.String,System.Object]'.
The error happens when I'm checking response.ErrorException != null on the List Contract
Json returned: Contract administrator is nested and blank error: ends is not nested blank and no error:
"result": [
{
"sys_id": "06dc3133db1747808c47499e0b96192e",
"number": "CNTR001234",
"short_description": "Contract 123",
"u_internal_contact": {
"link": "https://website",
"value": "5b4080490a0a3c9e016cb2a9f4eb57b1"
},
"vendor": {
"link": "https://website",
"value": "b7e7c073c0a801690143e7b7d29eb408"
},
"ends": "",
"payment_amount": "60000",
"u_status": "Active",
"starts": "2018-01-01",
"contract_administrator": ""
}
]
}
Code
public class Results
{
public List<Contract> items { get; set; }
}
public class Contract
{
public string sys_id { get; set; }
public string number { get; set; }
public string short_description { get; set; }
public string ends { get; set; }
public string payment_amount { get; set; }
public string u_status { get; set; }
public string starts { get; set; }
public Vendor vendor { get; set; }
public ContractAdmin contract_administrator { get; set; }
public InternalContact u_internal_contact { get; set; }
}
public class Vendor
{
public string link { get; set; }
public string value { get; set; }
}
public class ContractAdmin
{
public string link { get; set; }
public string value { get; set; }
}
public class InternalContact
{
public string link { get; set; }
public string value { get; set; }
}
public class refResults
{
public List<refName> itemName { get; set; }
}
public class refName
{
public string name { get; set; }
}
class ImportContracts
{
public static void ProcessImport()
{
RestClient contractsRequest = new RestClient(Properties.Settings.Default.RestURL);
contractsRequest.Authenticator = new HttpBasicAuthenticator(Properties.Settings.Default.userName, Properties.Settings.Default.password);
contractsRequest.AddHandler("application/json", new RestSharp.Deserializers.JsonDeserializer());
RestRequest request = new RestRequest();
request.RootElement = "result";
request.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
IRestResponse<List<Contract>> response = contractsRequest.Execute<List<Contract>>(request);
Console.WriteLine(response.Content);
if (response.ErrorException != null)
{
const string message = "Error retrieving response. Check inner details for more info.";
var ex = new ApplicationException(message, response.ErrorException);
throw ex;
}
foreach (Contract contract in response.Data)
{
//Console.WriteLine(contract.sys_id);
string strVendor = GetName(contract.vendor.link.ToString());
string strInternalContact = GetName(contract.u_internal_contact.link.ToString());
string strContractAdmin = GetName(contract.contract_administrator.ToString());
}
}
static public string GetName (string link)
{
RestClient nameRequest = new RestClient(link);
nameRequest.Authenticator = new HttpBasicAuthenticator(Properties.Settings.Default.userName, Properties.Settings.Default.password);
nameRequest.AddHandler("application/json", new RestSharp.Deserializers.JsonDeserializer());
RestRequest requestedName = new RestRequest();
requestedName.RootElement = "result";
requestedName.OnBeforeDeserialization = resp => { resp.ContentType = "application/json"; };
IRestResponse<List<refName>> response = nameRequest.Execute<List<refName>>(requestedName);
if (response.ErrorException != null)
{
const string message = "Error retrieving response. Check inner details for more info.";
var ex = new ApplicationException(message, response.ErrorException);
throw ex;
}
foreach (refName refname in response.Data)
{
return refname.name;
}
return "name not found";
}
}
Any help would be appreciated!
Looking at your JSON, "contract_administrator" is not null, it's an empty string. Your contract requires a ContractAdmin object, so what it's likely doing is attempting to cast an empty string to a ContractAdmin.
If you change "contract_administrator" to be null instead of an empty string, I'm willing to bet that it will parse correctly.

Get data from Json file C#

I have this Json file:
{"id":88319,"dt":1345284000,"name":"Benghazi",
"coord":{"lat":32.12,"lon":20.07},
"main":{"temp":306.15,"pressure":1013,"humidity":44,"temp_min":306,"temp_max":306},
"wind":{"speed":1,"deg":-7},
"weather":[
{"id":520,"main":"rain","description":"light intensity shower rain","icon":"09d"},
{"id":500,"main":"rain","description":"light rain","icon":"10d"},
{"id":701,"main":"mist","description":"mist","icon":"50d"}
],
"clouds":{"all":90},
"rain":{"3h":3}}
I can read the "name": "Benghazi" normally but the "temp":306.15 I can not read because it is inside "main":{}
I'm using a simple way to read, here is my C# code:
public class SkyWeather
{
string path = #"http://api.openweathermap.org/data/2.5/weather?q=Uberaba,br&units=metric";
string name;
string temp;
public string Name { get { return name; } set { name = value; } }
public string Temp { get { return temp; } set { temp = value; } }
public string GetTemperature()
{
var json = "";
try
{
json = new WebClient().DownloadString(path);
}
catch (Exception e)
{
return e.ToString();
}
string text = (string)json;
SkyWeather w = JsonConvert.DeserializeObject<SkyWeather>(text);
return w.temp;
}
}
How can I read it?
Assuming that SkyWeather represents the properties in your "main" object, you'll need to create another object that represents the wrapping object:
public class RootObject
{
public int id { get; set; }
public int dt { get; set; }
public string name { get; set; }
public SkyWeather main { get; set; }
}
... and then:
RootObject w = JsonConvert.DeserializeObject<RootObject>(text);
return w.main.temp;

Parsing Multiple Json Rows in windows phone

My json response which i am generating from php :
{"name":"abhi","age":"20","id":"1"}
{"name":"abhi","age":"21","id":"4"}
And the c# code is:
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
Load(textBox1.Text);
}
public void Load(string keyword)
{
var client = new RestClient("http://localhost/query.php?name="+keyword);
var request = new RestRequest(Method.GET);
//request.AddParameter("name", keyword);
/*request.AddParameter("v", "1.0");
request.AddParameter("q", keyword);
request.AddParameter("hl", "id");
request.AddParameter("rsz", 5);*/
client.ExecuteAsync<RootObject>(request, (response) =>
{
// var resp = response.Data.ToString();
// var respLines = resp.Split('\n');
RootObject rootObject=response.Data;
listBox1.Items.Clear();
if (rootObject == null)
MessageBox.Show("null");
else
{
listBox1.Items.Add(rootObject.age+" " + rootObject.name);
}
});
}
}
}
public class RootObject
{
public string name { get; set; }
public string age { get; set; }
public string id { get; set; }
}
i am able to fetch the first row but not for multiple rows. Anyone has any idea how to fetch multiple rows in json format. How to create multiple objects of json and populate them?
That does not look like valid JSON, try returning a JSON array from PHP:
{
"rows": [
{"name":"abhi","age":"20","id":"1"},
{"name":"abhi","age":"21","id":"4"}
]
}
These would be the corresponding C# classes for deserialization:
public class Row
{
public string name { get; set; }
public string age { get; set; }
public string id { get; set; }
}
public class RootObject
{
public List<Row> rows { get; set; }
}
And you can add your rows with:
foreach (var row in rootOject.rows)
{
listBox1.Items.Add(row.age+" " + row.name);
}

WP7 JSON returning list within a list

I'm trying to return json data from a list within a list. The data is being pulled using a webclient and deserialized using JSON.NET. I'd like to return a name and image from the "featuredCharts" list which is within the "Results" list. Here is part of the json data I'm referring to.
"results":{
"featuredCharts":[
{
"id":46082,
"type":"chart",
"name":"Exclusives On Beatport - Week 5",
"slug":"exclusives-on-beatport-week-5",
"description":"",
"publishDate":"2012-01-30",
"price":{
"code":"usd",
"symbol":"$",
"value":2390
},
"audioFormatFee":{
"wav":{
"code":"usd",
"symbol":"$",
"value":1000
},
"aiff":{
"code":"usd",
"symbol":"$",
"value":1000
}
},
"genres":[
{
"id":11,
"name":"Tech House",
"slug":"tech-house",
"type":"genre"
},
{
"id":5,
"name":"House",
"slug":"house",
"type":"genre"
},
{
"id":17,
"name":"Electro House",
"slug":"electro-house",
"type":"genre"
},
{
"id":15,
"name":"Progressive House",
"slug":"progressive-house",
"type":"genre"
}
],
"images":{
"small":{
"width":30,
"height":30,
"url":"http:\/\/geo-media.beatport.com\/items\/imageCatalog\/4000000\/900000\/50000\/1000\/200\/40\/4951247.jpg",
"secureUrl":"https:\/\/media.beatport.com\/items\/imageCatalog\/4000000\/900000\/50000\/1000\/200\/40\/4951247.jpg"
},
"medium":{
"width":60,
"height":60,
"url":"http:\/\/geo-media.beatport.com\/items\/imageCatalog\/4000000\/900000\/50000\/1000\/200\/40\/4951248.jpg",
"secureUrl":"https:\/\/media.beatport.com\/items\/imageCatalog\/4000000\/900000\/50000\/1000\/200\/40\/4951248.jpg"
},
"large":{
"width":130,
"height":130,
"url":"http:\/\/geo-media.beatport.com\/items\/imageCatalog\/4000000\/900000\/50000\/1000\/200\/40\/4951249.jpg",
"secureUrl":"https:\/\/media.beatport.com\/items\/imageCatalog\/4000000\/900000\/50000\/1000\/200\/40\/4951249.jpg"
},
"xlarge":{
"width":500,
"height":500,
"url":"http:\/\/geo-media.beatport.com\/items\/imageCatalog\/4000000\/900000\/50000\/1000\/200\/50\/4951250.jpg",
"secureUrl":"https:\/\/media.beatport.com\/items\/imageCatalog\/4000000\/900000\/50000\/1000\/200\/50\/4951250.jpg"
}
},
"chartOwner":null
},
My classes are currently setup like this.
public class NewReleasesCharts //Root Object
{
public Metadata metadata { get; set; }
public List<ResultHome> results = new List<ResultHome>();
public IEnumerator<ResultHome> GetEnumerator()
{
return this.results.GetEnumerator();
}
}
public class ResultHome
{
public List<FeaturedCharts> featuredCharts { get; set; }
public List<FeaturedReleases> featuredReleases { get; set; }
}
public class FeaturedCharts
{
public int id { get; set; }
public string type { get; set; }
public string name { get; set; }
public string slug { get; set; }
public ChartImages chartImages { get; set; }
}
public class ChartImages
{
public ChartSmall chartSmall { get; set; }
public ChartMedium chartMedium { get; set; }
public ChartLarge chartLarge { get; set; }
}
public class ChartMedium
{
public int width { get; set; }
public int height { get; set; }
public string url { get; set; }
public string secureUrl { get; set; }
}
This is the part I'm stuck on. After deserializing the data I thought about using nested foreach loops, but i currently get an error "Cannot convert type Beatport.Classes.ResultHome' to 'Beatport.Classes.FeaturedCharts". Here is the code.
UPDATE I updated my code per ColinE's answer and I am now getting a NullReferenceException error on the inner foreach loop.
// Deserialize home page data
void jsonHome_GetDataCompleted(object snder, DownloadStringCompletedEventArgs e)
{
try
{
NewReleasesCharts homeData = JsonConvert.DeserializeObject<NewReleasesCharts>(e.Result);
try
{
// Nested foreach loops to dispaly data
foreach (ResultHome rc in homeData)
{
try
{
foreach (FeaturedCharts fc in rc.featuredCharts)
{
// TODO: return name and image of chart
string name = fc.name;
listCharts.Items.Add(name);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
catch (Exception ex)
{
MessageBox.Show(ex.Message);
}
}
I'm still a beginner when it comes to c# so i'm not sure if the nested foreach loops is the right way to go. An example of how to do this properly would give me something to build off of, as i'll need to do this in other parts of my app.
Thanks.
Your second for loop is iterating over the same data as the first. You need to iterate over the featuredCharts property of the variable being iterated in the outer loop:
try
{
NewReleasesCharts homeData = JsonConvert.DeserializeObject<NewReleasesCharts>(e.Result);
// foreach loop to dispaly data
foreach (ResultHome rc in homeData)
{
foreach (FeaturedCharts fc in rc.featuredCharts)
{
// return name and image of chart
}
}
}
To solve this kind of problem in the feature, try setting breakpoints in your code and running in debug mode. You can then inspect the type of each variable to determine what you have done wrong.

Categories

Resources