Can't return specific nested class property - c#

I made a class for deserialize a JSON (I'm using JSON.net), this is the structure:
public class User
{
public string Name { get; set; }
public string Surname { get; set;}
}
public class RootObject
{
public List<User> Users { get; set; }
}
I deserialize the JSON like this:
var obj = JsonConvert.DeserializeObject<RootObject>(responseText);
Now If I want return all the JSON I simply do: return obj.Users; but how can I return a specific property of the class User? In particular the Name property. I tried this:
return obj.Users.name // user list does not contain any name property
Also I tried with LINQ:
obj.Select(c => c.Name).Single();
But I can't use Select because I need to declare obj as:
var obj = JsonConvert.DeserializeObject<List<RootObject>>(responseText);
If instead I return obj.user; I can use LINQ and access to the name. But how can do this in the method that return the response?

Add a reference to class
using System.Linq;
since user is of type List you can apply lambda expression in it. Do not use Single it will fail if user will have more than one record in it, use FirstOrDefault instead. It will work for zero or more number of elements
var obj = JsonConvert.DeserializeObject<RootObject>(responseText);
string name = obj.user.Select(p=> p.name).FirstOrDefault();
string surname = obj.user.Select(p=> p.surname).FirstOrDefault();

You have to use one user instead of the whole list as RootObject.user is a List<User> and not an instance of User:
var name = obj[0].Name;
Or whatever element within your list you want to use.
Alternativly use LINQ:
var user = obj.FirstOrDefault();
if (user != null) name = user.name;

Related

Return a list from class (Entity Framework)

I am writing an app with Entity Framework and I want to return from my table (champions) the column name - just that column.
In my business layer, I created a class with the method loadchampions to call it from my presentation layer. That way, I return the value to display in the datasource from my datagridview.
public List<Campeones> LoadChampions()
{
using (NarachiContext NarachiCTX = new NarachiContext())
{
var champions = (from p in NarachiCTX.Campeones
select p.Nombre).ToList();
return champions;
}
}
I get an error because I am returning a list from type string and I want return a list the type class (this class would be champions). So, I think I could solve the problem. Basically, I want to display the column NAME.
var champions = (from p in NarachiCTX.Campeones
select p.Nombre).ToList();
You're explicitly telling it to retrieve a List<string>, containing just the names. That's what select p.Nombre is saying: For every Campeones, get the Nombre property, and put it into a list.
If you want to return a List<Campeones>, then you should just be able to do this:
return NarachiCTX.Campeones.ToList();
I think below code will be use full to resolve your query.
public List<champions> LoadChampions()
{
using (NarachiContext NarachiCTX = new NarachiContext())
{
var champions = NarachiCTX.Campeones.Select(d => new champions
{
Name = d.Nombre
}).ToList();
return champions;
}
}
Here You must have exist class "champions" having property "Name" with string data type.
public class champions
{
Public string Name;
}
we are returning the list of "champions" class.

How to convert object into json array without property names

For this class
class Customer {
public string FirstName {get; set;}
public string LastName {get; set;}
}
I have collection
List<Customer> customers
When returning to browser client
return new JsonResult(new
{
data = customers
});
The client get
{"data":[{"firstName":"Johny","lastName":"Johnson"}]}
Is there some way to get
{"data":[{"Johny","Johnson"}]}
without doing foreach like
var output = new List<string[]>();
foreach (var r in customers)
{
output.Add(new string[] {
r.FirstName,
r.LastName
});
}
?
You could add another property in the Customer object,
public string[] FullName {get { return new string[]{FirstName, LastName}; } }
Decorate your Firstname and LastName properties with [JsonIgnore] so they don't get serialized.
Final product would look like so
public class Customer{
[JsonIgnore]
public string FirstName{get;set;}
[JsonIgnore]
public string LastName{get;set;}
[JsonProperty("data")]
public string[] FullName {get { return new string[]{FirstName, LastName}; } }
public Customer(string FirstName, string LastName){
this.FirstName = FirstName;
this.LastName = LastName;
}
}
public static void Main(string[] args)
{
Customer c = new Customer("Adrian", "i6");
Console.Write(JsonConvert.SerializeObject(c));
}
This of course won't return exactly the desired result, if you wanted to completely remove the property you'll have to override the JsonWrite method inside JsonConverter however that would cause the JSON to be invalid of course as the JSON object requires a key:value property.
DotNetFiddle runnable of the above.
If you want some sort of "automatically derive a table from an array of JSON objects" functionality that's general across any data type, the algorithm would be to:
Iterate over the array, collecting newly-encountered property names into a list as you go into column names. This is the only way to get all property names since it may not be guaranteed that all objects have the same properties in JSON.
Create a list for each object in the list
Map each object's property value into the list index of the column corresponding to the property name
This will give you two output artifacts: the column listings and the values by index. If you are safe assuming that the first object has the same properties as all the other objects in the Array, then you can avoid iterating over the entire collection for the first step. This is untested, but hopefully you get the gist.
using System.Collections.Generic;
using Newtonsoft.Json.Linq;
// ...
var payload = JObject.Parse(rawJson);
var dataArray = payload["data"] as JArray;
var firstItem = dataArray[0] as JObject;
var columns = firstItem.Properties().Select(prop => prop.Name).ToList();
var rows = (
from obj as JObject in dataArray
select columns.Select(col => obj[col]).ToList()
).ToList();

How to create an array of object?

I've created a dll that perform some request on my API. Now the request send me back a json response, what I want to do (from the dll), is return an array of object to be used in the program that implements the DLL. Now I've this class:
public class Details
{
public string name { get; set; }
public string age { get; set; }
}
public class Info
{
public List<object> info { get; set; }
}
public class User
{
public Details details { get; set; }
public Info info { get; set; }
}
public class RootObject
{
public User user { get; set; }
}
I deserialize the request like this:
var obj = JsonConvert.DeserializeObject<List<RootObject>>("json returned");
Now the json contains the details of the user, and in some case also the info, so I iterate through of it in this way:
foreach(var user in obj)
{
item.user.details.name;
//take some info (could not contain nothing)
foreach(var info in user.info.info)
{
info; //<- contains all the information
}
}
What I want to know is: How can I create a list of object? In particular I want send back the user object that have as property details and info. The result should be an array of object 'cause who reiceve the object need to iterate through of it and read each object property as:
user[0].details.name: //where 0 is the index of the user (php syntax)
I don't know if is possible in c#, someone could help me to achieve this target?
Your json converter returns List<RootObject>, and each RootObject contains only one property: user. A simple Linq query would change the List<RootObject> into a List<User> object:
var users = obj.Select(o => o.user).ToList();
Each element in users then is a User, with both the Details and Info property.
As an example on how to use this, consider you have a method that does the conversion from json and you want that method to return the list of users. That method would look something like this:
public List<User> GetUsersFromJson()
{
var obj = JsonConvert.DeserializeObject<List<RootObject>>("json returned");
var users = obj.Select(o => o.user).ToList();
return users;
}
You can iterate through the users object like this:
foreach (var user in users)
{
var detail = user.details;
var info = user.info;
}
You should consider changing your public properties to camel-case as is common practice in C#.
JsonConvert.DeserializeObject> returns the list of RootObject. You can use method ToArray() to change the list to array.
In this case:
var obj = JsonConvert.DeserializeObject<List<RootObject>>("json returned");
RootObject[] array = obj.ToArray();
string s = array[0].user.details.name;
object[] infos = array[0].user.info.info.ToArray();
and in this code:
foreach(var user in obj)
{
item.user.details.name;
//take some info (could not contain nothing)
foreach(var info in user.info.info)
{
info; //<- contains all the information
}
}
don't have sens, it should be like this:
foreach (RootObject elem in obj)
{
foreach (Info info in elem.user.info.info)
{
object[] localInfo = info.info.ToArray(); //<- contains all the information
}
}

How to extract an object name

i've got a class filled with lists of subclasses:
public class ClassOfKb
{
public List<Data> KbDatas {get;set;}
public List<Product> KbProducts {get;set}
}
public class Data
{
public Guid ID {get;set;}
public byte[] data {get;set;}
public string Name {get;set;}
}
public class Product
{
public Guid ID {get;set;}
public string Name {get;set;}
public byte[] Image {get;set;}
}
i create an object:
ClassOfKb kb = new ClassOfKb
now i'd like to extract the string "Datas" from the sub-object kb.KbDatas, I tried:
string name = kb.KbDatas.GetType().BaseType.Name.Substring(2);
aswell as:
string name = kb.KbDatas.GetType().Name.Substring(2);
but nothing gave me what I need, is there any way to do this?
EDIT: to specify my question, the string I need is the name of the list, except the first two letters! KbDatas => Datas
EDIT2: i did a mistake, the list-names and class-names are different and i need the list-name
You can use Type.GetGenericArguments to solve this
ClassOfKb kb=new ClassOfKb();
kb.KbData = new List<Data>();
string nameOfData = Type.GetType(kb.KbData.ToString()).GetGenericArguments().Single().Name;
OUTPUT : nameOfData = Data
kb.KbProduct = new List<Product>();
string nameOfProduct = Type.GetType(kb.KbProduct.ToString()).GetGenericArguments().Single().Name;
OUTPUT : nameOfProduct = Product
Since that's a collection it is likely that there are multiple Data objects in it, each with a name. You can use String.Join to concat them with a separator:
string names = string.Join(",", kb.KbData.Select(d => d.Name));
If there's just one object you don't get a comma at the end. If there's no object you get an empty string.
erm, since you have a List of Data there will be a sequence of Names.
IEnumerable<string> names = kb.KbData.Select(d => d.Name);
maybe you want just the first one?
string firstName = kb.KbData.First(d => d.Name);
Try this one
string name = kb.KbData[0].Name.Substring(2);
From the sounds of what you've written, you're looking to get the name of the type in the List instance KbData?
If so, I think this may be what you're looking for: https://stackoverflow.com/a/1043778/775479
If you are trying to get the name of the property. There are several methods for doing so.
Get the name of the generic argument from the property itself - If you know the name of the property.
ClassOfKb kb = new ClassOfKb()
{ KbData = new List<Data>(), KbProduct = new List<Product>() };
Console.WriteLine(kb.KbData.GetType().GetGenericArguments()[0].Name);
Get the name of the property from reflection, if you know the data type of the property.
System.Reflection.PropertyInfo pi = kb.GetType()
.GetProperties()
.FirstOrDefault(p=>p.PropertyType == typeof(List<Data>));
Console.WriteLine(pi.Name.Substring(2)); // ignoring the kb prefix
You can achieve this with reflection. This is example without any checks - just show the mechanism:
PropertyInfo propertyInfo = typeof(ClassOfKb).GetProperty("KbData");
Type propertyType = propertyInfo.PropertyType;
Type genericArgument = propertyType.GenericTypeArguments[0];
string name = genericArgument.Name;
Because property KbData is generic List<Data> you need ask for generic arguments of property type: propertyType.GenericTypeArguments[0] and you should test if the type is really generic by genericArgument.IsGenericType and check generic arguments count
If you need the property name than you can use Expression.
The code below define function for extract name prom a property:
public string GetPropertyName<T>(Expression<Func<T>> property)
{
return ((MemberExpression)property.Body).Member.Name;
}
This converts property to property name string:
GetPropertyName(()=>k.KbDatas).Substring(2)

Linq extracting objects

I have a JSON "multi-level" response that I need to deserialize and from the deserialized classes structure I need to extract all the objects of a certain class.
Below the code I'm using, at the end I find that my result is empty, not populated.
// given these two classes:
[DataContract]
public class ThingsList
{
[DataMember(Name = "status")]
public string Status { get; set; }
[DataMember(Name = "since")]
public double Since { get; set; }
[DataMember(Name = "list")]
public Dictionary<string, ThingsListItem> Items { get; set; }
public DateTime SinceDate { get { return UnixTime.ToDateTime(Since); } }
}
[DataContract]
public class ThingsListItem
{
[DataMember(Name = "url")]
public string Url { get; set; }
[DataMember(Name = "title")]
public string Title { get; set; }
}
// I can deserialize my json to this structure with:
ThingsList results = JsonConvert.DeserializeObject<ThingsList>(e.Result);
// now I need to "extract" only the ThingsListItem objects, and I'm trying this:
var theList = from item in results.Items.OfType<ThingsListItem>()
select new
{
Title = item.Title,
Url = item.Url
};
// but "theList" is not populated.
The points here are (I believe):
- I try to use results.Items.OfType() in order to extract only the ThingsListItem objects, that in the "upper" class are declared in the
public Dictionary Items { get; set; }
row.
Any idea? Tell if it's not clear...
Thanks
Andrea
EDIT: updated my response for clarity.
Since your Dictionary values are of type ThingsListItem you can access them directly by using the Dictionary's Values property. There is no need to use OfType to check their type and extract them. Simply use:
var items = results.Items.Values;
The Values property would return an ICollection<ThingsListItem>. You can then iterate over the results with a foreach. LINQ does not have to be used.
While the Values property described above should be sufficient, I will point out a few issues with your original LINQ query attempt.
1) The following query is probably what you were after. Again, the Dictionary's Values property is key (no pun intended) to accessing the items:
var theList = from item in results.Items.Values
select new
{
Title = item.Title,
Url = item.Url
};
2) Why are you using new? That will return an IEnumerable of anonymous types. You already have a defined class, so why project into a new anonymous type? You should retain the underlying ThingsListItem items by selecting the item directly to get an IEnumerable<ThingsListItem>:
var theList = from item in results.Items.Values
select item;
foreach (var item in theList)
{
Console.WriteLine("Title: {0}, Url: {1}", item.Title, item.Url);
}
You would usually project into a new anonymous type to define a type with data properties you are interested in. Generally you would use them immediately after the query, whereas a selection into an existing class could be used immediately or passed around to other methods that are expecting that type.
Hopefully this has cleared up some questions for you and you have a better idea of using LINQ and when to use the new keyword. To reiterate, for your purposes it seems the Values property should suffice. Using LINQ to select the item is redundant when there are other immediate means to do so.

Categories