Serialize Nested Classes in c#? - c#

What I'm trying to do is serialize Nested classes. My code first:
[Serializable]
public class SampleClass
{
[Serializable]
public class Person
{
[XmlElement("Name")]
public string Name { get; set; }
[XmlElement("Age")]
public ushort Age { get; set; }
}
[Serializable]
public class Adress
{
[XmlElement("Street")]
public string Street { get; set; }
[XmlElement("House number")]
public int Number { get; set; }
}
public SampleClass()
{
}
public SampleClass(string _name, byte _age, string _street, int _number)
{
Person p = new Person();
p.Name = _name;
p.Age = _age;
Adress a = new Adress();
a.Street = _street;
a.Number = _number;
}
}
I want to get xml like this
<?xml version="1.0"?>
<SampleClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" >
<Person>
<Name></Name>
<Age></Age>
</Person>
<Adress>
<Street></Street>
<HouseNumber></HouseNumber>
</Adress>
</SampleClass>
When I serialize this SimleClass:
using (Stream str = new FileStream(#"C:/test.xml", FileMode.Create))
{
XmlSerializer serial = new XmlSerializer(typeof(SampleClass));
SampleClass sClass = new SampleClass("John",15,"Street",34);
serial.Serialize(str, sClass);
label1.ForeColor = Color.Black;
label1.Text = "Ok";
}
It's give me test.xml file but inside of that file is :
<?xml version="1.0"?>
<SampleClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema" />
What am I doing wrong?
Thanks for advance:)

What you really want serialize is this :
Person p = new Person();
p.Name = _name;
p.Age = _age;
Adress a = new Adress();
But these variables are local.
Create a property of each one and decorate them with the serializable attribute too. Now it will work.
public SampleClass(string _name, byte _age, string _street, int _number)
{
this.Person = new Person();
Person p = this.Person;
p.Name = _name;
p.Age = _age;
this.Adress = new Adress();
Adress a = this.Adress;
a.Street = _street;
a.Number = _number;
}
[Serializable]
public Person Person { get; set; }
[Serializable]
public Adress Adress { get; set; }
BTW: Address takes 2 d.

If you serialize an instance of the main class, the serializer will serialize an instance of the nested class if and only if the object graph contains one. In this respect, nested classes are exactly the same as all other classes.
Basically you have to create properties for the nested class in the main one

This line is invalid:
[XmlElement("House number")]
As an element name can't have a space in it.

The reason you are getting an empty XML file is that your SampleClass has no properties to serialize.
In the constructor you are creating a Person and Address which are thrown away as soon as the method exists as you are not using them for anything. Change your code as follows and you should have more success.
[Serializable]
public class SampleClass
{
[Serializable]
public class Person
{
[XmlElement("Name")]
public string Name { get; set; }
[XmlElement("Age")]
public ushort Age { get; set; }
}
[Serializable]
public class Adress
{
[XmlElement("Street")]
public string Street { get; set; }
[XmlElement("HouseNumber")]
public int Number { get; set; }
}
public SampleClass()
{
}
public SampleClass(string name, byte age, string street, int number)
{
this.Person = new Person
{
Age = age,
Name = name
};
this.Adress = new Adress
{
Street = street,
Number = number
}
}
public Person Person { get; set; }
public Address Address { get; set; }
}

Related

Sending List of objects in c# web service

I have the following two objects:
public class Dog
{
public string Name {get;set;}
public int Age {get;set;}
}
public class Person
{
public string Name {get;set;}
public string City {get;set;}
public string ID {get;set;}
}
Now, in the server side, I build a mix List of Person and Dog, and I would like to return this List to the client via web-service (asmx).
The order is important, and eventually my list will hold more types.
How can I return a list of mixed object in web-service?
Thank you.
I think you should create new class that encapsulate your many classes
public class Dog : MyClass
{
public string Name {get;set;}
public int Age {get;set;}
}
public class Person : MyClass
{
public string Name {get;set;}
public string City {get;set;}
public string ID {get;set;}
}
public class NewClass
{
public enum OBJType {
Dog,Person
} // like a constant for specific object type
public Dog D_Dog { get; set; }
public Person D_Person { get; set; }
public OBJType Type { get; set; }
public int seq { get; set; }
}
Then it should be use like this
//At Server
List<NewClass> newList = new List<NewClass>();
NewClass Item1 = new NewClass();
Item1.D_Dog = new Dog() { Name = "Woof", Age = 3 };
Item1.seq = 1;
Item1.Type = NewClass.OBJType.Dog;
newList.Add(Item1);
NewClass Item2 = new NewClass();
Item2.D_Person = new Person() { Name = "John", City = "TPP" , ID =111 };
Item2.seq = 2;
Item2.Type = NewClass.OBJType.Person;
newList.Add(Item2);
//At Client
List<NewClass> newList = //..get form webservice
foreach (var Item in newList)
{
if (Item.Type == NewClass.OBJType.Dog)
{
// using Item.D_Dog;
}
else {
// using Item.D_Person
}
}
Not a pro at C# so excuse if its not the most efficient.
1st class ie Person.cs
public class Person : MyClass
{
public string Name { get; set; }
public string City { get; set; }
public string ID { get; set; }
}
2nd Class ie Dog.cs
public class Dog : MyClass
{
public string Name { get; set; }
public int Age { get; set; }
}
The inherited class ie MyClass.cs
public class MyClass
{
public string Type { get; set; }
}
Notice I have added a field Type to differentiate between objects in the program consuming the webservice. You can improve this with enums for type.
The Example function to return the data.
public List<MyClass> returnData()
{
List<MyClass> returningdata = new List<MyClass>();
Person pers = new Person();
pers.City = "NELSPRUIT";
pers.Name = "TED";
pers.ID = "5502226585665";
pers.Type = "PERSON";
returningdata.Add(pers);
Dog doggy = new Dog();
doggy.Name = "Tiny";
doggy.Age = 2;
doggy.Type = "DOG";
returningdata.Add(doggy);
return returningdata;
}
Hope this is what you wanted.

How to set list A equal to list B, where on B a property does not exist which does exist on A

I have a C# list which is of type Person. This list needs to be converted into JSON data format. The Person C# class look like this:
public class Person
{
public int ID { get; set; }
public static int PSID = 1;
public string name { get; set; }
public string nameToken { get; set; }
public double DOB { get; set; }
public List<Award> awards { get; set; }
public List<Link> links { get; set; }
public Person()
{
awards = new List<Award>();
links = new List<Link>();
ID = PSID;
PSID++;
}
}
As I am required to convert a C# list of type Person into JSON. I made another Class in C# called PersonJS. It is exactly like the Person C# class the only difference is that I have removed some of the properties that are not required in the JSON front-end. Namely: nameToken, PSID.
public class PersonJS
{
public int ID { get; set; }
public string name { get; set; }
public double DOB { get; set; }
public List<AwardJS> awards { get; set; }
public List<Link> links { get; set; }
}
One of the properties of PersonJS is a List called awards which is of Type AwardJS. A problem occurs below because I try and equal Person.awards List equal to PersonJS.awards List. However, they are of difference types so it is not possible to equal both lists. The reason why I have put them equal to different types is because the JSON data does not need all of the properties that I have used in C#. So I made two classes Award and AwardJS. The only difference is that Award contains a property called filmWebToken whereas AwardJS does not.
public class Award
{
public int filmID { get; set; }
public int categoryID { get; set; }
public string filmWebToken { get; set; }
}
public class AwardJS
{
public int filmID { get; set; }
public int categoryID { get; set; }
}
In my code I iterate over all of the properties in C# list of type Person and I attempt to create a personjs object and add it to a PersonJS C# list. The PersonJS list will go back to the front-end as JSON. However, because the award property in the class PersonJS is different to the award property in Person I get the error "Cannot implicitly convert type AwardJS to Award". The reason I get this error is because PersonJS does not contain filmWebToken which exists in the Person class. I don't want the filmWebToken to be in the PersonJS list as it is not meant to be a property in my JSON data. However, as there are property fields in Person.Award I still want access to: filmID and CategoryID how can I ignore/by-pass the filmWebToken field. This is what I have tried:
List<Person> allPersons = DataRepository.GetAllPersons(); // contains the C# data
List<PersonJS> personjs = new List<PersonJS>(); // empty to start with
foreach (var person in allPersons)
{
foreach (var award in person.awards)
{
personjs.Add(
new PersonJS
{
ID = person.ID,
links = person.links,
name = person.name,
DOB = person.DOB,
awards = person.awards // The types are not equal: Person contains filmWebToken whereas PersonJS does not
});
}
}
Add a method called ToAwardJS in Award:
public AwardJS ToAwardJS() {
return new AwardJS { filmID = this.filmID, categoryID = this.categoryID };
}
Then when you create the PersonJS object, do:
new PersonJS
{
ID = person.ID,
links = person.links,
name = person.name,
DOB = person.DOB,
awards = person.awards.Select(x => x.ToAwardJS()).ToList(),
});
What serializer are you using? Most provide attributes to specify which members to include in the serialization. For example, the DataContractJsonSerializer uses [DataContract] and [DataMember]. I think Json.net uses [JsonIgnore]. There's no need for multiple classes.
void Main()
{
var jsSer = new System.Runtime.Serialization.Json.DataContractJsonSerializer(typeof(Person));
var p = new Person {
ID = 1,
name = "John",
DOB = 1234.5,
nameToken = "token"
};
string result = null;
using (var ms = new MemoryStream())
{
jsSer.WriteObject(ms, p);
byte[] json = ms.ToArray();
ms.Close();
result = Encoding.UTF8.GetString(json, 0, json.Length);
}
Console.WriteLine(result);
}
[DataContract]
public class Person
{
//included
[DataMember]
public int ID { get; set; }
[DataMember]
public string name { get; set; }
[DataMember]
public string nameToken { get; set; }
[DataMember]
public double DOB { get; set; }
//ignored
public static int PSID = 1;
public List<string> awards { get; set; }
public List<string> links { get; set; }
public Person()
{
awards = new List<Award>();
links = new List<Link>();
ID = PSID;
PSID++;
}
}
Result:
{"DOB":1234.5,"ID":1,"name":"John","nameToken":"token"}

