Solved

How do serialize and deserialize different elements of the same business object?

Posted on 2010-11-22
5
760 Views
Last Modified: 2012-05-10
Attached is my Class.
I get an XML string as input to my application (from another application) and I have to deserialize it to my business object.

Once my processing of the object is over, I have to send a response XML - this XML contains totally different tags, but the same business object.

Take the below example, it has 7 members - Product, ParentCaseID, CaseID, UserID, Category, Type, Detail.
When I get the input XML I get Product, ParentCaseID, CaseID, UserID.
But When I send the response (XML string) I have to send the other 3 - Category, Type, Detail along with Product

How do I achieve this?

Note: both input and output are strings (XML strings), and they are as below.

below XML I get as input, and I want to deserialize this.
<?xml version="1.0" encoding="iso-8859-1"?>  
  <Request
    SourceSystem="xyz"
    xmlns="map.xml.pqr.vrsq.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="map.xml.pqr.vrsq.com Request.xsd">
    <Challenge>
      <Product>lmn</Product>
      <ParentCaseId>1234</ParentCaseId>
      <CaseId>1234</CaseId>
      <UserId>LJ34</UserId>
    </Challenge>
  </Request>


below XML is the one I need to send out in the form of a string.
<?xml version="1.0" encoding="iso-8859-1"?>  
  <Response
    SourceSystem="pqr"
    xmlns="map.xml.pqr.vrsq.com" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="map.xml.pqr.vrsq.com Response.xsd">
    <Challenge>
      <Product>lmn</Product>
      <Category>My Category</Category>
      <Type>My Type</Type>
      <Detail>My Detail</Detail>
    </Challenge>
  </Response>

Can anyone suggest me a best solution for this? And how do I achieve serialization and DEserialization in this case.
public class Challenge 

{ 

    [XmlElement("Product")] 

    public int Product { get; set; }     



    [XmlElement("ParentCaseId")] 

    public int ParentCaseId { get; set; } 

 

    [XmlElement("CaseId")] 

    public int CaseId { get; set; } 

 

    [XmlElement("UserId")] 

    public string UserId { get; set; } 

 

    [XmlIgnore("Category")] 

    public string Category { get; set; } 

 

    [XmlIgnore("Type")] 

    public string Type { get; set; } 

 

    [XmlIgnore("Detail")] 

    public string Detail { get; set; } 

}

Open in new window

0
Comment
Question by:GouthamAnand
5 Comments
 
LVL 11

Expert Comment

by:jasonduan
ID: 34191096
There is no shortcut here.

You'll have to implement IXmlSerializable interface, and set some kind of flag in the class to dispath the serialization/deserialization process into different path.

0
 
LVL 18

Expert Comment

by:Richard Lee
ID: 34196886
Before providing any code sample I will provide some thoughts.

1. Initially from a maintainability perspective (reducing complexity) I would have simply gone for two separate classes Request & Response and eliminating the Challenge class. I can see why the Challenge class would be convenient however - the structure of the XML required encourage the use of this Challenge class to provide the extra element.

2. Implementing the IXmlSerializable interface on the Request and Response classes does seem an attractive option since that lends itself ideally to having the challenge class embedded within both and then the custom ReadXml & WriteXml methods would just serialize or deserialize the elements that are needed. Also with this approach there is no need to decorate the Challenge Properties as serialization is dictated by the interface methods.

Question:

What about these attributes?

SourceSystem="xyz"
xmlns="map.xml.pqr.vrsq.com"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="map.xml.pqr.vrsq.com Request.xsd"

DaTribe
0
 
LVL 4

Assisted Solution

by:ricovox
ricovox earned 500 total points
ID: 34199643
Hi GouthamAnand

Now that I see a little more detail about what you want, I have some more suggestions.

It depends on the requirements you have for the business object, but what I would suggest is one of the following:

1) Create two different classes: Output and Input. Then create your Challenge class with just two properties: Output and Input. When you serialize the xml, just serialize the Output object (not the whole Challenge object).
When you deserialize the Input xml, you can deserialize it as a Input object and set the appropriate field of the Challenge class.
You can decorate both the Output and Input objects with the [XmlRoot("Challenge")] attribute to make sure the xml is formed properly in both cases.

Example Code:

[XmlRoot("Challenge")] 
public class ChallengeInput
    public int Product { get; set; }     
    public int ParentCaseId { get; set; } 
    public int CaseId { get; set; } 
    public string UserId { get; set; } 
}

