I am POSTing a JSON object to a controller action:
$.ajax({
url: "/path/to/action",
type: "POST",
dataType: "json",
data: {
name: "John Doe",
phone: "2323454543",
skills: {
code: "php",
design: "photoshop"
}
}
});
How can I map this data to some kind of key-value pair object? In PHP, these get mapped to an associative array invisibly. I would like to be able to access properties like this:
SomeDynamicType data = ...//something here to prepare json data
string codeSkills = data.skills.code; //codeSkills should = "php"
I'm not interested in model binding since these value do not correspond to a model - they are arbitrary.
In your .ajax call stringify Json:
data: {
json:
JSON.stringify({
name: "John Doe",
phone: "2323454543",
skills: {
code: "php",
design: "photoshop"
}
})
}
And accessing properties how you wanted in your controller:
[HttpPost]
public JsonResult Action(string json)
{
dynamic data = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(json);
string codeSkills = data.skills.code;
...
codeSkills is "php" string.
Newtonsoft Json library is available since .NET 4, if I recall correct.
Try using JSON.NET, this library parses JSON into a dictionary-like structure. It is used as follows:
JObject rss = JObject.Parse(json);
string codeSkills = (string)rss["skills"]["code"];
Related
I get this type of JSON data from Web API:
Data: {
FromDate: "2016-03-01",
Comment: "Bla bla",
...
},
FieldInfo: {
Items: [
{
Id: "FromDate",
Required: true,
DataType: "date"
},
{
Id: "Comment",
Required: true,
DataType: "string"
},
...
]
}
I need to serialize it to C# object and transform it to different representaion which should look something like this:
{
FieldInfo: {
Items: [
{
Id: "FromDate",
Required: true,
DataType: "date",
Value: "2016-03-01"
},
{
Id: "Comment",
Required: true,
DataType: "string"
Value: "Bla bla"
},
...
]
}
Basically map field values to its schema so it will not be separated.
Of course easiest way its just write a lot of if's for each field, which will not be very elegant solution and even not doable if we take into account that field schema and fields are dynamic so they can change. Property which I can rely on is Id in FieldInfo Item schema which should be a property name in Data object. One of the solution might be to use reflection in order to map Id value to property name in C# object representation. My question maybe there is another solution(s) to this problem or some tools which can help me in achieving this goal?
Using JSON.NET, you can parse the JSON into a JObject and manipulate it like so:
// Parse your json string into a JObject
JObject o = JObject.Parse(json);
// Retrieve the "Data" part of the json, i.e,
// the object that contains the values
var data = o["Data"];
// Retrieve the "FieldInfo" part. We will add values to this part.
var fieldInfo = o["FieldInfo"];
foreach (var token in fieldInfo["Items"])
{
var item = (JObject) token;
// Add the Value property to each item, get the value from the
// corresponding field
item["Value"] = data[(string)item["Id"]];
}
The variable fieldInfo will contain the information you wanted. Of course, it would be cleaner to create a new JObject to contain the information. But the example shows how you can retrieve and map the values you require.
You will have to implement some form of custom json converter to get the required output you desire to your new class structure. JSON.NET Custom JsonConverter:
http://www.newtonsoft.com/json/help/html/CustomJsonConverter.htm
Here is a nice beginners tutorial on how this is achieved:
http://geekswithblogs.net/DavidHoerster/archive/2011/07/26/json.net-custom-convertersndasha-quick-tour.aspx
I was trying to pass json data to .net mvc controller. it seems like mvc automatically converted id and lastdatetime to correct format, but not int[] currentIds, anyone know why?
var jsonData = {
"id": id,
"lastDataTime": lastDateTime,
"currentIds": [1, 2, 3, 4]
};
public void Process(int id, DateTime lastDateTime, int[] currentIds)
{
}
Please try this:
$.ajax({
type: "POST",
url:"#Url.Action("Index", "Home")" ,
data: {
"id": id,
"lastDataTime": lastDateTime,
"currentIds": [1, 2, 3, 4]
},
dataType: "json",
traditional: true,
success: function(msg){
alert(msg)
}
});
public ActionResult Index(int id, DateTime lastDateTime, int[] currentIds)
{
}
Simplify this problem and get the array working first, try this:
View
var myArray = ["1", "2", "3","4"];
$.ajax(
{
type: "POST",
url: '/ControllerName/ActionMethod/',
data: JSON.stringify(myArray),
cache: false,
//dataType: "html",
success: ///
})
Controller
public ActionResult Index(List<String> currentIds)
{
///
}
Debug this and check the list is populated then introduce the other objects.
I have following json created after I sereliaze a dictionary
{"Results":["{\"BaseCurrency\":\"USD\",\"TermCurrency\":\"JPY\"}","{\"BaseCurrency\":\"USD\",\"TermCurrency\":\"JPY\"}","{\"BaseCurrency\":\"USD\",\"TermCurrency\":\"JPY\"}","{\"BaseCurrency\":\"USD\",\"TermCurrency\":\"JPY\"}"],"Total":4}
When I try to load it into the extjs store , the store is not loaded
var store = Ext.create('Ext.data.Store', {
fields: fields,
pageSize: itemsPerPage,
proxy: {
type: 'ajax',
url: getDataWithPageURL,
reader: {
type: 'json',
root: 'Results',
totalProperty: 'Total'
}
}
});
But if I remove slash hard coded and it's working
{"Results":["{"BaseCurrency":"USD","TermCurrency":"JPY"}","{"BaseCurrency":"USD","TermCurrency":"JPY"}","{"BaseCurrency":"USD","TermCurrency":"JPY"}","{"BaseCurrency":"USD"}"],"Total":4}
I create json using Newtonsoft.Json
Dictionary<string, object> dict = new Dictionary<string, object>();
string s = JsonConvert.SerializeObject(dist);
How can I remove slash in server side in order to produce valid json for extjs store.
I tried
result = result.Replace("\"","'");
And
result =result.Replace("\"", #"""")
It's not working
Clearly, Ext doesn't like that you have encoded a json object as a string and then put them in another json object. You have two options that I see.
See if you can return the dict on the server-side without first converting it into a string. Some code, somewhere, is taking your string and putting it in a json object with 'Results' and 'Total'. Check to see if that code can take a Dictionary as-is.
Unwrap the 'Results' propery on the client-side. One way would be to make your own reader:
Ext.define('MyReader', {
extend: 'Ext.data.reader.Json',
alias: 'reader.my-json',
read: function(object) {
object.Results = Ext.Array.map(object.Results, Ext.decode);
return this.callParent([object]);
}
});
Then use type: 'my-json' in your reader config.
Here is my test case:
var data = {"Results":["{\"BaseCurrency\":\"USD\",\"TermCurrency\":\"JPY\"}","{\"BaseCurrency\":\"USD\",\"TermCurrency\":\"JPY\"}","{\"BaseCurrency\":\"USD\",\"TermCurrency\":\"JPY\"}","{\"BaseCurrency\":\"USD\",\"TermCurrency\":\"JPY\"}"],"Total":4};
Ext.define('Currency', {
extend: 'Ext.data.Model',
fields: [
{ name: 'BaseCurrency', type: 'string' },
{ name: 'TermCurrency', type: 'string' }
]
});
Ext.define('MyReader', {
extend: 'Ext.data.reader.Json',
alias: 'reader.my-json',
read: function(object) {
object.Results = Ext.Array.map(object.Results, Ext.decode);
return this.callParent([object]);
}
});
var store = Ext.create('Ext.data.Store', {
model: 'Currency',
data: data,
proxy: {
type: 'memory',
reader: {
type: 'my-json',
root: 'Results',
totalProperty: 'Total'
}
}
});
I am trying, and struggling, to send an array via JSON to a MVC controller action.
Here is what I have and what i've tried...
//Get checked records
var $checkedRecords = $(':checked'); //e.g. 3 rows selected = [input 4, input 5, input 6]
//Have tried following:
sendingVar: $checkedRecords.serializeArray(); // gives array of 0's
sendingVar: JSON.stringify($checkedRecords); // gives "{\"length\":1,\"prevObject\":{\"0\":{\"jQuery1313717591466\":1,\"jQuery1313717591653\":13},\"context\":{\"jQuery1313717591466\":1,\"jQuery1313717591653\":13},\"length\":1},\"context\":{\"jQuery1313717591466\":1,\"jQuery1313717591653\":13},\"selector\":\":checked\",\"0\":{}}"...wtf
//Post
$.post(url, { sendingVar: sendingVar }, function(data) {alert(data); });
How do I do it ?
edit: to those that suggest sending $checkedRecords "as is" from the top line - that is not working. I get a strange exception somewhere in the jquery framework :(
uncaught exception: [Exception... "Could not convert JavaScript argument" nsresult: "0x80570009 (NS_ERROR_XPC_BAD_CONVERT_JS)" location: "JS frame :: http://.../.../.../jquery-1.4.4.min.js :: <TOP_LEVEL> :: line 141" data: no]
which I think means it is attempting to assign null to something it cannot.
Edit: i'm using MVC2 not 3
Edit2: After #Monday's answer- the problem is due to how I have built the array like [input 4, input 5, input 6] and not [4,5,6] - any ideas how I can just get the values in the array instead ?
Edit3: Stop voting up duplicate when it's not. Did you actually read my problem or read the problems linked? this is a different issue
#Daveo:
I don't want to build in an overriding custom attribute just to send an array from JSON, that is rediculous as we've already covered in this question-it is not necessary.
MVC3 - irrelevant
Here is my demo,use mvc2,hope some helps~
The key to success is traditional
set the traditional parameter to true
$(function(){
var a = [1, 2];
$.ajax({
type: "POST",
url: "<%= ResolveUrl("~/Home/PostArray/") %>",
data: {orderedIds: a},
dataType: "json",
traditional: true,
success: function(msg){alert(msg)}
});
})
Since jquery 1.4 this parameter exists because the mechanism to serialize objects into query parameters has changed.
and action is~
[HttpPost]
public ActionResult PostArray(int[] orderedIds)
{
return Content(orderedIds.Length.ToString());
}
you can also use JSON.stringyfy to sent the data as a string then use JavaScriptSerializer class to retrive the data.
In C# code, to get the data, will look like this:
JavaScriptSerializer js = new JavaScriptSerializer();
js.Deserialize<T>(string paramiter);
use this simple code
var url = '/sampleController/sampleAction'
var params = {sendingVar: [1,2]}
$.post(url, params , function (data) {
$("#lblResult").html(' : ' + data);
}).fail(function (e) {
alert(e);
});
I build a navigation tree and save the structure using this function in an array
function parseTree(html) {
var nodes = [];
html.parent().children("div").each(function () {
var subtree = $(this).children("div");
var item = $(this).find(">span");
if (subtree.size() > 0)
nodes.push([item.attr("data-pId"), item.attr("data-id"), parseTree(subtree)]);
else
nodes.push(item.attr("data-pId"), item.attr("data-id"));
});
return nodes;
}
Then I serialize the data
var tree = $.toJSON(parseTree($("#MyTree").children("div")));
Get this array
[
["881150024","881150024",
[
"994441819","881150024",
"214494418","881150024"
]
],
["-256163399","-256163399",
[
"977082012","-256163399",
"-492694206","-256163399",
[
"1706814966","-256163399",
["-26481618","-256163399"]
]
]
]
]
And send it by ajax
$.ajax({
url: "Editor/SerializeTree",
type: "POST",
data: { tree: tree },
success: function (result) {
alert("OK");
}
});
Question: How do I Deserialize this JSON with JavaScriptSerializer in C#?
Here it seems like you've got an array of nodes and each node has a set of strings or another array of nodes, right? The first thing you could do is just deserialize this to a List<object> like so:
string treeData = "..."; // The JSON data from the POST
JavaScriptSerializer js = new JavaScriptSerializer();
List<object> tree = js.Deserialize <List<object>>(treeData);
This will turn your JSON into a list of objects, though you'll need to manually figure out what is what (if each object a string or another List<object>).
Generally, though, it helps to have some kind of class or struct to represent the "schema" for the the data you are giving the serializer, but it's a bit more work than the above.
In this instance, you'd need your input data to be an actual JSON object rather than just an array. Say you have this JSON (based on the above data):
{id: "root", children: [
{id: "881150024"},
{id: "881150024", children: [
{id: "994441819"}, {id: "881150024"}]},
{id: "-256163399"},
{id: "-256163399", children: [
{id: "-492694206"},
{id: "-256163399", children: [
{id: "1706814966"},
{id: "-256163399", children: [
{id: "-26481618"}, {id: "-256163399"}]}
]}]}]}
If you have a class like this:
public class Node
{
public String id;
public List<Node> children;
}
You can then do something like:
string treeData = "..."; // The JSON data from the POST
JavaScriptSerializer js = new JavaScriptSerializer();
Node root = js.Deserialize<Node>(treeData);
That will be much easier to work with in code.
Taking into account answer by #_rusty.
In MVC3 it is possible to bing JSON data into actions, so your controller code would be very simple
[HttpPost]
public void SerializeTree(IList<Node> tree)
{
// tree is deserialized JSON here
}
For those rare few of us still using VB.Net here and there:
Imports System.Web.Script.Serialization
'wsvcResponse<string> contains the following JSON object: { "foo":"bar", "foo2": { "bar2": "foobar" } }
Dim jsSerializer As New JavaScriptSerializer()
Dim jsonObject As List(Of Object) = jsSerializer.Deserialize(Of Object)(wsvcResponse)
Dim foo As String = jsonObject("foo").ToString ' "bar"
Dim bar2 As String = jsonObject("foo2")("bar2").ToString ' "foobar"