2012-12-04 26 views
17

私は 'd'ルート要素の中にラップされたJSON結果を返すWCFサービスを消費しています。 JSON応答は次のようになります。JSONを逆シリアル化する - ルート要素を無視する方法は?

{"d":[ 
    { 
    "__type":"DiskSpaceInfo:#Diagnostics.Common", 
    "AvailableSpace":38076567552, 
    "Drive":"C:\\", 
    "TotalSpace":134789197824 
    }, 
    { 
    "__type":"DiskSpaceInfo:#Diagnostics.Common", 
    "AvailableSpace":166942183424, 
    "Drive":"D:\\", 
    "TotalSpace":185149157376 
    } 
]} 

私は動的型付けを使用したくない、私はデシリアライズするときに使用する私のクラスのDiagnostics.Common.DiskSpaceInfoを持っています。

私はJson.NET(Netwonsoft JSON)を使用しています。

質問は、ルート要素(その 'd'要素)を無視し、内部にあるものを解析するように指示する方法です。

DiskSpaceInfo[] result = JsonConvert.DeserializeAnonymousType(json, new 
    { 
     d = new DiskSpaceInfo[0] 
    }).d; 

これは実際に動作しますが、私はそれを非常に好きではない:

私がこれまで持って最善の解決策は、匿名型を使用することです。別の方法がありますか?私が希望するようなものです:

そのような
DiskSpaceInfo[] result = JsonConvert.Deserialize(json, skipRoot: true); 

か何か...

+0

+1。 –

+0

中間の 'JToken'を解析せずにこれを行う方法を尋ねる関連質問:[JSON.NETは特定のプロパティを非直列化する](https://stackoverflow.com/questions/19438472/json-net-deserialize-a-specific-プロパティ)。 – dbc

答えて

16

この場合、ルートノードである "d"のように何を検索すればよいか知っていれば、次のことができます。

JObject jo = JObject.Parse(json); 
DiskSpaceInfo[] diskSpaceArray = jo.SelectToken("d", false).ToObject<DiskSpaceInfo[]>(); 

あなたは単にあなたがちょうどあなたがConsole.Write(test2);

 JObject o = JObject.Parse(json); 
     if (o != null) 
     { 
      var test = o.First; 
      if (test != null) 
      { 
       var test2 = test.First; 
       if (test2 != null) 
       { 
        DiskSpaceInfo[] diskSpaceArray = test2.ToObject<DiskSpaceInfo[]>(); 
       } 
      } 
     } 
+0

ありがとう!ニースのソリューション、私はそれらを試してみて、彼らは動作します。誰かが別のアプローチを提供している場合は、トピックを開いたままにしておきます。 しかし、特に解決策がないと、私の元の匿名型のアプローチを含めて、他のものよりももっと好きになるという強い感情が私に与えられます。おそらく、3つの方法のいずれかでパフォーマンス上の利点があるかどうかを確認するためにベンチマークを行うことができます。 –

1

Newtonsoftことで、私はあなたがJSon.netを使用すると仮定し、ここに私の解決策がある、私は可能なJSONにLINQのを使用このフレームワークでは:あなたが受け取ったJSONの最初のノードであるDの後、最初のノードを、見つける必要があるため

using System; 
using Newtonsoft.Json.Linq; 

namespace JSonTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      string json = @"{""d"":[ 
    { 
    ""__type"":""DiskSpaceInfo:#Diagnostics.Common"", 
    ""AvailableSpace"":38076567552, 
    ""Drive"":""C:\\"", 
    ""TotalSpace"":134789197824 
    }, 
    { 
    ""__type"":""DiskSpaceInfo:#Diagnostics.Common"", 
    ""AvailableSpace"":166942183424, 
    ""Drive"":""D:\\"", 
    ""TotalSpace"":185149157376 
    } 
]}"; 
     JObject o = JObject.Parse(json); 

     if (o != null) 
     { 
      var test = o.First; 

      if (test != null) 
      { 
       var test2 = test.First; 
       if (test2 != null) 
       { 
        Console.Write(test2); 
       } 
      } 
     } 

     Console.Read(); 

    } 
} 
} 

私は、プロパティまずを使用していました。

メインを再現する関数を作成するだけで、オブジェクトがnullにならないかどうかチェックすることを忘れないでください。NullReferenceException

+0

ありがとうGiu Json.NETの命名に対して、私は元の質問でそれを編集しました。 あなたの解決策に関して、どのようにして正しいタイプのDiskSpaceInfoにtest2をキャストしますか? test2はまだJToken型です。 –

1
の代わりに test2.ToObject<DiskSpaceInfo[]>();を使用することができることを 「@Giuド」ソリューションを使用することができ、その後知らないルートクラスを無視する場合

これまでの回答から引き続き、あなた自身の静的ユーティリティクラスの使用を提案したいと思います。これは再利用可能で、探している構文を取得することができます。

public static class JsonUtil 
{ 
    public static T Deserialize<T>(string json, bool ignoreRoot) where T : class 
    { 
     return ignoreRoot 
      ? JObject.Parse(json)?.Properties()?.First()?.Value?.ToObject<T>() 
      : JObject.Parse(json)?.ToObject<T>(); 
    } 
} 

あなたはこのようにそれを呼び出します:私はあなたの匿名型のソリューションを好きなので

var resultA = JsonUtil.Deserialize<DiskSpaceInfo[]>(json, ignoreRoot: true); 

または

var resultB = JsonUtil.Deserialize<DiskSpaceInfoRoot>(json, ignoreRoot: false); 
関連する問題