How to extract the data from Generic <T> List object - c#

I wanna create the generic function inwhich I will just pass the class name and get the data in CSV format that is from JSON object on the bases of Generic Class Type.
But I am not able to access the class member while foreach loop.
public class Lifetouch
{
public int LifetouchID { get; set; }
public string Data { get; set; }
}
public class Lifetemp
{
public int LifetempID { get; set; }
public string Data { get; set; }
}
main()
{
getPerodicListofVitalSigns <Lifetouch>(new Lifetouch());
}
public static void getPerodicListofVitalSigns <T>( T clazz)
{
List<T> list_of_measurements_Original = JsonConvert.DeserializeObject<List<T>>(json_response);
// Got the list_of_measurements_Original count 2.
StringBuilder sb = new StringBuilder();
sb.Append("[");
foreach (var element in list_of_measurements_Original)
{
sb.Append(element.LifetouchID + ", ") // Not able to access the element of list LifetouchID
}
sb.Append("]");
}

I would like to create the generic function inwhich I will just pass the class name and get the data (ID's) in CSV format that is from JSON object on the bases of Generic Class Type. That all the ids will pass through webservice and update the database. Its the requirement.
I would like to create the Generic function in which I would like to pass the class name as a paramenter. So in future its easy for me to use that generic function if new class added.
Now its working fine..
public class Lifetouch
{
public int LifetouchID { get; set; }
public string Data { get; set; }
}
public class Lifetemp
{
public int LifetempID { get; set; }
public string Data { get; set; }
}
main()
{
getPerodicListofVitalSigns <Lifetouch>(new Lifetouch());
getPerodicListofVitalSigns <Lifetemp>(new Lifetemp());
}
public static void getPerodicListofVitalSigns <T>( T clazz)
{
List<T> list_of_measurements_Original = JsonConvert.DeserializeObject<List<T>>(json_response);
// Got the list_of_measurements_Original count 2.
StringBuilder sb = new StringBuilder();
sb.Append("[");
foreach (var element in list_of_measurements_Original)
{
if (VitalSignName == "Lifetouch")
{
var vitalSign = element as Lifetouch;
dataString = dataString + (vitalSign.LifetouchID + ",");
}
else if (VitalSignName == "Lifetemp")
{
var vitalSign = element as Lifetemp;
dataString = dataString + (vitalSign.LifetempID + ",");
}
}
sb.Append("]");
string WebserviceAddress = "192..../json/reply/UpdateSyncStatus";
JSON_POST_Sender.ClassPost(WebserviceAddress, dataString), "true")
}

Related

C# : How to Deserialize json data

How to deserialized this type of json file usig C#
My Json
[{"data":{"CRC":"a459","PC":"3000","TID":"e2806810200000040a0652c8","antenna":3,"channel":922.75,"eventNum":396,"format":"epc","idHex":"e28068100000003c0a0652c8","peakRssi":-36,"phase":0.0,"reads":36},"timestamp":"2022-09-19T09:03:26.445+0700","type":"SIMPLE"}]
My Model
public class TagRead{
public string TID { get; set; }
}
public class Hdr{
public List<TagRead> data { get; set; }
}
My Controller
public ActionResult RefreshData()
{
string filepath = GetAndGenFilePath();
FileInfo fileInfo = new FileInfo(filepath);
bool isFileLocked = IsFileLocked(fileInfo);
if (isFileLocked)
{
return PartialView("TableTagView", GetListTag);
}
string rawData = System.IO.File.ReadAllText(filepath);
string[] lines = rawData.Split(';');
if (lines[0] == "")
{
HttpContext.Session["GetListTag"] = new List<Root>();
HttpContext.Session["LastChar"] = 0;
}
if (lines.Length > 0 && lines[0] != "" && LastChar != rawData.Length)
{
HttpContext.Session["GetListTag"] = new List<Root>();
foreach (var line in lines)
{
var deserialized = Newtonsoft.Json.JsonConvert.DeserializeObject<Hdr>(line);
var tag = deserialized.data.Select(s => new Root
{
TID = s.TID
}).ToList();
GetListTag.AddRange(tag);
}
HttpContext.Session["LastChar"] = rawData.Length;
}
return PartialView("TableTagView", GetListTag);
}
This json is from file, I want to get value then add into list
the values I want to get is TID,antenna,idHex
Thank you
This json is a collection so you'll need to deserialise it to a collection:
// List<Hdr>, not Hdr
var listOfHrds = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Hdr>>(json);
public class Hdr{
public TagRead data { get; set; }
}
Test:
var json = File.ReadAllText("data.json");
var listOfHdrs = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Hdr>>(json);
Console.WriteLine(listOfHdrs[0].data.TID); // Output: e2806810200000040a0652c8
public class Hdr{
public TagRead? data { get; set; }
}
public class TagRead{
public string? TID { get; set; }
}
if you need just one value, you don't need any custom classes at all
Console.WriteLine( "TID: " + JArray.Parse(json)[0]["data"]["TID"].ToString() );

