Parsing JSON using LINQ - c#

Hello I am facing a very simple problem but it is not getting Solved. Here is my class design
public class Program
{
public string ProgramName { get; set; }
public string ProgramTime { get; set; }
public string ProgramDetails { get; set; }
}
public class Listing
{
public string ChannelName { get; set; }
public string NowShowing { get; set; }
public string NowShowingTime { get; set; }
public string NowShowingDescription { get; set; }
public string NowShowingPicture { get; set; }
public List<Program> Programs { get; set; }
}
public class RootObject
{
public string status { get; set; }
public string about { get; set; }
public List<Listing> listings { get; set; }
}
I am parsing using the following code.
JObject json = JsonConvert.DeserializeObject(e.Result) as JObject;
Listing ls = new Listing
{
ChannelName = (string)json["listings"].Children()["ChannelName"],
NowShowing = (string)json["listings"].Children()["NowShowing"],
Programs = new Program
{
ProgramName = (string)json["listings"]["Program"]["ProgramName"]
}
};
Help me solve my lame approach. My concerns are parsing the items correctly and also how to add them to the nested list "Programs". The second one is more crucial.
Sample Json input-
{
"listings": [
{
"ChannelName": "NTV BANGLA",
"NowShowing": "Ei Shomoy (R)",
"NowShowingTime": "12:10",
"NowShowingDescription": "Ei Shomoy is a daily talk show ........",
"Programs": [
{
"ProgramName": "Ainer Chokhe (R)",
"ProgramTime": "13:00",
"ProgramDetails": "Human Rights and law based program Ainer Chokhe,"
},
{
"ProgramName": "Shonkhobash",
"ProgramTime": "15:10",
"ProgramDetails": "Drama serial Shonkhobash, script by Bipasha Hayat and"
}
]
},
{
"ChannelName": "CHANNEL i",
"NowShowing": "Taroka Kothon (Live)",
"NowShowingTime": "12:30",
"NowShowingDescription": "City Cell Taroka Kothon Live is a talk show ",
"Programs": [
{
"ProgramName": "Channel i Top News",
"ProgramTime": "13:00",
"ProgramDetails": "Mutual Trust Bank top news (Shirsho Shongbad)"
},
{
"ProgramName": "Ebong Cinemar Gaan",
"ProgramTime": "13:10",
"ProgramDetails": "Ebong Cinemar Gaan, a musical show based on "
}
]
}
]
}
EDIT1
var customers = JsonConvert.DeserializeObject<RootObject>(e.Result);
Listing ls = new Listing
{
ChannelName = customers.listings.First().ChannelName,
NowShowing=customers.listings.First().NowShowing,
Programs=??
};

if e.Result is string with your JSON try this
var jss = new JavaScriptSerializer();
var o = jss.Deserialize<RootObject>(e.Result);
UPDATE
possibly you need something like this
var customers = JsonConvert.DeserializeObject<RootObject>(e.Result);
Listing ls = new Listing
{
ChannelName = customers.listings.First().ChannelName,
NowShowing=customers.listings.First().NowShowing,
Programs=customers.listings.First().Programs
};
UPDATE2
if you want based on existing you can try comething like this
var customers = JsonConvert.DeserializeObject<RootObject>(e.Result);
Listing ls = new Listing
{
ChannelName = customers.listings.First().ChannelName,
NowShowing=customers.listings.First().NowShowing,
Programs=customers.listings.First().Programs.Select(p=>new Program{
ProgramName=p.ProgramName,
ProgramTime=p.ProgramTime,
ProgramDetails = p.ProgramDetails
}).ToList()
};
UPDATE3
or if you whant simply random you can try something like this
var customers = JsonConvert.DeserializeObject<RootObject>(e.Result);
Listing ls = new Listing
{
ChannelName = customers.listings.First().ChannelName,
NowShowing=customers.listings.First().NowShowing,
Programs=Enumerable.Range(1,10).Select(p=>new Program{
ProgramName="generated name",
ProgramTime="generated time",
ProgramDetails = "generated details"
}).ToList()
};

