Json.Net custom serialization - asp.net-mvc

[
{
"articles": [
[
"2016-03-04",
6
],
[
"2016-03-05",
10
],
[
"2016-03-06",
11
]
],
"accession": "00000446-201301000-00018"
},
{
"articles": [
[
"2016-03-04",
1
],
[
"2016-03-08",
17
],
[
"2016-03-09",
10
]
],
"accession": "00000446-201301000-00019"
}]
List is input { "Accession"= "00000446-201301000-00018", "Date"= "635926464000000000","Rank" =2},{ "Accession" = "00000446-201301000-00019", "Date" = "635931648000000000","Rank" = 2}
I want json data exactly like this,data is coming from list and list is dynamically growing.Form list, I want all dates and rank club to gether for the same accession number.
I want to use newtonsoft json custom serlization to convert my list to json.

What you want to do does not need any Custom Formatter, you just have to re-structure your data, Here is an example for restructuring a list based on Entity class to the new required one.
class Entity
{
public string Accession { get; set; }
public string Date { get; set; }
public int Rank { get; set; }
}
Add this line if you need to read the list from Json
var list = JsonConvert.DeserializeObject<List<Entity>>(input);
Here is the code for changing the structure of data to array based articles.
var translatedAsArray = list.GroupBy(e => e.Accession)
.Select(g =>
new {
//change new 'object[]' to 'new' to make the article an object
//you can convert i.Date, i.Rank and g.Key to anything you want here
Articles = g.Select(i => new object[] { i.Date , i.Rank }),
Accessing = g.Key
}
);
var json = JsonConvert.SerializeObject(translatedAsArray, Formatting.Indented);

Model
public class FinalList
{
public string accession {get;set;}
public List<ArticlesDetails> Articles{get;set;}
}
public class ArticlesDetails
{
public DateTime Date{get;set;}
public int number{get;set;}
}
Use ObjectContent instead of StringContent so we let the formatter (i.e. JsonMediaTypeFormatter) to deal with the serialization and deserialization
In config
config.Formatters.Insert(0, new YourCustomFormatter());
config.Formatters.Insert(1, new JsonMediaTypeFormatter());
and disable post in your custom formatter so that JsonMediaTypeFormatter desrializes the complex data

Related

How to create dynamic menu using tree

I have an Angular project but this is not directly related to Angular and I just need the logic of create dynamic menu using tree that can also be similar as in ASP.NET MVC project. So, your suggestion for ASP.NET MVC, etc. will also be helpfu for me.
I use PrimeNG Tree and want to obtain menu from a table in MSSQL database:
Menu Table (the data was changed for example usage):
Id | Order | ParentId | Name |
1 1 0 Documents
2 1 1 Work
3 1 2 Expenses.doc
4 2 2 Resume.doc
5 2 1 Home
6 1 5 Invoices.txt
...
In order to populate the menu items, I need to generate a JSON string as shown below:
{
"data":
[
{
"label": "Documents",
"data": "Documents Folder",
"expandedIcon": "fa-folder-open",
"collapsedIcon": "fa-folder",
"children": [{
"label": "Work",
"data": "Work Folder",
"expandedIcon": "fa-folder-open",
"collapsedIcon": "fa-folder",
"children": [{"label": "Expenses.doc", "icon": "fa-file-word-o", "data": "Expenses Document"}, {"label": "Resume.doc", "icon": "fa-file-word-o", "data": "Resume Document"}]
},
{
"label": "Home",
"data": "Home Folder",
"expandedIcon": "fa-folder-open",
"collapsedIcon": "fa-folder",
"children": [{"label": "Invoices.txt", "icon": "fa-file-word-o", "data": "Invoices for this month"}]
}]
},
... //omitted for brevity
]
}
So, I have really no idea about the logic and database table design (menus). Should I generate the JSON above on the Controller or another place? Could you please post suggestions and sample approaches regarding to this issue?
Your database Menu table is fine to generate the treeview using the PrimeNG Tree plugin except that you may want to include an additional property for the data property if you want. I would however suggest you make the ParentId property nullable so that your top level item (Documents) has a null value rather that 0.
In order to pass json in that format, your model need to be
public class MenuVM
{
public int Id { get; set; } // this is only used for grouping
public string label { get; set; }
public string expandedIcon { get; set; }
public string collapsedIcon { get; set; }
public string icon { get; set; }
public IEnumerable<MenuVM> children { get; set; }
}
You might also include other properties such as
public string data { get; set; }
to match the properties in the api
You also need a parent model for the data property
public class TreeVM
{
public IEnumerable<MenuVM> data { get; set; }
}
To generate the model, you controller code would be (note this is based on the ParentId field being null for the top level item as noted above)
// Sort and group the menu items
var groups = db.Menus
.OrderBy(x => x.ParentId).ThenBy(x => x.Order)
.ToLookup(x => x.ParentId, x => new MenuVM
{
Id = x.Id,
label = x.Name
});
// Assign children
foreach (var item in groups.SelectMany(x => x))
{
item.children = groups[item.Id].ToList();
if (item.children.Any())
{
.... // apply some logic if there a child items, for example setting
// the expandedIcon and collapsedIcon properties
}
else
{
.... // apply some logic if there are no child items, for example setting
// the icon properties - e.g. item.icon = "fa-file-word-o";
}
}
// Initialize model to be passed to the view
TreeVM model = new TreeVM
{
data = groups[null].ToList();
}
return Json(model, JsonRequestBehavior.AllowGet);
For your icons, you should consider some const values or an enum rather than hard-coding strings.

