This is what my logic looks like:
public void SetVideoInfo(string videoID)
{
var url = new RestClient("https://www.googleapis.com/youtube/v3/videos?
part=snippet&fields=items(snippet(title,description))&id=" + videoID +
"&key=somekey");
url.Timeout = -1;
var urlRequest = new RestRequest(Method.GET);
var urlResponse = url.Execute(urlRequest);
var response = JObject.Parse(urlResponse.Content);
var data = (JArray)response["items"];
for (int i = 0; i < data.Count; i++)
{
var videoTitle = data[i]["title"];
var videoDescription = data[i]["description"];
this.VideoTitle = videoTitle.ToString().Trim();
this.VideoDescription = videoDescription.ToString().Trim();
}
}
This is what the API response looks like:
{
"items": [
{
"snippet": {
"title": "some title",
"description": "some description"
}
}
]
}
My current logic gets up to "snippet" but I get nulls for title and description. I just want to know how am I able to get to the title and description attributes.
RestSharp has methods for parsing results directly into proper C# classes, use them instead of messing around with JObjects and JArrays. Off the top of my head, something like this should work.
First, make some classes to hold your data:
public class Root
{
public List<Item> Items { get; set; }
}
public class Item
{
public Snippet Snippet { get; set; }
}
public class Snippet
{
public string Title { get; set; }
public string Description { get; set; }
}
Now call the generic method of RestSharp:
var urlResponse = url.Execute<Root>(urlRequest);
Now you can access the properties in a type-safe way.
var title = urlResponse.Items[0].Snippet.Title
var description = urlResponse.Items[0].Snippet.Description
Related
I am trying to parse manually a string in json. This is how my json look like
{{
"dbViews": [
{
"viewID": 0,
"viewColumns": [
{
"dbTitle": "ColNmid",
"viewTitle": "string",
"activated": true,
"activatedLabel": "Afficher"
},
{
"dbTitle": "ColNmdelete",
"viewTitle": "string",
"activated": true,
"activatedLabel": "Afficher"
}
]
}
],
"AddViewName": "test"
}}
This is how i am trying to read it.
UserViewDto User = new UserViewDto();
dynamic obj = JObject.Parse(json);
User.id = obj.dbViews.viewID;
User.viewName = obj.AddViewName;
foreach (var item in obj.viewColumns)
{
if (obj.dbTitle == "ColNmid")
{
User.ColNmid = obj.viewTitle;
}
}
I can only read addViewName, i can't seem to access viewID or viewColumn.
Update:
after the comments I obviously miss the second array. Here my new code witch work
UserViewDto User = new UserViewDto();
dynamic obj = JObject.Parse(json);
User.viewName = obj.AddViewName;
foreach (var view in obj.dbViews)
{
User.id = view.viewID;
foreach (var item in view.viewColumns)
{
if (item.dbTitle == "ColNmid")
{
User.ColNmid = item.viewTitle;
}
}
}
Your json in question is invalid (extra { and } at start and end). It seems that you are using Newtonsoft's Json.NET library. Usual approach is to create model corresponding to your json structure and deserialize it:
public class Root
{
[JsonProperty("dbViews")]
public List<DbView> DbViews { get; set; }
[JsonProperty("AddViewName")]
public string AddViewName { get; set; }
}
public class DbView
{
[JsonProperty("viewID")]
public long ViewId { get; set; }
[JsonProperty("viewColumns")]
public List<ViewColumn> ViewColumns { get; set; }
}
public class ViewColumn
{
[JsonProperty("dbTitle")]
public string DbTitle { get; set; }
[JsonProperty("viewTitle")]
public string ViewTitle { get; set; }
[JsonProperty("activated")]
public bool Activated { get; set; }
[JsonProperty("activatedLabel")]
public string ActivatedLabel { get; set; }
}
var result = JsonConvert.DeserializeObject<Root>();
You don't need to include all properties in your class, you can include only needed ones.
If you don't want to create custom models and want to loop through the JObject properties in your case you can do it for example like that:
var jObj = JObject.Parse(json);
foreach(var view in jObj["dbViews"]) // dbViews is an array
{
Console.WriteLine(view["viewID"]);
foreach (var viewColumn in view["viewColumns"]) // viewColumns is an array
{
Console.WriteLine(viewColumn["dbTitle"]);
}
}
I am trying to compare json value and based on that i want to update the existing value,for example, currently we have "value" : [r0] in json, i want to compare and if value : [r0] ,then update it to [r0,r1] but iam hiting error that it cannot compare and there is a cast issue, could someone suggest what could be done
public void updateJsonParameter(string file)
{
try
{
var list = new List<string> { "joe", "test" };
JArray array = new JArray(list);
var jobject = JObject.Parse(file);
var ringvalue = (string)jobject["properties"]["parameters"]["ringValue"]["value"]; // unable to case here and compare
jobject["properties"]["parameters"]["ringValue"]["value"] = array; // able to update value but i want to update after comparing the existing values
var result = JsonConvert.SerializeObject(jobject);
}
following is the json format
{
"properties": {
"displayName": "jayatestdefid",
"description": "test assignment through API",
"metadata": {
"assignedBy": "xyz#gmail.com"
},
"policyDefinitionId": "/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test",
"parameters": {
"ringValue": {
"value": ["r0"]
}
},
"enforcementMode": "DoNotEnforce",
}
}
jobject.properties.parameters.ringValue.value is an array ["r0"] with one element "r0". If you want to check if it's an array with one element and that element is "r0", do exactly that:
var ringvalue = jobject["properties"]["parameters"]["ringValue"]["value"];
if(ringvalue.length == 1 && ringvalue[0] == "r0")
jobject["properties"]["parameters"]["ringValue"]["value"] = array;
You could compare the ringvalue (which is an JArray) using JArray.DeepEquals and then replace if the comparison returns true. For example,
var list = new List<string> { "joe", "test" };
JArray array = new JArray(list);
JArray valueToCompare = new JArray(new[]{"r0"});
var ringvalue = (JArray)jobject["properties"]["parameters"]["ringValue"]["value"];
if(JArray.DeepEquals(ringvalue,valueToCompare))
{
jobject["properties"]["parameters"]["ringValue"]["value"] = array;
}
First, as Klaycon said in his answer, it's worth noting that your "value" is not a single string. In json, whenever you see [ and ] then you have a collection, or an array, or a list.
When I work with json strings, I always like to be able to convert them into a strongly typed object. There is a very handy online tool I use all the time: http://json2csharp.com/
I took your json string that you provided and pasted it into that website. Here is that your object(s) look like when converted into c# classes:
public class RootObject // You can name this whatever you want
{
public Properties properties { get; set; }
}
public class Metadata
{
public string assignedBy { get; set; }
}
public class RingValue
{
public List<string> value { get; set; }
}
public class Parameters
{
public RingValue ringValue { get; set; }
}
public class Properties
{
public string displayName { get; set; }
public string description { get; set; }
public Metadata metadata { get; set; }
public string policyDefinitionId { get; set; }
public Parameters parameters { get; set; }
public string enforcementMode { get; set; }
}
Now, we can easily do the logic you need as follows:
// This is your json string, escaped and turned into a single string:
string file = "{ \"properties\": { \"displayName\": \"jayatestdefid\", \"description\": \"test assignment through API\", \"metadata\": { \"assignedBy\": \"xyz#gmail.com\" }, \"policyDefinitionId\": \"/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test\", \"parameters\": { \"ringValue\": { \"value\": [\"r0\"] } }, \"enforcementMode\": \"DoNotEnforce\", }}";
// Convert your json string into an instance of the RootObject class
RootObject jobject = JsonConvert.DeserializeObject<RootObject>(file);
// Get a list of all the "values"
List<string> values = jobject.properties.parameters.ringValue.value;
// Loop over your colleciton of "value" and do your logic
for (int i = 0; i < values.Count; ++i)
{
if (values[i] == "r0")
{
values[i] = "r0,r1";
}
}
// And finally, turn your object back into a json string
var result = JsonConvert.SerializeObject(jobject);
And this is the final result:
{
"properties":{
"displayName":"jayatestdefid",
"description":"test assignment through API",
"metadata":{
"assignedBy":"xyz#gmail.com"
},
"policyDefinitionId":"/providers/Microsoft.Management/managementgroups/MGTest/providers/Microsoft.Authorization/policyDefinitions/test",
"parameters":{
"ringValue":{
"value":[
"r0,r1"
]
}
},
"enforcementMode":"DoNotEnforce"
}
}
Im trying to add a new class called "Company" to a Json Array called Companies. I'm doing this using C# and Json .net Ive tried many different things. I have them all pares out and in Jobjects ready to be molded together but I can't find a way to do so. Im trying to get it to find "Companies" then insert the new company object in there.
This is what im trying to do.
public void CreateNewCompany()
{
Company company = new Company
{
CompanyName = textBox1.Text,
IPO = Convert.ToDouble(textBox2.Text),
Category = CategorycomboBox1.SelectedItem.ToString(),
Description = textBox4.Text,
StartDate = Convert.ToInt32(textBox5.Text)
};
AddProductListItemsToFinishedJSON(company);
AddNewsArticlesListItemsToFinishedJSON(company);
JObject newCompany = JObject.FromObject(company);
string existingFileContents = File.ReadAllText(path);
string newFileContents = newCompany.ToString();
var existingFileContentsToJSON = JObject.Parse(existingFileContents);
var newFileContentsToJSON = JObject.Parse(newFileContents);
Debug.WriteLine(existingFileContents);
SaveJSONFile(company);
}
public void SaveJSONFile(Company localcompany)
{
if (File.Exists(Path.Combine(#"D:\", "comp.json")))
{
File.Delete(Path.Combine(#"D:\", "comp.json"));
}
string RawJSON = JsonConvert.SerializeObject(localcompany);
string FormattedJSON = JToken.Parse(RawJSON).ToString(Formatting.Indented);
//Console.WriteLine(FormattedJSON);
File.WriteAllText(#"D:\comp.json", FormattedJSON);
}
These are the classes
public class Company
{
public string CompanyName { get; set; }
public double IPO { get; set; }
public string Category { get; set; }
public string Description { get; set; }
public int StartDate { get; set; }
public List<Product> Products = new List<Product>();
public List<NewsArticle> CompanySpecificNewsArticles = new List<NewsArticle>();
public List<string> EavesDropperList = new List<string>();
}
public class Product
{
[JsonProperty("ProductName")]
public string ProductName { get; set; }
}
public class NewsArticle
{
[JsonProperty("Type")]
public string Type { get; set; }
[JsonProperty("Content")]
public string Content { get; set; }
}
This is what the Json Looks like and I want to add it to 'Companies'
{
"Companies":[
{
"CompanyName":"",
"IPO":25.0,
"Category":"Gaming",
"Description":"A video game company",
"StartDate":"1-1-2000",
"Products":[
{
"ProductName":""
},
{
"ProductName":""
}
],
"CompanySpecificNewsArticles":[
{
"Type":"Positive",
"Content":"This company has had a very good year!"
},
{
"Type":"Negative",
"Content":"This company has had a very bad year!"
},
{
"Type":"Neutral",
"Content":"This company is doing okay, I guess"
}
],
"CompanySpecificEavesdropper":[
{
"Type":"Positive",
"Content":"This company has had a very good year!"
},
{
"Type":"Negative",
"Content":"This company has had a very bad year!"
},
{
"Type":"Neutral",
"Content":"This company is doing okay, I guess!"
}
]
}
//,
// Other companies omitted
]
}
A JSON file is just a text file, so there's no straightforward way to insert a record into the middle of the file. Instead, you will need to load the entire file into some in-memory representation, add your Company to the "Companies" array, then re-serialize the file back to disk.
To accomplish this, first create the following extension methods:
public class JsonExtensions
{
public static T LoadFromFileOrCreateDefault<T>(string path, JsonSerializerSettings settings = null) where T : new()
{
var serializer = JsonSerializer.CreateDefault(settings);
try
{
using (var file = File.OpenText(path))
{
return (T)JsonSerializer.CreateDefault(settings).Deserialize(file, typeof(T));
}
}
catch (FileNotFoundException)
{
return new T();
}
}
public static void SaveToFile<T>(T root, string path, Formatting formatting = Formatting.None, JsonSerializerSettings settings = null)
{
using (var file = File.CreateText(path))
using (var writer = new JsonTextWriter(file) { Formatting = formatting })
{
JsonSerializer.CreateDefault(settings).Serialize(writer, root);
}
}
}
Now you can add your Company to the array in CreateNewCompany() as follows:
var root = JsonExtensions.LoadFromFileOrCreateDefault<JObject>(Path);
var companiesArray = (JArray)root["Companies"] ?? (JArray)(root["Companies"] = new JArray());
companiesArray.Add(JObject.FromObject(company));
JsonExtensions.SaveToFile(root, Path, Formatting.Indented);
Demo fiddle #1 here.
Incidentally, since your entire file seems to have a fixed schema, you could simplify your code and get slightly better performance by deserializing directly to some root data model, omitting the JObject representation entirely.
First, create the following root data model:
public class CompanyList
{
public List<Company> Companies { get; } = new List<Company>();
}
Then modify CreateNewCompany() as follows:
var root = JsonExtensions.LoadFromFileOrCreateDefault<CompanyList>(Path);
root.Companies.Add(company);
JsonExtensions.SaveToFile(root, Path, Formatting.Indented);
Demo fiddle #2 here.
Notes:
By using generics in JsonExtensions we can use the same code to load from, and save to, a file, for both JObject and CompanyList.
Serializing directly from and to your file without loading to an intermediate string should improve performance as explained in Performance Tips: Optimize Memory Usage.
Company.StartDate is declared to be an int, however in your JSON it appears as a non-numeric string:
"StartDate": "1-1-2000"
You will need to adjust your data model to account for this.
There is no need to manually delete the old file as File.CreateText(String) creates or opens a file for writing UTF-8 encoded text. If the file already exists, its contents are overwritten.
Alternatively you might want to write to a temporary file and then overwrite the old file only after serialization finishes successfully.
It is better to catch the FileNotFoundException from File.OpenText() rather than checking File.Exists() manually in case the file is somehow deleted in between the two calls.
This should give you an idea of what you should be doing
public void CreateNewCompany()
{
Company company = new Company
{
CompanyName = "New Company",
IPO = Convert.ToDouble("0.2"),
Category = "Sample Category",
Description = "Sample Description",
StartDate = Convert.ToInt32("2009")
};
AddProductListItemsToFinishedJSON(company);
AddNewsArticlesListItemsToFinishedJSON(company);
SaveJSONFile(company);
}
public static void SaveJSONFile(Company localcompany)
{
if (File.Exists(path))
{
JObject arr = JObject.Parse(File.ReadAllText(path)));
(arr["Companies"] as JArray).Add(JToken.FromObject(localcompany));
string RawJSON = JsonConvert.SerializeObject(arr);
string FormattedJSON = JToken.Parse(RawJSON).ToString(Formatting.Indented);
File.WriteAllText(path, FormattedJSON);
}
else
{
JObject arr = new JObject();
arr.Add("Companies", new JArray());
(arr["Companies"] as JArray).Add(JToken.FromObject(localcompany));
string RawJSON = JsonConvert.SerializeObject(arr);
string FormattedJSON = JToken.Parse(RawJSON).ToString(Formatting.Indented);
File.WriteAllText(path, FormattedJSON);
}
}
Delete your existing json file then run this code. The first run creates the file with one object while subsequent runs adds object to it. You can refactor the code.
Json file will have the format below
{
"Companies": [
{
"Products": [],
"CompanySpecificNewsArticles": [],
"EavesDropperList": [],
"CompanyName": "New Company",
"IPO": 0.2,
"Category": "Sample Category",
"Description": "Sample Description",
"StartDate": 2009
},
{
"Products": [],
"CompanySpecificNewsArticles": [],
"EavesDropperList": [],
"CompanyName": "New Company",
"IPO": 0.2,
"Category": "Sample Category",
"Description": "Sample Description",
"StartDate": 2009
}
]
}
as per your comment on the order, you can set order on you class like below
public class Company
{
[JsonProperty(Order = 0)]
public string CompanyName { get; set; }
[JsonProperty(Order = 1)]
public double IPO { get; set; }
[JsonProperty(Order = 2)]
public string Category { get; set; }
[JsonProperty(Order = 3)]
public string Description { get; set; }
[JsonProperty(Order = 4)]
public int StartDate { get; set; }
[JsonProperty(Order = 5)]
public List<Product> Products = new List<Product>();
[JsonProperty(Order = 6)]
public List<NewsArticle> CompanySpecificNewsArticles = new List<NewsArticle>();
[JsonProperty(Order = 7)]
public List<string> EavesDropperList = new List<string>();
}
I am trying to deserialize JSON file and want to assign to object ScanResult. var text showing all the values but scanresult showing null some null values. https://gyazo.com/ff2ce386f845394c458a88d43a1f30d8
please suggest if I am missing something.
//MY jSon File SCAN Test 1-1543045410222.json 's code
{
"at": 1543045410222,
"i": 1000,
"s": {
"Sensor1": ["OFF"],
"Sensor2": ["OFF"],
"DataReady1": ["OFF"],
"DataReady2": ["OFF"],
"CV1": [5.0],
"CV2": [6.0]
}
}
//ViewModel Code is as below:
public void ResendScanResult()
{
var ScanActivities = scanActivityManager.GetAll();
foreach (var item in ScanActivities)
{
var scanName = item.ScanName;
var dir = _dataFilePath + scanName + "\\";
var jsonFileName = string.Format("{0}{1}-{2}.json", dir, scanName, item.ScanDateEpoch);
string fileName = Path.GetFileName(jsonFileName);
// ScanResult scanResult = new ScanResult();
var text = File.ReadAllText(jsonFileName);
//var scanResults = JsonConvert.DeserializeObject<ScanResult>(text);
Common.Model.ScanResult scanResult = JsonConvert.DeserializeObject<Common.Model.ScanResult>(text);
var Mvm = MonitorViewModel.Instance;
// TargetProvider target = Mvm.GetTargetProvider(scanResult);
// Mvm.PublishToServer(target, scanResult);
}
}
and my scanRescult class code is as below :
namespace ABX.Common.Model
{
public class ScanResult
{
public ScanResult()
{
At = DateTimeOffset.Now.ToUnixTimeMilliseconds();
Interval = 1;
}
public string Name { get; set; }
public long At { get; set; }
public long Interval { get; set; }
public JObject Values { get; set; }
public string FileName { get; set; }
public JObject ToJson()
{
JObject json = new JObject
{
{ "at", At },
{ "i", Interval },
{ "s", Values }
};
return json;
}
Either rename your class properties to match your JSON, rename your JSON to match your class properties, or implement a custom JsonConverter, where you can implement arbitrary mapping.
I do a request to a api that I'm using and this is the response that I get back.
{ "id": 1139, "performanceStatus": "OK", "availabilityStatus": "OK" }
I would like to convert this response in a list where I then can use a for/foreach loop and later can use linq and SelectMany to create a whole new list.
I got this far, but I am stuck the code is not hitting the var "newJson"..
Can someone help me out?
var json = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
dynamic parsedJson = JObject.Parse(json);
foreach (var j in parsedJson)
{
j.Replace(JObject.FromObject(
new {
id = j.id,
performance = j.performanceStatus,
availability = j.availabilityStatus
}));
}
var newJson = parsedJson.ToString();
Later I would like to Deserialize it into a strongly typed class. Like so
boi = await Task.Run(() => JsonConvert.DeserializeObject<Boi>(newJson)).ConfigureAwait(false);
Here is the strongly typed class
public class Boi
{
public int Id { get; set; }
public string PerformanceStatus { get; set; }
public string AvailabilityStatus { get; set; }
}
public class NewBoi
{
public List<Boi> eeg { get; set; }
}
You could do this:
var jsn = "{ \"id\": 1139, \"performanceStatus\": \"OK\", \"availabilityStatus\": \"OK\" }";
var bois = new List<Boi> { JsonConvert.DeserializeObject<Boi>(jsn) };
var newBoi = new NewBoi() { eeg = bois };
Although I would question the need for the NewBoi class - you could just work with the List.
To deserialize to a well known type use
JsonConvert.Deserialize<T>(jsonString,new JsonSerializerSettings
{
ContractResolver = new CamelCasePropertyNamesContractResolver()
});
where T is your well known type.