Json.net failing to load certain properties belonging to a class object? - c#

NOTE: I'm adding this community wiki entry to save someone the loss of time I just went through debugging this problem.
I have a class object with multiple public properties. I can serialize it fine using JSON.net. But when I load the JSON text back and deserialize it using JsonConvert.DeserializeObject<>, some of the fields are set to NULL when they definitely had valid values at the time of serialization. I inspected the serialized JSON string manually and I definitely see values for the NULL properties in the text. Why is this happening?

By default, Json.Net serializes and deserializes only the public members of a class. If you have public getters but private setters for your properties then the properties will be serialized to JSON but not deserialized back to your class.
The easy way to fix this is to make your setters public, but of course that breaks the immutability that private setters provide. If you want to be able to keep your setters private while still being able to deserialize them, you can annotate your properties with [JsonProperty] attributes instead. This will allow the deserializer to "see" them.
Here is a short fiddle to demonstrate: https://dotnetfiddle.net/4nZdGJ

Although it took me a while to hunt down the problem, the answer was simple. The object properties that always had NULL values when deserialized had private setters. I made the setters public and the problem went away.

Related

Are private fields mandatory for serialising xml files?

In all my learning about xml serialisation the samples showed using a public property with a private back store field.
But then I found this:
https://blog.udemy.com/csharp-serialize-to-xml/
I also learned that with c# 3.0 you don't always need the backing store field as it is done behind the scenes.
So should I simplify my code and follow the link and just use public properties?
Explicit private backing fields are completely unnecessary for XmlSerializer, which can only serialize public fields and properties. As long as the backing field is private, XmlSerializer has no way of detecting whether it is explicit or secretly created by the compiler as described in the docs:
When you declare [an auto-implemented property], the compiler creates a private, anonymous backing field that can only be accessed through the property's get and set accessors.
If you are only serializing using XmlSerializer (or json.net with DefaultContractResolver.IgnoreSerializableAttribute = true, which is the default), go right ahead and simplify your classes by using auto-implemented properties.
However, do be aware that auto-implemented properties work poorly with [Serializable]. When you mark a type with this attribute, you are indicating that it can be serialized by serializing its internal state -- its public and private fields1 -- rather than its external state -- its public properties. While this attribute is completely ignored by XmlSerializer, certain other serializers support it, including DataContractSerializer, DataContractJsonSerializer and BinaryFormatter. If you add the attribute to a type with auto-implemented properties, the names of the secret "anonymous" backing fields can start to appear in serialization streams created by those serializers. This sometimes leads to problems such as those in the following questions:
Is there a way to make DataContractSerializer output cleaner XML?.
How to remove k__BackingField from json when Deserialize.
DataContractJsonSerializer generating Ghost string to JSON keys?.
Binary Formatter and properties with\without backing fields.
Ignore Non Serialized property in BinaryFormatter Serialization.
So, if you are using auto-implemented properties, my recommendation would be to remove the [Serializable] attribute from your type. You probably don't need it, data contract serialization works better without it, and in any event its use is being deprecated in .NET Core, as shown here and here. (Though reportedly binary serialization is getting implemented to some extent in .NET Core 2.0, see here for details.)
1 Why fields? In the .Net 1.1 time frame, there were still debates about whether serializing private state might be preferable to serializing public state. This is no longer debated, serialization of public state (or of state as specified by some data contract) is preferred.

Set DataContract and DataMember Without All the Attributes