Neo4jClient: How to deserialize a collect result to a c# class

I have a query where I want only Id and name of the collection back to reduce the network traffic. I am able to get what i want from the database with the following part of the query
ShipToCities = Return.As<IEnumerable<string>>("COLLECT( [shipTo.InternalId, shipTo.Name])")
but the issue is i get back the data like this:
[ [ "IN.KA.MANG", "Mangalore" ], [ "IN.KA.MANG", "Mangalore" ], [ "IN.KA.BANG", "Bangalore" ] ]
but how can I map it to a C# object like
public class CityFound
{
public string CityId { get; set; }
public string CityName { get; set; }
}
is there a way to use some converter to achieve this without me having to use some ugly string manipulation myself?
UPDATE 1:
Actually my query is fairly complex and only way to get the data that I can think of is to handcraft the query like below to reduce the :
//selectedLoadQuery below is a complex query based on user selection...
var query = selectedLoadQuery
.Match("(load)-[:SHIPPED_BY]->(shipper)-[r:HAS_TRANSPORTER]->(transporter)")
.With("load, transporter, shipper, user, count(DISTINCT r) as MyClients")
.Match("p=(shipFrom:City)<-[:SHIP_FROM_CITY]-(load)-[:SHIP_TO_CITY]->(shipTo:City)")
.With("p, load, shipFrom, shipTo, transporter, MyClients")
.Return((load, shipFrom, shipTo) => new
{
TotalShipments = load.CountDistinct(),
FromMyClients = Return.As<long>("MyClients"),
ShipFromCities = Return.As<IEnumerable<string>>("COLLECT( [shipFrom.InternalId, shipFrom.Name])"),
ShipToCities = Return.As<IEnumerable<string>>("COLLECT( [shipTo.InternalId, shipTo.Name])"),
});
Regards
Kiran
You don't need to get so creative. You're only getting into this issue because you're hand crafting such a complex query that flattens out the structure of the data.
Create a class that describes what's in the node:
public class ShippingDestination
{
public long InternalId { get; set; }
public string Name { get; set; }
}
Use this to light up the following syntax in your Return statement:
var cities = graphClient
.Match(...)
.Return(shipTo => new {
Id = shipTo.As<ShippingDestination>().InternalId,
Name = shipTo.As<ShippingDestination>().Name,
})
.Results;

Can't get "likes" our of Facebook JSON data using MVC

