I have a Javascript object like this:
var jsonDataActual = {
"source": [{
"name": "testCaption0",
"desc": "testDescrip0",
"values": [{
"from": "/Date(1338811241074)/",
"to": "/Date(1346760041074)/",
"label": "testLabel0",
"customClass": "GanttRed"
}]
}],
"navigate": "scroll",
"scale": "weeks",
"maxScale": "months",
"minScale": "days",
"itemsPerPage": 11,
"onItemClick": function (data) { },
"onAddClick": function (dt, rowId) { }
};
it works fine for me. Now, because of my requirement and need, am making this entire object(including braces i.e.{ } and semicolon ;) as a string on server side (C#) and returning it to an ajax call (web Method) using a server side method:
in the server side method I do something like this:
return new JavaScriptSerializer().Serialize(jsonData);
but now this entire returned data (inside Success: function(msg){ var s=msg.d} ) is treated as string, hence it doesn't work.
I tried these:
1. var obj = eval('{' + msg.d +'}'); (removing beginning and ending braces in msg.d)
typeof(obj) is string. failed
2. eval('var obj ='+msg.d); (including beginning and ending braces in msg.d)
typeof(obj) is string. failed
3. var obj= jQuery.parseJson(msg.d);
typeof(obj) is string. failed
4. var obj = new Object();
//var obj = {};
obj=jQuery.parseJson(msg.d).
typeof(obj) is string. failed.
please help. How can I convert a server side returned json into object?
Why not is it working for me??. Is it because of structure of my json object??
and why does jsonDataActual works for me but not when sent as a string???
I saw this and this..
Please Help.....
found out solution to my specific problem.
I was constructing a string variable with my json data as its value. And then I would return this string to the client side function(the one making ajax request). i.e.
Server side method
[WebMethod]
public static string GetJsonData()
{
string jsonData = String.Empty;
foreach(var dataItem in objEntireData.Items)
{
// jsonData +=
}
return new JavaScriptSerializer().Serialize(result);
}
but it was not working. So instead of constructing a string variable and serializing it, I wrote a class with specific structure and sent it in the return statement(after serialzing).
i.e. see below classes
public class A
{
public A()
{
Values = new List<B>();
}
public string prop1 {get; set;}
public List<B> Values { get; set; }
}
public class B
{
public string prop2 { get; set; }
public string prop3 { get; set; }
}
and I would use this class as below:
[WebMethod]
public static string GetJsonData()
{
List<A> objA = new List<A>();
A objAItem = new A();
foreach (var dbItem in objDataBaseValues)
{
objA.prop1 = "test";
B objBItem = new B();
b.prop2="value";
b.prop3="value";
objA.Values.Add(objBItem);
}
return new JavaScriptSerializer().Serialize(objA);
}
wrapping up my entire data into a class structure and then serializing this worked for me. my client side function successfully recognized it as an object i.e.
$.ajax({
type: "POST",
url: "ProjectGanttChart.aspx/getData",
contentType: "application/json; charset=utf-8",
dataType: "json",
success: function (msg) {
var jsonData = jQuery.parseJSON(msg.d);
populateGantt(jsonData);
}
});
try this
var json=(typeof msg.d) == 'string' ? eval('(' + msg.d + ')') : msg.d;
I've run into this many times before. When a WCF service is decrypting the returned data into JSON, string data will always have " " around it. You should always return objects, or lists of objects from your WCF service - even if these are custom objects created at your service level.
So, your service should be, say:
[OperationContract]
[WebGet(BodyStyle = WebMessageBodyStyle.Bare, UriTemplate = "/Test?testId={testId}", RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json)]
List<TestObjectJSON> Test(int testId);
This will then do the deserialization for you on the service side, without using the Serializer.
How can I convert a server side returned json into object?
You can use JSON.parse to do that.
Example:
a = [1, 2];
x = JSON.stringify(a); // "[1,2]"
o = JSON.parse(x); // [1, 2];
Related
I have a C# view class such as this:
public class DataObject
{
public int Number { get; set; }
public dynamic Data { get; set; } // <-----
}
being used in an MVC method like this
[HttpPost]
public ActionResult SaveData(DataObject request) {}
The problem is that I want to recieve multiple types of objects in the Data property of the DataObject class.
That is, I want both these to work as valid input json objects.
Type 1
{
Number: 1,
Data: {
Text: "a text"
}
}
Type 2
{
Number: 2,
Data: {
Value: 1,
Options: { 1, 2, 3, 4 }
}
}
Is there a way of doing this with either dynamic objects or some other type of json library magic (just making the property dynamic did nothing)?
All i want to do is store this data in a SQL column nvarchar field and return at a later time (through Entity Framework).
An alternate solution would be to create a view model for each type of input but as there will be 100's of variants to it creating all these views and the corresponding input methods would be cumbersome to maintain.
Adding more details as per comment request: The method is called through Angular.
pub.Save = function (jsonData) {
return $http(
{
method: "POST",
url: baseURL + "/Save",
data: { request: jsonData}, // tried this for string
// data: jsonData, // original way
timeout: 30000
}
)
.then(function (result) {
return result.data;
});
}
At the server side, DTO class must match with the same property name which the payload is carrying.
public class DataObject
{
public string test { get; set; } // <-----
}
So, your save method remains the same:
[HttpPost]
public ActionResult SaveData(DataObject request) {}
The payload json is in the object request.test but its seralized.
Deseralize it using Json Library.
How is it handling multiple different types of variables?
Deseralize it to a dynamic type as:
dynamic obj = JsonConvert.DeserializeObject(request.test, typeof(object));
//Properties within the obj are checked at run time.
if(obj.Text != null) {
//Do your thing
}
if(obj.Value != null) {
//Do your thing
}
if(obj.Options != null) {
//Do your thing
}
By converting the data to a JSON string on the client side I was able to send it to the string property and thus being able to use the same typed view for all objects.
I ended up doing this when saving the object (I'm using angular on the front end), converting the Json object to a string.
entry.Data = angular.toJson(entryData.Data, false);
And then when getting the json string back from MVC I did this to get it back to a real javascript object.
entry.Data = angular.fromJson(entry.Data);
MVC would not accept the JSON object into the text property without making it into a json string first.
Using the above method I am storing data like this in my database:
"{\"Value\":123,\"Currency\":\"EUR\"}"
I have Developed the C# Web Method. In this Method Request and Response are Json Array Format.
When I Read Json Array from Post Request, Error Occurred.
My Json Array is
[{"partner_hotel_code": "510","reservation_id": "7660"},{"partner_hotel_code": "510","reservation_id": "7666"}]
Error is
"Type 'System.Collections.Generic.IDictionary`2[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089],[System.Object, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]' is not supported for deserialization of an array."
When i changed the Json into below mentioned format, My method is working Properly.
{"JsonData":[{"partner_hotel_code": "510","reservation_id": "7660"},{"partner_hotel_code": "510","reservation_id": "7666"}]}
But I don't want this format.
Please help, how to rectify the Problem.
You can map that JSON array to List of C# class.
public class RootObject
{
public string partner_hotel_code { get; set; }
public string reservation_id { get; set; }
}
In the web method add parameter List<RootObject> ObjectList
You are getting this error because the Json parameter is required to be an object of key-value pairs, that is:
{"JsonData":[{"partner_hotel_code": "510","reservation_id":
"7660"},{"partner_hotel_code": "510","reservation_id": "7666"}]}
{'Key': Value} => Key - JsonData, Value => array of items
With this in mind, you can make your models to match this structure as follows:
Prepare a model Item,
public class Item
{
public string partner_hotel_code { get; set; }
public string reservation_id { get; set; }
}
Then prepare a root 'Node' object that will take in a list of the items, let's call it Reservations:
public class Reservations
{
List<Item> JsonData { get; set; }
}
You can then deserialize as shown below:
var data = new JavaScriptSerializer().Deserialize<Reservations>(postData);
But the structure you wanted is something like: [{"partner_hotel_code": "510",...}]
You can achieve this by many ways, an example is using a foreach:
var list = new List<Item>();
foreach(var item in data.JsonData)
{
list.Add(item);
}
/*The value of list here will contain the items*/
listArray[] myArray = list.ToArray();
another solution to this problem is to serialize your array first, then create a JSON object with your method parameter name, and Serialize that...
it goes something like this
var myobj = { myArray: JSON.stringify(a) };
passedData = JSON.stringify(myobj);
$.ajax({
type: "POST", contentType: "application/json", data: passedData,
url: window.location.href + "/myMethod",
success: function (result) {
....
}
});
and the webMethod
public static void myMethod(String myArray)
{
dynamic jsonResponse = JsonConvert.DeserializeObject(myArray);
for (var i = 0; i < jsonResponse.Count; i++)
{
...........
}
}
I've got as simple asmx returning JSON:
[WebService(Namespace = "http://tempuri.org/")]
[WebServiceBinding(ConformsTo = WsiProfiles.BasicProfile1_1)]
[System.ComponentModel.ToolboxItem(false)]
[System.Web.Script.Services.ScriptService]
public class myWebService: System.Web.Services.WebService
{
[WebMethod]
[ScriptMethod(ResponseFormat = ResponseFormat.Json)]
public MyCustomClassObject GetTestData()
{
MyCustomClassObject x = new MyCustomClassObject();
x.PropertyA = "1";
x.PropertyC = "1";
return x;
}
c# class definition:
public class MyCustomClassObject
{
public string PropertyA { get; set; }
public string PropertyB { get; set; }
public string PropertyC { get; set; }
public object PropertyD { get; set; }
}
Called using jquery $.ajax:
var jqxhr = $.ajax(
{
type: 'POST',
contentType: "application/json; charset=utf-8",
url: "/WebServices/myWebService.asmx/GetTestData",
data: parameters,
dataType: "json",
success: successLoadingData,
error: errorLoadingData,
complete: function () { $("#LoadingImage").hide(); }
});
My JSON Response (with unwanted null values):
{"PropertyA":"1","PropertyB":null,"PropertyC":"1","PropertyD":null}
Question:
How do I only get the non null properties only in JSON using as much of what I have already as possible?
I've seen some answers on here where people are returning JSON objects and properties defined with JSON attributes but I'm simply returning my object and the webservice is converting it to JSON for me (due to the Response.Format attribute). If i have to I will change my approach but its my first JSON project so was hoping to keep it simple. Thanks.
Continuation from the comment section.
Even if you call a function to remove the null values, my personal opinion about it would be that it's bad design, having a dictionary and serializing that is a more elegant way than having to remove the properties we don't want after we're done.
What I would do is something like this:
public class MyCustomClassObject
{
public Dictionary<string, object> Foo { get; set; }
public MyCustomClassObject()
{
this.Foo = new Dictionary<string, object>();
}
}
public MyCustomClassObject GetTestData()
{
MyCustomClassObject x = new MyCustomClassObject();
x.Foo.Add("PropertyA", 2);
x.Foo.Add("PropertyC", "3");
return x.Foo;
}
this gives you a more generic object to work with and follows the JSON format better, since you theoretically could have a list or array of objects as a value, this is also more adaptable to work with since you can add the PropertyD here.
Why do you need something that removes the values after you've added them?
You can recursively remove the properties that are null, here's a snippet that does that:
function removeNulls(obj){
var res = {};
for(var key in obj){
if (obj[key] !== null && typeof obj[key] == "object")
res[key] = removeNulls(obj[key]);
else if(obj[key] !== null)
res[key] = obj[key];
}
return res;
};
The usage is removeNulls(jsonResult)
See it in action here
The following screen shot shows the data I'm sending (shown with firebug in firefox).
The code below then shows the method the ajax method calls. The Date and Id properties are correctly populated when hitting the server side method call but my array (of type CustomerRequests) has no values inside it, however the number of CustomerRequests in the post is correct.
Any ideas?
Thanks
My Controller method
public ActionResult Show(Customers request)
{
..
// Number of request.CustomerRequests is correct
// Although request.CustomerRequests[0].Name == null ?? which is wrong
Customers class below:
[DataContract]
public class Customers
{
[DataMember]
public CustomerRequests[] CustomerRequests{ get; set; }
[DataMember]
public DateTime Date { get; set; } // I can see this value
[DataMember]
public int Id{ get; set; } // I can see this value
}
[DataContract]
public class CustomerRequests
{
[DataMember]
public string Name { get; set; }
[DataMember]
public string Expression { get; set; }
}
Javascript
$('textarea').each(function () {
var theName = 'The Name';
var theExpression = 'The Expression';
var obj = {
'Name': theName,
'Expression': theExpression
};
expressionArray.push(obj);
}); // close each
// val is the posted data
var val = {
'Id': '1',
'Date': '2013-10-10',
'CustomerRequests': $.makeArray(expressionArray)
};
I've tried although it doesn't work.
JSON.stringify({ Customers: val })
After all, we just have to add a content-type to your call and to remove the name from data.
It's something like
$.ajax({
url: '/controller/action',
cache: false,
type: 'POST',
contentType: 'application/json; charset=utf-8',
data: JSON.stringify(viewModel)
});
Please note that:
hard coding the URL is a bad practice. You should use #Url.Content("") or something like that
JSON.stringify may not work with older browsers. You may need to add this lib: http://www.json.org/js.html
Although this is not exactly an answer, because I have never used the built-in serializers, I can advise you to use the Json.NET library. I've been using it now for a long time, and I like it very much.
As for your question, I would try using List<T> instead of array, and I would probably try to instantiate the List in the constructor of the model. But these are just guesses, to be honest.
Need to send the values of a Sqlite table to the server via an AJAX call to a web service. I can't figure out how to package the rows of this table in a way that the web service will accept it.
Web Method Signature
[WebMethod]
public void CVW(string[][] qAndA)
{}
Client Side
var qAndA = new Array();
tx.executeSql("Select * From CVW Where CallNumber=?", [call], function (tx, result) {
var i = 0;
$.each(result.rows, function () {
qAndA[i] = result.rows.item(i);
i++;
});
$.ajax({
type: "POST",
dataType: "json",
contentType: "application/json",
url: "Service.asmx/CVW",
data: JSON.stringify({ qAndA: qAndA }),
success: function (data) {
},
error: function (xhr, status, error) {
var err = eval("(" + xhr.responseText + ")");
alert(err.Message);
}
});
}, onSQLError);
This gives me No parameterless constructor defined for type System.String. I've tried changing the web method parameter to just string[] and List and same thing.
When I look at what is being sent in Fire Bug I see that it is sending over as Object[object Object][object Object][object Object]... for as many [object Object] as there are rows returned in the Sqlite Query. What is the corresponding type in C# that I can use as my parameter type?
EDIT: Final Solution
In the javascript I had to change
data: JSON.stringify({ qAndA: qAndA }),
to
var json = JSON.stringify(qAndA);
data: JSON.stringify({ qAndA: json });
and changed the Web Method thusly
[WebMethod]
public void CVW(string qAndA)
JavaScriptSerializer ser = new JavaScriptSerializer();
List<CVWQuestion> list = ser.Deserialize<List<CVWQuestion>>(qAndA);
[Serializable]
public class CVWQuestion
{
public string CallNumber {get;set;}
public string Question { get; set; }
public string P1 { get; set; }
public string P2 { get; set; }
public string P3 { get; set; }
public string P4 { get; set; }
public string P5 { get; set; }
public string P6 { get; set; }
}
Please see my edited post for the code that finally worked for me. Found in large part to #SteveB, but never submitted as answer so I couldn't accept it.
Change the String[][] parameter to just a String. The data being sent it just a string. You need to convert it from a stringified JSON object to something you can parse. Look into JObject.
Converting from your stringified JSON looks something like...
JObject.parse(myJSONString)
I would change the webservice to something like
public void CVW(string qAndAStringJson){
Object qAndAObj = JObject.parse(qAndAStringJson);
string someVar = qAndAObj["someStringIndex"];
}
Check out the documentation on Stringify here. Your call to Stringify is changing the data into a string representing a JSON object.
I took this from the link.
JSON.stringify({x: 5, y: 6}); // '{"x":5,"y":6}' or '{"y":6,"x":5}'
Notice it's just one long string.
So if you call JObject.parse() on '{"x":5,"y":6}' in your webservice method you can make calls like
string obj = JOBject.Parse('{"x":5,"y":6}');
string result = obj["x"]; //result = 5
You can pass your 2d array in following format
{
"values[0][0]": "Some value",
"values[1][0]": "Some value",
"values[0][1]": "Some value",
"values[1][2]": "Some value",
"values[2][0]": "Some value",
"values[0][2]": "Some value",
"values[2][3]": "Some value",
...
}
or, alternatively, as spots mentioned, use JSON.stringify.
Also, take a look at this post, Parse JSON in C#, which might be helpful to you.