I find the [DataContract] and [DataMember] attributes a bit messy and would rather do this with code in a config method or something. Is this possible?
You don't have to use these attributes at all. DataContractSerializer will serialize all public properties with getter and setter but in case of serializing entities with navigation properties you will easily end with exception due to "cyclic reference".
To avoid that exception you must either use [DataContract(IsReference = true)] on your entity class with DataMember on every property you want to serilize or IgnoreDataMember on every property you don't want to serialize.
The last and the most complex option is avoiding attributes completely and custom classes implementing IDataContractSurrogate to control serialization outside of the type.
You can also write your completely custom serialization process or use XML serialization or binary serialization with all its requirements.
No, the DataContractSerializer is an opt-in serializer - you have to tell it what you want included.
With other serializers you need to use things like NonSerializedAttribute or XmlIgnoreAttribute to tell the serializer to leave things alone.
I know this is a rather old post, but I came here thinking the same thing if there is a way to set all member attributes automatically on some legacy code with public fields and no getters and setters.
What makes it look just a little bit less messy is shortening up the name DataMember:
using DM = System.Runtime.Serialization.DataMemberAttribute;
[DataContract]
public class SomeClass
{
[DM] public bool IsMO;
[DM] public string LabCode;
[DM] public string OrderNumber;
}

Fields vs. Properties and XMLSerializers (101)

So I've been studying the use of various Serializers in the .NET Framework and while trying to experiment on preventing certain objects in a class from being serialized I was thrusted back to some very basic programming questions that I "thought" I knew. Given this example:
public class Example
{
public string examName;
[XmlIgnore]
public int exampleNumber;
public Example()
{ }
[XmlIgnore]
public int ExampleNumberTwo { get; set; }
}
I can create an instance of this class and using the XMLSerializer can output the content of this class in XML format. The [XmlIgnore] attribute actually does what I'd expected; it prevents the serialization of the referenced items.
So venturing further I replaced the [XmlIgnore] declaration for "exampleNumber" with [NonSerializable] expecting the similar results but the output did not change. After searching through resources, it was stated that the [NonSerializable] attribute should only be used on fields and [XmlIgnore] attributes should be used on properties.
Yet another post stated that the [NonSerializable] attribute has no effect when using the XMLSerializer but will produce the expected results when using the SOAP or BinaryFormatter. So I'm lost on the concept at this point.
But this brought me to the basic question, what defines a field vs. a property? I know its a basic question and I've even viewed other discussions here but the degree of clarity I am looking for still wasn't really clear.
I can use the [XmlIgnore] attribute on the property (ExampleNumberTwo) or the variable (exampleNumber) so the statement that it can ONLY be used on Properties doesn't seem correct.
But then again, I have always referred to the objects in my example such as (examName) and (exampleNumber) as being member variables. So what exactly is the signature of a "Field"
Can anyone shed some light on this?
The MSDN documentation supports the idea that [NonSerialized] only gives the expected results with the binary and SOAP serializers:
When using the BinaryFormatter or SoapFormatter classes to serialize
an object, use the NonSerializedAttribute attribute to prevent a field
from being serialized. For example, you can use this attribute to
prevent the serialization of sensitive data.
The target objects for the NonSerializedAttribute attribute are public
and private fields of a serializable class. By default, classes are
not serializable unless they are marked with SerializableAttribute.
During the serialization process all the public and private fields of
a class are serialized by default. Fields marked with
NonSerializedAttribute are excluded during serialization. If you are
using the XmlSerializer class to serialize an object, use the
XmlIgnoreAttribute class to get the same functionality. Alternatively,
implement the ISerializable interface to explicitly control the
serialization process. Note that classes that implement ISerializable
must still be marked with SerializableAttribute.
In terms of "field" vs. "property", fields are straight data variables contained by a class. Properties are actually specially named methods on the class (get_PropName() and set_PropName()). In your code, the compiler allows you to use properties the same way you would use a field, and then inserts the appropriate get/set call for you.
Oftentimes, properties will be simple wrappers around a field:
private int myField;
public int MyProperty
{
get { return myField; }
set { myField = value; }
}
But they don't have to be:
public int TodaysDate
{
get { return DateTime.Today; }
}
In general, you want all your fields to be private, since they're supposed to be implementation details. Any simple data that you'd like to expose should be done via a property, since you can easily surround the data access with (changeable) logic.
In C#, the short answer is that properties have get and/or set methods, while fields do not. VB.NET makes it a little more evident by requiring the "Property" qualifier to be used to differentiate one.
With C#, you can just append " { get; set; }" to the end of a field's definition and it's now a property.
Where this really comes into play is in reflection. Fields and Properties are segregated from one another into different enumerable collections.
This answer to What are the differences between the XmlSerializer and BinaryFormatter will help you get started in the right direction.

