C#Json.Net:{“无法将'System.Boolean [,]'类型的对象强制转换为'System.Collections.Generic.ICollection`1 [System.Boolean]'。”}}

时间:2016-06-03 10:42:10

标签: c# json deserialization

我正在尝试反序列化一个复杂的对象,它可以包含同一个类的实例(WorldInstance,它可以包含更多的WorldInstances),但它抛出了这个异常,我不知道为什么,或者如何修复它。 / p>

我知道这有点模糊,但我不知道需要什么信息,所以我会发布任何有关我的信息。

编辑1:这是我正在尝试序列化的整个课程。 http://pastebin.com/QTNH1HZH

我认为它在使用已发现的文件时失败,在第691行,即使它不应该对该数据做任何事情。

1 个答案:

答案 0 :(得分:0)

您的问题是您正在尝试使Json.NET反序列化只获取数组属性discoveredTiles,如以下简化版本的类所示:

public class WorldInstance
{
    protected WorldTile[,] m_Tiles;
    protected bool[,] m_Discovered;

    public WorldInstance(WorldTile[,] tiles)
    {
        m_Tiles = tiles;
        m_Discovered = new bool[m_Tiles.GetLength(0), m_Tiles.GetLength(1)];
    }

    public WorldTile[,] tiles
    {
        get
        {
            return m_Tiles;
        }
    }

    public bool[,] discoveredTiles
    {
        get
        {
            return m_Discovered;
        }
    }
}

public class WorldTile
{
}

即使数组是预先分配的并且与JSON数组具有相同的长度,目前也没有实现,因为Json.NET将尝试反序列化的项添加到预先分配的数组中,这当然是不可能的。 (请注意,tiles属性将通过将其传递给构造函数来进行反序列化,将JSON属性名称与构造函数参数名称相匹配。)

对于1d数组属性,抛出的异常解释了这个问题:

System.NotSupportedException: Collection was of a fixed size.
   at System.SZArrayHelper.Add[T](T value)
   at Newtonsoft.Json.Utilities.CollectionWrapper`1.Add(T item) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\Utilities\CollectionWrapper.cs:line 76
   at Newtonsoft.Json.Utilities.CollectionWrapper`1.System.Collections.IList.Add(Object value) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\Utilities\CollectionWrapper.cs:line 194
   at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.CreateObjectUsingCreatorWithParameters(JsonReader reader, JsonObjectContract contract, JsonProperty containerProperty, ObjectConstructor`1 creator, String id) in C:\Development\Releases\Json\Working\Newtonsoft.Json\Working-Signed\Src\Newtonsoft.Json\Serialization\JsonSerializerInternalReader.cs:line 2030

但是对于2d数组,引发的InvalidCastException不那么亮。

此问题有两种解决方法:

  1. 将受保护的构造函数添加到包含WorldInstance参数的bool[,] discoveredTiles并将其标记为[JsonConstructor],例如:

    [JsonConstructor]
    protected WorldInstance(WorldTile[,] tiles, bool[,] discoveredTiles)
    {
        if (tiles == null || discoveredTiles == null)
            throw new ArgumentNullException();
        // Ensure the tiles and discoveredTiles arrays have the same sizes
        if (tiles.GetLength(0) != discoveredTiles.GetLength(0) || tiles.GetLength(1) != discoveredTiles.GetLength(1))
            throw new InvalidOperationException("tiles.GetLength(0) != discoveredTiles.GetLength(0) || tiles.GetLength(1) != discoveredTiles.GetLength(1)");
        m_Tiles = tiles;
        m_Discovered = discoveredTiles;
    }
    

    请注意,参数名称discoveredTiles必须与相应的序列化属性名称相同。

  2. discoveredTiles添加私有或受保护的setter,并使用[JsonProperty]标记:

    [JsonProperty]
    public bool[,] discoveredTiles
    {
        get
        {
            return m_Discovered;
        }
        protected set
        {
            if (value == null)
                throw new ArgumentNullException();
            // Ensure the tiles and discoveredTiles arrays have the same sizes
            if (tiles != null && tiles.GetLength(0) != value.GetLength(0) || tiles.GetLength(1) != value.GetLength(1))
                throw new InvalidOperationException("tiles != null && tiles.GetLength(0) != value.GetLength(0) || tiles.GetLength(1) != value.GetLength(1)");
            m_Discovered = value;
        }
    }