C# - how to use invalid characters in a variable name

In C#, I'm building a class (simplified here for discussion purposes) that eventually will be serialized into some externally defined JSON:
{
"$schema": "http://example.com/person.json",
"name": "John",
"age": 86
}
In my code I would have something like:
public class Person
{
public const string $schema= #"http://example.com/person.json";
public string name {get;set; }
public int age {get; set;}
}
...
Person person = new Person();
person.name = "John";
person.age = 88;
JavaScriptSerializer serializer = new JavaScriptSerializer();
string json = serializer.Serialize(person);
In my code above the $schema is causing an "Unexpected character '$' error. Is there a workaround?
Provide the attribute [DataContract] to your Person class.
Also, did you mean to make schema const?
[DataContract]
public class Person
{
[DataMember(Name = "$schema")]
public string schema { get; set; }
public string name { get; set; }
public int age {get; set;}
}
If using JSON.NET, you can use the JsonProperty attribute:
public class Person {
[JsonProperty(PropertyName = "$schema")]
public string schema {get; set;} = #"lsjdhflsjkdf";
public string name {get;set;}
}

How can i Serialized a additional property of an object inhert by Collectionbase?

I have two class like below, I want to serialized the object student to a.xml file.I could create the xml file but could not with the 'ClassName' property.
[Serializable]
public class Person
{
[XmlAttribute]
public string FirstName { get; set; }
[XmlAttribute]
public string LastName { get; set; }
}
public class Student : System.Collections.CollectionBase, IEnumerable<Person>
{
[XmlAttribute]
public string ClassName { get; set; }
public void Add(Person person)
{
List.Add(person);
}
public Person this[int index]
{
get
{
return (Person)List[index];
}
}
#region IEnumerable<Person> 成员
public new IEnumerator<Person> GetEnumerator()
{
foreach (Person transducer in List)
yield return transducer;
}
#endregion
}
I got the xml content like this, and no ClassName field
Student student = new Student();
student.Add(new Person(){ FirstName = "bill", LastName = "gates" });
student.Add(new Person(){ FirstName = "bill", LastName = "gates" });
student.ClassName = "AAA";
XmlSerializer x2 = new XmlSerializer(typeof(Student));
x2.Serialize(File.Create("ab.xml"), student);
How can I get the Property???
The problem is in the default serialization over everything that implements IList. It just enumerates the contents, not the properties.
A solution for this is to not implement the CollectionBase in your serialized class, but to create a property that does:
public class Student
{
List<Person> Items { get; set; }
}

