0

I wonder why no constructor is necessary to deserialize a json string into a .Net/C# class object instance. I was surprised that the constructor is not invoked at all and removed it and the deserializer still created an object instance from the json string. Is this normal?

(I use the json serializer of ServiceStack)

Matt
  • 7,004
  • 11
  • 71
  • 117
  • At some point a constructor must have been involved, you probably don't see it since it is used inside the method for de-serialization. – Habib Jul 26 '13 at 13:13
  • @Habib, what do you mean with a constructor being inside the method of de-serialization? I designed the class object myself (without constructor) and I target the ServiceStack library directly. You mean that ServiceStack somehow "builds" a constructor dynamically through class property reflection or similarly? If yes, do you care to comment which .Net techniques are used to accomplish such? – Matt Jul 26 '13 at 13:15
  • 1
    Default (no parameters) constructor is created if no other constructors are specified. Try creating a constructor with at least one parameter to see what will happen. – Germann Arlington Jul 26 '13 at 13:17
  • ohhh now I get it, when you don't define a constructor in a class it gets a default parameter less constructor – Habib Jul 26 '13 at 13:17
  • @GermannArlington, well the json string contains property values and after deserialization the class instance reflects all property values that were stored in the json string. So, does this not go beyond an (empty) default constructor? So is it that Service Stack creates a class instance and then later maps the json content to the properties inside the class? – Matt Jul 26 '13 at 13:18
  • @MattWolf Deserialization will involve two steps - create empty object using default (no parameters) constructor and than set all values. If you class does NOT have default (no parameters) constructor deserialization will fail. – Germann Arlington Jul 26 '13 at 13:27
  • @GermannArlington, thanks, I was not aware how deserialization works under the hood, I thought a parameterized constructor is necessary. Just to clarify your last sentence, as a default constructor will be created if none is supplied deserialization should never fail, at least not due to a missing constructor, correct? I have not supplied ANY constructor, not even a default (no parameters) one and still the json string was correctly deserialized and populated the properties of the class instance. – Matt Jul 26 '13 at 13:32
  • The compiler creates a default (no parameters) constructor for you when ad only when NO constructor exists. If you create ANY constructor in your class this compiler behaviour will no longer apply. Deserialization never uses parametrised constructors as it is impossible for it to guess the correct constructor to use. Example: deserialization can not distinguish between `Constructor(String parameter1)` and `Constructor(String parameter2)` – Germann Arlington Jul 26 '13 at 13:35
  • Understand now except why some Serialization libraries (such as ProtoBuf-Net) require an "empty" constructor then. Thanks a lot for your explanations. If you like to just copy/paste your comments into an answer then I am happy to accept. – Matt Jul 26 '13 at 13:47

2 Answers2

5

Germanns answer is not entirely true. It is possible to instantiate an object that has no default constructor without executing any constructor.

This is done with FormatterServices.GetUninitializedObject.

ServiceStack is using this method if it cannot find a default constructor, hence it can deserialize objects that have no default constructor.

Ryan Kohn
  • 13,079
  • 14
  • 56
  • 81
Fresa
  • 51
  • 1
  • 2
2

Default (no parameters) constructor is created by the compiler if no constructors are specified. The compiler does that when and only when NO constructors exist. If you create ANY constructor in your class this compiler behaviour will no longer apply. (Try creating a constructor with at least one parameter to see what will happen)

Deserialization will involve two steps - create empty object using default (no parameters) constructor and than set all values. If you class does NOT have default (no parameters) constructor - either created by yourself explicitly or by the compiler - deserialization will fail.

Deserialization never uses parametrised constructors as it is impossible for it to guess the correct constructor to use. Example: deserialization can not distinguish between Constructor(String parameter1) and Constructor(String parameter2)

Germann Arlington
  • 3,315
  • 2
  • 17
  • 19
  • thanks, but I am still confused why some deserialization libraries, such as Protobuf-Net require a default constructor (no parameters)? – Matt Jul 29 '13 at 15:04
  • The default constructor (no parameters) is the one that any deserialization process will use. It is good practice to create one explicitly because if you don't create one and rely on the compiler your code will break as soon as you (or someone else) will create any constructor. Maybe this is what the libraries are doing - adding new constructor(s) to your class? (this is just a speculation though) – Germann Arlington Jul 29 '13 at 15:12