使用没有标签的复杂数组成员反序列化JSON

时间:2016-05-10 12:34:17

标签: c# json json-deserialization

我得到以下JSON:

{
    "NumberResults": 3,
    "Results": [
        ["1", "Name1", ""],
        ["2", "Name2", ""],
        ["17", "Name3", ""]
    ]
}

应将其反序列化为以下对象Response

    public class Response
    {
        public int NumberResults { get; set; }
        public List<Result> Results { get; set; } 
    }

    public class Result
    {
        public int Id { get; set; }
        public string Name { get; set; }
        public string Description { get; set; }
    }

我可以使用哪种API来执行此操作?我想我必须依赖Result类中的属性顺序,因为我没有结果的标签。

3 个答案:

答案 0 :(得分:1)

您可以使用此工具将json转换为c#class ..

您可以将RootObject重命名为您喜欢的名称。

http://json2csharp.com/

public class RootObject
{
    public int NumberResults { get; set; }
    public List<List<string>> Results { get; set; }
}

如果你想要它的格式,那么我建议你创建对象(Response)然后将其转换为json以查看json的样子。

<强>更新

得到你想要的json必须看起来像什么

{
    "NumberResults": 3,
    "Results": [ 
           {"id":"1", "Name": "Name1", "Description ":  ""},
           {"id":"2", "Name": "Name2", "Description ":  ""},
           {"id":"17", "Name": "Name3", "Description ":  ""}
      ]
}

如果您无法修改json,那么您将无法将其转换为您拥有的类型...

你可以把它投射到我先给的东西(RootOject)。然后在代码中,编写一些函数来转换它你想要的方式。

答案 1 :(得分:1)

如果使用Json.Net反序列化JSON,则可以使用自定义JsonConverter类处理此情况。转换器会将内部数组转换为对象。

class ResultConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(Result));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JArray array = JArray.Load(reader);
        return new Result
        {
            Id = (int)array[0],
            Name = (string)array[1],
            Description = (string)array[2]
        };
    }

    public override bool CanWrite
    {
        get { return false; }
    }

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

使用此转换器,您可以将JSON反序列化到您的类中,如下所示:

Response response = JsonConvert.DeserializeObject<Response>(json, new ResultConverter());

小提琴:https://dotnetfiddle.net/csyVC4

答案 2 :(得分:1)

根据Brian的回答,我构建了以下更通用的一个,它将适用于其他类,应该从类似的JSON反序列化。

public class GenericSearchResponseConverter : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return true;
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        var instance = Activator.CreateInstance(objectType);

        while (reader.Read())
        {
            if (reader.TokenType == JsonToken.PropertyName)
            {
                var property = objectType.GetProperty(reader.Value.ToString());
                if (property == null)
                {
                    continue;
                }

                reader.Read();

                switch (reader.TokenType)
                {
                        case JsonToken.StartArray:
                        var array = JArray.Load(reader);
                        var listInstance = (IList) Activator.CreateInstance(property.PropertyType);
                        var listObjectType = property.PropertyType.GetGenericArguments().First();
                        foreach (var child in array)
                        {
                            var listObjectInstance = Activator.CreateInstance(listObjectType);
                            var propertyIndex = 0;
                            foreach (var subProperty in listObjectType.GetProperties(BindingFlags.Public | BindingFlags.Instance))
                            {
                                var childValue = child[propertyIndex].ToObject(subProperty.PropertyType);
                                subProperty.SetValue(listObjectInstance, childValue, null);
                                propertyIndex++;
                            }
                            listInstance.Add(listObjectInstance);
                        }

                        property.SetValue(instance, listInstance);
                        break;

                    default:
                        var value = reader.Value;
                        var typedValue = Convert.ChangeType(value, property.PropertyType);
                        property.SetValue(instance, typedValue, null);
                        break;
                }
            }
        }

        return instance;
    }

    public override bool CanWrite => false;

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