7

I created a simple class with one field. class Test{int value;}

If I use the "preserve references" feature and set it to "all" (i.e. both objects and arrays), then when I simply serialize an array of Test objects, it gets serialized as a JSON object with a special "$values" member with the array values, along with the expected "$id" property to preserve the array reference. That much is fine, but once again the whole thing breaks on deserialization.

Stepping through the source code, I discovered that simply because the test for "IsReadOnlyOrFixedSize" is true, it sets a flag "createdFromNonDefaultConstructor" to true, which doesn't even make any sense, because although it is a fixed size array, it is created from a default constructor, unless it considers any fixed size array constructor a non-default constructor. The bottom line is that it should be able to handle something so basic, and yet it throws this error: "Cannot preserve reference to array or readonly list, or list created from a non-default constructor".

How can I deserialize a basic array while preserving all references in JSON.NET without getting an error?

Vickyexpert
  • 3,147
  • 5
  • 21
  • 34
Triynko
  • 18,766
  • 21
  • 107
  • 173
  • 1
    Did you managed to solve your problem ? –  May 11 '15 at 11:48
  • For a solution to a more general version of this problem, where the array might include recursive self-references, see [Cannot preserve reference to array or readonly list, or list created from a non-default constructor](http://stackoverflow.com/q/41293407/3744182). – dbc Dec 23 '16 at 22:03

2 Answers2

3

Got the same issue, I used List<T> instead of T[] to fix it.

ken2k
  • 48,145
  • 10
  • 116
  • 176
1

You are most likely missing a call to ToObject(...) and a type cast. This should work:

class Test { public int Value; }

class Program
{
    static void Main(string[] args)
    {
        var array = new Test[2];
        var instance = new Test {Value = 123};

        array[0] = instance;
        array[1] = instance;

        var settings = new JsonSerializerSettings
        {
            PreserveReferencesHandling = PreserveReferencesHandling.All
        };

        string serialized = JsonConvert.SerializeObject(array, settings);

        // Explicitly call ToObject() and cast to the target type
        var deserialized = (Test[]) ((JArray)JsonConvert.DeserializeObject(serialized, settings)).ToObject(typeof(Test[]));

        Debug.Assert(deserialized[0].Value == 123);
    }
}
tur
  • 328
  • 1
  • 8