反序列化变体JSON类型

时间:2013-08-08 13:51:51

标签: c# .net json json.net

我正在使用Newtonsoft JSON Converter来反序列化一些JSON文本,但是我有一个小问题,有时我会从Web服务返回给我一个对象数组,有时它只是一个对象,让我举个例子来说明我的意思:

{
   "T":{
      "S":"054",
      "T":"8",
      "D":"548"
   }
}

一个是数组而另一个只是一个对象。

{
   "T":[
      {
         "S":"054",
         "T":"8",
         "D":"548"
      },
      {
         "S":"054",
         "T":"8",
         "D":"548"
      },
      {
         "S":"054",
         "T":"8",
         "D":"548"
      }
   ]
}

当我尝试使用Newtonsoft反序列化时,我得到一个错误,因为它期望一个数组,有时只接收一个对象,有没有办法解决这个问题?

2 个答案:

答案 0 :(得分:2)

你可以检查你的第一个属性的类型:

JObject obj = JObject.Parse(json);
if (obj["T"] is JArray)
{
    // hit on second case
}
else
{
    // hit on first case
}

之后,您可以在List<T>T上反序列化您的对象。

希望它有所帮助!

编辑:使用你的pastebin类,我重建它们并在OnDeserialized上添加一个Callback:

class JSONResponse
{
    public Line ROOT;
}

class Line
{
    [JsonProperty("Time")]
    public Timestamp Time { get; set; }
    [JsonProperty("S")]
    public List<Station> S { get; set; }
}

class Timestamp
{
    [JsonProperty("@TimeStamp")]
    public string @TimeStamp { get; set; }
}

class Station
{
    [JsonProperty("@Code")]
    public string @Code { get; set; }
    [JsonProperty("@N")]
    public string @N { get; set; }
    [JsonProperty("P")]
    public List<Platform> P { get; set; }
}

class Platform
{
    [JsonProperty("@N")]
    public string @N { get; set; }
    [JsonProperty("@Code")]
    public string @Code { get; set; }

    [JsonProperty("T")]
    public JToken T { get; set; }

    [OnDeserialized]
    internal void OnDeserializedMethod(StreamingContext context)
    {
        if (this.T != null)
        {
            if (this.T is JArray)
            {
                this.Trains = JsonConvert.DeserializeObject<List<Train>>(this.T.ToString());
            }
            else
            {
                Train t = JsonConvert.DeserializeObject<Train>(this.T.ToString());
                this.Trains = new List<Train>() { t };
            }
        }
    }
    public List<Train> Trains;
}

class Train
{
    [JsonProperty("@S")]
    public string @S { get; set; }
    [JsonProperty("@T")]
    public string @T { get; set; }
    [JsonProperty("@D")]
    public string @D { get; set; }
    [JsonProperty("@C")]
    public string @C { get; set; }
    [JsonProperty("@L")]
    public string @L { get; set; }
    [JsonProperty("@DE")]
    public string @DE { get; set; }
}

您将在Platform.Trains酒店获得您的火车

答案 1 :(得分:0)

如果您只希望有一个对象类型要反序列化,则在尝试反序列化之前,一个选项是 JSON转换为数组(如果它只是一个元素)。 e.g。

// If only a single element, the JSON will not contain an opening bracket.
if (!str.Contains('['))
{
    var index = str.IndexOf("{",1);  // Ignore first brace.
    var lastIndex = str.LastIndexOf('}'); // Find last brace.
    str = str.Substring(0,index-1) + "[" + 
          str.Substring(index, str.Length - index); // Insert bracket.
    str = str.Substring(0, lastIndex) + "]}"; // Insert bracket.
}

您当然可以将上述内容优化为单个语句 - 但这只是让您了解如何在反序列化之前操作字符串。

这也假设您的JSON中没有子数组。否则,你会得到误报。