How to create the Google DataTable JSON expected source using C#? - c#

How can I create the JSON source expected by the google.visualization.datatable using C#? Obviously using the JavaScriptSerializer is out of the question since the expected JSON has a weird structure as described on the documentation:
var dt = new google.visualization.DataTable(
{
cols: [{id: 'task', label: 'Task', type: 'string'},
{id: 'hours', label: 'Hours per Day', type: 'number'}],
rows: [{c:[{v: 'Work'}, {v: 11}]},
{c:[{v: 'Eat'}, {v: 2}]},
{c:[{v: 'Commute'}, {v: 2}]},
{c:[{v: 'Watch TV'}, {v:2}]},
{c:[{v: 'Sleep'}, {v:7, f:'7.000'}]}
]
},
0.6
)

Though I'm not familiar in the .NET environment, there is a .NET helper for the Google Visualization API called bortosky-google-visualization. The library writes a JSON Google DataTable from a System.Data.DataTable object.

Another way to achieve this is to use the Google DataTable .Net Wrapper (https://googledatatablelib.codeplex.com/) which gives a possibility to work with a strongly typed System.DataTable that can then be converted into the google.datatable visualization JSON format.
This server side code
public string GetStatisticsForChart(string messageCode)
{
//some repository that returns data....
var data = _statisticsRepository.GetPerMessage(messageCode);
//It simply returns a list of objects with Year and Count properties.
var query = (from t in data
group t by new {t.TimeStamp.Year}
into grp
select new
{
grp.Key.Year,
Count = grp.Count()
}).ToList();
//let's instantiate the DataTable.
var dt = new Google.DataTable.Net.Wrapper.DataTable();
dt.AddColumn(new Column(ColumnType.String, "Year", "Year"));
dt.AddColumn(new Column(ColumnType.Number, "Count", "Count"));
foreach (var item in query)
{
Row r = dt.NewRow();
r.AddCellRange(new Cell[]
{
new Cell(item.Year),
new Cell(item.Count)
});
dt.AddRow(r);
}
//Let's create a Json string as expected by the Google Charts API.
return dt.GetJson();
}
would generate the following JSON output
{
"cols": [
{"type": "string", "id": "Year", "label": "Year"},
{"type": "number", "id": "Count", "label": "Count"}
],
"rows": [
{"c": [{"v": "2011"}, {"v": "1860"}]},
{"c": [{"v": "2012"}, {"v": "2000"}]}
]
}
and this can be used either in Asp.NET WebAPI or directly in the ASP.NET MVC controller.

The expected JSON in the example above is not JSON but a Javascript object literal. JSON is only a subset of Javascript object literal notation, but the example above should (and does) also work, if the Google DataTable is initialized with a similar looking JSON. (To get proper JSON just put double quotes around the keys.)
So actually you can use the DataContractJsonSerializer or JavaScriptSerializer to construct JSON for the Google DataTable. However, if your starting point is a System.Data.DataTable it is probably easier to use the library mentioned in the answer above.

The best way to create google charts datatable via c# is to iterate data and fill model class and return filled model as JSON , here is the model representation :-
public class GChartsDataTbl
{
public List<Col> cols { get; set; }
public List<Row> rows { get; set; }
}
public class Col
{
public string id { get; set; }
public string type { get; set; }
}
public class C
{
public string v { get; set; }
public object f { get; set; }
}
public class Row
{
public List<C> c { get; set; }
}

Related

How to get element value from response data to json

Im writing an API automation test with RestSharp.Any kind of help will be greatly appreciated!
I'm getting data values from the response & I need to write few values to my json file (which I will use for another test putting them as a body).
I managed to get 1 value from JArray but I need 2 more values and I cant wrap my head around how to do that.
Im attaching my api test code & the data I get from the response + the data I managed to write into my json file.
The value that I managed to get: FsNumber (declared it as financialNumber). What I need to add to the json: subjectName + subjectCode (they will be declared as companyName/companyCode). How do I access "Query" list with SubjectName/SubjectCode?
TEST
var queryResult = client.Execute<object>(request);
var data = JsonConvert.SerializeObject(queryResult.Data);
var jsonParse = JToken.Parse(data);
var fsObject = jsonParse.Value<JToken>("FinanceReportList");
var fsArray = fsObject.Value<JArray>("List");
foreach (var fs in fsArray)
{
var cfn = fs.Value<string>("FsNumber");
var queryObject = new DataQuery
{
financialNumber = cfn,
};
var queryObjectString = JsonConvert.SerializeObject(queryObject);
File.WriteAllText(#"C:\Users\TestAPI\myJsonWithValues.json", queryObjectString);
}
Data I get from the response:
{
"RequestDate": "2021-07-16",
"Message": "Active",
"ProductNumber": 666,
"Language": "EN",
"RequestId": "reqID666",
"Query": {
"SubjectCode": "MY-SUBJECT",
"SubjectName": "MY-NAME"
},
"FinanceReportList": {
"List": [
{
"FsNumber": "MY-NUMBER",
"Year": 2021,
So far I managed to get FsNumber to my myJsonWithValues.json file as this:
{"financialNumber":"MY-NUMBER","companyName":null,"companyCode":null}
What Im trying to do is, my json should look like
{"financialNumber":"MY-NUMBER","companyName":MY-NAME,"companyCode":MY-CODE}
You have to access "Query" object
var fsQuery = jsonParse.Value<JToken>("Query")
and use Children() method to access properties of "Query"
var children = fsQuery.Children();
It is a good practice to implement a class that encapsulates your resonse and deserialize it with JsonConvert.Deserialize eg.
public class Account
{
public string Email { get; set; }
public bool Active { get; set; }
public DateTime CreatedDate { get; set; }
public IList<string> Roles { get; set; }
}
Account account = JsonConvert.DeserializeObject<Account>(json);
Instead of using JObjects

Serialize JSON with numbers as property names

How can I serialize a DataTable which contains a list of phone numbers, BodyOverride and ChannelType to this structure? The final JSON should look like the sample below. I see some posts that suggest using a Dictionary, but not I'm not sure if I can achieve this.
{
"Addresses": {
"+1713XXXXXXX": {
"BodyOverride": "sent",
"ChannelType": "SMS"
},
"+1832XXXXXXX": {
"BodyOverride": "this is a text from PINPOINT",
"ChannelType": "SMS"
}
}
}
Try a using class structure like this:
public class Payload
{
public Dictionary<string, Item> Addresses { get; set; }
}
public class Item
{
public string BodyOverride { get; set; }
public string ChannelType { get; set; }
}
Assuming you are starting from a DataTable that looks like this:
DataTable dataTable = new DataTable();
dataTable.Columns.Add("Address");
dataTable.Columns.Add("BodyOverride");
dataTable.Columns.Add("ChannelType");
dataTable.Rows.Add("+1713XXXXXXX", "sent", "SMS");
dataTable.Rows.Add("+1832XXXXXXX", "this is a text from PINPOINT", "SMS");
...you can easily convert it to the desired class structure like this:
var payload = new Payload
{
Addresses = dataTable.Rows
.Cast<DataRow>()
.ToDictionary(row => (string)row["Address"],
row => new Item
{
BodyOverride = (string)row["BodyOverride"],
ChannelType = (string)row["ChannelType"]
})
};
...and finally serialize it to JSON using a decent serialization library like Json.Net:
string json = JsonConvert.SerializeObject(payload, Formatting.Indented);
Fiddle: https://dotnetfiddle.net/b7Ckzs
Important note: the above solution assumes that the phone numbers in the Address column will be distinct across all rows in the DataTable. If they are not, then this solution will not work, because dictionary keys are required to be unique. In that case you will need to split the data into multiple batches, or find some other solution to deal with duplicates.

Return JSON from MongoDb without $date

I am using MongoDb with C# in a WebApi app. My data does not lend well to mapped data types due to the dynamic nature of the document stored. For example, here is an example of some data. Note the Data section with values that can either be arrays or a single string (Technician):
{
"_id" : "5a59129d16d5c42f7444b83d",
"CreatedDate" : "2018-01-09T20:30:19.455Z",
"Data" : {
"AlcoholTest" : [
{
"Technician" : [
"STT",
"BAT"
],
"TestReason" : "not well"
}
]
}
}
When I attempt to return the data like above, I get this instead:
{
"_id": {
"$oid": "5a59129d16d5c42f7444b83d"
},
"CreatedDate": {
"$date": 1515529819455
},
"Data": {
"AlcoholTest": [
{
"Technician": [
"STT",
"BAT"
],
"TestReason": "drunk"
}
]
}
}
Here is the code I'm using:
public object FindById(string id)
{
var filter = new BsonDocument { { "_id", ObjectId.Parse(id) } };
var result = _collection2.Find(filter);
var note = result.Any() ? result.First() : null;
var json = note.ToJson(new JsonWriterSettings{OutputMode = JsonOutputMode.Strict});
return JObject.Parse(json);
}
I can't just return the note object since Newtonsoft does not know how to convert those $data and $oid into valid types and returns a parsing error.
When I attempted to use MongoDb mapping classes in .NET, this is what my class looked like (I'm not including the BsonClassMap.RegisterClassMap stuff for simplicity):
public class Note
{
public string Id { get; set; }
public DateTime? CreatedDate { get; set; }
public IDictionary<string, IList<IDictionary<string, object>>> Data { get; set; }
}
When I tried this code, the Newtonsoft did not know how to handle the case where the object in IList<IDictionary<string, object>> could be an array or string and saved some rather nasty JArray and JObject data instead.
So here are my questions:
Is there a way to make the above C# code return identical JSON as what is represented in the Mongo database (or what the UI is sending and expecting to get back)?
Or is there a way to map my Data document using .NET types that would allow me to use MongoDb mapping classes that accepts either string values, arrays, or both?
I ended up using a different approach for save vs get. For saving, I converted a generic object to BsonDocument, and saved it as it. This resulted in the data format I was expecting (first data format my above question).
I used a strongly-typed collection to get data from the MongoDB so I could avoid the second data format from my question above. To get the data returned in the correct format, I changed this property from
public IDictionary<string, IList<IDictionary<string, IList<string>>>> Data { get; set; }
to
public IDictionary<string, object> Data { get; set; }
This gave me the correctly formatted data I needed. Having two MongoDb collections for getting vs saving was not ideal, but it eliminated my original hack to parse the dictionary BsonDocument into my strongly-typed POCO.

Deserialize only one property of a JSON file

I am faced with a problem.
I want to deserialize a complex JSON response from a server, but I only need one part of it.
Here is an example:
{
"menu": {
"id": "file",
"value": "File",
"popup": {
"menuitem": [
{"value": "New", "onclick": "CreateNewDoc()"},
{"value": "Open", "onclick": "OpenDoc()"},
{"value": "Close", "onclick": "CloseDoc()"}
]
}
}
}
I also used Csharp2json to get the class objects that I need, I just modified the menu class according to my needs :
public class Menuitem
{
public string value { get; set; }
public string onclick { get; set; }
}
public class Popup
{
public IList<Menuitem> menuitem { get; set; }
}
public class Menu
{
public Popup popup { get; set; }
}
public class RootObjectJourney
{
public Menu menu { get; set; }
}
Now, how do I deserialize if I only need the popup value and his children?
You can actually utilize the Linq namespace of the NewtonSoft.Json and modify your code little bit to get only the "popup" elements from the JSON.
your class structure remains the same. Make sure you use the namespace(s)
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
then in your code once you have the JSON string with you, you can use the "JObject" static method "Parse" to parse the JSON, like
var parsedObject = JObject.Parse(jsonString);
This will give you the JObject with which you can access all your JSON Keys just like a Dictionary.
var popupJson = parsedObject["menu"]["popup"].ToString();
This popupJson now has the JSON only for the popup key.
with this you can use the JsonConvert to de- serialize the JSON.
var popupObj = JsonConvert.DeserializeObject<Popup>(popupJson);
this popupObj has only list of menuitems.
If you do not use Newtonsoft and are using System.Text.Json in .NET Core, you can use this:
var post = JsonDocument.Parse(stringifiedJson);
var cat = post.RootElement.GetProperty("category").GetString();
You see GetString here to cast the value to string, there are other overloads available to cast the json value to Int32 etc.
If the intend is to deserialize only one property, I generally perefer to use JsonPath due to its flexibility. Please check the code below
var jsonQueryString = "{ 'firstName': 'John',
'lastName' : 'doe',
'age' : 26,}";
JObject o = JObject.Parse(jsonQueryString);
JToken token= o.SelectToken("$.age");
Console.WriteLine(token);
If your Json is complex, you can use power of JsonPath.
you can check https://support.smartbear.com/readyapi/docs/testing/jsonpath-reference.html#examples for JsonPath detailed documentation and examples.
I also included example below for further usage information:
JObject o = JObject.Parse(#"{
'store': {
'book': [
{
'category': 'history',
'author': 'Arnold Joseph Toynbee',
'title': 'A Study of History',
'price': 5.50
},
...
]
},
'expensive': 10
}");
//gets first book object
Console.WriteLine(o.SelectToken("$..book[0]"));
//get first book's title
Console.WriteLine(o.SelectToken("$..book[0].title"));
// get authors of the books where the books are cheaper then 10 $
foreach (var token in o.SelectTokens("$..[?(#.price < 10)].author"))
Console.WriteLine(token);
.NET 5+
The solution is very simple:
using System.Text.Json;
var doc = JsonDocument.Parse(response.Content);
var popupJson= doc.RootElement.GetProperty("menu").GetProperty("popup");

Alter Json or ExtensionDataObject

I have a Json service I cannot alter as it is not mine.
Their Json is a formatted in a way that parsing it is difficult. It looks something like this.
"people": {
"Joe Bob": {
"name": "Joe Bob",
"id": "12345"
},
"Bob Smith": {
"name": "Bob Smith",
"id": "54321"
}
},
I would really prefer this was laid out like a JSon array, however it presently is not.
I am wondering the best approach here. Should I alter the Json to look like an array before I parse it or load up the ExtensionData and parse it from that?
There are other items in the feed that I do not have issue with. Just stuck with this one section.
Thanks
You can use json.net to deserialize the data (the json you pasted, and doing only one parsing, without modifying anything).
using dynamic foo = JsonConvert.DeserializeObject<dynamic>(data)
than, you can iterate the list using foo.people, accessing the Name and Value.
you can create a class (if you know what the schema is, and to deserialize the data into a list of the given class such as:
public class People
{
[JsonProperty(PropertyName="people")]
public IDictionary<string, Person> Persons { get; set; }
}
public class Person
{
[JsonProperty(PropertyName="name")]
public string Name { get; set; }
[JsonProperty(PropertyName = "id")]
public string Id { get; set; }
}
and than call:
var obj = JsonConvert.DeserializeObject<People>(data);
foreach (var item in obj.Persons.Values)
{
//item is instance of Person
}
Another good and possible option will be:
How can I navigate any JSON tree in c#?

Categories