Iteration cannot operate on variables of type public definition for 'getenumerator'

I am doing a search in which I am making an API call and get the XML response and SerializeXmlNode and DeserializeObject to my root object. Now the problem is when I tried to loop with foreach.
I get this error below:
foreach statement cannot operate on variables of type (Model.AccountLite) because does not contain public instance definition for 'getenumerator'
I have inspected this data = JsonConvert.DeserializeObject(json); and i can see the data.
I have tried to look at this previously asked question
Search API call
public static List<AccountLite> searchAccounts(string searchString)
{
List<AccountLite> result = new List<AccountLite>();
Root data = new Root();
string[] contains = searchString.Split(' ');
RestClient client = new RestClient(baseUrl);
foreach (string contain in contains)
{
if (contain.Length < 3) continue;
RestRequest request = new RestRequest($"/xx/xx/xx/xxx/xxx/account?xx=Lite&searchString={searchString}");
String encoded = System.Convert.ToBase64String(System.Text.Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password));
request.AddHeader("Authorization", "Basic " + encoded);
IRestResponse response = client.Execute(request);
string requestResponse = response.Content;
//Converting data from XML into Json and deserializet json object
try
{
XmlDocument doc = new XmlDocument();
doc.LoadXml(requestResponse);
string json = JsonConvert.SerializeXmlNode(doc);
data = JsonConvert.DeserializeObject<Root>(json);
}
catch (Exception)
{
continue;
}
if (data?.SiebelMessageEnvelope?.ListOfAccountLite?.AccountLite == null)
continue;
//this line is the one showing error.
foreach (AccountLite item in data.SiebelMessageEnvelope.ListOfAccountLite.AccountLite)
{
bool containsBoth = true;
foreach (string contain2 in contains)
{
if (!item.Name.ToLower().Contains(contain2.ToLower()) && !item.Id.ToLower().Contains(contain2.ToLower()))
containsBoth = false;
}
if (containsBoth)
{
if (result.FirstOrDefault(i => i.Id == item.Id) == null)
{
result.Add(item);
}
}
}
}
return result;
}
Model
public class AccountLite
{
public string Id { get; set; }
public string AccountStatus { get; set; }
public string AccountTypeCode { get; set; }
public string Location { get; set; }
public string Name { get; set; }
public string SRIntegrationFlag { get; set; }
}
public class ListOfAccountLite
{
public AccountLite AccountLite { get; set; }
}
public class SiebelMessageEnvelope
{
[JsonProperty("#xmlns")]
public string Xmlns { get; set; }
public ListOfAccountLite ListOfAccountLite { get; set; }
}
public class Root
{
public SiebelMessageEnvelope SiebelMessageEnvelope { get; set; }
}
Json Object
{
"SiebelMessageEnvelope":{
"#xmlns":"",
"ListOfAccountLite":{
"AccountLite":{
"Id":"",
"AccountStatus":"",
"AccountTypeCode":"",
"Location":"",
"Name":"",
"SRIntegrationFlag":""
}
}
}
}
Your ListOfAccountLite just contains a single AccountLite. It doesn't make sense to foreach over a single object, where that object is not enumerable (meaning: implemented IEnumerable[<T>] or contains an explicit GetEnumerator() method).
There's only one object, so... just take it. Instead of
if (data?.SiebelMessageEnvelope?.ListOfAccountLite?.AccountLite == null)
continue;
foreach (AccountLite item in data.SiebelMessageEnvelope.ListOfAccountLite.AccountLite)
{
// ... do the thing
}
simply
var item = data?.SiebelMessageEnvelope?.ListOfAccountLite?.AccountLite;
if (item is null)
continue;
// ... do the thing
That said: you should probably investigate whether ListOfAccountLite in the JSON etc is meant to be an array rather than a single object.

