1

The following class will roundtrip (serialize to string, then deserialize to object) just fine:

public class FoobarObject
{
    public readonly IFileLocation File1;
    public readonly IFileLocation File2;
    public readonly IFileLocation File3;

    public FoobarObject(IFileLocation file1, IFileLocation file2, IFileLocation file3)
    {
        File1 = file1;
        File2 = file2;
        File3 = file3;
    }
}

However, if I change it to the following, it will fail (the fields are returned as null):

public class FoobarObject
{
    //[JsonProperty("SomeFile1")]
    public readonly IFileLocation SomeFile1;
    public readonly IFileLocation File2;
    public readonly IFileLocation File3;

    public FoobarObject(IFileLocation file1, IFileLocation file2, IFileLocation file3)
    {
        SomeFile1 = file1;
        File2 = file2;
        File3 = file3;
    }
}

But, by uncommenting the JsonProperty line, the object will roundtrip properly.

The serialized string appears to be correct ("{\"SomeFile1\":\"C:\\\\vibwd541.u2q\\\\Foobar1\", \"File2\":\"C:\\\\vibwd541.u2q\\\\Foobar2\", \"File3\":null}", but the deserializing does not happen.

What is going on?

Gordon Bean
  • 4,272
  • 1
  • 32
  • 47
  • `readonly` is guilty. You can read about it more at: http://stackoverflow.com/questions/4179093/can-json-net-populate-readonly-fields-in-a-class – Orel Eraki Aug 07 '15 at 23:43

1 Answers1

2

The reason this is happening is that, by default, Json.NET uses the ConstructorHandling.Default algorithm to determine the constructor to use when deserializing a type. This algorithm works as follows, according to the docs:

ConstructorHandling Enumeration

Default                             First attempt to use the public default constructor, then fall back to single paramatized constructor, then the non-public default constructor. 
AllowNonPublicDefaultConstructor    Json.NET will use a non-public default constructor before falling back to a paramatized constructor. 

Your class has a single public constructor. It has three parameters IFileLocation file1, IFileLocation file2, IFileLocation file3. Thus Json.NET will use it to construct your object during deserialization, matching JSON property names to constructor parameter names using reflection. So if you rename File1 to SomeFile1 during serialization it will no longer match the name of any of the constructor arguments, and will not be deserialized.

To avoid this problem, make sure that the property names match the constructor argument names.

dbc
  • 104,963
  • 20
  • 228
  • 340