Xml Serialise class with a property being an interface - c#

I am trying to Serialise the class 'Person', which contains a property where the type is an interface.
I a getting an exception - System.NotSupportedException - saying
----> System.NotSupportedException : Cannot serialize member Tests.Person.Names of type Writer.Tests.INames because it is an interface.
Is there a way round this? Or just simply can not be done.
public interface INames
{
string First { get; set; }
string Last { get; set; }
}
public class Names : INames
{
public string First { get; set; }
public string Last { get; set; }
}
public class Person
{
public INames Names { get; set; }
public double WeightKg { get; set; }
public double HeightCm { get; set; }
}

Related

Entity Framework: One to many with the same class

I have the following requirement: There are basically two classes Object and Attribute. I want to model the database in such a way that one Object can have many Attributes which is easy to do. But the othe requirement is that one Object can also have many other Objects. How would that be possible to implement and what do I need to do in my Model Classes to achieve this?
So far I have this:
public class Object
{
public int ID { get; set; }
public Attribute Attribute { get; set; }
}
public class Attribute
{
public int ID { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public Object Object { get; set; }
}
I believe you can just add new property to your object class, that targets the object you want, so something like this:
public class Object
{
public int ID { get; set; }
public Attribute Attribute { get; set; }
public Object Object { get; set; }
}
public class Attribute
{
public int ID { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public Object Object { get; set; }
}
but from the code provided, your Object class references just one instance of the Attribute class, so you dont have 1:N relation as you said you want, but rather 1:1! If you want the Object class to point to several Attributes and several Object Instances, the code should be something like this:
public class Object
{
public int ID { get; set; }
public Object ParentObject { get; set; }
}
public class Attribute
{
public int ID { get; set; }
public string Name { get; set; }
public string Type { get; set; }
public Object ParentObject { get; set; }
}
EDIT: https://www.entityframeworktutorial.net/code-first/configure-one-to-many-relationship-in-code-first.aspx
I guess what your looking for is Many-to-many relationships for the Database.
You could structure it like this, which will give you one extra table.
public class Object
{
public int ID { get; set; }
}
public class Attribute
{
public int ID { get; set; }
public string Name { get; set; }
public string Type { get; set; }
}
public class ObjectAndAttribute
{
public int id { get; set; }
public Attribute Attribute { get; set; }
public Object Object { get; set; }
}

How do I deserialize JSON correctly in C#

I am trying to deserialize the Supreme New York JSON but I am getting an error.
I used json2csharp.com to convert the Json into classes.
Then I summarised them all into one called items
namespace SUPBOTTESTING
{
public class items
{
public string name { get; set; }
public int id { get; set; }
public string image_url { get; set; }
public string image_url_hi { get; set; }
public int price { get; set; }
public int sale_price { get; set; }
public bool new_item { get; set; }
public int position { get; set; }
public string category_name { get; set; }
public int price_euro { get; set; }
public int sale_price_euro { get; set; }
}
}
using System;
using System.Net;
using System.Web.Script.Serialization;
namespace SUPBOTTESTING
{
class Program
{
public static void Main()
{
{
string shop_json = new WebClient().DownloadString("https://www.supremenewyork.com/mobile_stock.json");
JavaScriptSerializer shop_object = new JavaScriptSerializer();
items[] shirt_stock = shop_object.Deserialize<items[]>(shop_json);
Console.WriteLine(shirt_stock[1]);
}
}
}
}
I am getting the error:
Default constructor not found for type SUPBOTTESTING.items[]
Ok here is the solution. You have the correct idea but you need to understand the structure of your Json data.
You are deserializing it into an array of Object whereas your Json data returned itself is not an Array or a List. It contains child nodes that are an array so you need to structure your Object accordingly to get a successful breakdown of data.
Here I have used Newtonsoft to deserialise the Json data into an Object.
I have tested the code and it returns a list of Shirts
static void Main(string[] args)
{
var shop_json = new WebClient().DownloadString("https://www.supremenewyork.com/mobile_stock.json");
var shirt_stock = JsonConvert.DeserializeObject<StockObject>(shop_json);
// Picking shirts to demonstrate how to display values for all shirts
var shirts = shirt_stock.products_and_categories.Shirts;
foreach (var shirt in shirts)
{
var shirtBuilder = new StringBuilder();
shirtBuilder.AppendLine($"Name: {shirt.name}");
shirtBuilder.AppendLine($"ID: {shirt.id.ToString()}");
shirtBuilder.AppendLine($"New Item: {shirt.new_item.ToString()}");
shirtBuilder.AppendLine($"Category Name: {shirt.category_name}");
Console.WriteLine(shirtBuilder);
}
}
public class StockObject
{
public ProductsCats Products_and_categories { get; set; }
}
public class ProductsCats
{
public Details[] Shirts { get; set; }
public Details[] Bags { get; set; }
public Details[] Accessories { get; set; }
public Details[] Pants { get; set; }
public Details[] Jackets { get; set; }
public Details[] Skates { get; set; }
public Details[] Hats { get; set;}
public Details[] Sweatshirts { get; set;}
[JsonProperty("Tops/Sweaters")]
public Details[] TopsSweaters { get;set;}
public Details[] New { get; set; }
}
public class Details
{
public string name { get; set; }
public int id { get; set; }
public string image_url { get; set; }
public string image_url_hi { get; set; }
public int price { get; set; }
public int sale_price { get; set; }
public bool new_item { get; set; }
public int position { get; set; }
public string category_name { get; set; }
public int price_euro { get; set; }
public int sale_price_euro { get; set; }
}
You see what I have done here?
So your Json data contains a parent node products_and_categories and its child node contains an array of Shirts which is what you are after?
StockObject class contains the Parent property called Products_and_categories of type object ProductsCats.
ProductsCats Object contains the property Shirts of type Details which is an array and will be used during the deserialising process.
Hope this helps?
Well you do not need to specify a default constructor. What is wrong is, i think you didn't check the json data properly. Because your items class is not in the first level of json. You need to create a couple of classes to be more accurate on deserializing.
First of all you need to know that this json file has a lot of bad-smells and bad-practices on it.
Note that you need to install Newtonsoft.Json before going further. It is much more convenient way to deserialize a json into C# classes.
Yet, i wrote a proper way of deserializing it:
public class BaseItem
{
public string Name { get; set; }
public int Id { get; set; }
public string Image_url { get; set; }
public string Image_url_hi { get; set; }
public int Price { get; set; }
public int Sale_price { get; set; }
public bool New_item { get; set; }
public int Position { get; set; }
public string Category_name { get; set; }
public int Price_euro { get; set; }
public int Sale_price_euro { get; set; }
}
public class Shirt : BaseItem { }
public class Bag : BaseItem { }
public class Accessory : BaseItem { }
public class Pant : BaseItem { }
public class Jacket : BaseItem { }
public class Skate : BaseItem { }
public class Hat : BaseItem { }
public class Sweatshirt : BaseItem { }
public class TopsSweater : BaseItem { }
public class New : BaseItem { }
public class RootObject
{
public List<object> Unique_image_url_prefixes { get; set; }
public ProductsAndCategories Products_and_categories { get; set; }
public string Release_date { get; set; }
public string Release_week { get; set; }
}
public class ProductsAndCategories
{
public List<Shirt> Shirts { get; set; }
public List<Bag> Bags { get; set; }
public List<Accessory> Accessories { get; set; }
public List<Pant> Pants { get; set; }
public List<Jacket> Jackets { get; set; }
public List<Skate> Skate { get; set; }
public List<Hat> Hats { get; set; }
public List<Sweatshirt> Sweatshirts { get; set; }
[JsonProperty("Tops/Sweaters")]
public List<TopsSweater> TopsSweaters { get; set; }
public List<New> New { get; set; }
}
First of all, all of your items are have the same properties on them, yet, they all marked as different properties. So that, i created a BaseItem class and other empty classes which are inherited from that.
Also you need other 2 classes -which are RootObject and ProductsAndCategories- to provide data on them. Note that there is a JsonProperty("blabla") on the TopsSweaters property. Because, in json file it is Tops/Sweaters, and you can not use that name on a C# property. That is the attribute for using that kind of different property names.
Then you can populate your object like this:
static void Main(string[] args)
{
var jsonData = "https://www.supremenewyork.com/mobile_stock.json";
string shopJson = new WebClient().DownloadString(jsonData);
RootObject shirtStock = JsonConvert.DeserializeObject<RootObject>(shopJson); //All json data is in this variable
Console.WriteLine(shirtStock.Products_and_categories.Shirts[1]);
}
Your problem is that youre using a class to load the JSON data in, where you should use a struct, alternatively you can also create a constructor that takes no arguments and sets all variables to default values, which is a lot of work so just replace class with struct:
public struct Items
{
public string Name { get; set; }
public int Id { get; set; }
public string Image_Url { get; set; }
public string Image_Url_Hi { get; set; }
public int Price { get; set; }
public int Sale_Price { get; set; }
public bool New_item { get; set; }
public int Position { get; set; }
public string Category_Name { get; set; }
public int Price_Euro { get; set; }
public int Sale_Price_Euro { get; set; }
}
Also please stick to C# naming conventions, you should be able to do this since most JSON parsers are case insensitive by default.
Some more info: A class doesnt really has a proper default constructor if you dont define one, where as a struct always has a default constructor, so when the JSON parser wants to init your class it cant because a default constructor isnt definded.
static void Main(string[] args)
{
string shop_json = new WebClient().DownloadString("https://www.supremenewyork.com/mobile_stock.json");
JavaScriptSerializer shop_object = new JavaScriptSerializer();
var shirt_stock = shop_object.Deserialize<NewYarkItems>(shop_json);
var v = shirt_stock;
}
public class NewYarkItems
{
public dynamic unique_image_url_prefixes { get; set; }
public products_and_categories products_And_Categories { get; set; }
public string release_date { get; set; }
public string release_week { get; set; }
}
public class products_and_categories
{
public List<items> Jackets { get; set; }
}
public class items
{
public string name { get; set; }
public int id { get; set; }
public string image_url { get; set; }
public string image_url_hi { get; set; }
public int price { get; set; }
public int sale_price { get; set; }
public bool new_item { get; set; }
public int position { get; set; }
public string category_name { get; set; }
public int price_euro { get; set; }
public int sale_price_euro { get; set; }
}

Inheriting from Multiple Classes in C#

I have a class Annotations, and 2 classes that inherit from it, HousingAnnotations and AutoAnnotations
public class Annotations
{
public string original_posting_date { get; set; }
public string price { get; set; }
}
public class HousingAnnotations : Annotations
{
public string laundry_on_site { get; set; }
public string condo { get; set; }
public string w_d_in_unit { get; set; }
public string street_parking { get; set; }
public string w_d_hookups { get; set; }
public string bedrooms { get; set; }
}
public class AutoAnnotations : Annotations
{
public string vin { get; set; }
public string year { get; set; }
}
What I would like to do is allow for population of either Auto or HousingAnnotation without specifying which type, for instance
AnnotationHelper annotation = new AnnotationHelper{bedrooms = "2", vin = "123"};
or something like that. Since I cannot inherit from both classes, how can I get around this? I know there are workarounds using interfaces, but I do not want to have to call out each property in my AnnotationHelper class. What are some ways to get around this?

What is causing this 'No Implicit Conversion' error?

I have a class and 2 subclasses:
public class User
{
public string eRaiderUsername { get; set; }
public int AllowedSpaces { get; set; }
public ContactInformation ContactInformation { get; set; }
public Ethnicity Ethnicity { get; set; }
public Classification Classification { get; set; }
public Living Living { get; set; }
}
public class Student : User
{
public Student()
{
AllowedSpaces = AppSettings.AllowedStudentSpaces;
}
}
public class OrganizationRepresentative : User
{
public Organization Organization { get; set; }
public OrganizationRepresentative()
{
AllowedSpaces = AppSettings.AllowedOrganizationSpaces;
}
}
I have created a data model to capture form data and to return the correct object type for the user:
public class UserData
{
public string eRaiderUsername { get; set; }
public int Ethnicity { get; set; }
public int Classification { get; set; }
public int Living { get; set; }
public string ContactFirstName { get; set; }
public string ContactLastname { get; set; }
public string ContactEmailAddress { get; set; }
public string ContactCellPhone { get; set; }
public bool IsRepresentingOrganization { get; set; }
public string OrganizationName { get; set; }
public User GetUser()
{
var user = (IsRepresentingOrganization) ? new OrganizationRepresentative() : new Student();
}
}
However, my ternary operation in the GetUser() method is failing with this error:
Type of conditional expression cannot be determined because there is no implicit conversion between {namespace}.OrganizationRepresentative and {namespace}.Student.
What am I missing?
You have to explicitly cast the first branch of the ternary expression to the base type (User) so that the compiler can determine what type the expression can evaluate to.
var user = (IsRepresentingOrganization)
? (User)new OrganizationRepresentative()
: new Student();
The compiler won't automatically deduce which base type should be used for the expression, so you have to specify it manually.

Inconsistent accessibility when everything is public

I am trying to Deserialize a JSON response from Google Maps Geocode.
Those are the classes I coded based on the response.
public class GoogleGeoCodeResponse
{
public string status { get; set; }
public results[] results { get; set; }
}
public class results
{
public address_component[] address_components { get; set; }
public String formatted_address { get; set; }
public Geometry geometry { get; set; }
public Boolean partial_match { get; set; }
public string[] types { get; set; }
}
public class address_component
{
public String long_name { get; set; }
public String short_name { get; set; }
public String[] types { get; set; }
}
public class Geometry
{
public bounds_viewport bounds { get; set; }
public LatLong location { get; set; }
public String location_type { get; set; }
}
public class bounds_viewport
{
public LatLong northeast { get; set; }
public LatLong southwest { get; set; }
}
public class LatLong
{
public double lon { get; set; }
public double lat { get; set; }
}
On my form button click I use this code.
var json = new WebClient().DownloadString("url");
GoogleGeoCodeResponse test = JsonConvert.DeserializeObject<GoogleGeoCodeResponse>(json);
MessageBox.Show(test.results[0].geometry.location.lat + " / " + test.results[0].geometry.location.lon);
Then I wanted to see if I get the correct information but I'm getting:
"Error 1 Inconsistent accessibility: property type 'WindowsFormsApplication1.results[]' is less accessible than property 'WindowsFormsApplication1.GoogleGeoCodeResponse.results'"
I've looked a bunch of post with the same problem but they always had something private or internal somewhere that would lead to this error. As you can see everything I declared is public.
I don't understand why something public inside of a class would be more accessible than the class itself.
I am fairly new to C# and JSON so this might be something really simple.
Ok so I took all of my class and put the code out of my form's class and it worked. I put it back in the class and it still worked I don't know what I have changed, maybe it was just bugged or something anyway thanks for the help!

Categories

Resources