2012-03-23 13 views
3

現在開発中のサーバー側のC++プログラムによって生成されたJSONストリームがあります。私は結果のJSONのサンプルを与えられました。私はGSONやJacksonのようなツールで提供される通常のクラスマッピングを使用することができないため、jsonを手で解析する必要があることを心配しています。JSONからJavaオブジェクトへのjsonストリームのモデリングのベストプラクティス

提供している次の(やや)人為的な例を見てください。私が関心を持っているセクションは、さまざまなパラメータを持つメタデータ "serie"配列です。たとえば、キー(キー)は配列要素の1つにのみ存在します。これは、この配列を特定のクラスのコレクションにマップしようとしても問題にはなりませんか?

最後に、私は "ポイント"オブジェクトが似ていないことを心配しています。 JSON(旧式のJavaスイング開発者)の理解は非常に限られていますが、「ポイント」キーの値のペアが異なる可能性があることは問題です。

このjsonストリームの全体的なアイデアは、進行状況を示し、基盤となるハードウェアからより多くのものを求める仕組みを提供するテーブルを記述することです。また、なぜこのようなデータストリームをシンクライアント(htmlブラウザ)と共有しているのか不思議です。

私はこれが簡単にJavaオブジェクトに変換されないことを修正しましたか?

{ 
    "abort": "abort;session=sessionname", 
    "data": { 
    "metadata": [ 
     { 
     "protocol": "HTTP", 
     "serie": [ 
      { 
      "name": "k1", 
      "description": "xDR ID", 
      "tooltip": "ASDR Unique Identifier - UiD", 
      "type": "int64", 
      "key": "1" 
      }, 
      { 
      "name": "c1", 
      "description": "Answered", 
      "tooltip": "Request with Response", 
      "type": "bool" 
      }, 
      { 
      "name": "c2", 
      "description": "Active", 
      "tooltip": "Session status: active or closed/down", 
      "type": "bool" 
      } 
     ] 
     }, 
     { 
     "protocol": "DNS", 
     "serie": [ 
      { 
      "name": "k1", 
      "description": "xDR ID", 
      "tooltip": "ASDR Unique Identifier - UiD", 
      "type": "int64", 
      "key": "1" 
      }, 
      { 
      "name": "k2", 
      "description": "Transaction ID", 
      "type": "int64", 
      "key": "1", 
      "display": "number" 
      }, 
      { 
      "name": "k3", 
      "description": "Client", 
      "tooltip": "Source IP Address", 
      "type": "string", 
      "key": "1", 
      "display": "ip" 
      } 
     ] 
     } 
    ], 
    "summary": [ 
     { 
     "timestamp": "1331192727", 
     "protocol": "HTTP", 
     "activity": "www.google.com", 
     "results": "OK", 
     "point": { 
      "k1": "1", 
      "c1": "true", 
      "c2": "true" 
     } 
     }, 
     { 
     "timestamp": "1331192727", 
     "protocol": "DNS", 
     "activity": "www.google.com", 
     "results": "OK", 
     "point": { 
      "k1": "1", 
      "k2": "1.1.4.229" 
     } 
     } 
    ] 
    }, 
    "progress": { 
    "perc": "100" 
    }, 
    "more": "13,39,1331192727,1331192760,27236,1.1.4.229,limit=1000,session=sessionname" 
} 

ご提供いただきありがとうございます。

GSONで-Dクロッツ

答えて

4

は、あなたにデシリアライズされたクラスは、JSONに表示されるすべての名前のフィールドを持っていると仮定して、JSONには見られない分野だけではnullを残しされます。

https://sites.google.com/site/gson/gson-user-guide#TOC-Finer-Points-with-Objects

任意のフィールド名はアーカンソー場合「のデシリアライズ、nullにオブジェクトに対応するフィールドを設定することでJSONの結果で不足しているエントリは、一方で」

