Solved

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

Posted on 2010-11-22
5
767 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
[X]
Welcome to Experts Exchange

Add your voice to the tech community where 5M+ people just like you are talking about what matters.

  • Help others & share knowledge
  • Earn cash & points
  • Learn & ask questions
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

Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

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

Suggested Solutions

Introduction This article series is supposed to shed some light on the use of IDisposable and objects that inherit from it. In essence, a more apt title for this article would be: using (IDisposable) {}. I’m just not sure how many people would ge…
Calculating holidays and working days is a function that is often needed yet it is not one found within the Framework. This article presents one approach to building a working-day calculator for use in .NET.
Finding and deleting duplicate (picture) files can be a time consuming task. My wife and I, our three kids and their families all share one dilemma: Managing our pictures. Between desktops, laptops, phones, tablets, and cameras; over the last decade…
Suggested Courses

732 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