2

こんばんは。

私は現在、製品WinFlareのクロスプラットフォーム互換バージョンを開発しています。私が直面している問題は、SuperObjectがまだFiremonkeyとクロスプラットフォーム互換ではないということです。どうしても元のバージョンで使っていたのですが、今はWindowsだけではなく、クロスプラットフォーム版を作りたいので面倒です。

DBXJSON何時間にもわたる調査の結果、私が見つけた唯一のクロスプラットフォームソリューションですが、それは試して対処するのにイライラすることを証明しています。私が見つけたほとんどすべての例は、私の状況に当てはまらないか、複雑すぎて有用なものを光らせることができません。たくさんの議論がありますが、私はSuperObjectでのこのような単純なタスクを理解するのに苦労しています。私は今夜​​の大部分を、構築に役立つものを見つけるために費やしましたが、私が試したすべてのことで、私は正方に戻りました。

理想的には、SuperObjectを修正したいのですが、OS Xとクロスプラットフォーム互換にする(そしてモバイルスタジオに対応できるようにする)ための知識が不足しています。それについての提案を歓迎しますが、誰もそのような巨大なタスクを実行する時間がないことを想像しているので、DBXJSONが私の唯一の選択肢のようです。

私が扱っているJSONレイアウトはまだ同じです。

{
  response: {
    ips: [
       {
         ip: "xxx.xxx.xxx.xxx",
         classification: "threat",
         hits: xx,
         latitude: xx,
         longitude: xx,
         zone_name: "domain-example1"
         },
        {
         ip: "yyy.yyy.yyy.yyy",
         classification: "robot",
         hits: yy,
         latitude: xx,
         longitude: xx,
         zone_name: "domain-example2"
         }
       ]
   }
  result : "success",
  msg: null
}

ips配列には何百もの結果が含まれる可能性があります。配列内のすべての項目を解析して、すべてのlatitude値を抽出するとします。また、少しの間、それらを配列に出力するつもりであると仮定しましょう。これが私が使用したい種類のコードテンプレートです。

procedure ParseJsonArray_Latitude(SInput : String);
var
  i : Integer;
  JsonArray : TJsonArray;
Begin
  // SInput is the retrieved JSON in string format
  { Extract Objects from array }

  for i := 0 to JsonArray.Size-1 do
  begin
    Array_Latitude[i] := JsonArray.Item[i].ToString;
  end;
end;

基本的に、それが言うところ{ Extract Objects from array }の、私は私の問題を解決するであろうDBXJSONを使用する最も基本的な解決策が欲しいです。明らかに、上記のテンプレートに関連して示した呼び出しは正しくない可能性があります。これらは単に補助として機能するためのものです。JsonArray

4

3 に答える 3

3

まず、文字列を解析してオブジェクトを取得します。

var
  obj: TJsonObject;

obj := TJsonObject.ParseJsonValue(SInput) as TJsonObject;

これにより、response、result、およびmsgの3つの属性を持つオブジェクトが得られます。はのParseJsonValueメソッドでTJsonObjectあり、特定の文字列入力はたまたまオブジェクト値を表しますが、TJsonValue指定されたJSONテキストに応じて、任意の子孫のインスタンスを返すことができます。それがどこから始めるべきかを知ることは、おそらくDbxJsonでの作業の最も難しい部分です。

次に、応答属性値を取得します。

response := obj.Get('response').JsonValue as TJsonObject;

その結果は別のオブジェクトになります。今回は1つの属性ipsがあります。その属性を取得します。この属性には、値の配列が必要です。

ips := response.Get('ips').JsonValue as TJsonArray;

最後に、配列から値を取得できます。値が数値であることを期待しているように見えるので、そのようにキャストできます。

for i := 0 to Pred(ips.Size) do
  Array_Latitude[i] := (ips.Get(i) as TJsonObject).Get('latitude').JsonValue as TJsonNumber;

obj終了したら、ここで言及されている他の変数ではなく、解放することを忘れないでください。

于 2013-02-04T05:20:45.397 に答える
2

完成のために、質問にはDBXJSONクロスプラットフォームに代わるものはないと述べられていたので、最初の質問以降に登場した2つのオープンソースの選択肢を指摘したいと思います。

  • XSuperObjectのAPIはSuperObjectに非常に近いですが、クロスプラットフォームです。
  • SynCrossPlatformJSON.pasユニットは、との両方よりも軽量ではるかに高速です。DBXJSONXSuperObject

SynCrossPlatformJSONは、スキーマのないオブジェクトまたは配列を作成し、プロパティにアクセスするための遅延バインディングvariantを含むカスタムタイプを介して、JSONとしてそれらをシリアル化および非シリアル化することができます。

あなたの問題については、次のように書くことができます。

var doc: variant;
    ips: PJSONVariantData; // direct access to the array
    i: integer;
...
  doc := JSONVariant(SInput);   // parse JSON Input and fill doc custom variant type
  if doc.response.result='Success' then       // easy late-binding access
  begin
    ips := JSONVariantData(doc.response.ips); // late-binding access into array
    SetLength(Arr_Lat,ips.Count);
    for i := 0 to ips.Count-1 do begin
      Arr_lat[i] := ips.Values[i].latitude;
      Memo1.Lines.add(ips.Values[i].latitude); 
     end;
  end;  
... // (nothing to free, since we are using variants for storage)

遅延バインディングとバリアントストレージにより、かなり読みやすいコードが可能になります。

于 2014-05-19T20:06:47.893 に答える
0

ロブ・ケネディの支援のおかげで、私は問題を解決するソリューションを構築することができました。

var
  obj, response, arrayobj : TJSONObject;
  ips : TJSONArray;
  JResult : TJsonValue;
  i : Integer;
  Arr_Lat : Array of string;
begin
try
  Memo1.Lines.Clear;
  obj := TJsonObject.ParseJSONValue(SInput) as TJSONObject;
  response := Obj.Get('response').JsonValue as TJSONObject;
  ips := response.Get('ips').JsonValue as TJSONArray;
  SetLength(Arr_Lat, ips.Size-1);
  for i := 0 to ips.Size-1 do
    begin
      arrayobj := ips.Get(i) as TJSONObject;
      JResult := arrayobj.Get('latitude').JsonValue;
      Arr_lat[i] := JResult.Value;
      Memo1.Lines.Add(JResult.Value);
    end;
finally
  obj.Free;
end;

これにより、結果が両方の配列(Arr_Lat)に追加され、メモ(Memo1)に出力されます。

于 2013-02-04T19:13:15.313 に答える