物事はもう少し複雑になりますeはJSONで許可されます。たとえば、Pointがc1、c2、... cnを許可する場合などです。しかし、カスタムデシリアライザでこれを処理できます。

https://sites.google.com/site/gson/gson-user-guide#TOC-Writing-a-Deserializer

編集:

は、ここでは、ポイントのカスタムデシリアライザを書くかもしれない方法は次のとおりです。

private class DateTimeDeserializer implements JsonDeserializer<Point> { 
    public Point deserialize(JsonElement json, Type typeOfT, 
      JsonDeserializationContext context) throws JsonParseException { 
     List<PointPart> parts = Lists.newArrayList(); 

     for(Map.Entry<String,JsonElement> entry : 
       json.getAsJsonObject().entrySet()) { 
      char type = ; 
      int index = Integer.parseInt(entry.getKey().substring(1)) - 1; 

      while(parts.size() <= index) { 
       parts.add(new PointPart()); 
      } 

      PointPart part = parts.get(index); 
      switch(entry.getKey().charAt(0)) { 
      case 'c': 
       part.c = entry.getValue().getAsBoolean(); 
       break; 
      case 'k': 
       part.k = entry.getValue().getAsInt(); 
       break; 
      } 
     } 

     return new Point(parts); 
    } 
} 

class Point { 
    List<PointPart> parts; 

    Point(List<PointPart> parts) { 
     this.parts = parts; 
    } 
} 

class PointPart { 
    boolean c; 
    int k; 
} 
+0

ありがとう。フィールドがjsonではなくクラスに存在しない場合、どうなりますか? –

+0

私はそれが通常は解析例外をスローすると信じています。ターゲットクラスに表示されないフィールドを除外する 'ExclusionStrategy'を作成することで、それらのフィールドを無視させることができます。 (ただし、カスタムデシリアライザはより良いオプションです) –

+0

カスタムデシリアライザの作成を避けることを望んでいます。これは開発サイクルの早い段階でこれをキャッチしています。私はこれについてもう少し頭を傷つけるつもりです。アドバイスをいただきありがとうございます。 –

2

私はデータ内のメタデータフィールドのように見えるものともっと心配だろうストリーム。最上位の「abort」属性と「more」属性は、構文解析する必要のある構造化された文字列のように見えますか?それとは別に、各Javaオブジェクトを、外部プログラムから送信されるフィールドの可能な限り広い範囲でモデル化する必要があります。送信されたデータに1つ以上のフィールドがない場合、ほとんどのJSONライブラリはnullを逆シリアル化します。また、ほとんどのJSONライブラリでは、未知の受信フィールドを無視するように指定することもできます。

フィールドの欠落をデシリアライズするときと追加のフィールドを無視するときの間に、解析するのがよいでしょう。

+0

jsonストリームの余分なフィールドは無視されると言っていますか?私はライブラリーに依存していると思っています。 –

+0

はい、それはライブラリに依存し、より多くの点では、前記ライブラリの構成に依存します。たとえば、この動作はJacksonではデフォルトではオフになっていますが、構成設定でオンにすることができます。 – Perception

+0

私は答えとして1つ以上の投票やマークを付けることはできません。私はこれも答えとしてマークしたいと思います。助けてくれてありがとう。 –

1

これは特にJavaオブジェクトに逆シリアル化するのは難しくありません。JSONには、プリミティブ以外の情報を入力する手掛かりがありません。タイプ情報を失うことに対する懸念の大部分は、逆シリアル化したいオブジェクトを見るか、またはデシリアライズしたいオブジェクトをユーザーに提供させることによって回復できます。これはflexjsonがどのように動作するかを正確に示しています。また、各ポイントでデシリアライズする方法を柔軟に定義することができます。これはほとんどの問題に対しては妥当なデフォルトを持っていますが、JSONストリームでObjectFactoryを特定のクラスまたはパスにアタッチすることはいつでも可能です。

http://flexjson.sourceforge.net

関連する問題