【问题标题】:Cannot Deserialize JSON Object [duplicate]无法反序列化 JSON 对象 [重复]
【发布时间】:2018-08-10 16:31:52
【问题描述】:

我的问题是我收到了这个错误

"无法将当前 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 ??

提前致谢……

【问题讨论】:

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


    【解决方案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; }
    }
    

    【讨论】:

    • 你是对的,谢谢,但我仍然收到错误...真正的问题是当序列化第一个旅程不是 List 时。所以这就是为什么给我这个“无法将当前 JSON 对象(例如 {\"name\":\"value\"})反序列化为类型 'System.Collections.Generic.List`1[api.Controllers.Journey]'因为该类型需要一个 JSON 数组(例如 [1,2,3])才能正确反序列化”
    • @AlyDanielZuniagaRamos 这里的问题是,JSON 不允许在最后一个元素之后使用 逗号。因此"Id": "5b6db9c6bfac4", } 必须去掉} 之前的最后一个逗号 才能生效。这必须在 , } 的所有实例中完成。
    • 不,这是我在这里输入错误...但没有解决我的问题...谢谢
    • @AlyDanielZuniagaRamos 好的,那么还有另一个问题。请参阅stackoverflow.com/questions/44100383/… 您的 JSON 在其结构中不是静态的。请查看提供的链接,并随时投票并将我的答案标记为正确。
    【解决方案2】:

    我认为您的问题是您的 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; }
    

    这应该处理旅程以数组或对象的形式出现的情况。

    【讨论】:

      【解决方案3】:

      所以这里有一些问题。 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")] 属性来告诉序列化程序名称.

      【讨论】:

      • 你是对的,谢谢,但我仍然收到错误...真正的问题是当序列化第一个旅程不是 List 时。所以这就是为什么给我这个“无法将当前 JSON 对象(例如 {\"name\":\"value\"})反序列化为类型 'System.Collections.Generic.List`1[api.Controllers.Journey]'因为该类型需要一个 JSON 数组(例如 [1,2,3])才能正确反序列化”
      猜你喜欢
      • 1970-01-01
      • 2019-06-20
      • 1970-01-01
      • 2016-12-30
      • 2014-08-04
      • 1970-01-01
      • 1970-01-01
      • 2017-12-30
      相关资源
      最近更新 更多