XML serialization related question and c# - c#

Suppose i have one customer class and i will serialize the class to xml. After serialization we will get xml data but i need some property of customer class to be serialized on demand based on few condition. Is it possible?
I have no concept how to do it. Can anyone help me with this?

You can add one or more ShouldSerializeXXXXXX() methods, where XXXXXX is the name of each property you want to serialize based on a condition.
E.g.:
public class Customer
{
[DefaultValue(null)]
public string SomeInfo { get; set; }
[DefaultValue(null)]
public string SomeOtherInfo { get; set; }
#region Serialization conditions
// should SomeInfo be serialized?
public bool ShouldSerializeSomeInfo()
{
return SomeInfo != null; // serialize if not null
}
// should SomeOtherInfo be serialized?
public bool ShouldSerializeSomeOtherInfo()
{
return SomeOtherInfo != null; // serialize if not null
}
#endregion
}

You can use XmlAttributeOverrides and overide the XmlIgnore attribute for your property.
(there is an example in the XmlIgnore msdn page)

Related

JSON.NET (WebApi2) - Serialize property, but skip during deserialization

I know of [JsonIgnore] which ignores properties altogether, I know of ShouldSerializePropertyName which gives conditional serialization, but I cannot find anything to mark property to be serialized into JSON normally, but not set during deserialization.
I could write a workaround:
[JsonIgnore]
public string MyValue{get;set;}
public string MyValueForJson {get{return MyValue;}
but it is a last resort. Is there some way - other than custom converters etc. - to express that I don't want that field to be populated during deserialization?
As I understand you want to serialize object with all properties in json string but retrieve only selected properties while deserialization on that string.
If this is case then, I had a similar requirement where I created BaseType and DerivedType classes then I serialize derived type into Json string while deserialization I want it in Base type instance. So wrote this code :
using System.Web.Script.Serialization;
public static TB CastToBase<T, TB>(this T derivedTypeInstance)
{
var serializer = new JavaScriptSerializer();
var baseTypeInstance = serializer.Deserialize<TB>(serializer.Serialize(derivedTypeInstance));
return baseTypeInstance;
}
I think you can put [JsonObject(MemberSerialization.OptIn)] property on the class, which requires to explicitly state which properties to serialize. Then you can use both [JsonProperty] and [JsonIgnore] on a property you'd like to serialize as normal but ignore on deserialization.
Example:
[JsonObject(MemberSerialization.OptIn)]
private class UserData
{
[JsonProperty]
public string Token { get; set; }
[JsonProperty]
public string Username { get; set; }
[JsonIgnore]
[JsonProperty]
public string Password { get; set; }
}

c# - Deserialize a Json in two steps

I would like to deserialize my Json in two step because I have to read the first part to know what kind of Object it is.
I have to read this kind of Json :
{"header":3,"data":{"result":"myResult"}}
it's more readable like that
{
"header":3,
"data":{
"result":"myResult"
}
}
I deserialize this Json in a class named ProtocolHeader :
public class ProtocolHeader
{
[JsonProperty("header")]
public int Header { get; set; }
[JsonProperty("data")]
public string Data { get; set; }
}
To do this I use this code :
JsonConvert.DeserializeObject<ProtocolHeader>(Json)
Depending on the value of the Header, I will choose different class to deserialize the end of the file.
For example, I could have another class
public class ProtocolResult
{
[JsonProperty("result")]
public string Result{ get; set; }
}
or like that
public class ProtocolError
{
[JsonProperty("errorNumber")]
public int ErrorNumber{ get; set; }
[JsonProperty("additionalInformation")]
public string AdditionalInformation{ get; set; }
}
Do you have an idea to seperate the Deserialize Object in two steps ?
Thanks
You could make 3 classes.
One common class (not base) which has all of the fields, then a ProtocolResult & ProtocolError
Then implement an implicit cast to each.
You could also put a IsError getter on to your common class to decide how to use it.
You can use a reader to only read as long as you need, then skip out of the reader and do your real deserialization.
Probably not a whole lot better than deserializing into a simple object first then a real object later, but it's an alternative.
You can probably tweak this a bit.
string json = #"{""header"":3,""data"":{""result"":""myResult""}}";
using (var stringReader = new StringReader(json))
{
using (var jsonReader = new JsonTextReader(stringReader))
{
while (jsonReader.Read())
{
if (jsonReader.TokenType == JsonToken.PropertyName
&& jsonReader.Value != null
&& jsonReader.Value.ToString() == "header")
{
jsonReader.Read();
int header = Convert.ToInt32(jsonReader.Value);
switch (header)
{
case 1:
// Deserialize as type 1
break;
case 2:
// Deserialize as type 2
break;
case 3:
// Deserialize as type 3
break;
}
break;
}
}
}
}
Option 1: Without using an abstract base class for your data classes.
The easiest I've found to do this is as follows:
Declare your class using JToken as the field type for the unknown object.
[JsonObject(MemberSerialization.OptIn)]
public class ProtocolHeader
{
[JsonProperty("header")]
private int _header;
[JsonProperty("data")]
private JToken _data;
}
Expose the specialized data in properties.
public ProtocolResult Result
{
get
{
if (_data == null || _header != ResultHeaderValue)
return null;
return _data.ToObject<ProtocolResult>();
}
}
public ProtocolError Error
{
get
{
if (_data == null || _header != ErrorHeaderValue)
return null;
return _data.ToObject<ProtocolError>();
}
}
Option 2: With using an abstract base class for your data classes.
Another option is to create an abstract base class for the various data types, and create a static method in the abstract base class to perform the type selection and proper deserialization. This is particularly useful when the type information is contained in the object itself (e.g. if header was a property inside the data object).
The LoadBalancerConfiguration<T>._healthMonitor field has the type JObject, but the HealthMonitor property in the same class returns a HealthMonitor object.
The HealthMonitor.FromJObject method performs the actual deserialization.

Replacing XML serialization of class member

In my class (Camera), that I need to serialize, I have one member which doesn't have much serialization means and I can't modify its class. But there are only 2-3 parameters out of whole class that I can serialize and then de-serialize based on that.
XmlSerializer SerializerObj = new XmlSerializer(typeof(Camera));
TextWriter WriteFileStream = new StreamWriter(#"C:\test.xml");
SerializerObj.Serialize(WriteFileStream, cc);
WriteFileStream.Close();
How and where can I put custom serialization code, to take those 2-3 parameters from object and give to serializer, then during de-serialization create again that object using those 2-3 parameters.
Update. The example code:
[Serializable()]
public class Camera
{
public string name;
public int index;
public double distance;
public List<string> CameraList { get; set; }
[XmlIgnore()]
public GMarkerGoogle marker;
public Camera()
{
}
}
marker is the member that doesn't have serialization means. But there with marker.position, marker.rotation I can re-create that object.
If you can't or don't want to Xml serialize your GMarker then make sure that you do serialize the properties needed to reconstruct it (kind of what you already suggested). That way you can make a property with backing field to lazy recreate the GMarker.
[Serializable()]
public class Camera
{
public string name;
public int index;
public double distance;
public List<string> CameraList { get; set; }
private GMarkerGoogle _marker;
[XmlIgnore()]
public GMarkerGoogle Marker
{
set
{
_marker = value;
MarkerPosition = _marker.position;
MarkerRotation = _marker.rotation;
}
get
{
if (_marker == null)
{
_marker = new GMarkerGoogle(MarkerPosition, MarkerRotation);
}
return _marker;
}
}
public double MarkerPosition { get; set; }
public double MarkerRotation { get; set; }
public Camera()
{
}
}
Does this help? I made up a thing or two because I don't know the API for the marker, but I hope you can draw the picture from this point onwards.
By implementing the IXmlSerializable interface in your Camera class.
Check MSDN for more info.
Alternatively you could use the [XmlIgnore] attribute to flag the properties you do not want to serialize to XML.
Check MSDN for more info :).
PS: If you post some code I can show you an example but you probably don't need me. Let me know if you do though.

DataContractSerializer not serializing one property

When I serialize the following class, the ContentPageId XML element is missing from the resulting XML file.
[CollectionDataContract(ItemName = "Widget")]
public sealed class StructurePage : List<Widget>, IEquatable<StructurePage>
{
[DataMember]
public int ContentPageId
{
get;
set;
}
public StructurePage(){}
public StructurePage(int pageId)
{
this.ContentPageId = pageId;
}
public bool Equals(StructurePage other)
{
return this.ContentPageId.Equals(other.ContentPageId);
}
}
Why is the property skipped when serializing and how to include it as XML element?
Is it possible to include it in serialization as an XML attribute to the StructurePage element? Was looking for this around the net but could find any info on it, apparently with XmlSerializer there was XmlAttributeAttribute attribute but no such thing with DataContractSerializer.
Go through this post http://social.msdn.microsoft.com/Forums/eu/wcf/thread/57eb195a-43a9-47fe-8b1a-a9d23feb2df2
According to this
Collection data contract classes cannot contain extra data members.
Hope this helps.

Prevent Property from being serialized

I tried something like this:
[NonSerialized]
private string _DecodeText;
public string DecodeText { get { return _DecodeText; } set { _DecodeText = value; } }
But it does not work. "DecodeText" is still in the serialized file. How can i prevent the property from serializing?
I Suspect you're using the XmlSerializer? If so use the [XmlIgnore] attribute instead.
This should be applied to the property instead of the backing field as the XmlSerializer serializes public fields and properties (whereas the BinaryFormatter uses refelction to get at the private fields - hence the marking of the private field with NonSerialized when using a BinaryFormatter).
I was able to use the following and not have the property serialized (.NET 4.0):
private string _DecodeText;
[System.Xml.Serialization.XmlIgnore]
public string DecodeText { get { return _DecodeText; } set { _DecodeText = value; } }
Updated Answer
The [NonSerialized] atttibute is on the variable not the property, but it cannot be on the attribute. So it is not going to help.
One way to prevent the property being serialized is to add a method
public bool ShouldSerializeDecodeText() {
return false;
}
and this (for the XmlSerializer at least) will prevent the property being serialized.
If you don't want to add lots of methods to the class just for serialization you might try inheriting from it and adding the methods to the derived class.
hth,
Alan.
I built on top of #John's answer and modified ef.tt template
to include [System.Xml.Serialization.XmlIgnore]
Here is the code
foreach (var navigationProperty in navigationProperties)
{
if (navigationProperty.ToEndMember.RelationshipMultiplicity == RelationshipMultiplicity.Many)
{
#>
[System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Usage", "CA2227:CollectionPropertiesShouldBeReadOnly")]
[System.Xml.Serialization.XmlIgnore]
<#
}
#>
<#=codeStringGenerator.NavigationProperty(navigationProperty)#>
<#
}
I think this code that will be help you all. With properties you declared and you want it to be serialized only. Then you should add a method return type as boolean and name method is ShouldSerialize as prefix with [NameProperty]. A scratch code as below and link reference to Newtonsoft for you:
public class DisplayFieldSetting
{
public bool ShouldSerializeHidden()
{
return false;
}
public bool ShouldSerializeKeepOriginialColumnName()
{
return false;
}
public string Hidden { get; set; }
public string KeepOriginialColumnName{ get; set; }
}

Categories