Json.net没有反序列化对象列表

时间:2014-04-22 15:16:36

标签: c# json.net

我有以下模型结构:

public class Step : ActivityElement
{
    public Step()
    {
        this.Id = Guid.NewGuid();
        this.Label = "Basic Step";
        this.Type = "step";
    }

    public Guid Id { get; set; }
    public string Label { get; set; }
    public Input Input { get; set; }
}

public abstract class Input
{
    public string Type { get; set; }
    public object Value { get; set; }
}

public class GridInput : Input
{
    public GridInput()
    {
        this.Type = "grid";
        this.GridHeader = new GridHeader();
        this.RowList = new List<GridRow>();
    }

    public GridHeader GridHeader { get; set; }
    public List<GridRow> RowList { get; set; }
}

public class GridRow
{
    public GridRow()
    {
        this.IsDeleted = false;
        this.CellList = new List<GridCell>();
    }

    public List<GridCell> CellList { get; set; }
    public bool IsDeleted { get; set; }
}

public class GridCell
{
    public GridCell()
    {
        this.name = "not set yet";
        this.Input = null;
    }

    public string name { get; set; }
    public Input Input { get; set; }
}

这是我试图反序列化的JSON

{
    "Id":"e833ceae-57e5-4c52-8d56-b047790cb7c7",
    "Label":"Grid time!",
    "Input":
    {
        "GridHeader":{"ColumnDefinitionList":[{"field":"column1","title":"Column 1"},{"field":"column2","title":"Column 2"},{"field":"column3","title":"Column 3"},{"field":"column4","title":"Column 4"}]},
        "RowList":
        [
            {
                "CellList":
                [
                    {"name":"column1","Input":{"Type":"text","Value":"cell 1 row 1"}},
                    {"name":"column2","Input":{"Type":"text","Value":"cell 2 row 1"}},
                    {"name":"column3","Input":{"Type":"text","Value":"cell 3 row 1"}},
                    {"name":"column4","Input":{"Type":"text","Value":"cell 4 row 1"}}
                ],
                "IsDeleted":false
            },
            {
                "CellList":
                [
                    {"name":"column1","Input":{"Type":"text","Value":"cell 1 row 2"}},
                    {"name":"column2","Input":{"Type":"text","Value":"cell 2 row 2"}},
                    {"name":"column3","Input":{"Type":"text","Value":"cell 3 row 2"}},
                    {"name":"column4","Input":{"Type":"text","Value":"cell 4 row 2"}}
                ],
                "IsDeleted":false
            }
        ],
        "Type":"grid",
        "Value":null
    },
    "DisplayPosition":2,
    "Type":"step"
}

这是自定义反序列化器,它确保GridInput是作为输入创建的对象:

public abstract class JsonCreationConverter<T> : JsonConverter
{
    protected abstract T Create(Type objectType, JObject jObject);

    public override bool CanConvert(Type objectType)
    {
        return typeof(T).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // Load JObject from stream
        JObject jObject = JObject.Load(reader);

        // Create target object based on JObject
        T target = Create(objectType, jObject);

        // Populate the object properties
        serializer.Populate(jObject.CreateReader(), target);

        return target;
    }
}
public class InputJsonConverter : JsonCreationConverter<Input>
{
    protected override Input Create(Type objectType, JObject jObject)
    {
        var type = (string)jObject.Property("Type");
        switch (type)
        {
            case "grid":
                return new GridInput();
            case "text":
                return new TextInput();
            case "dropdown":
                return new DropdownInput();
            case "checkbox":
                return new CheckboxInput();
        }

        throw new ApplicationException(String.Format("The given type {0} is not supported!", type));
    }
}

我已经实现了一些东西,以便GridHeader被滑动(我不需要它反序列化,所以它只是在反序列化过程中创建一个空的GridHeader),但是RowList最终总是空的 GridInput反序列化后。 我尝试了很多东西,但是我已经没想完了......

TL:DR:GridInput已创建,但RowList为空

1 个答案:

答案 0 :(得分:1)

我无法重现这个问题。您是否有可能忘记让Json.NET使用InputJsonConverter类?以下代码有效。

