Formating Json data from string and Datatable - c#

I have a situation where I need to format json data into below .
[WebMethod]
public static string ConvertDatadttoString(string appName)
{
var sample = new List<SampleClass>
{
new SampleClass()
{
columns = new List<SampleItem>()
{
new SampleItem() {title = "NAME" },
new SampleItem() {title = "COUNTY" },
},
data = new List<List<string>>()
{
new List<string> { "John Doe", "Fresno" },
new List<string> { "Billy", "Fresno" },
new List<string> { "Tom", "Kern" },
new List<string> { "King Smith", "Kings" },
}
}
};
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(sample);
return json;
}
public class SampleClass
{
public IEnumerable<SampleItem> columns { get; set; }
public IEnumerable<IEnumerable<string>> data { get; set; }
}
public class SampleItem
{
public string title { get; set; }
}
The above code is giving the correct json data for me, but I need to do some modifications in the code so that it can intake data from my source.First of all new SampleItem() {title = "NAME" }, needs to be populated from stringarray which is like
string columnNames = "Name,County";
string[] arrcolumnNames = columnNames.Split(',');
and secondly,new List<string> { "John Doe", "Fresno" }, needs to be populated from .net DataTable. How to do it.
I tried to add for loop and add the values from string array:
for(int i = 0; i <= arrcolumnNames.Length; i++)
{
new SampleItem() { title = arrcolumnNames[i] }
}
but I'm getting an error.

Try this
public static string ConvertDatadttoString(string appName = "")
{
var columnNames = "Name,County";
var employees = CreateEmployeesTable();
var sample = new List<SampleClass>
{
new SampleClass()
{
columns = columnNames.Split(',').Select(x=> new SampleItem
{
title = x
}),
data = employees.AsEnumerable().Select(row=> new List<string>
{
row.Field<string>("EmployeeName"),
row.Field<string>("Company")
})
}
};
var serializer = new JavaScriptSerializer();
var json = serializer.Serialize(sample);
return json;
}
The private method CreateEmployeesTable
private DataTable CreateEmployeesTable()
{
var table = new DataTable()
{
Columns = { "EmployeeName", "Company" },
TableName = "Employees"
};
table.Rows.Add("John Doe", "Fresno");
table.Rows.Add("Billy", "Fresno");
table.Rows.Add("Tom", "Kern");
table.Rows.Add("King Smith", "Kings");
return table;
}
Update
DataRowExtensions.Field Method has five overload.
The integer overload that accepts an integer (index). If you want to get the first column the index will be 0. So call it like row.Field<string>(0)

Related

Serialize Json Array with Asp.net MVC

