2017-04-03 17 views
0

Visual Studioの自動生成REST Webアプリケーションプロジェクト構造を使用して、JSON入力を消費するRESTful APIを作成しています。C#でJSON配列からカスタムクラスにオブジェクトをキャストする

あまり詳細に入るがなければ、私はこれらのようなJSON構造を定義しようとしています

例1:

"operation": { 
    "type": "EXIST", 
    "args": [ 
     { 
     "ColumnName": "SomeColumnA", 
     "Row": 2 
     } 
    ] 
    } 

例2:

"operation": { 
    "type": "ADD", 
    "args": [ 
     { 
     "type": "ADD", 
     "args": [ 
      { 
      "columnName": "SomeColumnB", 
      "row": 12 
      }, 
      { 
      "columnName": "SomeColumnC", 
      "row": 18 
      } 
     ] 
     }, 
     20 
    ] 
    } 

operationのうちの1つを表し、任意の数の基本データベース操作とそれらの操作の引数私の最初の例では、操作はEXISTです。値が存在するかどうかを確認するにはデータベースセルをチェックする必要があります。この操作のargsは、セルをチェックするための列と行の情報を含むオブジェクトです(これをValueと呼びます)。私の2番目の例では、関数はADDであり、2つの値を加算して合計を返す必要があります。ここで、引数は20の定数で、ネストされたADD関数です。それ自体は2つのValuesをとります。したがって、一般にargs配列は、プリミティブ値、別のネストされたoperation、または実際の値を読み取るセルを表す値のいずれかをとることができます。ここでの最終目標は、関数、セル値、定数の組み合わせをネストして、AverageまたはSumのような複合関数を作成する一般的な構造を作成することです。私のモデルフォルダに

、私はに私のデータをキャストする次のクラスを持っている:

public class Instruction 
{ 
    public Operation[] Operations { get; set; } 
} 

public class Operation 
{ 
    public string Type { get; set; } 
    public object[] Args { get; set; } 
} 

public class Value 
{ 
    public string ColumnName { get; set; } 
    public int Row { get; set; } 
} 

OperationArgsはタイプobject[]であることに注意してください。

このJSONをPOSTしてWebアプリケーションを呼び出すと、C#はJSONを自動的にModelsフォルダに定義されたオブジェクトに解析します。我々は実施例1を使用言う:

[HttpPost] 
public IHttpActionResult Foo(Instruction instruction) 
{ 
    foreach(Operation op in instruction.Operations) { 
     switch (op.Type) { 
      case "EXIST": 
       Console.WriteLine("exist"); // works fine 

       // since we got here, expect Args[0] to be type 'Value' 
       var value = (Value) op.Args[0]; // InvalidCastException 
       // logic for EXIST 
      case "ADD": 
       // logic for ADD 
      // ... 
     } 
    } 
} 

それだけで罰金Operationをキャストだ、と私は正しく出Typeを取得します。私はまた、Argsを孤独な要素を持つobject[]としています。しかし、それをValueにキャストしようとすると、正しくキャストすることを拒否します。

私の質問はすべてこの後です:私はここにしようとしているように見えるようにするための最良の方法は何ですか?正しい軌道にいるのですか?もしそうなら、私のエラーは何ですか?私がこれを間違った方向に向けるなら、より良い練習方法は何ですか? Visual Studioのすぐ使えるWebアプリケーションフレームワークを使用しているので、JSONを脱灰する関数にアクセスできないように見えるので、カスタムデシリアライザを構築することはできません。

+0

、なぜ最初にあなたのクラスを定義して開始し、多くのクラスツーJSONプレビューツールのいずれかを使用していませんか?そうすれば、デシリアライゼーション中に問題が発生することはありません。XMLと同じですが、私は怠惰で常にクラスを最初に作成します – MickyD

+0

どのJSON配列をキャストしたいのですか?Example1はExample2とは異なります –

+0

Argを 'public Value [] Args {get; set; } '?また、C#で動的な型を調べます。あなたのOperationモデルのArgを 'public dynamic Args {get; set;}'として定義することができます。そこから、別のモデルを必要とせずに 'Args [0] .row 'を使うことができます。 – garethb

答えて

2

ダイナミックタイプの使い方を示すこのフィドルをご覧ください。あなたには、いくつかの既に公表JSONペイロードの仕様に準拠しようとしている場合を除き

Fiddle

public static void Main() 
{ 
    var json = @"{""operation"": { 
     ""type"": ""ADD"", 
     ""args"": [ 
      { 
       ""type"": ""ADD"", 
       ""args"": [ 
        { 
         ""columnName"": ""SomeColumnB"", 
         ""row"": 12 
        }, 
        { 
         ""columnName"": ""SomeColumnC"", 
         ""row"": 18 
        } 
       ] 
      } 
     ] 
    }}"; 
    dynamic data = JsonConvert.DeserializeObject(json); 

    Console.WriteLine(data.operation.type.ToString()); 
    Console.WriteLine(data.operation.args[0].args[0].columnName.ToString()); 
    Console.WriteLine((int)data.operation.args[0].args[0].row); 
} 
+0

私は正確な問題に集中しようとするために私が少しコードを抽象化したことを告白する必要があります。私は、コードがどのように見えるのかをより正確に表現して質問を編集しました。基本的に、JSONには任意の数の 'Operation'があり、それぞれが異なっています。その上に、 'ADD'のような演算の場合、可能な' Args'は 'Operation'、' Value'、またはプリミティブです。だから私は 'try {var colName = op.args [0] .columnName; } catch {} 'を使って' Value'をチェックするなどしますか?それはうまくいくだろうが、より良い答えがあるのだろうかと思う。 – Fawfulcopter

+0

argsがjson配列かjsonオブジェクトかを調べることができます。私は頭の上から文法がわからない。任意の数のargをテストできるように、チェックを行う関数を記述します。 – garethb

関連する問題