无法反序列化JSON对象

时间:2018-08-10 16:31:52

标签: c# .net json json.net json-deserialization

我的问题是我遇到此错误

“无法反序列化当前JSON对象(例如{\“ name \”:\“ value \”})为类型'System.Collections.Generic.List`1 [api.Controllers.Journey]',因为该类型需要一个JSON数组(例如[1,2,3])以正确反序列化”“ ...当我尝试序列化我的API json响应时。

API返回如下内容:

{
"Transport": [
    {
        "$id": "6",
        "SourceID": "1",
        "Context": "1",
        "Id": "AMADEUS#1",
        "Provider": null,
        "Journey": {
            "SourceID": "R1G0S0",
            "Duration": "42000",
            "Id": "5b6db9c6bfac4"
        }

    },
    {
        "$id": "7",
        "SourceID": "1",
        "Context": "1",
        "Id": "AMADEUS#1",
        "Provider": null,
        "Journey": [
            {
                "SourceID": "R1G0S0",
                "Duration": "42000",
                "Id": "5b6db9c6bfac4"
            },
            {
                "SourceID": "R1G0S1",
                "Duration": "42000",
                "Id": "5b6db9c6bsac4"
            }
        ]

    }
]
}

Journey字段的第一个结果是一个JObject,但第二个结果是一个JArray ...

反序列化时出现错误:

Transport Transport = JsonConvert.DeserializeObject<Transport>(json_response);

我的课程属性:

public class Transport{
    public string SourceID { get; set; }
    public string Context { get; set; }
    public string Id { get; set; }
    public ProviderOD Provider { get; set; }
    public Journey[] Journey { get; set; }
    public PriceOD Price { get; set; }
}
public class Journey
{
    public string Id { get; set; }
    public string SourceID { get; set; }
    public string Duration { get; set; }
}

我该怎么做,以动态设置Journey []或Journey?

预先感谢...

3 个答案:

答案 0 :(得分:1)

您的类声明不正确,您必须使用以下内容进行解码

TransportRootObject Transport = JsonConvert.DeserializeObject<TransportRootObject>(json_response);

和此类声明

public class TransportRootObject
{
    public List<Transport> Transport { get; set; }
}
public class Transport
{
    [JsonProperty("$id")]
    public string Id { get; set; }
    public string SourceID { get; set; }
    public string Context { get; set; }
    public string Id { get; set; }
    public ProviderOD Provider { get; set; }
    public List<Journey> Journey { get; set; }
}
public class Journey
{
    public string Id { get; set; }
    public string SourceID { get; set; }
    public string Duration { get; set; }
}

答案 1 :(得分:0)

所以这里有一些问题。 JSON中的顶级Transport对象实际上是一系列传输对象。因此,您需要一个额外的课程:

public class DocumentRoot
{
    public List<Transport> Transport { get; set; }
}

然后您要:

var DocumentRoot = JsonConvert.DeserializeObject<DocumentRoot>(json_response);
//DocumentRoot.Transport is now a List<Transport> of your transport elements from the document.

在您的JSON中,成员名称之一是“ $ id”,该名称在C#中当然是无效的,因此,要使其表现这种行为,您需要在ID属性上添加一个[JsonProperty(PropertyName = "$id")]属性以告知序列化程序名字。

答案 2 :(得分:0)

我认为您的问题是您的API返回了格式错误的JSON。如果Journey是一个数组,则应始终以数组/列表的形式返回……如果只有1,则不是对象,如果有多个,则不是数组。

如果这是您无法修复的第三方API,那么您的下一个选择是使用自定义转换器来处理这种奇怪格式的json。

我不记得我在哪里找到了原始的源代码/解决方案,但我将逐步指导您。

首先,您需要创建一个像这样的新类。

public class SingleOrArrayConverter<T> : JsonConverter
{
    public override bool CanConvert(Type objectType)
    {
        return (objectType == typeof(List<T>));
    }

    public override object ReadJson(JsonReader reader, Type objectType, object existingValue, JsonSerializer serializer)
    {
        JToken token = JToken.Load(reader);
        if (token.Type == JTokenType.Array)
        {
            return token.ToObject<List<T>>();
        }
        return new List<T> { token.ToObject<T>() };
    }

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

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

这是您的自定义转换器,用于处理“有时为数组,有时为对象”的情况。差不多只是进行测试以确定它是数组还是对象并进行相应处理。

然后,在运输类中,将属性像这样添加到Journey数组属性上方。

[JsonConverter(typeof(SingleOrArrayConverter<Journey>))]
public List<Journey> Journey { get; set; }

然后,这应该处理旅程作为数组或对象通过的情况。