I am doing json serialization using NewtonSoft.Json
public class CommonBase
{
[JsonProperty(PropertyName = "u_customer_id")]
public long CustomerId { get; set; }
}
I want to do a conditional serialization so that if CustomerId value is 0, I want to set a blank value for CustomerId during json serialization. Since CommonBase is a base class and I am not able to change data type from long to string.
How can I achieve this?
You almost have the answer in your question title. What you are looking for is Conditional Property Serialization
You just need to add method named like this: ShouldSerialize + PropertyName. In your case method should look like:
public bool ShouldSerializeCustomerId()
{
return SomeCondition;
}
P.s. if you are creating base class, you probably want to have abstract class.
I have solved this issue by changing CustomerId property as nullable.
public long? CustomerId { get; set; }
Related
I am having a class with a set of properties that I use as user level settings. Each property has a Default Value attribute. Few has XmlIgnore attribute to avoid the serialization.
When serializing this class object as memory stream and it writes it correct, but while de-serializing it actually creates an object with all the properties default value which was not part of the serialized object. How can I ignore this default value initialization for few properties? Thanks in advance.
XmlSerializer serializer = new mlSerializer(typeof(DisplayPreferences));
DisplayPreferences newPrefs = null;
MemoryStream ms = new System.IO.MemoryStream(System.Text.Encoding.UTF8.GetBytes(prefs));
newPrefs = (DisplayPreferences)serializer.Deserialize(ms);
if (newPrefs != null)
{
newPrefs.CopyTo(Editor.prefs);
}
This app is built in .NET 4.6 (winforms)
Welcome to stackoverflow.
You've given very little information on how you are de-serializing them (a code snippet would help), but I assume you are de-serializing them into a typed object. If that is the case, then what you are experiencing is standard behavior. That is the whole point of the default value, you can't "partially de-serialize a typed object".
What you can do however is either:
de-serializing the object into a raw xmlObject, and write a custom serializer for it.
Make the properties nullable, this is typically where DTO's are useful.See below.
public class SomeTypedObjectDTO
{
public Guid? NullableGuid { get; set; }
public int? NullableInt { get; set; }
}
----UPDATE----
I tired to keep this in line with your code. Lets say you have the following object.
public class DisplayPreferences
{
public Guid Id { get; set; }
public string Name { get; set; }
public int Level { get; set; }
public bool CanDisplay { get; set; }
}
And lets say you only want to serialize the "CanDisplay" and the "level" properties. You can create a DTO (Data Transfer object) for it, which is basically a stripped down version of the original object.
DTO:
public class DisplayPreferencesDTO
{
public int Level { get; set; }
public bool CanDisplay { get; set; }
}
Then I believe all you need to do is change the generic typeof() to use the DTO instead of the actual object.
XmlSerializer serializer = new mlSerializer(typeof(DisplayPreferencesDTO));
You can then map the DTO back to the original object when you like and if you like. You can either do this mapping manually or use a framework called Automapper. Automapper was explicitly designed for mapping DTO's.
If you need me to clarify anything let me know.
Happy coding!
You may want to make them as null? just make them to nullable prop
such as make a int to int?
I think I have quite a unique problem here, where the developer of an API I need to utilize did something I don't quite understand. Yet I have to deal with it.
It is probably the best to explain the problem by showing an example:
{
"type": "type-A",
"value": "{'propA': 'type-A specific element', 'propA2': 'another typeA specific element'}"
}
We are dealing with a quite normal REST API, where the response is a json string - nothing too special. Because of some abstraction going on within the API, there is a type and a value field in each response. Depending on the type, the value will have differently structured content. Also nothing too special.
The problem is now that the content in the value field is not just a normal json object, but a string containing a json object. Therefore deserialization with JsonConvert.DeserializeObject<TargetType>(jsonString) fails with the exception
Newtonsoft.Json.JsonSerializationException: Error converting value
"{'propA': 'type-A specific element', 'propA2': 'another typeA
specific element'}" to type 'My.Project.TargetType'.
Is there any neat built-in support in the json.net library I might use to counter this issue or do I have to go a manual route and fix the json or the deserialization in some other way?
Edit: to give a bit more context: The API does indeed try to abstract its interface with equal requests and responses, but I am still able to request very specific responses in my code. Therefore I make use of a generic class which contains the common properties and a generic type for the value like so:
public class Response<TValue>
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("value")]
public TValue Value { get; set; }
}
In fact, the type isn't even relevant for me, because I know beforehand which type I will receive as response (due to my specific request). Therefore I am also able to determine the response type of value. My actual deserialization looks like this JsonConvert.DeserializeObject<Response<TargetType>>(jsonString).
Yet I did not find a neat way of parsing my value together with the Response object. Any suggestions are highly appreciated.
No, in your case you just need two steps:
public class RootObject
{
public string type {get;set;}
public string value {get;set;}
}
RootObject r = JsonConvert.DeserializeObject<RootObject>(json);
And then, depending on the type, deserialize the other object:
if (r.type == "typeA")
{
TypeA t = JsonConvert.DeserializeObject<TypeA>(r.value);
}
If all types share some common properties, you might put them in an interface or base class. This will also ease reusing the deserialized class.
I solved the problem myself by using a built-in which calls a method after deserialization of the object itself.
public class Response<TValue>
{
[JsonProperty("type")]
public string Type { get; set; }
[JsonProperty("value")]
private string ValueString { get; set; }
public TValue Value { get; set; }
[OnDeserialized]
internal void DeserializeValue(StreamingContext context)
{
Value = JsonConvert.DeserializeObject<TValue>(ValueString);
}
}
This allows me to simply call JsonConvert.DeserializeObject<Response<TargetType>>(json), where it will first deserialize the Response and after that the value property will be deserialized to TargetType.
Hi I Have a class derived from another class . Like this :
public class Customer
{
public string Date{ get; set; }
public string InstallationNo{ get; set; }
public string SerialNo { get; set; }
}
Then I have created a class named Customer_U which derived from Customer
public class Customer_U:Customer
{
public string Bill{ get; set; }
}
I have simple question. I have google many time but no answer. I have list filled with data like:
List<Customer_U> customer= new List<Customer_U>() I create a excel using this list. In excel colum order is like this :
Bill --- Date --- InstalltionNo --- SerialNo.
Idont want this order. I want "Bill" member to be last columns . How to set order of member when createin a class derived from another class
There is no defined order in a CLR class; it is up to the implementation that is inspecting the metadata of the class to determine how a class is interpreted.
For example, your Excel library is probably using reflection to inspect the class you pass it and reflection makes no guarantees as to the order in which things are processed.
Other implementations such as the WCF DataContractSerializer or ProtoBuf.NET handle order through the use of DataMember.
That said, if your library can handle dynamic or anonymous types then you can use the approach detailed in the other answers. .NET seems to consistently reflect these types in the same order that they were created.
var x = new { Z = "", Y = 1, X = true };
Console.WriteLine(x.GetType().GetProperties().Select(y => y.Name));
However it should be noted that this is an implementation detail and should not be relied upon. I'd see if you library allows you to specify the mapping between properties in your class and columns in your spreadsheet otherwise you might run into weird bugs in the future!
There is no ordering of class members in .NET. Whenever someone iterates over members in a class, they are imposing some order themselves.
The default seems to be shallow-first. So in your case, first all of Customer_U members are enumerated, and then Customer's.
If you do the enumeration yourself, there's nothing easier than simply using your own enumeration method:
class A
{
public string Date { get; set; }
public string SerialNo { get; set; }
}
class B : A
{
public string Bill { get; set; }
public string InstallationNo { get; set; }
}
public static IEnumerable<PropertyInfo> GetProperties(Type type)
{
if (type.BaseType == typeof(object)) return type.GetProperties().OrderBy(i => i.Name);
return GetProperties(type.BaseType)
.Concat
(
type
.GetProperties
(BindingFlags.DeclaredOnly | BindingFlags.Public | BindingFlags.Instance)
.OrderBy(i => i.Name)
);
}
This simple recursive method will output
Date
SerialNo
Bill
InstallationNo
Deep-first, alphabetical. If you don't want the alphabetical sort, you can omit the OrderBys, but note that then the order is simply unspecified, not necessarily the order you used in your class.
You can use this when building your Excel, for example - if there's a way to impose an order in the output data. If there's no way to impose your own order in whatever you're using to output your data, you could do a mapping to a new object based on this data, and hope that it turns out well - however, doing this dynamically is actually quite a bit of work.
As the other answers have pointed out, there is no such thing as a defined order for class properties in .NET.
However, it seems that what you are looking for is not an ordering of the properties themselves, but in fact a way to sort the properties when serializing the objects, e.g. to Excel.
This IS easily implemented using classes from the System.Runtime.Serialization namespace. There are various classes there that could help you control the serialization process, and allow you to be as specific as you want.
The simplest solution would likely be simply applying the DataMember attribute:
[DataContract]
public class Customer
{
[DataMember(Order = 1)]
public string Date{ get; set; }
[DataMember(Order = 2)]
public string InstallationNo{ get; set; }
[DataMember(Order = 3)]
public string SerialNo { get; set; }
}
You can create a new anonymous class using linq:
var x = from costumerItem in YourList
select new { Date = costumerItem.Date, ...and so on };
Afterwards, move this class to the excel.
Create a wrapper list like
var reOrderedCustomer = Customer.select(a => new { a.Date, a.InstallationNo ,
a.SerialNo, a.Bill }).ToList()
Or do this in your first select method which fills Customer list (If you want to avoid anonymous type)
I need to deserialize the flowing xml in c#
<Show>
<status>Canceled</status>
</Show>
<Show>
<status>2</status>
</Show>
my class is
[XmlRoot("Show")]`
public class Show
{
[XmlElement(ElementName = "status")]
public object status { get; set; }
}
and it works but i would like to deserialize it into an enum where in this example cancel is equal 2
public enum ShowStatus
{
[XmlEnum("Canceled")]
Canceled = 2
}
is there any way to do that without parse the public object status { get; set; } string value to enum
If you want to Deserialize the Enum using the name or the integer you can decorate the Enum with XmlEnum attribute and supply the integer.
This will deserialise "Canceled" and "2" as your Enum.
Example:
[XmlRoot("Show")]
public class Show
{
[XmlElement(ElementName = "status")]
public ShowStatus status { get; set; }
}
public enum ShowStatus
{
[XmlEnum("2")]
Canceled = 2
}
Test xml:
<?xml version="1.0"?>
<ArrayOfShow xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Show>
<status>Canceled</status>
</Show>
<Show>
<status>2</status>
</Show>
</ArrayOfShow>
you cannot use object directly, XmlSerializer simply refuses to work with generics. Objects still have an underlying type, and when its de-serialzied, you have no idea what that type is. I made a workaround for it here but its not very pretty, or very useful.
You can custom implement IXmlSerializable, but that is a headache and a half.
I am assuming that the source of the problem is that you are taking this in as input from another source, and the field could be either integer or text, which you want to store as an enumerable. You are probably better of de-serializing it into a string, then simply parsing it later, afterwards. That would probably be the easiest way to do it. Everything else I can find is either about deserializing only the string values, or only the integer values, I have no idea if either of them can handle both forms of data, but it seems unlikely.
This Function will probably help you out a lot when it comes to that, it looks like it can handle the string or the numerical value, but I dont think XmlSerializer can use it. You would be better off with a string "dummy" that can save back to the Enum property using the Parse function. see this stackoverflow question for an example of the dummy property.
Example
Generally speaking it would look something like this:
[XmlRoot("Show")]`
public class Show
{
[XmlIgnore()]
public ShowStatus status { get; set; }
[XmlElement(ElementName = "status")]
public string StatusString
{
get { return status.ToString(); }
set { status = Enum.Parse(ShowStatus, value); }
}
}
I want to serialize a class. In this class there's a property of type Class1 that in turn has its own properties.
public abstract class ComponentBase
{
[ToSerialize] //An attribute defined my me, indicating whether or not to serialize this property.
public ComponentArgs Parameters { get; set; }
}
public class ComponentArgs
{
public string WorkingPath { get; set; }
public IList<Language> Languages { get; set; }
public string ComponentOutputPath { get; set; }
}
The information serialized must be put into a Dictionary<string,string>, such as
ComponentSettings[str_Name] = str_Value;
The method used in reading this value is Reflection
// pinfo: Property Info got via Type.GetProperties();
componentSettings.Add(pinfo.Name, pinfo.GetValue((object)this, null).ToString());
The information after serialization is:
<Parameters>MS.STBIntl.Pippin.Framework.ComponentArgs</Parameters>
instead of the value of ComponentArgs.WorkingPath.
The solution I thought of is to append to the following line an if judgement:
componentSettings.Add(pinfo.Name, pinfo.GetValue((object)this, null).ToString());
if(pinfo is ComponentArgs)
componentSettings.Add(pinfo.Name, pinfo.GetValue(
(ComponentArgs)this, null).WorkingPath+"\n"+
LanguageList+"\n"+ //Language list is a concatinated string of all elements in the list.
(ComponentArgs)this, null).ComponentOutputPath+"\n"+
);
When deserializing, add a judgement of whether the value contains more than 2 "\n", if so, extract each value from the string.
But this way seems clumsy and much more like an workaround. I wonder if there's any more professional way of doing it? My reviewer is very particular and he won't accept such a solution. If you know a way, could you please share it with me? Thanks a lot.
There are lots of ways to use inbuilt serialization.
The simplest and oldest is the [Serializable] attribute that tells .NET to serialize the members.
You can also use the WCF [DataContract] attribute to serialize stuff.
There is also the IXMLSerializable interface which allows you to implement custom XML readers and writers for you classes.
The bottom line is, there is no need to roll your own - it has been done.