关于在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"); ... }
下面都是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响应结果
一旦你完成了业务逻辑代码并生成了输出结果,那么你必须将输出结果序列化成JSON或者用另一种方式将其流化并将其返回给客户端。本小节将介绍如何将你的输出结果序列化成JSON。
为了生成JSON响应结果,你需要首先创建一个SOESupport.JsonObject的实例,然后通过JsonObject中的一些辅助方法向JsonObject中添加内容。你可以在REST SOE的模板中看到该代码片段,如下所示:
[C#]
JsonObject result = new JsonObject(); result.AddString("parm1", parm1Value);
{ "parm1" : "myFirstParameter" }
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;
"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 . . . ] ] } ]
[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); }