I'm trying to display the # of "likes" of a user selected entity that has a facebook site. The url that's passed in is the entities facebook name:
public int GetLikes(string url)
{
string jsonString = new WebClient().DownloadString("http://graph.facebook.com/?ids=" + url);
Dictionary<string, dynamic> values = JsonConvert.DeserializeObject<Dictionary<string, dynamic>>(jsonString);
int keyValues = values.Count;
int likes = values["likes"];
return likes;
}
I get an error that "likes" is not found in the value. But it's clearly there. Below is a sample of the JSON data that's returned from facebook:
{
"disney": {
"about": "\"It's kind of fun to do the impossible.\" - Walt Disney",
"category": "Company",
"checkins": 26,
"description": "This Page is a place for our Fans. However, we do need to have certain rules. Please be aware that we do not accept or consider unsolicited idea submissions and, also, we must reserve the right to remove any posting or other material that we find off-topic, inappropriate or objectionable.",
"founded": "1923",
"is_published": true,
"talking_about_count": 543991,
"username": "Disney",
"website": "http://disney.com",
"were_here_count": 0,
"id": "11784025953",
"name": "Disney",
"link": "http://www.facebook.com/Disney",
"likes": 46622418,
"cover": {
"cover_id": "10152010506970954",
"source": "http://sphotos-d.ak.fbcdn.net/hphotos-ak-prn1/t1.0-9/s720x720/1960125_10152010506970954_1312297640_n.png",
"offset_y": 0,
"offset_x": 0
}
}
}
I have tried many different things. Getting and deserializing the JSON data isn't a problem but I haven't been able to find a way to get any of the elements. Any help is appreciated.
First Create a class that mimics your JSON string (object) structure:
public class JSONobject
{
public Disney = new Disney();
}
public class Disney
{
public string about { get; set; }
public string category{get;set;}
public int checkins = {get;set;}
........
public int likes = {get;set;}
........
public Cover = new Cover();
}
public class Cover
{
public int cover_id { get;set; }
........
}
Then, initialize the object as well as the serializer:
JSONobject jsonOb = new JSONobject();
JavaScriptSerializer serializer = new JavaScriptSerializer();
Finally, parse the jsonString into your defined class:
try
{
jsonOb = serializer.Deserialize<JSONobject>(jsonString);
//ViewBag.jsondecoded = "Yes";
}
catch (Exception e)
{
//ViewBag.jsonDecoded = "No" + ", Exception: " + e.Message.ToString();
}
Retrieving variables:
string about = jsonOb.Disney.about;
string category = jsonOb.Disney.category;
int checkins = jsonOb.Disney.checkins;
int likes = jsonOb.Disney.likes;
Cover cover = jsonOb.Disney.Cover;
Hope this helps.

Custom Web API Formatting

I've been playing around with asp.net web api, and I noticed that default generated returned json doesn't include the object level key. I was also wondering how to customize the output of the json string. For example:
Getting a User usually returns
{
"Name": "ChaoticLoki",
"Age": 22,
"Sex": "Male"
}
I was hoping I could return something like:
{
"data": {
"Name": "ChaoticLoki",
"Age": 22,
"Sex": "Male",
},
"success": true
}
You can then create a class wrapping the data and status like this
public class JsonResult{
public object data { get; set;}
public boolean success { get; set;}
}
And then in your Web Api methods, you can do
var data = ... //getting from repo
return Json(new JsonResult{data = data, success = true});

How to return JSON in specific format in ASP.NET MVC using Json() with no property names

I am using a charting javascript library that expects its data in a specific JSON format - without property names.
I have an object in my Model that I am using to return the data to the charts. This looks as follows:
public class ChartData
{
public string Key { get; set; }
public int Value { get; set; }
}
An action looks as follows:
public ActionResult AssetsPerFloor(Guid id)
{
var results = from a in surveyRepository.GetAssetsForBuidling(id)
group a by a.Room.Floor into g
select new ChartData{ Key = g.Key.ToString(), Value = g.Count() };
return Json(results);
}
This returns JSON in the format [{"Key":"Main Building","Value":1}]
However, the chart requires no property names, eg: [[5, 2], [6, 3], [8, 2]]
Is there anyway I can return the results in this format. I'm sure there's a simple trick to it, but I cant think of it.
As far as I understand, it needs to return a multi-dimensional array. Try this :
var results =
(from a in surveyRepository.GetAssetsForBuidling(id)
group a by a.Room.Floor into g
select new ChartData{ Key = g.Key.ToString(), Value = g.Count() })
.Select(x => new string[] { x.Key, x.Value.ToString() };
return Json(results);

Resources