[XmlRoot("Challenge")] 
public class ChallengeOutput
    public int Product { get; set; }     
    public string Category { get; set; } 
    public string Type { get; set; } 
    public string Detail { get; set; } 
}

public class Challenge 
{ 
	public ChallengeInput input { get; set;}
	public ChallengeOutput output { get; set;}

	//Here is the deserialization method. 
	//It reads the input XML and returns a new Challenge object
	public static Challenge Deserialize(Stream s) {
		Challenge c = new Challenge();
		XmlSerializer xs = new XmlSerializer(typeof(ChallengeInput));
		c.input = (ChallengeInput)xs.Deserialize(s);
		c.output = new ChallengeOutput();
	}
	
	//Here is the serialization method. 
	//It writes the output XML
	public void Serialize(Stream s) {
		XmlSerializer xs = new XmlSerializer(typeof(ChallengeOutput));
		this.output.Product = this.input.Product; //just make sure these fields match.
		xs.Serialize(s, this.output);
	}
}


//use it like this:
Stream inXml = ...//get the xml stream from file etc.
var c = Challenge.Deserialize(inXml);
//now change some properties etc.
c.output.Category = blablah;
//send the output
Stream outXml = ...;
c.Serialize(outXml);

Open in new window

0
 
LVL 4

Accepted Solution

by:
ricovox earned 500 total points
ID: 34205520
Or if the previous solution won't work for the rest of your business application, you can create the challenge object as you have listed it originally, and then ALSO create the Input and Output classes as I have written them above. THEN you can create implicit or explicit conversions between the two for easy serialization.

For example:

//Assume Challenge object has ALL properties (as originally posted).
//Assume Input and Output objects as listed in my previous post.

public class Challenge {
	//place the properties of the challenge object here
	//just as you have listed them originally.
	
	//now add an explicit conversion from an Input object
	public static explicit operator Challenge(ChallengeInput input) {
		Challenge c = new Challenge();
		c.Product = input.Product;
		c.ParentCaseId = input.ParentCaseId;
		c.CaseId = input.CaseId;
		c.UserId = input.UserId;
		return c;
	}
	
	//now add an explicit conversion to an Output object
	public static explicit operator ChallengeOutput(Challenge c) {
		ChallengeOutput output = new ChallengeOutput();
		output.Product = c.Product;
		output.Category = c.Category;
		output.Type = c.Type;
		output.Detail = c.Detail;
		return output;
	}
	
	//now here are the NEW serialize and deserialize methods
	//------------------------------------------------------
	//Here is the deserialization method. 
	//It reads the input XML and returns a new Challenge object
	public static Challenge Deserialize(Stream s) {
		XmlSerializer xs = new XmlSerializer(typeof(ChallengeInput));
		//deserialize to an input object first.
		ChallengeInput input = (ChallengeInput)xs.Deserialize(s);
		//explicitly convert to a challenge object for use in your business app.
		return (Challenge)input; 
	}
	
	//Here is the serialization method. 
	//It writes the output XML
	public void Serialize(Stream s) {
		//explicitly convert this challenge object to an output object.
		ChallengeOutput output = (ChallengeOutput)this; 
		//now serialize the output object
		XmlSerializer xs = new XmlSerializer(typeof(ChallengeOutput));
		xs.Serialize(s, output);
	}
}

Open in new window

0
 

Author Closing Comment

by:GouthamAnand
ID: 34235547
Thanks a lot. Your idea is good.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Introduction                                                 Was the var keyword really only brought out to shorten your syntax? Or have the VB language guys got their way in C#? What type of variable is it? All will be revealed.   Also called…
In order to hide the "ugly" records selectors (triangles) in the rowheaders, here are some suggestions. Microsoft doesn't have a direct method/property to do it. You can only hide the rowheader column. First solution, the easy way The first sol…
This video demonstrates how to create an example email signature rule for a department in a company using CodeTwo Exchange Rules. The signature will be inserted beneath users' latest emails in conversations and will be displayed in users' Sent Items…
I designed this idea while studying technology in the classroom.  This is a semester long project.  Students are asked to take photographs on a specific topic which they find meaningful, it can be a place or situation such as travel or homelessness.…

943 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

10 Experts available now in Live!

Get 1:1 Help Now