From a web service method I am returning an object of type 'GridBindingDataSet'. But its not getting serialized as JSON automatically.
Is there some way of making sure that the object gets serialized as JSON? I am using AJAX enabled web service that can be called from client-side using jQuery.
public class GridBindingDataSet
{
public int TotalCount { get; set; }
public DataTable Data { get; set; }
}
EDIT 1:
I am getting the following error when the web service method is called from jQuery:
A circular reference was detected while serializing an object of type 'System.Reflection.RuntimeModule'
EDIT 2:
I used JSON.net to serialize the above object of GridBindingDataSet. The web service is now returning a string rather than a GridBindingObject. Code for this is as below. But the browser cannot understand d.TotalCount and d.Data even though they are there in JSON returned.
[WebMethod]
public string GetJSONDataSetForGrid()
{
...
...
DataTable dt = GetDataForPage0();
int total = GetTotalCount();
GridBindingDataSet gridBindingData = new GridBindingDataSet ( total, dt);
//return a JSON serialized string
return JsonConvert.SerializeObject(gridBindingData,
Formatting.None, new JsonSerializerSettings
{
PreserveReferencesHandling = Newtonsoft.Json.PreserveReferencesHandling.None
});
}
But the JSON being returned is full of back slashes which the browser is not interpreting since the grid using the JSON string is showing up as empty. d.Data and d.TotalCount are not being parsed from the JSON string.
JSON retuned is as below:
{"d":"{\"TotalCount\":81,\"Data\":[{\"ProductName\":\"Alice Mutton\",\"UnitPrice\":39.00,
\"UnitsInStock\":0,\"Discontinued\":true},{\"ProductName\":\"Aniseed Syrup\",\"UnitPrice\":10.00,
\"UnitsInStock\":13,\"Discontinued\":false}]}"}
Also its worth having a look at Json.Net, many would say one of the best Json serializers available, I use it for all of my projects.
In response to the circular referece have a look at preserving references in the documentation, from their examples:
Directory root = new Directory { Name = "Root" };
Directory documents = new Directory { Name = "My Documents", Parent = root };
File file = new File { Name = "ImportantLegalDocument.docx", Parent = documents };
documents.Files = new List<File> { file };
string preserveReferenacesObjects = JsonConvert.SerializeObject(documents, Formatting.Indented, new JsonSerializerSettings
{
PreserveReferencesHandling = PreserveReferencesHandling.Objects
});
// {
// "$id": "1",
// "Name": "My Documents",
// "Parent": {
// "$id": "2",
// "Name": "Root",
// "Parent": null,
// "Files": null
// },
// "Files": [
// {
// "$id": "3",
// "Name": "ImportantLegalDocument.docx",
// "Parent": {
// "$ref": "1"
// }
// }
// ]
// }
Related
How to fill ObservableCollection using JSON? Now there is only the script itself and the model in the desktop application. I can not understand how to tie it up.
I get it after running the script:
{
"records": [
{
"brand_id": "1",
"brand_name": "Gigabyte"
},
{
"brand_id": "2",
"brand_name": "MSI"
},
{
"brand_id": "3",
"brand_name": "Lenovo"
},
{
"brand_id": "4",
"brand_name": "Dell"
},
{
"brand_id": "5",
"brand_name": "Google"
}
]}
And I have a Model in app:
public class Brands
{
int brand_id;
string brand_name;
public int Brand_id { get => brand_id; set => brand_id = value; }
public string Brand_name { get => brand_name; set => brand_name = value; }
}
And Collection:
public class BrandsCollection
{
private ObservableCollection<Brands> brands;
public ObservableCollection<Brands> Brands { get => brands; set => brands = value; }
}
It is fairly straight forward, especially with packages available to simplify a lot of the work. The Nuget Package System.Net.Http will have the packages you need to create an HttpClient to Get() your JSON from the web. I recommend Newtonsoft.Json to parse JSON into a C# object. And then having the object you just need to set the DataGrid.ItemSource to be an array of objects of any type for it to generate columns.
A simple example:
First you would define a simple object representation of your JSON data.
For instance if you had the following data:
[
{
"Name":"Test",
"Data": ["Item1","Item2"]
},
{
"Name":"Test 2",
"Data": ["Item3","Item4"]
}
]
You would have to create an equivalent C# representation.
Basically this is a List of objects so:
public class OuterObject : List<InnerObject> {}
The inner object is as follows:
public class InnerObject {
public string Name { get; set; }
public List<string> Data { get; set; }
}
Having the objects defined you can do something like:
HttpClient client = new HttpClient { BaseAddress = new Uri("ADDRESS") };
var json = await client.GetAsync("/ENDPOINT");
JsonSerializer serializer = JsonSerializer.CreateDefault();
using (StringReader reader = new StringReader(json))
{
using (JsonTextReader jsonReader = new JsonTextReader(reader))
{
var result = serializer.Deserialize<OuterObject>(jsonReader);
}
}
Then to access the data in your program you can access it like so:
string name = result[0].Name;
Or set it to a DataGrid's ItemSource to have the Data show up magically.
grid1.ItemSource = result;
As long as the result is an array of items it will create a row per item.
You may want to specify which items are shown but that is done by modifying DataGrid.Columns definitions and setting DataGrid.AutogenerateColumns = false
EDIT: With your data and models
//Just a small change to the Collection
public class BrandsCollection {
private ObservableCollection<Brands> _records;
public ObservableCollection<Brands> records { get => _records; set => _records= value; }
}
And to parse the data...
JsonSerializer serializer = JsonSerializer.CreateDefault();
using (StringReader reader = new StringReader(json))
{
using (JsonTextReader jsonReader = new JsonTextReader(reader))
{
var result = serializer.Deserialize<BrandsCollection>(jsonReader);
}
}
You have to remember to either use the same names as the json labels or use Json Attributes. For more info on that you can go to the official Newtonsoft.Json documentation
I have a bunch of API which generates the following 2 kinds of reply in response body:
{ "error": null, "object_type": { /* some object */ } }
{ "error": null, "object_type": [{ /* some object */ }, { /* some object */ }, ...] }
While I have a class corresponding to the object structure, I want to deserialize the API endpoints directly into either an object of the class or a List<class>, without creating some "result" classes to match the response JSON structure. Is this possible?
For example there is 2 API:
/api/getAllCompanies
returns
{ "error": null, "company": [ { "name": "Microsoft", "country": "US" }, { "name": "Apple", "country": "US" } ]
while
/api/getUserCompany
returns
{ "error": null, "company": { "name": "Microsoft", "country": "US" } }
I have a class in code:
public class Company {
string Name { get; set; }
string Country { get; set; }
}
How can I directly deserialize the data into a Company object or a List<Company> without creating a bunch of other class?
(The JSON property name (company) is known so don't need to extract it elsewhere.)
I've been trying to first deserialize the response JSON into an ExpandoObject then copy the properties to an instance of destination class using the code here then convert it using the following code, but this seems not to work with lists.
private static async Task<T> GetApiObject<T>(string api, string extractedObjName) where T: class, new()
{
var retstr = await /* get API response as string */;
dynamic retobj = JsonConvert.DeserializeObject<ExpandoObject>(retstr, new ExpandoObjectConverter());
var ret = new T();
Mapper<T>.Map((ExpandoObject)((IDictionary<string, object>)retobj)[extractedObjName], ret);
return ret;
}
You can use JObejct to extract the information you need before deserialize it into the object.
var str = "{ \"error\": null, \"company\": [{ \"name\": \"Microsoft\", \"country\": \"US\" } ,{ \"name\": \"Apple\", \"country\": \"US\" } ]}";
var temp = JObject.Parse(str).GetValue("company");
var companies = temp.Select(x => x.ToObject<Company>()).ToList();
Same goes for /api/getUserCompany
var str = "{ \"error\": null, \"company\": { \"name\": \"Microsoft\", \"country\": \"US\" } }";
var temp = JObject.Parse(str).GetValue("company");
var company = temp.ToObject<Company>();
I try to deserialize a DataSet from a JSON String with Json.NET. The Json String contents a status, message and the table that I want to use:
{
"status": "ok",
"message": "",
"table": [{
"column1": "value1",
"column2": "value2"
}, {
"column1": "value3",
"column2": "value4"
}]
}
Here my source:
public class RequestResult
{
public string status { get; set; }
public string message { get; set; }
}
...
var serializer = new JsonSerializer();
var sr = new StreamReader(response.GetResponseStream()).ReadToEnd();
var rr = JsonConvert.DeserializeObject<RequestResult>(sr);
// Without status and message the following works fine like here:
// http://www.newtonsoft.com/json/help/html/DeserializeDataSet.htm
DataSet dataSet = JsonConvert.DeserializeObject<DataSet>(sr);
gridControlMain.DataSource = dataSet.Tables["table"];
If I use the Json String without status and message it works fine, but I need status and message! Exception message from Json.NET is:
Unexpected JSON token when reading DataTable. Expected StartArray, got String. Path 'status', line 1, position 14.
How can I manage that?
Best regards
Your snippet shows an object with three properties, status, message and table. This object can't be deserialized as a DataTable. The table property can.
You can deserialize this snippet to a class with two string and one DataTable property, eg:
class MyTableUtilClass
{
public string Status{get;set;}
public string Message {get;set;}
public DataTable Table{get;set;}
}
var myUtil=JsonConvert.DeserializeObject<MyTableUtilClass>(jsonText);
DataTable myTable=myUtil.Table;
To test a class I need some dummy objects which are realistic.
My question is that: While debugging can I get an already constructed object as string? I want to copy this string and paste(assign) it to the dummy object in the test class.
public class Employee
{
public string Name;
public int Age;
public List<string> NamesOfChildren;
}
For example for an instance of this class in debug mode I need some string like
new Employee() {Name = "Serdar", Age = 30, NamesOfChildren = new List() {"NameOfChild1", "NameOfChild2"}}
In other words in debug mode I can see all public and private fields and their values of an object. Can I take this data as string? I need it in the format of creating that object in the editor. (Of course only public fields)
I'm not sure about the private fields, but I believe the Json.NET can help you. You're going to have to add the object name, but I believe you can automate this easily.
You can install it using Nuget:
Install-Package Newtonsoft.Json
You can find more information at: http://james.newtonking.com/json
Here is a example their site has:
Product product = new Product();
product.Name = "Apple";
product.Expiry = new DateTime(2008, 12, 28);
product.Sizes = new string[] { "Small" };
string json = JsonConvert.SerializeObject(product);
//{
// "Name": "Apple",
// "Expiry": "2008-12-28T00:00:00",
// "Sizes": [
// "Small"
// ]
//}
The same idea goes for Deserializing the object:
string json = #"{
'Name': 'Bad Boys',
'ReleaseDate': '1995-4-7T00:00:00',
'Genres': [
'Action',
'Comedy'
]
}";
Movie m = JsonConvert.DeserializeObject<Movie>(json);
string name = m.Name;
// Bad Boys
I'm trying to create a viewmodel in C# that can be serialized into a json document required by amazon S3. Documentation here. One of the properties looks like this,
["starts-with", "$key", "user/john/"]
What would the C# object look like so when it's serialized it would come out like this?
Rest of document looks like this.
{ "expiration": "2007-12-01T12:00:00.000Z",
"conditions": [
{"acl": "public-read" },
{"bucket": "johnsmith" },
["starts-with", "$key", "user/john/"],
]
}
Just use a string array
string[] data = new string[] { "starts-with", "$key", "user/john/" };
The object structure for the second part would be something like
public class S3Expiration {
DateTime expiration { get; set; }
object[] conditions { get; set; }
}
and to populate it you would write something like
var expiration = new S3Expiration {
expiration = DateTime.Now,
conditions = new object[] {
new { acl = "public-read" },
new { bucket = "johnsmith" },
new string[] { "starts-with", "$key", "user/john/" }
}
};