Solved

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

Posted on 2010-11-22
5
757 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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
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
Comment Utility
Thanks a lot. Your idea is good.
0

Featured Post

Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

Join & Write a Comment

Introduction Although it is an old technology, serial ports are still being used by many hardware manufacturers. If you develop applications in C#, Microsoft .NET framework has SerialPort class to communicate with the serial ports.  I needed to…
This article describes a simple method to resize a control at runtime.  It includes ready-to-use source code and a complete sample demonstration application.  We'll also talk about C# Extension Methods. Introduction In one of my applications…
Internet Business Fax to Email Made Easy - With eFax Corporate (http://www.enterprise.efax.com), you'll receive a dedicated online fax number, which is used the same way as a typical analog fax number. You'll receive secure faxes in your email, fr…
Here's a very brief overview of the methods PRTG Network Monitor (https://www.paessler.com/prtg) offers for monitoring bandwidth, to help you decide which methods you´d like to investigate in more detail.  The methods are covered in more detail in o…

771 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

12 Experts available now in Live!

Get 1:1 Help Now