Use DataContractJsonSerializer to parse json string in windows phone.
MemoryStream memoryStream = new MemoryStream(Encoding.Unicode.GetBytes(e.Result));
DataContractJsonSerializer dataContractJsonSerializer = new DataContractJsonSerializer(typeof(List<RootObject>));
RootObject itemDataList = dataContractJsonSerializer.ReadObject(memoryStream) as RootObject;
ChannelName = itemDataList.listings.First().ChannelName;

Related

Add value in json in each records

I have json format as below. In that I have multiple records coming, check below json.
{
"metadata":{
"TotalCount":11,
"CurrentPageNumber":1,
},
"records":[
{
"offerId":"e1b75d86-67b1-4557-a381-5474383da3fb",
"isContract":true,
"transportRouteId":"e1b75d86-67b1-4557-a381-5474383da3fb",
"transportOrderId":"SEZYMY-210720-010097",
"schedule":null,
},
]
}
Now I want to add new value in each this records array, so how can I do that.
I want to add this value : ("carrierExpiredDate", (carrierExpiredDate.ComplianceExpiryDate.Value).Date);
So this new json should look like this.
{
"metadata":{
"TotalCount":11,
"CurrentPageNumber":1,
},
"records":[
{
"offerId":"e1b75d86-67b1-4557-a381-5474383da3fb",
"isContract":true,
"transportRouteId":"e1b75d86-67b1-4557-a381-5474383da3fb",
"transportOrderId":"SEZYMY-210720-010097",
"schedule":null,
"carrierExpiredDate": (carrierExpiredDate.ComplianceExpiryDate.Value).Date)
},
]
}
var json =
#"{
"metadata":{
"TotalCount":11,
"CurrentPageNumber":1,
},
"records":[
{
"offerId":"e1b75d86-67b1-4557-a381-5474383da3fb",
"isContract":true,
"transportRouteId":"e1b75d86-67b1-4557-a381-5474383da3fb",
"transportOrderId":"SEZYMY-210720-010097",
"schedule":null
},
]
}";
var jObject = JObject.Parse(json);
var jList=jObject["records"].Children().ToList();
foreach(var jtoken in jList)
{
jtoken["carrierExpiredDat"] = (carrierExpiredDate.ComplianceExpiryDate.Value).Date));
}
string output = Newtonsoft.Json.JsonConvert.SerializeObject(jObject, Newtonsoft.Json.Formatting.Indented);
Try this. The code was tested using Visual Studio and Postman
.....
var expDate=DateTime.Now;
var json = await response.Content.ReadAsStringAsync()
var deserializedJson = JsonConvert.DeserializeObject<TransportRoot>(json);
deserializedJson.Records.ForEach(i=> i.carrierExpiredDate=expDate);
var newJson= JsonConvert.SerializeObject(deserializedJson);
classes
public class Metadata
{
public int TotalCount { get; set; }
public int CurrentPageNumber { get; set; }
}
public class Record
{
public string offerId { get; set; }
public bool isContract { get; set; }
public string transportRouteId { get; set; }
public string transportOrderId { get; set; }
public object schedule { get; set; },
public object carrierExpiredDate { get; set; }
}
public class TransportRoot
{
public Metadata Metadata { get; set; }
public List<Record> Records { get; set; }
}
if you have a problem with a camel case json, I highly recommend to change your startup
services.AddControllers()
// or services.AddControllersWithViews()
.AddNewtonsoftJson(options =>
options.SerializerSettings.ContractResolver =
new CamelCasePropertyNamesContractResolver());

Adding JObject to JArray

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>();
}

Issue with accessing json nodes from C#

