JSON.NET cannot handle simple array deserialization?
Asked Answered
L

2

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?

Lindane answered 2/12, 2013 at 8:1 Comment(2)
Did you managed to solve your problem ?Tolbutamide
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.Shareeshareholder
H
3

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

Handfasting answered 28/10, 2016 at 9:16 Comment(0)
A
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);
    }
}
Arguseyed answered 11/5, 2015 at 19:33 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.