1

Newtonsoft JSON Converter を使用して JSON テキストをデシリアライズしていますが、ちょっとした問題があります。これは、Web サービスから返されたオブジェクトの配列を取得する場合と、単一のオブジェクトである場合があることです。あなたは私が言いたいことの例です:

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

1 つは配列ですが、もう 1 つは単一のオブジェクトです。

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

Newtonsoft を使用してこれをデシリアライズしようとすると、エラーが発生します。これは、配列を予期していて、単一のオブジェクトしか受信しない場合があるためです。これを回避する方法はありますか?

4

2 に答える 2

2

次のように、最初のプロパティのタイプを確認できます。

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

List<T>その後、またはでオブジェクトを逆シリアル化できますT

それが助けになることを願っています!

EDIT:あなたのペーストビンクラスで、私はそれらを再構築し、 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 プロパティで列車を取得します

于 2013-08-08T14:12:54.013 に答える
0

逆シリアル化するオブジェクト タイプを 1 つだけにしたい場合は、逆シリアル化を試みる前に、JSON を配列に変換するのが 1 つのオプションです (要素が 1 つだけの場合)。例えば

// 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 内にサブ配列がないことも前提としています。そうしないと、誤検知が発生します。

于 2013-08-08T14:20:50.213 に答える