web-dev-qa-db-ja.com

JContainer、JObject、JToken、およびLinqの混乱

JContainerJObject、およびJTokenを使用するタイミングを理解できません。 「標準」から、JObjectJPropertiesで構成され、JTokenはすべてのJToken型の基本抽象クラスであることがわかりますが、JContainerがわかりません。

C#を使用していて、LinqPad Pro 5を購入しました。

ファイルにJSONデータソースがあるため、次のステートメントを使用して、ファイルのコンテンツを正常に逆シリアル化します。

string json;
using (StreamReader reader = new StreamReader(@"myjsonfile.json"))
{
    json = reader.ReadToEnd();
}

その時点で、JSON文字列オブジェクトを取得し、JObjectにデシリアライズします(これは私の間違いかもしれません。おそらく、jsonWorkJTokenまたはJContainerにする必要があります)。

JObject jsonWork = (JObject)JsonConvert.DeserializeObject(json);

JSONデータ(JSONで表される文字列)には、3つのオブジェクトがあります。トップレベルのオブジェクトは次のようになります。

{
  "Object1" : { ... },
  "Object2" : { ... },
  "Object3" : { ... }
}

各オブジェクトはあらゆる種類のトークン(配列、文字列、その他のオブジェクトなど)で構成されているため、動的JSONです。 (この質問を大量のJSONデータで埋め尽くすのではなく、楕円をプレースホルダーとして使用しました。)

ただし、LINQを使用して、"Object1""Object2"、および"Object3"を個別に処理します。だから、理想的には、私はこのようなものが欲しいです:

// these lines DO NOT work    
var jsonObject1 = jsonWork.Children()["Object1"]
var jsonObject2 = jsonWork.Children()["Object2"]
var jsonObject3 = jsonWork.Children()["Object3"]

しかし、上記の行は失敗します。

上記のvarを使用したのは、使用するオブジェクトタイプがわからないためです:JContainerJObject、またはJToken!上記のjsonObject#変数が適切に割り当てられたら、LINQを使用してそれらに含まれるJSONを照会したいと思います。非常に簡単な例を次に示します。

var query = from p in jsonObject1
   where p.Name == "Name1"
   select p

もちろん、私のLINQは最終的に、jsonObject変数でJSON配列、オブジェクト、文字列などをフィルタリングします。いったん始めたら、LinqPadを使用して、LINQを使用してJSONをフィルター処理できると思います。

私が使用した場合:

// this line WORKS 
var jsonObject1 = ((JObject)jsonWork).["Object1"];

次に、jsonObject1JObject型を取得します。これは正しいアプローチですか?

JContainerおよびJTokenオブジェクトがLINQで非常にうまく機能しているように思えるときに、JObjectをいつ/なぜ使用するかはわかりません。 JContainerの目的は何ですか?

42
Jazimov

JContainerは、子アイテムを持つJSON要素の基本クラスです。 JObjectJArrayJPropertyおよびJConstructorはすべてそれを継承します。

たとえば、次のコード:

(JObject)JsonConvert.DeserializeObject("[1, 2, 3]")

InvalidCastExceptionをスローしますが、JContainerにキャストする場合は問題ありません。

元の質問に関して、最上位にJSONオブジェクトがあることがわかっている場合は、次を使用できます。

var jsonWork = JObject.Parse(json);
var jsonObject1 = o["Object1"];
18
Eli Arbel

ほとんどの場合、JContainerについて心配する必要はありません。 LINQ-to-JSON を適切にファクタリングされたコードに整理および構造化するのに役立ちます。

JToken 階層は次のようになります。

JToken             - abstract base class     
   JContainer      - abstract base class of JTokens that can contain other JTokens
       JArray      - represents a JSON array (contains an ordered list of JTokens)
       JObject     - represents a JSON object (contains a collection of JProperties)
       JProperty   - represents a JSON property (a name/JToken pair inside a JObject)
   JValue          - represents a primitive JSON value (string, number, boolean, null)

JObjectisa JContainer 、whichisa JToken .

基本的な経験則は次のとおりです。

  • オブジェクトがあることを知っている場合(JSONでは中括弧{および}で示されます)、 JObject を使用します
  • 配列またはリスト(角括弧[および]で示されている)があることがわかっている場合は、 JArray を使用します
  • プリミティブな値があることがわかっている場合は、 JValue を使用します
  • 持っているトークンの種類がわからない場合、または上記のいずれかを一般的な方法で処理したい場合は、 JToken を使用します。次に、そのTypeプロパティを確認して、どのようなトークンであるかを判断し、適切にキャストできます。
206
Brian Rogers