How to serialize selected properties only

I have one class Person and it has some public properties . Now I want to serialize person class but with some selected properties only. This can be achieve by making that property private but I don't want to change any property as private.
If its not possible using serialisation then, what is another way to create xml doc for object with selected properties only.
Note: All properties must be public.
class Program
{
static void Main(string[] args)
{
Person person = new Person();
using (MemoryStream memoryStream = new MemoryStream())
{
XmlSerializer xmlSerializer = new XmlSerializer(person.GetType());
xmlSerializer.Serialize(memoryStream, person);
using (FileStream fileStream = File.Create("C://Output.xml"))
{
memoryStream.WriteTo(fileStream);
fileStream.Close();
}
memoryStream.Close();
}
}
}
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
public double Salary { get; set; }
public Person()
{
Id = 1;
Name = "Sam";
Salary = 50000.00;
}
}
Current Output
<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Id>1</Id>
<Name>Sam</Name>
<Salary>50000</Salary>
</Person>
Expected Output
<?xml version="1.0"?>
<Person xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Salary>50000</Salary>
</Person>
You could use an XmlIgnore attribute..
public class Person
{
[XmlIgnore]
public int Id { get; set; }
[XmlIgnore]
public string Name { get; set; }
public double Salary { get; set; }
public Person()
{
Id = 1;
Name = "Sam";
Salary = 50000.00;
}
}
See this
can you give a try to below code and just use XmlIgnore attribute on he properties which you not require :-
[XmlIgnore]
public int Id { get; set; }
[XmlIgnore]
public string Name { get; set; }
public double Salary { get; set; }

Categories