Could someone helpe me?
How can I code 'Shippings' class as an Array to get the json example below?
{
"seller_id": "123",
"amount": 100,
"order": {
"order_id": "1111",
"sales_tax": 0,
"product_type": "service"
},
"shippings": [{
"first_name": "John",
"phone_number": "5551999887766",
"shipping_amount": 3000,
"address": {
"street": "Street 35 Conts",
"number": "1000",
"complement": "ap1",
"postal_code": "90230060"
}
}],
"credit": {
"delayed": false,
"authenticated": false
}
}
I am doing this below, using asp.net mvc, but don't know how to get Shippings as Array [].
Can someone give me some exemplo or anything else... I'll appreciate.
var request = new GetNetRoot() {
SellerId = seller_id,
Amount = orderItens.Amount
Order = new GetNetPagOrder() {
OrderId = order.id.ToString(),
SalesTax = orderItens.Tax,
ProductType = orderItens.ProdType
},
Shippings = new GetNetPagShippings() {
FirstName = "",
PhoneNumber = usr.PhoneNumber,
ShippingAmount = orderItens.AmountShip,
Address = new GetNetPagAddress() {
Street = catEnd.IdEnderecoLogradouroNavigation.IdRuaNavigation.Nome,
Number = catEnd.NumEndereco,
Complement = catEnd.Complemento,
PostalCode = catEnd.IdEnderecoLogradouroNavigation.Cep
}
},
Credit = new GetNetPagCredit() {
Delayed = false,
Authenticated = false
}
};
var requestBody = JsonConvert.SerializeObject(request)
You should initialize Shippings like an array:
Shippings = new[] {
new GetNetPagShippings()
{
FirstName = "",
PhoneNumber = usr.PhoneNumber,
ShippingAmount = orderItens.AmountShip,
Address = new GetNetPagAddress()
{
Street = catEnd.IdEnderecoLogradouroNavigation.IdRuaNavigation.Nome,
Number = catEnd.NumEndereco,
Complement = catEnd.Complemento,
PostalCode = catEnd.IdEnderecoLogradouroNavigation.Cep
}
}
public class GetNetPagamentoRoot
{
...
public GetNetPagShippings[] Shippings { get; set; }
}
You can use array initializer syntax. Simplistic example would be array of int:
int[] myArray = new [] { 1, 2, 3 }
In your code Shippings should be initialized as an array.
var request = new GetNetRoot()
{
SellerId = seller_id,
Amount = orderItens.Amount
Order = new GetNetPagOrder()
{
OrderId = order.id.ToString(),
SalesTax = orderItens.Tax,
ProductType = orderItens.ProdType
},
// Array initializer with 2 elements.
Shippings = new[] {
new GetNetPagShippings()
{
FirstName = "",
PhoneNumber = usr.PhoneNumber,
ShippingAmount = orderItens.AmountShip,
Address = new GetNetPagAddress()
{
Street = catEnd.IdEnderecoLogradouroNavigation.IdRuaNavigation.Nome,
Number = catEnd.NumEndereco,
Complement = catEnd.Complemento,
PostalCode = catEnd.IdEnderecoLogradouroNavigation.Cep
}
},
new GetNetPagShippings()
{
FirstName = "",
PhoneNumber = usr.PhoneNumber,
ShippingAmount = orderItens.AmountShip,
Address = new GetNetPagAddress()
{
Street = catEnd.IdEnderecoLogradouroNavigation.IdRuaNavigation.Nome,
Number = catEnd.NumEndereco,
Complement = catEnd.Complemento,
PostalCode = catEnd.IdEnderecoLogradouroNavigation.Cep
}
}
},
Credit = new GetNetPagCredit()
{
Delayed = false,
Authenticated = false
}
};
var requestBody = JsonConvert.SerializeObject(request);
Your GetNetRoot outer class needs to define the "Shippings" property as a list or array of the GetNetPagShippings class as opposed to a single instance. When you serialize it to JSON, it will be represented as a JSON array of the object.
using System;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace ConsoleApp1
{
class Program
{
static void Main(string[] args)
{
var myClassInstance = new MyOuterClass()
{
OuterProperty = "Outer Property",
MyInnerClassList = new List<MyInnerClass>()
{
new MyInnerClass()
{
InnerProperty = "Inner Property Item 1"
},
new MyInnerClass()
{
InnerProperty = "Inner Property Item 2"
}
}
};
string json = JsonConvert.SerializeObject(myClassInstance);
Console.WriteLine(json);
}
}
public class MyOuterClass
{
public string OuterProperty { get; set; }
public List<MyInnerClass> MyInnerClassList { get; set; }
}
public class MyInnerClass
{
public string InnerProperty { get; set; }
}
}

Consider missing object keys as null in JSON.net with JSON Path

My JSON looks like this sometime, which has name key missing in 2nd object. It may be any key in thousands of JSON file I read dynamically to extract fields required using JSON Path queries.
void Main()
{
string jsonText = #"[
{
'rank': 1,
'name': 'name 1',
'year': '1991'
},
{
'rank': 2,
'year': '1992'
},
{
'rank': 3,
'name': 'name 3',
'year': '1993'
}
]";
JToken json = JToken.Parse(jsonText);
List<Fields> fields = new List<Fields>
{
new Fields
{
name = "rank",
path = "$.[*].rank",
result = new List<string>()
},
new Fields
{
name = "name",
path = "$.[*].name",
result = new List<string>()
},
new Fields
{
name = "year",
path = "$.[*].year",
result = new List<string>()
}
};
foreach(var field in fields)
{
var result = json.SelectTokens(field.path);
foreach (var token in result)
{
if (token is JObject || token is JArray)
{
field.result.Add(token.ToString(Newtonsoft.Json.Formatting.None));
}
else
{
field.result.Add(token.ToString());
}
}
}
fields.Dump();
}
public class Fields
{
public string name { get; set; }
public string path { get; set; }
public List<string> result {get; set;}
}
Which results in below incorrect table as the "name 3" moved one row up on 2nd row. While it should be on 3rd row and the 2nd row should have null value.
Here is one way (Updated to fix trailing missing fields):
void Main()
{
string jsonText = #"[
{
'rank': 1,
'name': 'name 1',
'year': '1991'
},
{
'rank': 2,
'year': '1992'
},
{
'rank': 3,
'name': 'name 3',
}
]";
JToken json = JToken.Parse(jsonText);
List<Fields> fields = new List<Fields>
{
new Fields
{
name = "rank",
path = "$.[*].rank",
result = new List<string>()
},
new Fields
{
name = "name",
path = "$.[*].name",
result = new List<string>()
},
new Fields
{
name = "year",
path = "$.[*].year",
result = new List<string>()
}
};
var max = json.SelectTokens("$.[*]").Count().Dump();
foreach (var field in fields)
{
var result = json.SelectTokens(field.path);
var index = 0;
foreach (var token in result)
{
while(!token.Path.StartsWith($"[{index++}]"))
field.result.Add(null);
if (token is JObject || token is JArray)
{
field.result.Add(token.ToString(Newtonsoft.Json.Formatting.None));
}
else
{
field.result.Add(token.ToString());
}
}
field.result.AddRange(Enumerable.Range(0,max-result.Count()).Select(z=>(string)null));
}
fields.Dump();
}
public class Fields
{
public string name { get; set; }
public string path { get; set; }
public List<string> result { get; set; }
}

