反序列化数组中的数组

时间:2018-01-19 20:07:53

标签: c# json json.net deserialization

我刚刚使用all current MTG sets/cards下载了一个巨大的 JSON文件,我希望将其全部反序列化。

我已经将每个set的大部分反序列化,但是当我尝试反序列化每个Set中的booster对象时,我遇到了麻烦:

enter image description here

enter image description here

从上面的两张图片中可以看出,每个booster对象中都有一个字符串列表,但对于某些booster个对象,还有一个更多字符串的附加数组。反序列化一个专门的字符串数组不是问题。当我遇到需要反序列化的booster对象 中的字符串数组时,我的问题就出现了。

目前我设置的用于处理此反序列化的属性是:

public IEnumerable<string> booster { get; set; }

但是当我遇到booster中有另一个数组的情况时,我会抛出一个异常,Newtonsoft.Json抱怨它不知道如何处理反序列化。

那么,我的问题就变成了:如何反序列化字符串数组中包含的字符串数组?在C#代码中,对象需要用什么来处理那种反序列化?

4 个答案:

答案 0 :(得分:1)

您可以将每个项目反序列化为string[],甚至认为该项目不是集合。因此,提供自定义序列化程序;

public class StringArrayConverter : JsonConverter
{
    public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
    {
        throw new NotImplementedException();
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JArray array = JArray.Load(reader);
        for (int i = 0; i < array.Count; i++)
        {
            //If item is just a string, convert it string collection
            if (array[i].Type == JTokenType.String)
            {
                array[i] = JToken.FromObject(new List<string> {array[i].ToObject<string>()});
            }
        }
        return array.ToObject<List<string[]>>();
    }

    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(List<string[]>));
    }
}
public class JsonObject
{
    [JsonConverter(typeof(StringArrayConverter))]
    public List<string[]> booster { get; set; }
}

然后反序列化json;

var data = JsonConvert.DeserializeObject<JsonObject>(json);

最后,您可以像我在下面提供的那样反序列化json;

{
    "booster": [
      "1",
      "2",
          ["3","4"]
    ]
}

答案 1 :(得分:0)

如果您使用C#作为编程语言,请使用以下链接从JSON字符串生成C#类

http://json2csharp.com/

然后,您可以使用代码中生成的类,使用JsonConvert.DeserializeObject(jssonstring)将json字符串反序列化为对象

答案 2 :(得分:0)

最简单的解决方案是将类型更改为IEnumerable<object>。因此,它可以存储stringstring[]

或者您可以使用类型Itemstring的两个属性创建一个类string[]。然后你可以创建另一个属性,返回一个非空的属性,所以现在不是整个项目是object,你可以有一个特殊的类只返回两种类型之一,所以你可以确保您获得stringstring[]。希望这是有道理的。

您的财产:public IEnumerable<Item> booster { get; set; }

public class Item
{
    private string _text;
    private string[] _array;
    public object Value => (object)_text ?? (object)_array;

    public Item(string text) { _text = text; }
    public Item(string[] array) { _array = array; }
}

当您需要使用此值时,您可以检查它的字符串或字符串[]是否如下所示:

if(myItem is string text)
{
  // operate on variable text
}
else // you can be sure that myItem is of type string[]  because we covered this up in the Item class
{
  var array = (string[])myItem;
  // operate on variable array
}

答案 3 :(得分:0)

另一个选择是建模&#34;助推器&#34;如public class ForceStringToArrayConverter : JsonConverter { public override bool CanConvert(Type objectType) { return (objectType == typeof(IEnumerable<string[]>)); } public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer) { var listObject = new List<string[]>(); var jObject = JToken.Load(reader); foreach (JToken token in jObject.Children()) { if (token.Type == JTokenType.Array) { var arrayObj = (JArray)token; listObject.Add(arrayObj.ToObject<string[]>()); } else if (token.Type == JTokenType.String) { listObject.Add(new string[] { token.ToString() }); } } return listObject; } public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer) { throw new NotImplementedException(); } } 然后使用自定义JsonConverter强制字符串到数组。在测试这个理论的过程中,我为你写了一个(经过最低限度测试但功能齐全的)转换器:)

    var obj = Newtonsoft.Json.JsonConvert.DeserializeObject<YourTypeHere>(testJson, new ForceStringToArrayConverter() );

然后,当您调用DeserializeObject时,将其传递给您的自定义转换器:

id