Denote properties of class to not be serialized

I'm using silverlight on WP7.
I have a class I am trying to serialize to isolatedstorage. I know the framework will take care of serializing the class automatically for me, assuming every property is serializable.
For this class, I have some properties (such as BitmapImage) that are not serializable. Is there a way to tell the framework to NOT serialize that property (and instead, set it as null when it deserializes it?)
I know implementing XmlSerializable is a possibility, but I don't want to have to set/get each manually. I'd rather it serialize what I tell it to, and I can go and set the other properties after it has deserialized.
thanks
You can use XmlIgnoreAttribute to tell XmlSerializer to ignore your property.

JSON.NET - exclude properties of a specific type at runtime

I'm wondering how to exclude/strip certain properties of given type(s) (or collections of those) from being serialized using Json.NET library?
I tried to write my own contract resolver (inheriting from DefaultContractResolver) with no luck.
I know that I could be done using DataAnnotations, decorating the excluded properties with ScriptIgnoreAttribute, but it's not applicable in my scenario. The objects serialized can be virtually anything, so I don't know which properties to exclude at design-time. I know only the types of properties that should not be serialized.
It looks like a rather simple task, but unfortunately I couldn't find a decent solution anywhere...
BTW - I'm not bound to Json.NET library - if it can easily be done with default/other .NET JSON serializers it'd be an equally good solution for me.
UPDATE
The properties has to be excluded before trying to serialize them. Why?
Basically, the types of objects I'm receiving and serializing can have dynamic properties of type inheriting from IDynamicMetaObjectProvider. I'm not going to describe all the details, but the DynamicMetaObject returned from GetMetaObject method of these objects doesn't have DynamicMetaObject.GetDynamicMemberNames method implemented (throws NotImplementedException...). Summarizing - the problem is those objects (I need to exclude) doesn't allow to enumerate their properties, what Json.NET serializer tries to do behind the scenes. I always end up with NotImplementedException being thrown.
I have tried both the WCF JSON serialization as well as the System.Web.Script.Serialization.JavaScriptSerializer. I have found if you want solid control of the serialization process and do not want to be bound by attributes and hacks to make things work, the JavaScriptSerializer is the way to go. It is included in the .NET stack and allows you to create and register JavaScriptConverter subclasses to perform custom serialization of types.
The only restriction I have found that may cause you a problem is that you cannot easily register a converter to convert all subclasses of Object (aka, one converter to rule them all). You really need to have knowledge of common base classes or preregister the set of types up front by scanning an assembly. However, property serialization is entirely left up to you, so you can decide using simple reflection which properties to serialize and how.
Plus, the default serialization is much much much better for JSON than the WCF approach. By default, all types are serializable without attributes, enums serialize by name, string-key dictionaries serialize as JSON objects, lists serialize as arrays, etc. But for obvious reasons, such as circular trees, even the default behavior needs assistance from time to time.
In my case, I was supporting a client-API that did not exactly match the server class structure, and we wanted a much simpler JSON syntax that was easy on the eyes, and the JavaScriptSerializer did the trick every time. Just let me know if you need some code samples to get started.
Create your own contract resolver, override the method that creates the properties for an object and then filter the results to only include those that you want.
Have you considered using the ShouldSerialize prefix property to exclude the property of your specific type at runtime?
public class Employee
{
public string Name { get; set; }
public Employee Manager { get; set; }
public bool ShouldSerializeManager()
{
return (Manager != this);
}
}

Categories

Resources