Can I use LINQ GroupBy to do this more cleanly?

In this contrived example, which closely resembles my real-world problem, I have a data set coming from an external source. Each record from the external source takes the following form:
[Classification] NVARCHAR(32),
[Rank] INT,
[Data] NVARCHAR(1024)
I am looking to build an object where the Rank and Data are patched into a single instance of a response object that contains list properties for the three hard-coded Classification values, ordered by Rank.
I have something that works, but I can't help but think that it could be done better. This is what I have:
public static void Main()
{
IEnumerable<GroupingTestRecord> records = new List<GroupingTestRecord>
{
new GroupingTestRecord { Classification = "A", Rank = 1, Data = "A1" },
new GroupingTestRecord { Classification = "A", Rank = 2, Data = "A2" },
new GroupingTestRecord { Classification = "A", Rank = 3, Data = "A3" },
new GroupingTestRecord { Classification = "B", Rank = 1, Data = "B1" },
new GroupingTestRecord { Classification = "B", Rank = 2, Data = "B2" },
new GroupingTestRecord { Classification = "B", Rank = 3, Data = "B3" },
new GroupingTestRecord { Classification = "C", Rank = 1, Data = "C1" },
new GroupingTestRecord { Classification = "C", Rank = 2, Data = "C2" },
new GroupingTestRecord { Classification = "C", Rank = 3, Data = "C3" },
};
GroupTestResult r = new GroupTestResult
{
A = records.Where(i => i.Classification == "A").Select(j => new GroupTestResultItem { Rank = j.Rank, Data = j.Data, }).OrderBy(k => k.Rank),
B = records.Where(i => i.Classification == "B").Select(j => new GroupTestResultItem { Rank = j.Rank, Data = j.Data, }).OrderBy(k => k.Rank),
C = records.Where(i => i.Classification == "C").Select(j => new GroupTestResultItem { Rank = j.Rank, Data = j.Data, }).OrderBy(k => k.Rank),
};
The source record DTO:
public class GroupingTestRecord
{
public string Classification { get; set; }
public int? Rank { get; set; }
public string Data { get; set; }
}
The destination single class:
public class GroupTestResult
{
public IEnumerable<GroupTestResultItem> A { get; set; }
public IEnumerable<GroupTestResultItem> B { get; set; }
public IEnumerable<GroupTestResultItem> C { get; set; }
}
The distination child class:
public class GroupTestResultItem
{
public int? Rank { get; set; }
public string Data { get; set; }
}
Ouput
{
"A":[
{
"Rank":1,
"Data":"A1"
},
{
"Rank":2,
"Data":"A2"
},
{
"Rank":3,
"Data":"A3"
}
],
"B":[
{
"Rank":1,
"Data":"B1"
},
{
"Rank":2,
"Data":"B2"
},
{
"Rank":3,
"Data":"B3"
}
],
"C":[
{
"Rank":1,
"Data":"C1"
},
{
"Rank":2,
"Data":"C2"
},
{
"Rank":3,
"Data":"C3"
}
]
}
Fiddle
Is there a better way to achieve my goal here?
The same JSON output was achieved using GroupBy first on the Classification and applying ToDictionary on the resulting IGrouping<string, GroupingTestRecord>.Key
var r = records
.GroupBy(_ => _.Classification)
.ToDictionary(
k => k.Key,
v => v.Select(j => new GroupTestResultItem { Rank = j.Rank, Data = j.Data, }).OrderBy(k => k.Rank).ToArray()
);
var json = JsonConvert.SerializeObject(r);
Console.WriteLine(json);
which should easily deserialize to the destination single class (for example on a client)
var result = JsonConvert.DeserializeObject<GroupTestResult>(json);
is it possible to get the top level result into a GroupTestResult object?
Build the result from the dictionary
var result = new GroupTestResult {
A = r.ContainsKey("A") ? r["A"] : Enumerable.Empty<GroupTestResultItem>();,
B = r.ContainsKey("B") ? r["B"] : Enumerable.Empty<GroupTestResultItem>();,
C = r.ContainsKey("C") ? r["C"] : Enumerable.Empty<GroupTestResultItem>();,
};
Or this
var result = records.GroupBy(x => x.Classification)
.ToDictionary(x => x.Key, x => x.Select(y => new {y.Rank, y.Data})
.OrderBy(y => y.Rank));
Console.WriteLine(JsonConvert.SerializeObject(result));
Full Demo Here

MongoDb c# driver consecutive SelectMany

If I have objects, lets call them Group that has list of some other objects I will call it Brand, and this object has a list of objects called Model.
Is there a way to get only list of Models using MongoDb c# driver.
I tried using SelectMany multiple times but with no success. If I put more than one SelectMany I always get an empty list.
Code should be self-explanatory.
At the end is comment that explains what confuses me.
class Group
{
[BsonId(IdGenerator = typeof(GuidGenerator))]
public Guid ID { get; set; }
public string Name { get; set; }
public List<Brand> Brands { get; set; }
}
class Brand
{
public string Name { get; set; }
public List<Model> Models { get; set; }
}
class Model
{
public string Name { get; set; }
public int Produced { get; set; }
}
class Program
{
static void Main(string[] args)
{
MongoClient client = new MongoClient("mongodb://127.0.0.1:32768");
var db = client.GetDatabase("test");
var collection = db.GetCollection<Group>("groups");
var fca = new Group { Name = "FCA" };
var alfaRomeo = new Brand { Name = "Alfra Romeo" };
var jeep = new Brand { Name = "Jeep" };
var ferrari = new Brand { Name = "Ferrari"};
var laFerrari = new Model { Name = "LaFerrari", Produced = 4 };
var wrangler = new Model { Name = "Wrangler", Produced = 3 };
var compass = new Model { Name = "Compass", Produced = 8 };
var giulietta = new Model { Name = "Giulietta", Produced = 7 };
var giulia = new Model { Name = "Giulia", Produced = 8 };
var _4c = new Model { Name = "4C", Produced = 6 };
fca.Brands = new List<Brand> { ferrari, alfaRomeo, jeep };
ferrari.Models = new List<Model> { laFerrari };
jeep.Models = new List<Model> { wrangler, compass };
alfaRomeo.Models = new List<Model> { giulietta, giulia, _4c };
collection.InsertOne(fca);
Console.WriteLine("press enter to continue");
Console.ReadLine();
var models = collection.AsQueryable().SelectMany(g => g.Brands).SelectMany(b => b.Models).ToList();
Console.WriteLine(models.Count); //returns 0 I expected 6
Console.ReadLine();
}
}
Try
var models = collection.AsQueryable()
.SelectMany(g => g.Brands)
.Select(y => y.Models)
.SelectMany(x=> x);
Console.WriteLine(models.Count());
Working output (with extra Select())
aggregate([{
"$unwind": "$Brands"
}, {
"$project": {
"Brands": "$Brands",
"_id": 0
}
}, {
"$project": {
"Models": "$Brands.Models",
"_id": 0
}
}, {
"$unwind": "$Models"
}, {
"$project": {
"Models": "$Models",
"_id": 0
}
}])
OP Output without extra Select()
aggregate([{
"$unwind": "$Brands"
}, {
"$project": {
"Brands": "$Brands",
"_id": 0
}
}, {
"$unwind": "$Models"
}, {
"$project": {
"Models": "$Models",
"_id": 0
}
}])

To serialize the object into JSON

Below is my code for object
var obj_series = new
{
name = s_Name,
data = p_Value
};
which after serializing gives the below JSON format,
["series":[{"name":"01. Target"}],"data":[14,18,12]}]
How I am going to take multiple series name inside the object so that output can be as follows,
"series":
{
name: 'Target',
data: [14,18,12]
}, {
name: 'Alarm',
data: [14,18,12]
}, {
name: 'Actual',
data: [14,18,12]
}
List<object> modified_listofstrings = new List<object>();
System.Web.Script.Serialization.JavaScriptSerializer jSearializer = new System.Web.Script.Serialization.JavaScriptSerializer();
List<string> s_Name = new List<string>();
List<float> p_Value = new List<float>();
modified_listofstrings.Add(obj_series);
jSearializer.Serialize(modified_listofstrings);
This is one way to do it:
Create classes for your objects:
public class Serie
{
public string Name { get; set; }
public List<long> Data { get; set; }
public Serie()
{
Data = new List<long>();
}
}
public class SeriesCollection
{
public List<Serie> Series { get; set; }
public SeriesCollection()
{
Series = new List<Serie>();
}
}
Serialize it:
SeriesCollection collection = new SeriesCollection();
collection.Series.Add(new Serie() { Name = "Target", Data = { 1, 2, 3 } });
collection.Series.Add(new Serie() { Name = "Alarm", Data = { 1, 2, 3 } });
collection.Series.Add(new Serie() { Name = "Actual", Data = { 1, 2, 3 } });
System.Web.Script.Serialization.JavaScriptSerializer jSearializer = new System.Web.Script.Serialization.JavaScriptSerializer();
string seriesStr = jSearializer.Serialize(collection);
Output:
{"Series":[{"Name":"Target","Data":[1,2,3]},
{"Name":"Alarm","Data":[1,2,3]},
{"Name":"Actual","Data":[1,2,3]}
]}
UPDATE:
I don't know if it suits your needs, but here is another way:
var seriesdasda = new { series = new List<object>() };
seriesdasda.series.Add(new { name = "Target", data = { 1, 2, 3 }});
seriesdasda.series.Add(new { name = "Alarm", data = { 1, 2, 3 }});
seriesdasda.series.Add(new { name = "Actual", data = { 1, 2, 3 }});
string seriesStr2 = jSearializer.Serialize(seriesdasda);
If I get it correct, then there is no special consideration is required in order to serialize a custom collection using JavaScriptSerializer. Try this approach.

Categories