Parse the JSON syntax if it is not parsed well

How do I parse the JSON data if it is not well parsed from newtonsoft json. Please refer my below code:
var web_uri = new Uri("www.example.com");
var resp = await client2.GetAsync(web_uri);
var resp_to_str = await resp.Content.ReadAsStringAsync();
var json_obj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(resp_to_str);
Finally i parsed the JSON. now, it produces as expected.
{
"Sex": "Male",
"category": "A",
"ID": 14,
"created": "2016-03-03",
"Tag": "2340",
"members": [{
"type": "A",
"name": "fam_mem",
"state": "ca",
"Family": {
"myGuardName": "tony",
"details": [{
"address": "ca",
"type": "A"
}]
}
}]
}
**RootObject omyclass = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(json_obj);**
Now i am getting error at the above line:
An exception of type 'Microsoft.CSharp.RuntimeBinder.RuntimeBinderException' occurred in System.Linq.Expressions.dll but was not handled in user code
Additional information: The best overloaded method match for 'Newtonsoft.Json.JsonConvert.DeserializeObject(string)' has some invalid arguments
public class Detail
{
public string address { get; set; }
public string type { get; set; }
}
public class Family
{
public string myGuardName { get; set; }
public List<Detail> details { get; set; }
}
public class Member
{
public string type { get; set; }
public string name { get; set; }
public string state { get; set; }
public Family Family { get; set; }
}
public class RootObject
{
public string Sex { get; set; }
public string category { get; set; }
public int ID { get; set; }
public string created { get; set; }
public string Tag { get; set; }
public List<Member> members { get; set; }
}
TextBlock.Text = omyclass
I have updated the question
Hope it helps:
var web_uri = new Uri("www.example.com");
var resp = await client2.GetAsync(web_uri);
var resp_to_str = await resp.Content.ReadAsStringAsync();
RootObject omyclass = JsonConvert.DeserializeObject<RootObject>(resp_to_str); //pass the response string here.
Updated from OP's comment:
textBlock2.Text = omyclass + "----!"; will not work because omyclass is RootObject, not a string
You have to get the info you need and append it to textBlock2:
textBlock2.text = omyclass.Sex + "----!";
UPDATE 2 (OP get string as key value pair):
Usage: textBlock2.text = omyclass + "----!";
Override RootObject.ToString() and use Reflection to get properties & property values
public class RootObject
{
public string Sex { get; set; }
public string category { get; set; }
public int ID { get; set; }
public string created { get; set; }
public string Tag { get; set; }
public List<Member> members { get; set; }
public override string ToString()
{
var values = new List<string>();
foreach (var property in GetType().GetProperties())
{
values.Add(property.Name + ": " + property.GetValue(this));
}
return string.Join(", ", values);
}
}
The problem is that JsonConvert.DeserializeObject<T>(string) expects a string as an input argument -- but you are not passing in a string. You are passing in json_obj which is a dynamic returned by a previous call to deserialize:
var json_obj = Newtonsoft.Json.JsonConvert.DeserializeObject<dynamic>(resp_to_str);
var omyclass = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(json_obj);
What JsonConvert returns from the first dynamic call is in fact a JToken containing a tree of LINQ-to-JSON tokens -- not a string. This causes the RuntimeBinderException upon making the second call.
There is no need to double-deserialize the JSON string in this manner. Just pass the resp_to_str to JsonConvert.DeserializeObject<RootObject>():
var omyclass = Newtonsoft.Json.JsonConvert.DeserializeObject<RootObject>(resp_to_str);
Prototype fiddle.
Update
If you want to see all the fields and properties of the deserialized class in a text box, you could re-serialize it to JSON:
var reserializedJson = JsonConvert.SerializeObject(omyclass, Formatting.Indented);
textBlock2.Text = reserializedJson;
If you do
textBlock2.Text = omyclass + "----!"
You are just showing the ToString() value for your class. And since you have not overridden this method it will just show the class name.
If you don't want to re-serialize you could use the following extension method:
public static class ObjectExtensions
{
public static StringBuilder ToStringWithReflection<T>(this T obj, StringBuilder sb)
{
sb = sb ?? new StringBuilder();
if (obj == null)
return sb;
if (obj is IEnumerable)
{
sb.Append("[");
var first = true;
foreach (var item in ((IEnumerable)obj))
{
if (!first)
sb.Append(",");
sb.Append(item == null ? "" : item.ToString());
first = false;
}
sb.Append("]");
}
else
{
var type = obj.GetType();
var fields = type.GetFields();
var properties = type.GetProperties().Where(p => p.GetIndexParameters().Length == 0 && p.GetGetMethod(true) != null && p.CanRead);
var query = fields
.Select(f => new KeyValuePair<string, object>(f.Name, f.GetValue(obj)))
.Concat(properties
.Select(p => new KeyValuePair<string, object>(p.Name, p.GetValue(obj, null))));
sb.Append("{").Append(obj.GetType().Name).Append(": ");
var first = true;
foreach (var pair in query)
{
if (!first)
sb.Append(", ");
sb.Append(pair.Key).Append(": ");
if (pair.Value is IEnumerable && !(pair.Value is string))
pair.Value.ToStringWithReflection(sb);
else
sb.Append(pair.Value == null ? "null" : pair.Value.ToString());
first = false;
}
sb.Append("}");
}
return sb;
}
public static string ToStringWithReflection<T>(this T obj)
{
return obj.ToStringWithReflection(new StringBuilder()).ToString();
}
}
Then do
textBlock2.Text = omyclass.ToStringWithReflection() + "----!"
Update 2
Or, if you want to include properties from your object hierarchy recursively, you can override the ToString() method of each, like so:
public class Detail
{
public string address { get; set; }
public string type { get; set; }
public override string ToString() { return this.ToStringWithReflection(); }
}
public class Family
{
public string myGuardName { get; set; }
public List<Detail> details { get; set; }
public override string ToString() { return this.ToStringWithReflection(); }
}
public class Member
{
public string type { get; set; }
public string name { get; set; }
public string state { get; set; }
public Family Family { get; set; }
public override string ToString() { return this.ToStringWithReflection(); }
}
public class RootObject
{
public string Sex { get; set; }
public string category { get; set; }
public int ID { get; set; }
public string created { get; set; }
public string Tag { get; set; }
public List<Member> members { get; set; }
public override string ToString() { return this.ToStringWithReflection(); }
}
Then the ToString() output will be:
{RootObject: Sex: Male, category: A, ID: 14, created: 2016-03-03, Tag: 2340, members: [{Member: type: A, name: fam_mem, state: ca, Family: {Family: myGuardName: tony, details: [{Detail: address: ca, type: A}]}}]}
You Can Use a Custom Json formatter and parse it the way you want.It can be implemented at framework level so that all data is parsed according to your requirements.Inherit the custom formatter from MediaTypeFormatter.
Implement the virtual and abstract functions of MediaTypeFormatter.Pasre the data according to your requirements here.
I have implemented the formatter this way and it even parses complex data to match the data that i want.
When serializing complex Json if not deserialized correctly the value becomes null.For deserializing complex Json use JsonMediaTypeFormatter.
My Example
In your config File add
config.Formatters.Clear();
config.Formatters.Insert(0, new JsonNetFormatterDecide()); // My custom formatter
config.Formatters.Insert(1, new JsonMediaTypeFormatter());//Default Formatter
config.MapHttpAttributeRoutes();`
So i used my custom formatter for all get operations.Format the data as i want and sent to client.The problem i faced was while accepting complex Json data(such as Jsonarrays within Jsonobjects). So in my config file i added the JsonMediaTypeFormatter() in index 1 of Config.formatters.
In my custom formatter
public override bool CanReadType(Type type)
{
return false;
}
This makes JsonMediaTypeFormatter which is a very popular formatter to Deserialize complex data to do the deserialization.
The bottomline is that you can use JsonMediaTypeFormatter toDeserialize complex Json Data
It has some predefined functions to deserialize.
By looking at your Json it seems as if Json arrays within Json objects is the reason why your Json is not deserialing correctly
If you plan to write your custom Json formatter ,You can implement at framework level like
public class JsonNetFormatterDecide : MediaTypeFormatter
{
//......
public override bool CanReadType(Type type)
{
return false; //this causes the // project to use the second formatter in the config file ie,JsonMediaTypeFormatter or the //default Json Formatter
}
}

Convert JSON object to a list of objects C#

I have a web api service that converts JSON object to a specific list:
here is the model class:
public class rest_all_data
{
public string RestaurantName { get; set; }
public string CategoryName { get; set; }
public string FourSquareID { get; set; }
}
public class rest_collection
{
public List<rest_all_data> rest_all_data { get; set; }
}
and here is the service:
public void AddRestaurantMultiple([FromBody] JObject rest_all)
{
string k = rest_all.ToString();
rest_collection result = new System.Web.Script.Serialization.JavaScriptSerializer().Deserialize<rest_collection>(k);
}
and here is the json object:
"restaurants" : [{"RestaurantName":"a","CategoryName":"b","FourSquareID":"c"},{"RestaurantName":"d","CategoryName":"e","FourSquareID":"f"}]
the rest_all object always comes with data and the k string is also a success but the result variable is always null...
try it i have made few changes in your code
public class rest_collection
{
public IEnumerable<rest_all_data> rest_all_datas { get; set; }
}
public void AddRestaurantMultiple([FromBody] JObject rest_all)
{
string k = rest_all.ToString();
JavaScriptSerializer serializer = new JavaScriptSerializer();
rest_collection collection = serializer.Deserialize<rest_collection>(k);
}
try:
public void AddRestaurantMultiple([FromBody] string rest_all)
{
var obj = JsonConvert.DeserializeObject<rest_collection>(rest_all);
}

Parsing Multiple Json Rows in windows phone

My json response which i am generating from php :
{"name":"abhi","age":"20","id":"1"}
{"name":"abhi","age":"21","id":"4"}
And the c# code is:
public partial class MainPage : PhoneApplicationPage
{
// Constructor
public MainPage()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
Load(textBox1.Text);
}
public void Load(string keyword)
{
var client = new RestClient("http://localhost/query.php?name="+keyword);
var request = new RestRequest(Method.GET);
//request.AddParameter("name", keyword);
/*request.AddParameter("v", "1.0");
request.AddParameter("q", keyword);
request.AddParameter("hl", "id");
request.AddParameter("rsz", 5);*/
client.ExecuteAsync<RootObject>(request, (response) =>
{
// var resp = response.Data.ToString();
// var respLines = resp.Split('\n');
RootObject rootObject=response.Data;
listBox1.Items.Clear();
if (rootObject == null)
MessageBox.Show("null");
else
{
listBox1.Items.Add(rootObject.age+" " + rootObject.name);
}
});
}
}
}
public class RootObject
{
public string name { get; set; }
public string age { get; set; }
public string id { get; set; }
}
i am able to fetch the first row but not for multiple rows. Anyone has any idea how to fetch multiple rows in json format. How to create multiple objects of json and populate them?
That does not look like valid JSON, try returning a JSON array from PHP:
{
"rows": [
{"name":"abhi","age":"20","id":"1"},
{"name":"abhi","age":"21","id":"4"}
]
}
These would be the corresponding C# classes for deserialization:
public class Row
{
public string name { get; set; }
public string age { get; set; }
public string id { get; set; }
}
public class RootObject
{
public List<Row> rows { get; set; }
}
And you can add your rows with:
foreach (var row in rootOject.rows)
{
listBox1.Items.Add(row.age+" " + row.name);
}

Categories

Resources