I tried to use the dynamic attributes approach within my prototype mongoDB application.
Basically the approach just gives you something like this:
{
SKU: "Y32944EW",
type: "shoes",
attr: [
{ "k": "manufacturer",
"v": "ShoesForAll",
},
{ "k": "color",
"v": "blue",
},
{ "k": "style",
"v": "comfort",
},
{ "k": "size",
"v": "7B"
}
]
}
(Source: http://askasya.com/post/dynamicattributes).
The problem is that for example Kendo Grid does not support such nested structures in their data source.
Does anyone know if Sencha ExtJS Grid Component can do this?
Update: SKU should be a column and each v of the attr array should be a column.
Update: I am trying to setup a sencha fiddle with the help of your answer.
https://fiddle.sencha.com/#fiddle/evc
app.js (rev2)
// create the new type
Ext.data.Types.DYNAMIC = {
convert: function(value, record) {
for (var i = 0, ln = value.length; i < ln; i++) {
var item = value[i];
record.set(item.k, item.v);
}
return '';
},
type: 'dynamic',
sortType: Ext.data.SortTypes.none
};
// define a model
Ext.define('TestModel', {
extend: 'Ext.data.Model',
fields: [{name: "_id",type: "string"},
{name: "attr",type: Ext.data.Types.DYNAMIC}],
idProperty: '_id'
});
// create a store with the model assigned
Ext.create('Ext.data.Store', {
storeId: 'MyStore',
model: 'TestModel',
autoLoad: true,
proxy: {
type: 'ajax',
url: '/data.json',
reader: {
idProperty: '_id',
type: 'json',
root: 'data'
}
}
});
Ext.create('Ext.grid.Panel', {
title: 'Grid',
store: Ext.data.StoreManager.lookup('MyStore'),
columns: []
});
Ext.widget('window',{height: 200,width: 400, items: [grid ] }).show();
store.on('metachange', function(store, meta) {
grid.reconfigure(store, meta.columns);
});
data.json (rev2)
{
"metaData": {
"idProperty": "_id",
"rootProperty": "data",
"fields": [
{ "name": "_id","type": "string" },
{ "name": "de", "type":"string" },
{ "name": "en", "type":"string" },
{ "name": "fr", "type":"string" },
{ "name": "attr", "type": "dynamic"}
],
"columns": [
{
"header": "de",
"dataIndex": "de"
},
{
"header": "en",
"dataIndex": "en"
}
,
{
"header": "fr",
"dataIndex": "fr"
}
]
},
"data":
[
{"_id": "MyTextId1",
"attr":[
{
"k": "de",
"v": "GermanText Sample"
},
{
"k": "en",
"v": "English Text Sample"
},
{
"k": "fr",
"v": "French Text Sample"
},
]
},
{"_id": "MyTextId2",
"attr":[
{
"k": "de",
"v": "GermanText Sample 1"
},
{
"k": "en",
"v": "English Text Sample 1"
},
{
"k": "fr",
"v": "French Text Sample1 1"
},
]
}
]
}
Error Message:
Uncaught Error: [Ext.createByAlias] Unrecognized alias: data.field.[object Object]
Update:
Works with the snippet posted in the last edit of sra. Thank you!
Yes you can. And most of it is already Build in. Lets's start with the basics
Response MetaData
The server can return metadata in its response, in addition to the record data, that describe attributes of the data set itself or are used to reconfigure the Reader. To pass metadata in the response you simply add a metaData attribute to the root of the response data. The metaData attribute can contain anything, but supports a specific set of properties that are handled by the Reader if they are present:
root: the property name of the root response node containing the record data
totalProperty: property name for the total number of records in the data
successProperty: property name for the success status of the response
messageProperty: property name for an optional response message
fields: Config used to reconfigure the Model's fields before converting the response data into records
An initial Reader configuration containing all of these properties might look like this ("fields" would be included in the Model definition, not shown):
reader: {
type : 'json',
root : 'root',
totalProperty : 'total',
successProperty: 'success',
messageProperty: 'message'
}
If you were to pass a response object containing attributes different from those initially defined above, you could use the metaData attribute to reconifgure the Reader on the fly. For example:
{
"count": 1,
"ok": true,
"msg": "Users found",
"users": [{
"userId": 123,
"name": "Ed Spencer",
"email": "ed#sencha.com"
}],
"metaData": {
"root": "users",
"totalProperty": 'count',
"successProperty": 'ok',
"messageProperty": 'msg'
}
}
You can also place any other arbitrary data you need into the metaData attribute which will be ignored by the Reader, but will be accessible via the Reader's metaData property (which is also passed to listeners via the Proxy's metachange event (also relayed by the store). Application code can then process the passed metadata in any way it chooses.
A simple example for how this can be used would be customizing the fields for a Model that is bound to a grid. By passing the fields property the Model will be automatically updated by the Reader internally, but that change will not be reflected automatically in the grid unless you also update the column configuration. You could do this manually, or you could simply pass a standard grid column config object as part of the metaData attribute and then pass that along to the grid. Here's a very simple example for how that could be accomplished:
// response format:
{
...
"metaData": {
"fields": [
{ "name": "userId", "type": "int" },
{ "name": "name", "type": "string" },
{ "name": "birthday", "type": "date", "dateFormat": "Y-j-m" }
],
"columns": [
{ "text": "User ID", "dataIndex": "userId", "width": 40 },
{ "text": "User Name", "dataIndex": "name", "flex": 1 },
{ "text": "Birthday", "dataIndex": "birthday", "flex": 1, "format": 'Y-j-m', "xtype": "datecolumn" }
]
}
}
The Reader will automatically read the meta fields config and rebuild the Model based on the new fields, but to handle the new column configuration you would need to handle the metadata within the application code. This is done simply enough by handling the metachange event on either the store or the proxy, e.g.:
var store = Ext.create('Ext.data.Store', {
...
listeners: {
'metachange': function(store, meta) {
myGrid.reconfigure(store, meta.columns);
}
}
});
That for the basics. Now the details for your data-structure:
first we need a converter function to read the custom data
convert: function(value,record) {
for(var i=0,ln=value.length;i<ln;i++) {
var item = value[i];
record.set(item.k,item.v);
}
return ''; let's save memory an drop it
}
and we can publish the basic fields (and columns (not displayed)) - but we don't need becaouse the metachange can handle it all
{ name: "SKU", type:"string") }, // don't forget to mark this as the idProperty in the reader and in the model
{ name: "type", type:"string") },
{ name: "attr", type:"auto", convert: convert() }
all fields & columns below are published by the server with metachange
"metaData": {
"fields": [
{ name: "SKU", type:"string") },
{ name: "type", type:"string") },
{ name: "attr", type:"auto", convert: convert() },
// and the dynamic datafields
{ name: "manufacturer", type:"string" },
{ name: "style", type:"string" },
// ... and so on
],
"columns": [
{ "text": "ID", "dataIndex": "SKU", "width": 40 },
{ "text": "ID", "dataIndex": "SKU", "width": 40 },
// and the dynamic datacolumns
{ "text": "Manufacturer", "dataIndex": "manufacturer" },
{ "text": "Style", "dataIndex": "stlye" },
// ... and so on
]
}
Edit:
I recommend to either create your own reader which transform the data to a normalized JSON before processing it further or your own Ext.data.Types type. Because I think it is a bit faster I recommend to create your own data-type. The downside in your case is, that the field with this property need to be always AFTER the dynamic field, otherwise the reader will override the dynamic fields.
Here is a snipped that I tested with 4.2.3
// create the new type
Ext.data.Types.DYNAMIC = {
convert: function(value, record) {
for (var i = 0, ln = value.length; i < ln; i++) {
var item = value[i];
record.data[item.k] = item.v;
}
return '';
},
type: 'dynamic',
sortType: Ext.data.SortTypes.none
};
// define a model
Ext.define('TestModel', {
extend: 'Ext.data.Model',
fields: [{name: "_id",type: "string"},
{name: "attr",type: "dynamic"}],
idProperty: '_id'
});
// create a store with the model assigned
Ext.create('Ext.data.Store', {
storeId: 'MyStore',
model: 'TestModel',
autoLoad: true,
proxy: {
type: 'ajax',
url: '/data.json',
reader: {
idProperty: '_id',
type: 'json',
root: 'data'
}
}
});
Ext.create('Ext.grid.Panel', {
title: 'Grid',
store: Ext.data.StoreManager.lookup('MyStore'),
columns: []
});
Ext.widget('window',{height: 200,width: 400, items: [grid ] }).show();
store.on('metachange', function(store, meta) {
grid.reconfigure(store, meta.columns);
});
And the data
{
"metaData": {
"idProperty": "_id",
"rootProperty": "data",
"fields": [
{ "name": "_id","type": "string" },
{ "name": "de", "type":"string" },
{ "name": "en", "type":"string" },
{ "name": "fr", "type":"string" },
{ "name": "attr", "type": "dynamic" }
],
"columns": [
{
"header": "de",
"dataIndex": "de"
},
{
"header": "en",
"dataIndex": "en"
}
,
{
"header": "fr",
"dataIndex": "fr"
}
]
},
"data":
[
{"_id": "MyTextId1",
"attr":[
{
"k": "de",
"v": "GermanText Sample"
},
{
"k": "en",
"v": "English Text Sample"
},
{
"k": "fr",
"v": "French Text Sample"
},
]
},
{"_id": "MyTextId2",
"attr":[
{
"k": "de",
"v": "GermanText Sample 1"
},
{
"k": "en",
"v": "English Text Sample 1"
},
{
"k": "fr",
"v": "French Text Sample1 1"
},
]
}
]
}
Edit:
This snipped is tested in 5.1 and it worked
Ext.data.Types.DYNAMIC = {
convert: function(value, record) {
for (var i = 0, ln = value.length; i < ln; i++) {
var item = value[i];
record.data[item.k] = item.v;
}
return '';
},
type: 'dynamic',
sortType: Ext.data.SortTypes.none
};
Ext.define('Ext.data.field.Dynamic', {
extend: 'Ext.data.field.Field',
alias: 'data.field.dynamic',
sortType: 'none',
isDynamicField: true,
convert: function(value, record) {
for (var i = 0, ln = value.length; i < ln; i++) {
var item = value[i];
record.data[item.k] = item.v;
}
return '';
},
getType: function() {
return 'dynamic';
}
});
Ext.define('TestModel', {
extend: 'Ext.data.Model',
fields: [{name: "_id",type: "string"},{name: "attr",type: "dynamic"}],
idProperty: '_id'
});
var store = Ext.create('Ext.data.Store', {
storeId: 'MyStore',
model: 'TestModel',
autoLoad: true,
proxy: {
type: 'ajax',
url: '/qat/Content/TST/data.js',
reader: {
idProperty: '_id',
type: 'json',
rootProperty: 'data'
}
}
});
var grid = Ext.create('Ext.grid.Panel', {
title: 'Grid',
store: Ext.data.StoreManager.lookup('MyStore'),
dockedItems: [{xtype: 'pagingtoolbar',store: Ext.data.StoreManager.lookup('MyStore'), dock: 'bottom',displayInfo: false}],
columns: []
});
Ext.widget('window',{height: 200,width: 400, items: [grid ] }).show();
store.on('metachange', function(store, meta) {
// Apply the column definitions to the Grid
grid.reconfigure(store, meta.columns);
});
Related
When I try to query a document using a field within it that I have tried to index then RavenDB complains that it is not in fact indexed.
The document - "jobs/332" - is as follows:
{
"Type": "Outbound",
"Flight": {
"Operator": "SAS",
"Number": "267",
"Origin": "MAN",
"Gate": "019",
"Stand": "A12",
"STD": "2015-08-20T09:15:00.0000000Z",
"ETD": "2015-08-20T09:16:00.0000000Z",
"Status": "On Time",
"Seat": "16F"
},
"PAX": {
"Name": "Mr. John Smith",
"Types": [
{
"Description": "WCHC"
},
{
"Description": "DPNA"
}
],
"Prenotified": true
},
"Stages": [
{
"AssignedAgents": [
{
"Id": 34,
"Name": "Derek Brown"
}
],
"StageStart": {
"Location": "T1 Checkin",
"Time": "2015-08-20T08:00:00.0000000Z"
},
"StageEnd": {
"Location": "Lounge 1",
"Time": "2015-08-20T08:25:00.0000000Z"
}
},
{
"AssignedAgents": null,
"StageStart": {
"Location": "Lounge 1",
"Time": "2015-08-20T08:45:00.0000000Z"
},
"StageEnd": {
"Location": "Gate 019",
"Time": "2015-08-20T08:55:00.0000000Z"
}
}
]
}
I have created the following static index:
public class Job_Agent : AbstractIndexCreationTask<Job>
{
public Job_Agent()
{
Map = jobs => from job in jobs
from stage in job.Stages
from agent in stage.AssignedAgents
select new
{
agent.Id
};
}
}
When I try to query the document with the following query:
_session.Query<Job, Job_Agent>()
.First(u => u.Stages
.Any(t => t.AssignedAgents
.Any(a => a.Id == 34)));
Then I get the following message:
The field 'Stages_AssignedAgents_Id' is not indexed, cannot query on fields that are not indexed
Does anyone have any thoughts on where I have gone wrong here?
You index should be specified like so:
from job in docs.Jobs
select new
{
Stages_AssignedAgents_Id = job.Stages.SelectMany(x=>x.AssignedAgents).Select(x=>x.Id)
}
I want to display data using jQuery data table. I'm passing JSON response from C# using a Webmethod. The data jQuery is receiving is correctly formatted. The data table is showing an empty structure for certain rows and an alert as shown below:
Data tables warning : table id - example Requested unknown parameter 1 for row 0.
Also, the table structure is showing double quotes in the 1st column, and that's it.
I searched on that alert but the information got was not at all useful. Something is there I miss out. Kindly help me with this one.
My code:
$(document).ready(function () {
$.ajax({
type: "POST",
url: "data_table2.aspx/BindDatatable",
data: "{}",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (data) {
console.log(JSON.parse(data.d));
console.log(JSON.parse(data.d));
$('#example').dataTable({
"aaData": data.d,
"aoColumns": [
{ "aaData": "UserId" },
{ "aaData": "UserName" },
{ "aaData": "Location" }
]
});
}
});
});
Webmethod:
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public static string BindDatatable()
{
DataTable dt = new DataTable();
dt = getData();
List<User5> data = new List<User5>();
foreach (DataRow dtrow in dt.Rows)
{
User5 user = new User5();
user.UserId = dtrow["id"].ToString();
user.UserName = dtrow["name"].ToString();
user.Location = dtrow["city"].ToString();
data.Add(user);
}
System.Web.Script.Serialization.JavaScriptSerializer jSearializer = new System.Web.Script.Serialization.JavaScriptSerializer();
string aaData = jSearializer.Serialize(data);
// aaData = "{\"data\": " + aaData + "}";
return aaData;
}
The data jQuery receives is:
[{
"UserId": "2",
"UserName": "Nitin",
"Location": "Mumbai"
}, {
"UserId": "3",
"UserName": "NAkshay",
"Location": "Thane"
}, {
"UserId": "4",
"UserName": "Nil",
"Location": "Pune"
}, {
"UserId": "5",
"UserName": "Vinit",
"Location": "KArve nagar"
}, {
"UserId": "6",
"UserName": "Rahul",
"Location": "Kothrud"
}, {
"UserId": "7",
"UserName": "Pravin",
"Location": "Hinjewadi"
}, {
"UserId": "8",
"UserName": "Pavan",
"Location": "Mg City"
}]
if I removed that commentd line in c# code o/p will be
{
"data": [{
"UserId": "2",
"UserName": "Nitin",
"Location": "Mumbai"
}, {
"UserId": "3",
"UserName": "NAkshay",
"Location": "Thane"
}, {
"UserId": "4",
"UserName": "Nil",
"Location": "Pune"
}, {
"UserId": "5",
"UserName": "Vinit",
"Location": "KArve nagar"
}, {
"UserId": "6",
"UserName": "Rahul",
"Location": "Kothrud"
}, {
"UserId": "7",
"UserName": "Pravin",
"Location": "Hinjewadi"
}, {
"UserId": "8",
"UserName": "Pavan",
"Location": "Mg City"
}]
}
$('#example').dataTable({
"aaData": JSON.parse(data.d),
"aoColumns": [
{ "mData": "UserId" },
{ "mData": "UserName" },
{ "mData": "Location" }
]
});
Need to parse the info with "aaData": JSON.parse(data.d) one.
The problems is Datatables JS stays in state "processing" and the Chrome debug throws:
Uncaught TypeError: Cannot read property 'length' of undefined
The code in question that "feeds" datatables js is (data is some linq query):
var jsonData = Json(data);
return jsonData;
The response is (textual response):
[{
"TotalCredito": 1649112940.000000,
"TotalClientes": 1040,
"Balance7": 188974066.000000,
"Balance37": 25152742.000000,
"Balance67": 53268069.000000,
"Mes": 1
}, {
"TotalCredito": 1910576150.000000,
"TotalClientes": 941,
"Balance7": 332301396.000000,
"Balance37": 84407873.000000,
"Balance67": -7053061.000000,
"Mes": 2
}, {
"TotalCredito": 1852843443.000000,
"TotalClientes": 809,
"Balance7": 300589569.000000,
"Balance37": 87170595.000000,
"Balance67": 41900708.000000,
"Mes": 3
}, {
"TotalCredito": 1736522626.000000,
"TotalClientes": 747,
"Balance7": 235758479.000000,
"Balance37": 107699635.000000,
"Balance67": 60831390.000000,
"Mes": 4
}, {
"TotalCredito": 1611546395.000000,
"TotalClientes": 702,
"Balance7": 201209547.000000,
"Balance37": 59028449.000000,
"Balance67": 64171607.000000,
"Mes": 5
}, {
"TotalCredito": 1306131513.000000,
"TotalClientes": 697,
"Balance7": 552835099.000000,
"Balance37": 67349028.000000,
"Balance67": 50490441.000000,
"Mes": 6
}]
And the script function in the view is:
<script>
$(document).ready(function () {
var datatable = $('#informe').dataTable({
"language": { "url": "http://cdn.datatables.net/plug-ins/28e7751dbec/i18n/Spanish.json" },
"bFilter": false,
"processing": true,
"serverSide": true,
"ajax": {
"url": "somesupercoolurl",
"type": "POST",
"dataType": "json"
},
"columns": [
{ "data": "Balance7" },
{ "data": "Balance37" },
{ "data": "Balance67" },
{ "data": "Mes" },
{ "data": "TotalClientes" },
{ "data": "TotalCredito" }
],
});
});
Finally, the table is:
<table id="informe">
<thead>
<tr>
<th>Balance7</th>
<th>Balance37</th>
<th>Balance67</th>
<th>Mes</th>
<th>TotalClientes</th>
<th>TotalCredito</th>
</tr>
</thead>
</table>
I find it strange that while the information is properly formatted, is not able to process.
Finally, i resolve this
after seeing many examples, I noticed it's necessary include this 3 variables to json before parse the json object to datatables js; In the controller:
var totalDatos = data.Count();
var jsonData = Json(new {
iTotalDisplayRecords = totalDatos,
iTotalRecords = totalDatos,
aaData = data
});
return jsonData;
Whit this 'function', the json object is like this
{"iTotalDisplayRecords":6,"iTotalRecords":6,"aaData":[{"TotalCredito":1649112940.000000,"TotalClientes":1040,"Balance7":188974066.000000,"Balance37":25152742.000000,"Balance67":53268069.000000,"Mes":1},{"TotalCredito":1910576150.000000,"TotalClientes":941,"Balance7":332301396.000000,"Balance37":84407873.000000,"Balance67":-7053061.000000,"Mes":2},{"TotalCredito":1852843443.000000,"TotalClientes":809,"Balance7":300589569.000000,"Balance37":87170595.000000,"Balance67":41900708.000000,"Mes":3},{"TotalCredito":1736522626.000000,"TotalClientes":747,"Balance7":235758479.000000,"Balance37":107699635.000000,"Balance67":60831390.000000,"Mes":4},{"TotalCredito":1611546395.000000,"TotalClientes":702,"Balance7":201209547.000000,"Balance37":59028449.000000,"Balance67":64171607.000000,"Mes":5},{"TotalCredito":1306131513.000000,"TotalClientes":697,"Balance7":552835099.000000,"Balance37":67349028.000000,"Balance67":50490441.000000,"Mes":6}]}
The table, in the view:
<table id="informe">
<thead>
<tr>
<th>Mes</th>
<th>TotalCredito</th>
<th>TotalClientes</th>
<th>Balance7</th>
<th>Balance37</th>
<th>Balance67</th>
</tr>
</thead>
</table>
The Script is:
<script>
$(document).ready(function () {
var arrayDatos = {
'canal': $(" #ListaCanales ").val(),
'anio': $(" #ListaAnios ").val(),
'vendedorsigla': $(" #ListaVendedores ").val()
};
var datatable = $('#informe').dataTable({
"language": { "url": "http://cdn.datatables.net/plug-ins/28e7751dbec/i18n/Spanish.json" },
"bFilter": false,
"processing": true,
"serverSide": true,
"ajax": {
"url": "mensualajax",
"type": "POST",
"dataType": "json",
"data": arrayDatos
},
"columns": [
{ "data": "Mes", "bSortable": false },
{ "data": "TotalCredito" },
{ "data": "TotalClientes" },
{ "data": "Balance7" },
{ "data": "Balance37" },
{ "data": "Balance67" }
],
});
$(" #FiltrarResultados ").click(function () {
var arrayDatos = {
'canal': $(" #ListaCanales ").val(),
'anio': $(" #ListaAnios ").val(),
'vendedorsigla': $(" #ListaVendedores ").val()
};
datatable.fnClearTable();
$('#informe').dataTable({
"bDestroy": true,
"language": { "url": "http://cdn.datatables.net/plug-ins/28e7751dbec/i18n/Spanish.json" },
"bFilter": false,
"processing": true,
"serverSide": true,
"ajax": {
"url": "mensualajax",
"type": "POST",
"dataType": "json",
"data": arrayDatos
},
"columns": [
{ "data": "Mes", "bSortable": false },
{ "data": "TotalCredito" },
{ "data": "TotalClientes" },
{ "data": "Balance7" },
{ "data": "Balance37" },
{ "data": "Balance67" }
],
});
});
});
is important remark, i use the 'click' function to reload whit ajax the datatables, the 'click' function is nearly equal to the another, but i aggregate "bDestroy": true,in the datatable constructor to reload the datatables (It is not very elegant, but work).
Finally, my new superduper controller to render, capture and updating data with DatatablesJs
//repository with the query
var repositorio = new Repositorios.InformeMensualController();
//capture ajax
string canal = String.Join("", Request.Form.GetValues("canal"));
string auxAnio = String.Join("", Request.Form.GetValues("anio"));
int anio = Convert.ToInt32(auxAnio);
string auxVendedorCodigo = String.Join("", Request.Form.GetValues("vendedorsigla"));
int vendedorCodigo = Convert.ToInt32(auxVendedorCodigo);
//set up data
var data = repositorio.CargaDatos(canal, anio, vendedorCodigo);
//Transformación a JSON y Datatables JS.
var totalDatos = data.Count();
var jsonData = Json(new {
iTotalDisplayRecords = totalDatos,
iTotalRecords = totalDatos,
aaData = data});
return jsonData;
I hope this is useful to someone
regards! :)
I'm currently stuck on JSON deserialization.
Here is two type of JSON, I can receive :
{
"code": 0,
"response": {
"isFollowing": false,
"isFollowedBy": false,
"connections": {
"google": {
"url": "",
"id": "c35f4e",
"name": "jean"
},
"facebook": {
"url": "https://www.facebook.com/",
"id": "1000064139",
"name": "jean mic"
}
},
"isPrimary": true,
"id": "780",
"location": "",
"isPrivate": false,
"joinedAt": "2013-10-18T16:04:09",
"username": "jeandavid",
"numLikesReceived": 0,
"about": "",
"name": "jean",
"url": "",
"profileUrl": "",
"reputation": ,
"avatar": {
"small": {
"permalink": "https://picture.jpg",
"cache": "https://picture.jpg"
},
"isCustom": false,
"permalink": "https://picture.jpg",
"cache": "/noavatar9.png",
"large": {
"permalink": "w",
"cache": "https://picture.jpg"
}
},
"isAnonymous": false
}
}
And this one :
{
"response": [
{
"uid": 2017156,
"first_name": "David",
"last_name": "Jean",
"sex": 1,
"nickname": "",
"bdate": "12.12.1990",
"photo_medium": "img.jpg"
}
]
}
At beginning, I use :
Dictionary<string, string> deserializedObj = JsonConvert.DeserializeObject<Dictionary<string, string>>(response);
But it works only with unidimensional Json data.
So after looking on Google, I tried to use :
JArray jArr = (JArray)JsonConvert.DeserializeObject(response);
foreach (var item in jArr)
{
Console.WriteLine(item);
}
But I receive this exception :
Unable to cast object of type 'Newtonsoft.Json.Linq.JObject' to type 'Newtonsoft.Json.Linq.JArray'.
For the first JSON data I would like to get the Google and Facebook data and also the username, the reputation, the avatar, the id of the user, ...
Thanks for any help!!
namespace WebApplication1.Site
{
public partial class WebForm1 : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
var accessToken = "" // Token
var client = new FacebookClient(accessToken);
dynamic myInfo = client.Get("me/friends", new { fields = "name,id,work" });
foreach (dynamic friend in myInfo)
{
foreach (dynamic work in friend.work ?? new[] { new { employer = new { name = string.Empty }, position = new { name = string.Empty } } })
{
Response.Write("Employer: " + work.employer.name);
}
}
}
}
}
I am getting the following error on line 21. I cannot figure out what is causing it.
'System.Collections.Generic.KeyValuePair' does not contain a definition for 'work'
Sample JSON Return from the Facebook GraphAPI. This is only the first three friends. There are closer to 4000 friends I am parsing, obviously this gives some context for the structure of the data:
{
"data": [
{
"name": "Mia xxx",
"id": "11381",
"work": [
{
"employer": {
"id": "100982923276720",
"name": "New-York Historical Society"
},
"location": {
"id": "108424279189115",
"name": "New York, New York"
}
}
]
},
{
"name": "Leilah xxx",
"id": "1133"
},
{
"name": "xxx,
"id": "1231",
"work": [
{
"employer": {
"id": "104362369673437",
"name": "Bye Bye Liver: The Philadelphia Drinking Play"
},
"location": {
"id": "101881036520836",
"name": "Philadelphia, Pennsylvania"
},
"position": {
"id": "121113421241569",
"name": "Actress/Bartender"
},
"description": "A sketch comedy/improv show every Saturday night at Downey's on South & Front. Come thirsty!",
"start_date": "2011-09"
},
{
"employer": {
"id": "100952634348",
"name": "Act II Playhouse"
},
"location": {
"id": "109249869093538",
"name": "Ambler, Pennsylvania"
},
"position": {
"id": "125578900846788",
"name": "My Fair Lady"
},
"description": "11 actor version of the classic musical.",
"start_date": "0000-00"
},
An alternative to relying on the dynamic is to capture and parse the JSON with JSON.net, it's designed for querying json data and is really much safer than using dynamic
http://json.codeplex.com/
And deserializing into classes:
http://dotnetbyexample.blogspot.ca/2012/02/json-deserialization-with-jsonnet-class.html
Look at this:
Response.Write("Employer: " + myInfo.work.employer.name);
I suspect you meant:
Response.Write("Employer: " + work.employer.name);
Put it this way - if that's not what you meant, what's the purpose of your work variable?