What is the fastest way to convert data into JSON format? - json

I need to convert some data to JSON format so I can use the data in my React.js project.
The current format of data is as follows:
["'Your Cut'"] = {
["id"] = 3400,
["tier"] = 1,
["type"] = {"Distributed"},
["limit"] = "Only granted by {{cai|Death from Below|Pyke}}.",
["maps"] = {
["sr"] = true,
["ha"] = true,
["nb"] = true,
["tt"] = true,
["cs"] = false,
},
["effects"] = {
["consume"] = "Grants {{g|text=*none*}}{{pp|100;112;140;176;220;274;300|-7+x;0+|type=target's kill bounty|color=gold}}, increased by {{g|100}} for [[First Blood]]. '''Can be used while [[dead]].'''",
},
},
["Abyssal Mask"] = {
["id"] = 8020,
["tier"] = 3,
["maps"] = {
["sr"] = true,
["ha"] = true,
["nb"] = true,
},
["menu"] = {
["tank"] = true,
},
["stats"] = {
["ah"] = 10,
["hp"] = 450,
["mr"] = 35,
},
["effects"] = {
["pass"] = {
["name"] = "Unmake",
["unique"] = true,
["description"] = "Enemy champions within {{tt|550 units|center to edge}} of you become cursed, reducing their {{as|magic resistance by 5}} {{as|(+ {{fd|1.2}}% '''bonus''' health)}}, capped at a reduction of {{as|25 magic resistance}}. Gain {{as|9 '''bonus''' magic resistance}} per cursed enemy.",
},
},
["recipe"] = {"Kindlegem", "Spectre's Cowl"},
["buy"] = 2700,
},
["Aegis of the Legion"] = {
["id"] = 3105,
["tier"] = 2,
["maps"] = {
["sr"] = true,
["ha"] = true,
["nb"] = true,
},
["menu"] = {
["tank"] = true,
["support"] = true,
},
["stats"] = {
["ah"] = 10,
["armor"] = 30,
["mr"] = 30,
},
["recipe"] = {"Null-Magic Mantle", "Cloth Armor"},
["buy"] = 1400,
},
... and so on for another 6000 lines.
I've tried doing it with replace using REGEX inside Visual Studio Code but it stopped responding and crashed the program.
What is the correct way to approach this?
Should I make a script in some language to convert the data? If so should I use REGEX or is there a smarter approach?
Thank you