I have a json file that needs to be saved as sql server table. This is test.json that has Student details with coursework.
[{
"Studentid": "001006360",
"Grade": "2",
"ExtraWork": {
"TopRecommended": ["000133692",
"102067155",
"887273865"],
"OtherCourses": ["228963647",
"138909237",
"899791144",
"216165613",
"113239563"]
},
"Courses": [{
"smalldesc": "this is a test ",
"Details": {
"description": "Summary of the course",
"collegeCode": "32466"
}
},
{
"smalldesc": "Second test",
"Details": {
"description": "Business- Course Summary",
"collegeCode": "32469"
}
}]
}]
Below is the C# program.
I do not know how to access "smalldesc" and "collegeCode".
var jsonText = File.ReadAllText(#"C:\test.json");
var ser = JsonConvert.DeserializeObject<List<RootObject>>(jsonText);
for (int i = 0; i < ser.Count; i++)
{
string Studentid = ser[i].Studentid;
string Grade = ser[i].Grade;
var result = JsonConvert.DeserializeObject<List<Course>>(jsonText);
for (int k = 0; k < result.Count; k++)
{
string smalldesc = result[k].smalldesc;
string collegeCode = result[k].Details.collegeCode;
}
}
Json object class definition:
public class ExtraWork
{
public List<string> TopRecommended { get; set; }
public List<string> OtherCourses { get; set; }
}
public class Details
{
public string description { get; set; }
public string collegeCode { get; set; }
}
public class Course
{
public string smalldesc { get; set; }
public Details Details { get; set; }
}
public class RootObject
{
public string Studentid { get; set; }
public string Grade { get; set; }
public ExtraWork ExtraWork { get; set; }
public List<Course> Courses { get; set; }
}
what's the best way to save to sql server tables.
This line:
var ser = JsonConvert.DeserializeObject<List<RootObject>>(jsonText);
Is already doing all the deserialization for you, there is no need to call it again inside a loop.
Your code can be as simple as this:
var ser = JsonConvert.DeserializeObject<List<RootObject>>(jsonText);
foreach (var s in ser)
{
string Studentid = s.Studentid;
string Grade = s.Grade;
foreach(var course in ser.Courses)
{
string smalldesc = course .smalldesc;
string details = course .Details.collegeCode;
}
}
FYI: using a foreach loop is much simpler to work with when iterating a collection (assuming your collection type implements IEnumerable which most of the included collections will).

C# JObject parsing

How to parse this json object???
{{
"track": "t1",
"category": {
"c1": {
"skills": [
"s1"
]
},
"c2": {
"skills": [
"s1",
"s2"
]
}
}
}}
This is what I've tried so far and yet I don't understand how to do this in c#.
This is my first time doing c# projects and still not able to move from JAVA to C#
[HttpPost]
[Route("api/TCSAPI/SaveTCS")]
public HttpResponseMessage SaveTCS([FromBody] dynamic tcsObject)
{
JToken token = JObject.Parse(tcsObject.ToString());
string track = token.SelectToken("track").ToString();
List<JToken> category = token.SelectToken("category").ToList();
foreach (var cat in category) {
var data = cat;
// dont know after this
}
return Helper.ComposeResponse(HttpStatusCode.OK, string.Empty);
}
The problem with the JSON is {{ and }} so you need to trim the JSON string to make it { and }
string jsonstr = File.ReadAllText(YourJSONFile);
jsonstr = jsonstr.Replace("{{", "{");
jsonstr = jsonstr.Replace("}}", "}");
and then you can install Newtonsoft JSON to deseralize the JSON.
Your class sturcture would look something like this
public class C1
{
public List<string> skills { get; set; }
}
public class C2
{
public List<string> skills { get; set; }
}
public class Category
{
public C1 c1 { get; set; }
public C2 c2 { get; set; }
}
public class DataItem
{
public string track { get; set; }
public Category category { get; set; }
}
Then you can deseralize it like
var ser = JsonConvert.DeserializeObject<DataItem>(jsonstr);
Edit
Since C1 and C2 are dynamic you can use class like this
public class SomeCat
{
public List<string> skills
{
get;
set;
}
}
public class DataItem
{
public string track
{
get;
set;
}
public Dictionary<string, SomeCat> Category
{
get;
set;
}
}
and deseralize it like
string jsonstr = File.ReadAllText(YourJSON);
jsonstr = jsonstr.Replace("{{", "{");
jsonstr = jsonstr.Replace("}}", "}");
var ser = JsonConvert.DeserializeObject<DataItem>(jsonstr);
The screenshot to see how the data looks and you can access it using the index.

Json parse sub-collection in c#

How can I do JSON in C# like the data below ?
{
"Aliases": [ "teddy", "freddy", "eddy", "Betty" ],
"Name":"reacher gilt",
"Address":"100 East Way",
"Age":74,
"Bars": {
"items": [
{
"Sub_Property1":"beep",
"Sub_Property2":"boop"
},
{
"Sub_Property1":"meep",
"Sub_Property2":"moop"
},
{
"Sub_Property1":"feep",
"Sub_Property2":"foop"
}
]
}
}
Actually my problem is inside the sub-collection. I saw someone did something
like this
person.Bars.Add("items",
new List<BarClass>(new[]{
new BarClass("beep","boop"),
new BarClass("meep","moop"),
new BarClass("feep","foop"),
}));
So, I have to add new BarClass("beep","boop"), but I need to do something
like this
String [] no1 = {1,2,3}
String [] no2 = {4,5,6}
person.Bars.Add("items",
new List<BarClass>(new[]{
for ()
{
new BarClass(no1[i],no2[i])
}
}));
How can i do this? Thanks and please help..
To read the JSON
The best way to read the whole JSON is to Deserialize it to a native C# object. If you do not already have the classes with your, you can create it in Visual Studio as
Copy your JSON text
Create a new empty class file in VS
Edit > Paste Special > Paste JSON As Classes
Here are the classes
public class Person
{
public string[] Aliases { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public int Age { get; set; }
public Bars Bars { get; set; }
}
public class Bars
{
public Item[] items { get; set; }
}
public class Item
{
public string Sub_Property1 { get; set; }
public string Sub_Property2 { get; set; }
}
Now you can use some .NET JSON library to deserialize. JSON.Net aka Newtonsoft JSON is a great library. You get get it from NuGet as well.
Then it's pretty easy to get the C# object from the JSON
//using Newtonsoft.Json;
var jsonString = File.ReadAllText(#"C:\YourDirectory\person.json");
var person = JsonConvert.DeserializeObject<Person>(jsonString);
If you want to read the sub-collection only, you can rather use Linq-to-JSON to read the items directly, like this
//using Newtonsoft.Json.Linq;
var jObject = JObject.Parse(jsonString);
List<Item> details = jObject["Bars"]["items"].ToObject<List<Item>>();
To create the JSON
You first need to create the object, then Serialize to JSON
string[] subProperties1 = new string[] { "1", "2", "3" };
string[] subProperties2 = new string[] { "4", "5", "6" };
Person person = new Person { Name = "Johny", Age = 7, Address = "Earth", Aliases = new string[] { "Sony", "Monty" } };
person.Bars = new Bars {
items = subProperties1.Zip(subProperties2,
(prop1, prop2) => new Item { Sub_Property1 = prop1, Sub_Property2 = prop2 })
.ToArray() };
var json = JsonConvert.SerializeObject(person);
To create the items from your existing string arrays, I have used IEnumerable.Zip function from Linq. You can read about them here.
This is the created JSON data
{
"Aliases": [ "Sony", "Monty" ],
"Name": "Johny",
"Address": "Earth",
"Age": 7,
"Bars": {
"items": [
{
"Sub_Property1": "1",
"Sub_Property2": "4"
},
{
"Sub_Property1": "2",
"Sub_Property2": "5"
},
{
"Sub_Property1": "3",
"Sub_Property2": "6"
}
]
}
}
You should create some classes
public class Person
{
public string Name {get;set;}
public string Address{get;set;}
public int Age {get;set;}
public Header {get;set;}
}
public class Header
{
public Detail[] Details {get;set;}
}
public class Detail
{
public string Sub1 {get;set;}
public string Sub2 {get;set;}
}
Create instance from Person class and initialize to instance after than
JavaScriptSerializer serializer =new JavaScriptSerializer();
var result=serializer.Serialize(instanceOfPerson);
"result" is json data
Assuming that you mean you want to create JSON string, you need to create those classes and use something like Newtonsoft JSON.net:
public class Item
{
public string Sub_Property1 { get; set; }
public string Sub_Property2 { get; set; }
}
public class Bars
{
public List<Item> items { get; set; }
}
public class Person
{
public List<string> Aliases { get; set; }
public string Name { get; set; }
public string Address { get; set; }
public int Age { get; set; }
public Bars Bars { get; set; }
}
Please read the documentation here: http://www.newtonsoft.com/json/help/html/Introduction.htm

Categories

Resources