void Main()
{
    var step = JsonConvert.DeserializeObject<Step>(s);
    Console.WriteLine(((GridInput)step.Input).RowList.Count); // 2
}
public class GridHeader { }
public class ActivityElement { public string Type { get; set; } }
public class Step : ActivityElement
{
    public Step()
    {
        this.Id = Guid.NewGuid();
        this.Label = "Basic Step";
        this.Type = "step";
    }

    public Guid Id { get; set; }
    public string Label { get; set; }
    public Input Input { get; set; }
}
[JsonConverter(typeof(InputJsonConverter))]
public abstract class Input
{
    public string Type { get; set; }
    public object Value { get; set; }
}

public class TextInput : Input
{
    public TextInput()
    {
        this.Type = "text";
    }
}
public class GridInput : Input
{
    public GridInput()
    {
        this.Type = "grid";
        this.GridHeader = new GridHeader();
        this.RowList = new List<GridRow>();
    }

    public GridHeader GridHeader { get; set; }
    public List<GridRow> RowList { get; set; }
}

public class GridRow
{
    public GridRow()
    {
        this.IsDeleted = false;
        this.CellList = new List<GridCell>();
    }

    public List<GridCell> CellList { get; set; }
    public bool IsDeleted { get; set; }
}

public class GridCell
{
    public GridCell()
    {
        this.name = "not set yet";
        this.Input = null;
    }

    public string name { get; set; }
    public Input Input { get; set; }
}
public abstract class JsonCreationConverter<T> : JsonConverter
{
    protected abstract T Create(Type objectType, JObject jObject);

    public override bool CanConvert(Type objectType)
    {
        return typeof(T).IsAssignableFrom(objectType);
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        // Load JObject from stream
        JObject jObject = JObject.Load(reader);

        // Create target object based on JObject
        T target = Create(objectType, jObject);

        // Populate the object properties
        serializer.Populate(jObject.CreateReader(), target);

        return target;
    }
    public override void WriteJson(
    JsonWriter writer,
    Object value,
    JsonSerializer serializer
)
    {
        throw new NotImplementedException();
    }
}
public class InputJsonConverter : JsonCreationConverter<Input>
{
    protected override Input Create(Type objectType, JObject jObject)
    {
        var type = (string)jObject.Property("Type");
        switch (type)
        {
            case "grid":
                return new GridInput();
            case "text":
                return new TextInput();
//            case "dropdown":
//                return new DropdownInput();
//            case "checkbox":
//                return new CheckboxInput();
        }

        throw new ApplicationException(String.Format("The given type {0} is not supported!", type));
    }
}
string s = @"{
    ""Id"":""e833ceae-57e5-4c52-8d56-b047790cb7c7"",
    ""Label"":""Grid time!"",
    ""Input"":
    {
        ""GridHeader"":{""ColumnDefinitionList"":[{""field"":""column1"",""title"":""Column 1""},{""field"":""column2"",""title"":""Column 2""},{""field"":""column3"",""title"":""Column 3""},{""field"":""column4"",""title"":""Column 4""}]},
        ""RowList"":
        [
            {
                ""CellList"":
                [
                    {""name"":""column1"",""Input"":{""Type"":""text"",""Value"":""cell 1 row 1""}},
                    {""name"":""column2"",""Input"":{""Type"":""text"",""Value"":""cell 2 row 1""}},
                    {""name"":""column3"",""Input"":{""Type"":""text"",""Value"":""cell 3 row 1""}},
                    {""name"":""column4"",""Input"":{""Type"":""text"",""Value"":""cell 4 row 1""}}
                ],
                ""IsDeleted"":false
            },
            {
                ""CellList"":
                [
                    {""name"":""column1"",""Input"":{""Type"":""text"",""Value"":""cell 1 row 2""}},
                    {""name"":""column2"",""Input"":{""Type"":""text"",""Value"":""cell 2 row 2""}},
                    {""name"":""column3"",""Input"":{""Type"":""text"",""Value"":""cell 3 row 2""}},
                    {""name"":""column4"",""Input"":{""Type"":""text"",""Value"":""cell 4 row 2""}}
                ],
                ""IsDeleted"":false
            }
        ],
        ""Type"":""grid"",
        ""Value"":null
    },
    ""DisplayPosition"":2,
    ""Type"":""step""
}";