You would need to know the exact syntax rules for the input. For instance, if it is possible for string literals to include special characters like newline or double quote (the delimiter), and how that would be encoded.
But for the example given, I see the following transformations that need to be done to make it valid JSON:
The square brackets around the key names should be removed
The curly braces that terminate arrays should be turned into square brackets
The whole input should be wrapped in a pair of curly braces
Trailing commas (after the last key of an object literal) should be removed
Seeing the input structure, I made several assumptions, including:
Arrays open and close on a single line;
Arrays are not nested;
Object keys are always defined on separate lines;
Key names and string values are always double quoted.
No string interpolation is performed (the double braces remain untouched)
Here is a runnable implementation of that transformation in JavaScript, which produces a result for the sample input you provided:
function toJSON(input) {
return ("{\n"
+ input.replace(/^(\s*)\[("[^"]*")](\s*)=/gm, "$1$2$3:")
.replace(/\{(.*)}(,?)[ \t]*$/gm, "[$1]$2")
+ "\n}").replace(/,(\s*\})/g, "$1");
}
// Demo on the example:
let input = `["'Your Cut'"] = {
["id"] = 3400,
["tier"] = 1,
["type"] = {"Distributed"},
["limit"] = "Only granted by {{cai|Death from Below|Pyke}}.",
["maps"] = {
["sr"] = true,
["ha"] = true,
["nb"] = true,
["tt"] = true,
["cs"] = false,
},
["effects"] = {
["consume"] = "Grants {{g|text=*none*}}{{pp|100;112;140;176;220;274;300|-7+x;0+|type=target's kill bounty|color=gold}}, increased by {{g|100}} for [[First Blood]]. '''Can be used while [[dead]].'''",
},
},
["Abyssal Mask"] = {
["id"] = 8020,
["tier"] = 3,
["maps"] = {
["sr"] = true,
["ha"] = true,
["nb"] = true,
},
["menu"] = {
["tank"] = true,
},
["stats"] = {
["ah"] = 10,
["hp"] = 450,
["mr"] = 35,
},
["effects"] = {
["pass"] = {
["name"] = "Unmake",
["unique"] = true,
["description"] = "Enemy champions within {{tt|550 units|center to edge}} of you become cursed, reducing their {{as|magic resistance by 5}} {{as|(+ {{fd|1.2}}% '''bonus''' health)}}, capped at a reduction of {{as|25 magic resistance}}. Gain {{as|9 '''bonus''' magic resistance}} per cursed enemy.",
},
},
["recipe"] = {"Kindlegem", "Spectre's Cowl"},
["buy"] = 2700,
},
["Aegis of the Legion"] = {
["id"] = 3105,
["tier"] = 2,
["maps"] = {
["sr"] = true,
["ha"] = true,
["nb"] = true,
},
["menu"] = {
["tank"] = true,
["support"] = true,
},
["stats"] = {
["ah"] = 10,
["armor"] = 30,
["mr"] = 30,
},
["recipe"] = {"Null-Magic Mantle", "Cloth Armor"},
["buy"] = 1400,
},`;
const json = toJSON(input);
console.log(JSON.parse(json));

Related

Ajax Response Capitalizations Rules

A was using DataTables plugin, and when displaying my columns I needed to put the first letter to LowerCase for it to recognize the property/object, e.g:
// Object name is actually: EngineeringChange.Responsible
{
title: "Responsible",
data: "engineeringChange.responsible",
className: "columnName columnHeader",
},
I just assumed the first letter would always be capitalized to LowerCase. I tried creating a new property inside EngineeringChange named ECRNumber, so I tried:
{
title: "ECR Number",
data: "engineeringChange.eCRNumber",
className: "columnName columnHeader",
},
Isn't recognized as a parameter... After a bit of searching I find out the Json response I get on AJAX it's called ecrNumber. So now I'm actually lost on which are the rules that are automatically applied to the Json Response. How does it turn ecr to LowerCase and Number to UpperCase (the N)??
Edit
Sry, can´t think of any easy way to exactly reproduce my problem on a demo
TableDesign/Creation
table = $('#tblEntries2').DataTable({
order: [[0, 'desc']],
deferRender: true,
ajax: {
url: '#Url.Action("GetEntries", "AlteracaoEngenharia")',
method: 'GET',
dataSrc: '',
beforeSend: function () {
onBegin();
$content.hide();
$loader.show();
},
complete: function (jsonResponse) {
console.log(jsonResponse);
onComplete();
$loader.hide();
$content.fadeIn();
$('#ExcelExport').show();
table.column(5).visible(false);
table.column(6).visible(false);
table.column(7).visible(false);
table.column(9).visible(false);
table.column(10).visible(false);
table.column(11).visible(false);
}
},
dom: "<'row'<'col-2'l><'col-7 text-center'B><'col-3'f>>" +
"<'row'<'col-12'tr>>" +
"<'row'<'col-5'i><'col-7'p>>",
lengthMenu: [
[10, 25, 50, 100, -1],
['10', '25', '50', '100', 'Todos'],
],
columns: [
{
title: "Id (yr-id)",
data: "creationYear",
className: "columnNumber columnHeader",
},
{
title: "ECR Number",
data: "engineeringChange.ecrNumber",
className: "columnNumber columnHeader",
},
{
title: "Criador Alteração de Engenharia",
data: "engineeringChange.responsible",
className: "columnName columnHeader",
},
...
Handler
public IActionResult GetEntries()
{
GetDataEntries();
int count = 0;
int currentYear = 0;
foreach (var entry in EntriesList)
{
EngineeringChangesListViewModel h = new EngineeringChangesListViewModel
{
EngineeringChange = entry
};
if (currentYear != entry.DataCriacao.Year)
{
count = 1;
currentYear = entry.DataCriacao.Year;
}
else
{
count++;
}
h.DeadLine = entry.FinishedGood.Week + " - " + entry.DataCriacao.Year.ToString();
if (entry.OldPart == null)
{
h.EngineeringChange.OldPart = new Part();
}
if (entry.NewPart == null)
{
h.EngineeringChange.NewPart = new Part();
}
if (entry.FinishedGood == null)
{
h.EngineeringChange.FinishedGood = new FinishedGood();
}
if (entry.OldPart != null && entry.OldPart.CDP.HasValue)
h.OldPartValue = entry.OldPart.CDP * entry.OldPart.Stock;
if (entry.NewPart != null && entry.NewPart.CDP.HasValue)
h.NewPartValue = entry.NewPart.CDP * entry.NewPart.Stock;
h.EngineeringChange.ECRNumber = entry.ECRNumber;
//toString("D4") padds the number to always be 4 digits
h.CreationYear = entry.DataCriacao.Year.ToString() + "_" + count.ToString("D4");
h.IdYear = count;
EntriesListaViewModel.Add(h);
}
var errorsJson = JsonConvert.SerializeObject(EntriesListaViewModel);
Console.WriteLine(errorsJson);
return new JsonResult(EntriesListaViewModel);
}
HANDLER OUTPUT
[{"CreationYear":"2021_0001","IdYear":1,"OldPartValue":null,"NewPartValue":2061.09155,"DeadLine":"15 - 2021","EngineeringChange":{"Id":8,"DataCriacao":"2021-03-11T16:15:24.6630956","Responsible":"José António","ECRNumber":"X1232","State":"Aberto","Comment":"Teste","UserId":1,"User":null,"Component":null,"FinishedGood":{"Id":31,"Week":15,"EngineeringChangeId":8},"OldPart":{"Id":5,"Reference":"FS12848AC","Stock":null,"CDP":1.43584776,"LastExpired":null},"NewPart":{"Id":6,"Reference":"FS12848AD","Stock":1650,"CDP":1.24914646,"LastExpired":"2021-03-11T00:00:00"},"Transformation":{"Id":188,"Possible":true,"Cost":1090.0,"WillBeTransformed":true,"TransformationDate":"2021-03-13T08:48:00","Responsible":"Miguel","EngineeringChangeId":8}}},]
PAGE/AJAX OUTPUT outputs are created by console.log() and Console.WriteLine() displayed above.
ECRNumber gets named to ecrNumber...

JQGgrid- How to generate a pdf / excel file from the grid data

I have the following JQGrid table, which is being generated from JSON data. I want to be able to generate/export or create a pdf file based on the table data state that is view able. I am using JSON , Jqgrid and Javascript
How do I generate a pdf file from the data ?
Here My FIDDLE
JS CODE
$(document).ready(function() {
var jsonData = {
"Name": "Julie Brown",
"Account": "C0010",
"LoanApproved": "12/5/2015",
"LastActivity": "4/1/2016",
"PledgedPortfolio": "4012214.00875",
"MaxApprovedLoanAmt": "2050877.824375",
"LoanBalance": "1849000",
"AvailableCredit": "201877.824375",
"Aging": "3",
"Brokerage": "My Broker",
"Contact": "Robert L. Johnson",
"ContactPhone": "(212) 902-3614",
"RiskCategory": "Yellow",
"rows": [{
"ClientID": "C0010",
"Symbol": "WEC",
"Description": "Western Electric Co",
"ShareQuantity": "20638",
"SharePrice": "21.12",
"TotalValue": "435874.56",
"LTVCategory": "Equities",
"LTVRatio": "50%",
"MaxLoanAmt": "217937.28"
}, {
"ClientID": "C0010",
"Symbol": "BBB",
"Description": "Bins Breakers and Boxes",
"ShareQuantity": "9623",
"SharePrice": "74.29125",
"TotalValue": "714904.69875",
"LTVCategory": "Equities",
"LTVRatio": "50%",
"MaxLoanAmt": "357452.349375"
}, {
"ClientID": "C0010",
"Symbol": "GPSC",
"Description": "Great Plains Small Cap Stock",
"ShareQuantity": "49612",
"SharePrice": "14.24",
"TotalValue": "706474.88",
"LTVCategory": "Mutual Funds - Small Cap",
"LTVRatio": "40%",
"MaxLoanAmt": "282589.952"
}]
},
mmddyyyy = "";
/*********************************************************************/
$("#output").jqGrid({
url: "/echo/json/",
mtype: "POST",
datatype: "json",
postData: {
json: JSON.stringify(jsonData)
},
colModel: [
/** { name: 'ClientID', label:'ClientID',width: 80, key: true },****/
{
name: 'Symbol',
width: 65
}, {
name: 'Description',
width: 165
}, {
name: 'ShareQuantity',
align: 'right',
width: 85,
classes: "hidden-xs", labelClasses: "hidden-xs",
formatter: 'currency',
formatoptions: {
prefix: " ",
suffix: " "
}
}, {
name: 'SharePrice',
label: 'Share Price',
align: 'right',
width: 100,
classes: "hidden-xs", labelClasses: "hidden-xs",
template: "number",
formatoptions: {
prefix: " $",
decimalPlaces: 4
}
},
/*{ label: 'Value1',
name: 'Value1',
width: 80,
sorttype: 'number',
formatter: 'number',
align: 'right'
}, */
{
name: 'TotalValue',
label: 'Total Value',
width: 160,
sorttype: 'number',
align: "right",
search: false,
formatter: 'currency',
formatoptions: {
prefix: " $",
suffix: " "
}
}, {
name: 'LTVRatio',
label: 'LTV Ratio',
width: 70,
sorttype: 'number',
align: "right",
formatter: 'percentage',
formatoptions: {
prefix: " ",
suffix: " "
}
}, {
name: 'LTVCategory',
label: 'LTV Category',
classes: "hidden-xs", labelClasses: "hidden-xs",
width: 120,
width: 165
},
{
name: 'MaxLoanAmt',
label: 'MaxLoanAmount',
width: 165,
sorttype: 'number',
align: "right",
search: false,
formatter: 'currency',
formatoptions: {
prefix: " $",
suffix: " "
}
}
],
additionalProperties: ["Symbol", "Description"],
subGrid: true,
subGridRowExpanded: function (subgridDivId, rowid) {
var item = $(this).jqGrid("getLocalRow", rowid);
$("#" + $.jgrid.jqID(subgridDivId)).html("Symbol: <em>" + item.Symbol +
"</em><br/>Description: <em>" + item.Description + "</em>");
},
beforeProcessing: function (data) {
var symbolsMap = {}, symbolsValues = ":All", rows = data.rows, i, symbol;
for (i = 0; i < rows.length; i++) {
symbol = rows[i].Symbol;
if (!symbolsMap.hasOwnProperty(symbol)) {
symbolsMap[symbol] = 1;
symbolsValues += ";" + symbol + ":" + symbol;
}
}
$(this).jqGrid("setColProp", 'Symbol', {
stype: "select",
searchoptions: {
value: symbolsValues
}
}).jqGrid('destroyFilterToolbar')
.jqGrid('filterToolbar', {
stringResult: true,
searchOnEnter: false,
defaultSearch : "cn"
});
},
/*beforeProcessing: function (data) {
var item, i, n = data.length;
for (i = 0; i < n; i++) {
item = data[i];
item.Quantity = parseFloat($.trim(item.Quantity).replace(",", ""));
item.LTVRatio = parseFloat($.trim(item.LTVRatio *10000).replace(",", ""));
item.Value = parseFloat($.trim(item.Value).replace(",", ""));
item.Num1 = parseInt($.trim(item.Num1).replace(",", ""), 10);
item.Num2 = parseInt($.trim(item.Num2).replace(",", ""), 10);
}
}, */
iconSet: "fontAwesome",
loadonce: true,
rownumbers: true,
cmTemplate: {
autoResizable: true,
editable: true
},
autoResizing: {
compact: true
},
autowidth: true,
height: 'auto',
forceClientSorting: true,
sortname: "Symbol",
footerrow: true,
caption: "<b>Collateral Value</b> <span class='pull-right' style='margin-right:20px;'>Valuation as of: " + mmddyyyy + "</span>",
loadComplete: function() {
var $self = $(this),
sum = $self.jqGrid("getCol", "Price", false, "sum"),
sum1 = $self.jqGrid("getCol", "MaxLoanAmt", false, "sum");
//ltvratio = $self.jqGrid("getCol","LTVRatio:addas", "Aved Loan Amount");
$self.jqGrid("footerData", "set", {
LTVCategory: "Max Approved Loan Amount:",
Price: sum,
MaxLoanAmt: sum1
});
}
});
$("#output").jqGrid('filterToolbar', {stringResult: true, searchOnEnter: false, defaultSearch : "cn"});
$(window).on("resize", function () {
var newWidth = $("#output").closest(".ui-jqgrid").parent().width();
$("#output").jqGrid("setGridWidth", newWidth, true);
}).triggerHandle("resize");
});
There is no build in method to export jqgrid data to pdf. You have to use third party tools( I personally like iTextSharp which can be downloaded from Here . You have to create action method for printing the grid data in your controller.
Here is also another one example one guy made.
Here is also another example in trirand. If you see the source code they are using iTextHsarp.
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using JQGridMVCExamples.Models;
using Trirand.Web.Mvc;
using System.IO;
//
// For PDF export we are using the free open-source iTextSharp library.
//
using iTextSharp.text;
using iTextSharp.text.pdf;
using System.Data;
namespace JQGridMVCExamples.Controllers.Grid
{
public partial class GridController : Controller
{
// This is the default action for the View. Use it to setup your grid Model.
public ActionResult ExportPDF()
{
// Get the model (setup) of the grid defined in the /Models folder.
var gridModel = new OrdersJqGridModel();
var ordersGrid = gridModel.OrdersGrid;
// Setting the DataUrl to an action (method) in the controller is required.
// This action will return the data needed by the grid
ordersGrid.DataUrl = Url.Action("PDFGrid_DataRequested");
// customize the default Orders grid model with custom settings
// NOTE: you need to call this method in the action that fetches the data as well,
// so that the models match
SetPDFExportGrid(ordersGrid);
// Pass the custmomized grid model to the View
return View(gridModel);
}
// This method is called when the grid requests data
public JsonResult PDFGrid_DataRequested()
{
// Get both the grid Model and the data Model
// The data model in our case is an autogenerated linq2sql database based on Northwind.
var gridModel = new OrdersJqGridModel();
var northWindModel = new NorthwindDataContext();
// customize the default Orders grid model with our custom settings
SetPDFExportGrid(gridModel.OrdersGrid);
// Save the current grid state in Session
// We will later need it for PDF Export
JQGridState gridState = gridModel.OrdersGrid.GetState();
Session["gridState"] = gridState;
// return the result of the DataBind method, passing the datasource as a parameter
// jqGrid for ASP.NET MVC automatically takes care of paging, sorting, filtering/searching, etc
return gridModel.OrdersGrid.DataBind(northWindModel.Orders);
}
public JsonResult PDFExport_AutoCompleteShipName(string term)
{
var northWindModel = new NorthwindDataContext();
JQAutoComplete autoComplete = new JQAutoComplete();
autoComplete.DataField = "ShipName";
autoComplete.AutoCompleteMode = AutoCompleteMode.BeginsWith;
autoComplete.DataSource = from o in northWindModel.Orders
select o;
return autoComplete.DataBind();
}
private void SetPDFExportGrid(JQGrid ordersGrid)
{
// show the search toolbar
ordersGrid.ToolBarSettings.ShowSearchToolBar = true;
ordersGrid.ToolBarSettings.ShowSearchButton = true;
var orderDateColumn = ordersGrid.Columns.Find(c => c.DataField == "OrderDate");
orderDateColumn.DataFormatString = "{0:yyyy/MM/dd}";
orderDateColumn.SearchType = SearchType.DatePicker;
orderDateColumn.DataType = typeof(DateTime);
orderDateColumn.SearchControlID = "DatePicker";
orderDateColumn.SearchToolBarOperation = SearchOperation.IsEqualTo;
var shipNameColumn = ordersGrid.Columns.Find(c => c.DataField == "ShipName");
shipNameColumn.SearchType = SearchType.AutoComplete;
shipNameColumn.DataType = typeof(string);
shipNameColumn.SearchControlID = "AutoComplete";
shipNameColumn.SearchToolBarOperation = SearchOperation.Contains;
var orderIDColumns = ordersGrid.Columns.Find(c => c.DataField == "OrderID");
orderIDColumns.Searchable = true;
orderIDColumns.DataType = typeof(int);
orderIDColumns.SearchToolBarOperation = SearchOperation.IsEqualTo;
SetPDFCustomerIDSearchDropDown(ordersGrid);
SetPDFFreightSearchDropDown(ordersGrid);
}
private void SetPDFCustomerIDSearchDropDown(JQGrid ordersGrid)
{
// setup the grid search criteria for the columns
JQGridColumn customersColumn = ordersGrid.Columns.Find(c => c.DataField == "CustomerID");
customersColumn.Searchable = true;
// DataType must be set in order to use searching
customersColumn.DataType = typeof(string);
customersColumn.SearchToolBarOperation = SearchOperation.IsEqualTo;
customersColumn.SearchType = SearchType.DropDown;
// Populate the search dropdown only on initial request, in order to optimize performance
if (ordersGrid.AjaxCallBackMode == AjaxCallBackMode.RequestData)
{
var northWindModel = new NorthwindDataContext();
var searchList = from customers in northWindModel.Customers
select new SelectListItem
{
Text = customers.CustomerID,
Value = customers.CustomerID
};
customersColumn.SearchList = searchList.ToList<SelectListItem>();
customersColumn.SearchList.Insert(0, new SelectListItem { Text = "All", Value = "" });
}
}
private void SetPDFFreightSearchDropDown(JQGrid ordersGrid)
{
// setup the grid search criteria for the columns
JQGridColumn freightColumn = ordersGrid.Columns.Find(c => c.DataField == "Freight");
freightColumn.Searchable = true;
// DataType must be set in order to use searching
freightColumn.DataType = typeof(decimal);
freightColumn.SearchToolBarOperation = SearchOperation.IsGreaterOrEqualTo;
freightColumn.SearchType = SearchType.DropDown;
// Populate the search dropdown only on initial request, in order to optimize performance
if (ordersGrid.AjaxCallBackMode == AjaxCallBackMode.RequestData)
{
List<SelectListItem> searchList = new List<SelectListItem>();
searchList.Add(new SelectListItem { Text = "> 10", Value = "10" });
searchList.Add(new SelectListItem { Text = "> 30", Value = "30" });
searchList.Add(new SelectListItem { Text = "> 50", Value = "50" });
searchList.Add(new SelectListItem { Text = "> 100", Value = "100" });
freightColumn.SearchList = searchList.ToList<SelectListItem>();
freightColumn.SearchList.Insert(0, new SelectListItem { Text = "All", Value = "" });
}
}
public ActionResult ExportToPDF(string exportType)
{
var gridModel = new OrdersJqGridModel();
var northWindModel = new NorthwindDataContext();
var grid = gridModel.OrdersGrid;
// Get the last grid state the we saved before in Session in the DataRequested action
JQGridState gridState = Session["GridState"] as JQGridState;
// Need to set grid options again
SetExportGrid(grid);
if (String.IsNullOrEmpty(exportType))
exportType = "1";
DataTable exportData;
switch (exportType)
{
case "1":
grid.ExportSettings.ExportDataRange = ExportDataRange.All;
exportData = grid.GetExportData(northWindModel.Orders);
ExportToPDF(exportData);
break;
case "2":
grid.ExportSettings.ExportDataRange = ExportDataRange.Filtered;
exportData = grid.GetExportData(northWindModel.Orders, gridState);
ExportToPDF(exportData);
break;
case "3":
grid.ExportSettings.ExportDataRange = ExportDataRange.FilteredAndPaged;
exportData = grid.GetExportData(northWindModel.Orders, gridState);
ExportToPDF(exportData);
break;
}
return View();
}
private void ExportToPDF(DataTable dt)
{
//
// For PDF export we are using the free open-source iTextSharp library.
//
Document pdfDoc = new Document();
MemoryStream pdfStream = new MemoryStream();
PdfWriter pdfWriter = PdfWriter.GetInstance(pdfDoc, pdfStream);
pdfDoc.Open();//Open Document to write
pdfDoc.NewPage();
Font font8 = FontFactory.GetFont("ARIAL", 7);
PdfPTable PdfTable = new PdfPTable(dt.Columns.Count);
PdfPCell PdfPCell = null;
//Add Header of the pdf table
for (int column = 0; column < dt.Columns.Count; column++)
{
PdfPCell = new PdfPCell(new Phrase(new Chunk(dt.Columns[column].Caption, font8)));
PdfTable.AddCell(PdfPCell);
}
//How add the data from datatable to pdf table
for (int rows = 0; rows < dt.Rows.Count; rows++)
{
for (int column = 0; column < dt.Columns.Count; column++)
{
PdfPCell = new PdfPCell(new Phrase(new Chunk(dt.Rows[rows][column].ToString(), font8)));
PdfTable.AddCell(PdfPCell);
}
}
PdfTable.SpacingBefore = 15f; // Give some space after the text or it may overlap the table
pdfDoc.Add(PdfTable); // add pdf table to the document
pdfDoc.Close();
pdfWriter.Close();
Response.ClearContent();
Response.ClearHeaders();
Response.ContentType = "application/pdf";
Response.AppendHeader("Content-Disposition", "attachment; filename=gridexport.pdf");
Response.BinaryWrite(pdfStream.ToArray());
Response.End();
}
}
}

Kendo UI - JSON Response for - Grid using Remote Data Source W/Server Grouping & Server Aggregates

I have a project in which I'm using the KendoUI Grid using the server to get the data instead of locally.
I'm not sure what the JSON response should be from my server to get grouping to work however. My goal is when the user drags a column to the grouping header that I know what kind of JSON response to give back so the GRID groups by that column and any other columns that might be added to that header.
Given the image above, how do I create a JSON response to fulfill it (so its showing what its supposed to grouped)? I get I have to do this on my own on the server but not sure how JSON needs to be formated. Furthermore if I want to show a 'count' field next to the groups when they are created so I know how many items are in each group (which I believe is the aggregate?)
My current grid codes looks like the following:
<div id="grid" style="height:100%;"></div>
<script>
$(window).on("resize", function() {
kendo.resize($("#grid"));
});
var crudServiceBaseUrl = "/api",
dataSource = new kendo.data.DataSource({
transport: {
read: {
url: crudServiceBaseUrl + "/companies",
dataType: "json",
type: "POST"
},
update: {
url: crudServiceBaseUrl + "/companies/update",
dataType: "json",
type: "POST"
},
destroy: {
url: crudServiceBaseUrl + "/companies/destroy",
dataType: "json",
type: "POST"
},
create: {
url: crudServiceBaseUrl + "/companies/create",
dataType: "json",
type: "POST"
},
parameterMap: function(options, operation) {
if (operation !== "read" && options.models) {
return {models: kendo.stringify(options.models)};
}
}
},
error: function (e) {
/* the e event argument will represent the following object:
{
errorThrown: "custom error",
errors: ["foo", "bar"]
sender: {... the Kendo UI DataSource instance ...}
status: "customerror"
xhr: null
}
*/
//alert("Status: " + e.status + "; Error message: " + e.errorThrown);
console.log("Status: " + e.status + "; Error message: " + e.errorThrown);
console.log("Errors: " + e.errors.join("; "));
},
autoSync: false,
serverPaging: true,
serverFiltering: true,
serverSorting: true,
serverGrouping: true,
serverAggregates: true,
pageSize: 20,
columnResizeHandleWidth: 6,
schema: {
total: "itemCount",
data: "items",
groups: "groups",
aggregates: "aggregates",
group: {
field: "phone", aggregates: [{ field: "phone", aggregate: "count" }]
},
model: {
id: "id",
fields: {
id: { editable: false, nullable: true },
name: { validation: { required: true } },
phone: {
type: "string",
validation: {
required: true,
phonerule: function(e){
if (e.is("[data-phonerule-msg]"))
{
var input = e.data('kendoMaskedTextBox');
//If we reached the end of input then it will return -1 which means true, validation passed
//Otherwise it won't === -1 and return false meaning all the characters were not entered.
return input.value().indexOf(input.options.promptChar) === -1;
}
return true; //return true for anything else that is not data-phonerule-msg
}
}
},
email: { type: "string", validation: { required: true, email:true } }
}
}
}
});
$("#grid").kendoGrid({
dataSource: dataSource,
groupable: true,
sortable: {
mode: "multiple",
allowUnsort: true
},
selectable: "multiple cell",
allowCopy:true,
toolbar: ["create","excel"],
excel: {
fileName: "Kendo UI Grid Export.xlsx",
//Below is only used as fallback for old browsers without support
proxyURL: "//demos.telerik.com/kendo-ui/service/export",
filterable: true
},
pageable: {
refresh: true,
pageSizes: true,
buttonCount: 5
},
reorderable: true,
resizable: true,
columnMenu: true,
filterable: true,
editable: "popup",
mobile: true,
columns: [
{
field: "name",
title: "Company Name",
aggregates: ["count"],
groupFooterTemplate: "Count: #=count#"
},
{
field: "phone",
title: "Phone",
editor: function(container, options){
//pattern="[(][0-9]{3}[)] [0-9]{3}-[0-9]{4}"
var input = $('<input type="tel" data-phonerule-msg="Invalid Phone Number!" class="k-textbox" required />');
input.attr("name", options.field);
input.kendoMaskedTextBox({
mask: "(999) 000-0000"
});
input.appendTo(container);
},
aggregates: ["count"],
groupFooterTemplate: "Count: #=count#"
},
{
field: "email",
title: "Email",
editor: function(container, options){
var input = $('<input type="email" data-email-msg="Invalid email!" class="k-textbox" required/>');
input.attr("name", options.field);
input.appendTo(container);
},
aggregates: ["count"],
groupFooterTemplate: "Count: #=count#"
},
{
command: ["edit", "destroy"],
title: "Operations",
width: "240px"
}
],
});
</script>
My current code that generates the demo javascript via Symfony 3.0 is below in..
DefaultController.php
/**
* #Route("/api/companies", name="api_companies_read")
*/
public function apiCompaniesReadAction(Request $request)
{
$data["itemCount"] = "7";
// $tdata["field"] = "";
// $tdata["value"] = "";
// $tdata["items"] = "hey";
// $data["groups"][] = $tdata;
$tdata["id"] = "1";
$tdata["name"] = "Joe";
$tdata["phone"] = "(714)475-8651";
$tdata["email"] = "Joe#whatever.com";
$data["items"][] = $tdata;
$tdata["id"] = "2";
$tdata["name"] = "Rachel";
$tdata["phone"] = "(563)812-4184";
$tdata["email"] = "rachel#yahoo.com";
$data["items"][] = $tdata;
$tdata["id"] = "3";
$tdata["name"] = "John";
$tdata["phone"] = "(563)812-4184";
$tdata["email"] = "John#yahoo.com";
$data["items"][] = $tdata;
$tdata["id"] = "4";
$tdata["name"] = "Richard";
$tdata["phone"] = "(563)812-4184";
$tdata["email"] = "John#yahoo.com";
$data["items"][] = $tdata;
$tdata["id"] = "5";
$tdata["name"] = "Sister";
$tdata["phone"] = "(563)812-4184";
$tdata["email"] = "John#yahoo.com";
$data["items"][] = $tdata;
$tdata["id"] = "6";
$tdata["name"] = "Brother";
$tdata["phone"] = "(563)812-4184";
$tdata["email"] = "Brother#yahoo.com";
$data["items"][] = $tdata;
$tdata["id"] = "7";
$tdata["name"] = "Sibling";
$tdata["phone"] = "(563)812-4184";
$tdata["email"] = "Sibling#yahoo.com";
$data["items"][] = $tdata;
// schema: {
// total: "total",
// model: {
// id: "CompanyID",
// fields: {
// CompanyID: { editable: false, nullable: true },
// Name: { validation: { required: true } },
// Phone: { type: "string" },
// Email: { type: "string" }
// }
// }
// }
// replace this example code with whatever you need
return new JsonResponse($data);
}
The current JSON it creates looks like this.
JSON
{"itemCount":"7","items":[{"id":"1","name":"Joe","phone":"(714)475-8651","email":"Joe#whatever.com"},{"id":"2","name":"Rachel","phone":"(563)812-4184","email":"rachel#yahoo.com"},{"id":"3","name":"John","phone":"(563)812-4184","email":"John#yahoo.com"},{"id":"4","name":"Richard","phone":"(563)812-4184","email":"Richard#yahoo.com"},{"id":"5","name":"Sister","phone":"(563)812-4184","email":"Sister#yahoo.com"},{"id":"6","name":"Brother","phone":"(563)812-4184","email":"Brother#yahoo.com"},{"id":"7","name":"Sibling","phone":"(563)812-4184","email":"Sibling#yahoo.com"}]}
I found an article here that looks close to what I want just hard to understand. This might also help.
I created JSFiddle that can be played around with, just needs to be supplied valid data.
Update
I got server paging to work! The first major change is on the transport for the datasource you have to change the parameterMap to send json so you can access what its trying to tell your server to change.
dataSource = new kendo.data.DataSource({
transport: {
read: {
url: crudServiceBaseUrl + "/companies",
dataType: "json",
type: "POST"
},
update: {
url: crudServiceBaseUrl + "/companies/update",
dataType: "json",
type: "POST"
},
destroy: {
url: crudServiceBaseUrl + "/companies/destroy",
dataType: "json",
type: "POST"
},
create: {
url: crudServiceBaseUrl + "/companies/create",
dataType: "json",
type: "POST"
},
parameterMap: function(options, operation) {
return kendo.stringify(options);
}
},
My datasource looks like above, but you could adjust to your needs. Next my php file below.
PHP
/companies
/**
* #Route("/api/companies", name="api_companies_read")
*/
public function apiCompaniesReadAction(Request $request)
{
$request_body = file_get_contents('php://input');
$json = json_decode($request_body);
//Based on the JSON Payload response adjust the search in the database
if($json){
$page = $json->page;
$pageSize = $json->pageSize;
$skip = $json->skip;
$take = $json->take;
}else{
$page = 1;
$pageSize = 20;
$skip = 1;
$take = 1;
}
$repository = $this->getDoctrine()->getRepository('AppBundle:Company');
/*
findBy(
array $criteria,
array $orderBy = null,
integer|null $limit = null,
integer|null $offset = null
)
*/
$company_total = $repository->findAll();
$company_records = $repository->findBy(array(),array(),$pageSize,($page-1)*$pageSize);
$data["total"] = count($company_total);
foreach($company_records as $company){
$temp["id"] = $company->getId();
$temp["name"] = $company->getName();
$temp["phone"] = $company->getPhone();
$temp["email"] = $company->getEmail();
$data["data"][] = $temp;
}
//converts data to JSON
return new JsonResponse($data);
}
Please remember the above is a Symfony 3.0 php implementation using annotations to set the route. The important part in that code is.
$request_body = file_get_contents('php://input');
$json = json_decode($request_body);
//Based on the JSON Payload response adjust the search in the database
if($json){
$page = $json->page;
$pageSize = $json->pageSize;
$skip = $json->skip;
$take = $json->take;
}else{
$page = 1;
$pageSize = 20;
$skip = 1;
$take = 1;
}
The file_get_contents('php://input'); gets the javascript object that the KendoUI control sends back.
UPDATE # 3 Got Server Sorting Working!
Below is an example implementaiton using Symfony 3.0 and Doctrine to do Server Sorting!
PHP
/**
* #Route("/api/companies", name="api_companies_read")
*/
public function apiCompaniesReadAction(Request $request)
{
$request_body = file_get_contents('php://input');
$json = json_decode($request_body);
//print_r($json);
//default parameters in case of error.
$page = 1;
$pageSize = 20;
$skip = 1;
$take = 1;
$sort = array();
//Based on the JSON Payload response adjust the search in the database
if(isset($json)){
$page = $json->page;
$pageSize = $json->pageSize;
$skip = $json->skip;
$take = $json->take;
if(isset($json->sort)){
//"sort":[{"field":"name","dir":"asc"}]}:
foreach($json->sort as $sortObj){
$sort[$sortObj->field] = $sortObj->dir;
}
}
}
$repository = $this->getDoctrine()->getRepository('AppBundle:Company');
/*
findBy(
array $criteria,
array $orderBy = null,
integer|null $limit = null,
integer|null $offset = null
)
*/
$company_total = $repository->findAll();
$company_records = $repository->findBy(array(),$sort,$pageSize,($page-1)*$pageSize);
$data["total"] = count($company_total);
foreach($company_records as $company){
$temp["id"] = $company->getId();
$temp["name"] = $company->getName();
$temp["phone"] = $company->getPhone();
$temp["email"] = $company->getEmail();
$data["data"][] = $temp;
}
//converts data to JSON
return new JsonResponse($data);
}
That first link is spot on. I had to export data from a grid to pdf and excel adhering to the grid grouping. I finally figured out the semantics. The grid has columns and data objects which you can get through grid calls. The data object holds the grouping information. Here is the processing operation.
In a nutshell, you have to recursively iterate the data object tpo determine the grouping. For each element in the data you need to inspect if the data[x].value exists. If it exists then it is a group object with child data. If it does not exists then you use the normal data[row][column].field to get to the child data. The trick here is to call a recurisive function for each point where dat[0].value has data and finally process the data[row][column] on the unwind.
Below is a js function you can use to inspect the Grid's json dta. I would add a group or two to your grid and see the difference between the data with/without grouping applied and that should be what you need to add to your data....I think you pretty much add data as data={[[],[]]}unless it is a group, then it is data={[value='groupName',{[],[]}]}.
function showData(gridName) {
var grid = $('#' + gridName).data('kendoGrid');
var data = grid.dataSource.data().toJSON();
console.log(data);
}

getting exception while reading JSON response

I am getting exception while reading JSON response which is provided by HTTPBuilder in Groovy. please find the JSON string below. I am getting JSON response without quotes. I am using Groovy HTTPBuilder.
String x = {
apenvironments = [], temptype = dflt, audit = {
createdAt = 1438605399389,
createdBy = xxxxxx testing
}, basicInfo = {
id = AU7zkFVftRWGykHHiM1R,
name = MED_FREQ83282
}, id = AU7zkFVftRWGykHHiM1R, name = MED_FREQ83282,
policyElements = [{
authenticationType = AUTH12, type = AUTH
}, {
aggType = COUNT, soft = false, targets = [{
targetType = APPS, type = BasePolicyElementTarget
}], type = numrclmt, value = 5, valueEqualsZero = false
}, {
aggType = COUNT, soft = false, targets = [{
targetType = DEVICE, type = BasePolicyElementTarget
}], type = numerratlimt, value = 3, valueEqualsZero = false
}, {
enabled = true, type = ANALYTICS
}, {
meteringPayloadType = REQUEST, metricField = PAYLOAD, type = PAYLOAD_METERING
}, {
field = PAYLOAD, load = {
bandwidthUnit = KB, payloadType = REQUEST, type = payload, value = 26
}, soft = false, type = Payload, valueEqualsZero = false
}, {
aggType = COUNT, soft = false, targets = [{
targetType = USER, type = elementTarget
}], type = ratelt, value = 4, valueEqualsZero = false
}, {
hitType = ALL, metricField = HITS, type = meter
}, {
frequencyUnit = MINUTE, hits = {
hitType = ALL, hits = 3
}, metricField = HITS, soft = false, type = freqratelt, valueEqualsZero = false
}], templateName = tempv, type = plctem
};
ObjectMapper mapper = new ObjectMapper();
try {
JsonNode df=mapper.readValue(x,JsonNode.class);
...............
Exception:
com.fasterxml.jackson.core.JsonParseException: Unexpected character ('a' (code 97)): was expecting double-quote to start field name
Please help me on this.

HighCharts & MVC: How to load whole graph definition and data with JSON?

I'd like to know how it is possible to load options & data graph or whole graph structure returning a JSON object?
In particular, I'd like to dynamically create options, categories, axis, data, etc. with JSON; I think it is possible, but I only found informations describing how to load data& series, not options.
For example, I'd like to define title, xAxis, etc, returning a JSon Object:
[...]
title: {
text: 'Total fruit consumtion, grouped by gender'
},
xAxis: {
categories: []
},
[...]
In particular, I need to dynamically create a more complex graph, similar to this one: http://www.highcharts.com/demo/column-stacked-and-grouped
Thanks in advance!
With DotNet.Highcharts is possible to create the chart on the server side as you like without using JavaScript or JSON. Here is the example which you would like do with the library:
Highcharts chart = new Highcharts("chart")
.InitChart(new Chart { DefaultSeriesType = ChartTypes.Column })
.SetTitle(new Title { Text = "Total fruit consumtion, grouped by gender" })
.SetXAxis(new XAxis { Categories = new[] { "Apples", "Oranges", "Pears", "Grapes", "Bananas" } })
.SetYAxis(new YAxis
{
AllowDecimals = false,
Min = 0,
Title = new YAxisTitle { Text = "Number of fruits" }
})
.SetTooltip(new Tooltip { Formatter = "TooltipFormatter" })
.SetPlotOptions(new PlotOptions { Column = new PlotOptionsColumn { Stacking = Stackings.Normal } })
.SetSeries(new[]
{
new Series
{
Name = "John",
Data = new Data(new object[] { 5, 3, 4, 7, 2 }),
Stack = "male"
},
new Series
{
Name = "Joe",
Data = new Data(new object[] { 3, 4, 4, 2, 5 }),
Stack = "male"
},
new Series
{
Name = "Jane",
Data = new Data(new object[] { 2, 5, 6, 2, 1 }),
Stack = "female"
},
new Series
{
Name = "Janet",
Data = new Data(new object[] { 3, 0, 4, 4, 3 }),
Stack = "female"
}
});
You can find a lot of ASP.NET MVC examples here: http://dotnethighcharts.codeplex.com/releases/view/80650