在REST SOE中處理JSON

孫群發表於2013-01-27

關於在REST SOE中處理JSON

通常當客戶端和伺服器以REST方式進行通訊的時候,它們是以JSON為媒介進行。JSON是一種兩個應用程式之間進行傳遞的資料的高度結構化的格式,在Web服務中非常有用。

問題是ArcObjects不識別JSON資料格式。因此你的處理函式必須反序列化JSON格式的輸入,這意味著處理函式需要從中抽取出你的業務邏輯所需要的值。當完成了業務邏輯程式碼之後,你需要將輸出結果轉換成JSON格式,即對返回結果進行序列化。這一小節將介紹如何進行此項操作。

SOESupport庫包含了用於反序列化以及序列化JSON的輔助函式。當客戶端發出了REST請求的時候,JSON輸入資料在處理函式中變成了一個SOESupport.JsonObject類的物件。你也可以在處理函式中以JsonObject例項的形式傳送結果。

反序列化JSON輸入

操作中的JSON輸入對應著處理函式中的SOESupport.JsonObject例項。為了能夠進行反序列化JSON輸入,你可以使用JsonObject中的一系列TryGet*方法。

你會在REST SOE的模板的操作的處理函式中看到同樣的程式碼片段,如下所示:

[C#]

private byte[] SampleOperHandler(NameValueCollection boundVariables, JsonObject
    operationInput, string outputFormat, string requestProperties, out string
    responseProperties)
{
    responseProperties = null;
    string parm1Value;
    bool found = operationInput.TryGetString("parm1", out parm1Value);
    if (!found || string.IsNullOrEmpty(parm1Value))
        throw new ArgumentNullException("parm1");
    ...
}

在上面的程式碼示例中,想通過JsonObject 方法的TryGetString方法獲取一個字串引數("parm1")的值。需要注意的是需要書寫錯誤處理的程式碼以防該引數沒有找到。

下面都是SOESupport.JsonObject中的TryGet方法:

TryGetArray
TryGetAsBoolean
TryGetAsDate
TryGetAsDouble
TryGetAsLong
TryGetJsonObject (獲取JSON中的JSON屬性)
TryGetObject
TryGetString

TryGet方法允許你從JSON引數中提取相應的值並將其賦值給程式碼中的變數。然後你就可以用這些變數建立你所需要的ArcObjects型別。

如果你想反序列化geometries,你可以使用SOESupport.Conversion.ToGeometry()方法,該方法以JSON物件或字串作為輸入引數,返回IGeometry型別。

如下程式碼將一個JsonObject型別的“location”引數轉換為了IPoint型別:

[C#]

JsonObject jsonPoint;
if (!operationInput.TryGetJsonObject("location", out jsonPoint))
    throw new ArgumentNullException("location");
IPoint location = Conversion.ToGeometry(jsonPoint,
    esriGeometryType.esriGeometryPoint)as IPoint;

需要再強調一遍,當你使用這些方法的時候,必須編寫錯誤檢查的程式碼。如果你的JSON物件包含了x值和y值,比如{x:-123,y:47},你會得到一個IPoint型別的變數。如果JSON物件沒有全部包含構造該點所需的全部引數,那麼就會丟擲異常。

序列化JSON響應結果

一旦你完成了業務邏輯程式碼並生成了輸出結果,那麼你必須將輸出結果序列化成JSON或者用另一種方式將其流化並將其返回給客戶端。本小節將介紹如何將你的輸出結果序列化成JSON。

為了生成JSON響應結果,你需要首先建立一個SOESupport.JsonObject的例項,然後通過JsonObject中的一些輔助方法向JsonObject中新增內容。你可以在REST SOE的模板中看到該程式碼片段,如下所示:

[C#]

JsonObject result = new JsonObject();
result.AddString("parm1", parm1Value);

上述程式碼示例建立了一個空的JsonObject,並向其中新增了一個值為變數parm1Value的parm1屬性。如果parm1Value的值為“myFirstParameter”,那麼JSON結果如下所示:

{
  "parm1" : "myFirstParameter"
}

下面這些是在你序列化JSON響應的時候可以使用的Add方法。(不用驚訝,這些方式是和你在反序列化輸入的時候所使用的TryGet方法是對應的。)

AddArray
AddBoolean
AddDate
AddDouble
AddJsonObject (向JSON中新增JSON屬性)
AddLong
AddObject
AddString

對某些geometries進行序列化有時候是非常棘手的,因為其內部又包含objects 和arrays。因此, SOESupport.Conversion.ToJsonObject() 方法對你序列化geometries是非常有幫助的。你可以傳遞任何實現了IGeometry介面的物件,並將其序列化成JSON。

在下面的示例程式碼中,resultsGeometry是一個要序列化成JSON的geometry物件。如果你有多個geometries需要進行序列化,那麼此處可以進行迴圈操作。該程式碼示例使用了.Net中的list來儲存所有序列化的geometries。然後通過JsonObject.AddArray()方法將該list新增到一個最終的JSON物件中。

[C#]

// Create an empty .NET list of JsonObjects.
List < JsonObject > jsonGeometries = new List < JsonObject > ();
// Optionally, you could start a loop here.
JsonObject jsonResultsGeometry = Conversion.ToJsonObject(resultsGeometry);
jsonGeometries.Add(jsonResultsGeometry);
// You would end the optional loop here.
// Add the list of json objects to a final json object as an array.
JsonObject resultJsonObject = new JsonObject();
resultJsonObject.AddArray("geometries", jsonGeometries.ToArray());
// Get byte array of json and return results.
byte[] result = Encoding.UTF8.GetBytes(resultJsonObject.ToJson());
return result;

上述示例程式碼中的JSON能夠很容易的被客戶端進行解析。比如下面的程式碼就是一個JSON,其中的每個polygon都由rings表示:

"geometries" : [
    {
      "rings" : [
        [
          [
            537677.56250619888,
            4900994.4999926779
          ],
          [
            537952.21783445403,
            4900502.2883762196
          ],
          [
            537942.24243737175,
            4900503.3471435569
          ],
          etc. . .
        ]
      ]
    },
    {
      "rings" : [
        [
          [
            537952.21783445403,
            4900502.2883762196
          ],
          [
            537677.56250619888,
            4900994.4999926779
          ],
          [
            537826.87501833774,
            4901122.9999607969
          ],
          etc . . .
        ]
      ]
    }
  ]

在ArcGIS JavaScript API中,你可以迴圈遍歷這些geometries並建立Polygon物件。示例程式碼如下:

[JavaScript]

var geometries = response.geometries;
// Loop through all graphics in the JSON.
for (var i = 0, il = geometries.length; i < il; i++){
    // Make a new polygon.
    var polygon = new esri.geometry.Polygon(sr);
    // Loop through all rings in the JSON and add to polygon.
    for (var j = 0, jl = geometries[i].rings.length; j < jl; j++){
        polygon.addRing(geometries[i].rings[j]);
    }
    // Create a graphic from the polygon and add it to the map.
    var currentGraphic = new esri.Graphic(polygon, symbol, attr, infoTemplate);
    map.graphics.add(currentGraphic);
}


相關文章