在REST SOE中处理JSON

关于在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);
}


你可能感兴趣的:(REST,REST,REST,SOE)