Json.Net - 反序列化包含对象列表的对象列表

时间:2016-06-01 14:34:25

标签: c# json list json.net deserialization

我试图反序列化描述以下内容的json:

Item类型的对象列表,每个Item包含一些属性以及列表' recipe' Effect类型的对象包含它们自己的三个属性(action,value和target)。

当我使用' JsonConvert.SerializeObject'序列化我的列表时我得到以下json:

[
  {
    "name": "WOOD",
    "yield": 1.0,
    "recipe": [
      {
        "action": "ADD",
        "value": 1.0,
        "target": "WOOD"
      }
    ],
    "count": 0.0,
    "numWorkers": 0,
    "id": 1
  },
  {
    "name": "CLAY",
    "yield": 2.0,
    "recipe": [
      {
        "action": "ADD",
        "value": 2.0,
        "target": "CLAY"
      }
    ],
    "count": 0.0,
    "numWorkers": 0,
    "id": 2
  },
  {
    "name": "SPEAR",
    "yield": 0.5,
    "recipe": [
      {
        "action": "ADD",
        "value": 0.5,
        "target": "SPEAR"
      },
      {
        "action": "SUB",
        "value": 1.0,
        "target": "WOOD"
      },
      {
        "action": "SUB",
        "value": 5.0,
        "target": "CLAY"
      }
    ],
    "count": 0.0,
    "numWorkers": 0,
    "id": 3
  },
  {
    "name": "STICK",
    "yield": 4.0,
    "recipe": [
      {
        "action": "ADD",
        "value": 4.0,
        "target": "STICK"
      },
      {
        "action": "SUB",
        "value": 1.0,
        "target": "WOOD"
      }
    ],
    "count": 0.0,
    "numWorkers": 0,
    "id": 4
  }
]

但是当我尝试使用&#39; Items = JsonConvert.DeserializeObject<List<Item>>(jsonstring);&#39;进行反序列化时我收到此错误:A first chance exception of type 'System.NullReferenceException' occurred in Newtonsoft.Json.dll和我的&#39;项目&#39;列表为空。

当我使用json2csharp生成c#时,我得到以下内容:

public class Recipe
{
    public string action { get; set; }
    public double value { get; set; }
    public string target { get; set; }
}

public class RootObject
{
    public string name { get; set; }
    public double yield { get; set; }
    public List<Recipe> recipe { get; set; }
    public double count { get; set; }
    public int numWorkers { get; set; }
    public int id { get; set; }
}

它认为我的Item对象是&#39; RootObject&#39;并且它给了我一份食谱&#39;对象而不是效果列表&#39;列表中的对象&#39;配方&#39;

这里有我的游戏和课程的一些代码,以便您可以看到我正在使用的内容:

public List<Item> Items;

private void Game_Load(object sender, EventArgs e) 
    {
        Items = JsonConvert.DeserializeObject<List<Item>>(jsonstring);
    }

public class Item
{
    public string name;
    public double yield;
    public List<Effect> recipe = new List<Effect>();
    public double count;
    public int numWorkers;
    public int id;

    public Item()
    {
        name = "";
        //configureItem();
    }

    public Item(string nm)
    {
        name = nm.ToUpper();
        //configureItem();
    }

    public List<Effect> getRecipe() {
        return recipe;
    }
}

public class Effect
{
    public string action;
    public double value;
    public string target;

    public Effect(string act, double val, string tar)
    {
        action = act.ToUpper();
        value = val;
        target = tar.ToUpper();
    }
}

我的班级中的所有变量是否需要{ get; set; }?我之前试图添加它,但它似乎导致我的VS在调试期间跳过行和各种其他怪异。或者它只是一个Json格式问题?任何帮助将不胜感激,我已经遍布这个网站和谷歌一般,我在这里撕开我的头发。

2 个答案:

答案 0 :(得分:3)

您的Event类没有默认(无参数)构造函数,因此Json.Net正在尝试使用它具有的构造函数。但是,参数名称与JSON中的任何内容都不匹配(不存在actvaltar属性。在这种情况下,Json.Net将为参数传递默认值(即null)以获取构造的对象,然后返回并尝试设置字段。问题是你的构造函数没有配备处理null值。它假定acttar在调用ToUpper()时不会为空。这是NullReferenceException来自的地方。

一种解决方案是重命名构造函数参数以匹配JSON(我还会添加适当的空检查以确保安全性):

public Effect(string action, double value, string target)
{
    this.action = (action != null ? action.ToUpper() : null);
    this.value = value;
    this.target = (target != null ? target.ToUpper() : null);
}

另一种可能的解决方案是将ToUpper逻辑移动到属性中并提供默认构造函数。

public class Effect
{
    private string _action;
    public string Action
    {
        get { return _action; }
        set { _action = (value != null ? value.ToUpper() : null); }
    }

    public double Value { get; set; }

    private string _target;
    public string Target
    {
        get { return _target; }
        set { _target = (value != null ? value.ToUpper() : null); }
    }

    public Effect()
    {
    }
}

答案 1 :(得分:1)

重命名构造函数的参数名称以匹配json中的属性名称,否则它是不明确的,因此Json.net无法确定哪个字段属于哪里。

public class Effect
{
    public string action;
    public double value;
    public string target;

    //public Effect(string act, double val, string tar)
    public Effect(string action, double value, string target)
    {
        this.action = action.ToUpper();
        this.value = value;
        this.target = target.ToUpper();
    }
}