22

I'm using JSON.NET 6.0.1. When I use the SerializeObject method to serialize an object of my derived class, it serializes properties from base class only. Here is the code snippet:

string v = JsonConvert.SerializeObject(
                service, 
                Formatting.Indented, 
                new JsonSerializerSettings()
                {
                    TypeNameHandling = TypeNameHandling.All
                });

base class:

[DataContract]
public abstract partial class DataEntity : IDataEntity, INotifyPropertyChanging, INotifyPropertyChanged
{
    ...
}

derived class:

[Table(Name = "dbo.mytable")]
public sealed class mytable : DataEntity
{
    ...
}

Am I missing something?

Gman
  • 1,781
  • 1
  • 23
  • 38
frosty
  • 2,421
  • 6
  • 26
  • 47

3 Answers3

32

Yes, you are missing the [DataContract] attribute on the derived class. You also need to add [DataMember] to any properties or fields that you want serialized, if you haven't already added them. Json.Net was changed in version 5.0 release 1 (April 2013) such that the [DataContract] attribute is not inherited.

Note that if you remove all instances of [DataContract] and [DataMemeber] from your classes, Json.Net behaves differently: in that case, the default behavior is for Json.Net to serialize all public properties, both in the base and derived classes.

Brian Rogers
  • 125,747
  • 31
  • 299
  • 300
  • Is there any way to change this behavior? – JoelFan Apr 19 '16 at 15:24
  • @JoelFan You'll have to be more specific. – Brian Rogers Apr 19 '16 at 16:49
  • I want to be able to tell JsonConvert.SerializeObject to serialize all the properties, regardless of any attributes. I have a class that derives from a class marked [DataContract], but my derived class is not marked. As a result, only the base class's properties are being serialized. – JoelFan Apr 19 '16 at 17:50
  • @JoelFan See [Configure JSON.NET to ignore DataContract/DataMember attributes](http://stackoverflow.com/q/11055225/10263) – Brian Rogers Apr 19 '16 at 19:42
  • JSON.NET [incorrectly (de)serializes data contracts](http://iaroslavkovtunenko.blogspot.com/2012/08/jsonnet-serializer-returns-empty-object.html). Brian seems to have misinterpreted the quote he included. It doesn't mean derived types need the `DataContract`/`DataMember` attributes. Reading [this](https://msdn.microsoft.com/en-us/library/cc656732.aspx#Anchor_1) may clear up the confusion. – HappyNomad Sep 16 '16 at 19:22
  • @BrianRogers Your quote seems to indicate the opposite of what you said. If the subclass doesn't have the DataContractAttribute it should not have any of the behavior activated by the DataContractAttribute. – João Portela Nov 04 '20 at 15:10
  • Apparently it was done like that because the [author wasn't aware of that when he wrote it](https://github.com/JamesNK/Newtonsoft.Json/issues/603#issuecomment-136095131). And now he can't change it [because of backwards compatibility](https://github.com/JamesNK/Newtonsoft.Json/issues/872#issuecomment-216017651) – João Portela Nov 04 '20 at 15:19
  • 1
    @JoãoPortela I've removed the quote since it seems to be causing confusion for people. The answer is still useful without it. – Brian Rogers Nov 04 '20 at 22:41
4

Adding the attribute [JsonObject(MemberSerialization.OptOut)] to your derived class will include all its public members to be serialized.

[Table(Name = "dbo.mytable")]
[JsonObject(MemberSerialization.OptOut)]
public sealed class mytable : DataEntity
{
    ...
}

Alternatively, if you only want certain properties of your derived class to be serialized you can add the attribute [JsonProperty] to each one (This would be equivalent of adding [DataMember] to each property along with [DataContract] on the class).

Ray
  • 187,153
  • 97
  • 222
  • 204
  • Fantastic @Ray, thanks! I don't understand why did is not the accepted/most upvoted answer, as it is well commented on the web that TypeNameHandling.All brings security issues. Just a side note, if your derived class is Internal, just like mine, the [JsonObject(MemberSerialization.OptOut)] will not work. You'll have to use the [JsonProperty] on each base class member. It works just fine though! – Luis Gouveia Jan 07 '21 at 21:55
-2

JsonConvert.SerializeObject was only return {} for me. I found that I needed to add a new constructor to the class before it serialized properly.

masteroleary
  • 1,014
  • 2
  • 16
  • 33