Stiamo parlando delle classi JSONSerializerGdb e JSONDeserializerGdb che permettono di serializzare e deserializzare oggetti di alto livello in classi JSON e da JSON.
Ad esempio, se dovessimo deserializzare una geometria JSON ESRI (vedi GeoService REST Specification ) in ArcObjects, possiamo scrivere:
string jsonGeometryPoint = "{\"x\" : -118.15, \"y\" : 33.80, \"spatialReference\" : {\"wkid\" : 4326}}"; IJSONReader jsonReader = new JSONReaderClass(); jsonReader.ReadFromString(jsonGeometryPoint); IJSONDeserializer jsonDeserializer = new JSONDeserializerGdbClass(); jsonDeserializer.InitDeserializer(jsonReader, null); IGeometry geometry = ((IExternalDeserializerGdb)jsonDeserializer).ReadGeometry(esriGeometryType.esriGeometryPoint); IPoint point = (IPoint)geometry; Console.Write("X:{0} - Y:{1} - Factory Code: {2}", point.X, point.Y, point.SpatialReference.FactoryCode); Console.Read();
Se dovessimo deserializzare uno spatial Reference JSON ESRI in ArcObjects, possiamo operare in modo analogo:
string jsonSpatialReference = "{\"wkid\" : 4326}"; IJSONReader jsonReader = new JSONReaderClass(); jsonReader.ReadFromString(jsonSpatialReference); IJSONDeserializer jsonDeserializer = new JSONDeserializerGdbClass(); jsonDeserializer.InitDeserializer(jsonReader, null); ISpatialReference spatialReference = ((IExternalDeserializerGdb)jsonDeserializer).ReadSpatialReference(); Console.Write("Name:{0} - FactoryCode:{1}", spatialReference.Name, spatialReference.FactoryCode); Console.Read();
Ora vediamo i casi inversi, ovverosia serializzare in classi JSON geometrie e spatialReference ArcObjects:
////ArcObjects Geometry to json geometry ESRI IPoint point = new PointClass(); point.PutCoords(-118.15, 33.80); IJSONWriter jsonWriter = new JSONWriterClass(); jsonWriter.WriteToString(); IJSONSerializer jsonSerializer = new JSONSerializerGdbClass(); jsonSerializer.InitSerializer(jsonWriter, null); ((IExternalSerializerGdb)jsonSerializer).WriteGeometry(null, point); Console.Write(Encoding.UTF8.GetString(jsonWriter.GetStringBuffer())); Console.Read(); ////ArcObjects spatialReference to json spatialReference ESRI Type factoryType = Type.GetTypeFromProgID("esriGeometry.SpatialReferenceEnvironment"); object obj = Activator.CreateInstance(factoryType); ISpatialReferenceFactory spatialReferenceFactory = obj as ISpatialReferenceFactory; IProjectedCoordinateSystem spatialReference = spatialReferenceFactory.CreateProjectedCoordinateSystem((int)esriSRProjCSType.esriSRProjCS_World_Mercator); IJSONWriter jsonWriter = new JSONWriterClass(); jsonWriter.WriteToString(); IJSONSerializer jsonSerializer = new JSONSerializerGdbClass(); jsonSerializer.InitSerializer(jsonWriter, null); ((IExternalSerializerGdb)jsonSerializer).WriteSpatialReference(null, spatialReference); Console.Write(Encoding.UTF8.GetString(jsonWriter.GetStringBuffer())); Console.Read();
oppure
IJSONConverterGeometry jsonConvert = new JSONConverterGeometryClass(); IJSONObject spatRefObj = new JSONObjectClass(); jsonConvert.QueryJSONSpatialReference(spatialReference, spatRefObj); JsonObject spatRefJson = new JsonObject(spatRefObj.ToJSONString(null));
Per convertire una feature class possiamo impostare un Recordset e, nel caso, filtrarlo sia come campi che come record tramite un QueryFilter (2° argomento del metodo SetSourceTable di RecordSet)
//convert feature class in json esri Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory"); IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType); IWorkspace workspace = workspaceFactory.OpenFromFile(@"E:\Temp\Test2.gdb", 0); IFeatureWorkspace featureWorkspace = (IFeatureWorkspace)workspace; IFeatureClass featureClass = featureWorkspace.OpenFeatureClass("streets"); IRecordSet recordset = new RecordSet(); IRecordSetInit recordSetInit = recordset as IRecordSetInit; recordSetInit.SetSourceTable(featureClass as ITable, null); IGeometryResultOptions geometryResultOptions = new GeometryResultOptionsClass(); geometryResultOptions.GeneralizeGeometries = true; geometryResultOptions.DensifyGeometries = true; IPropertySet propertySet = new PropertySetClass(); propertySet.SetProperty("GeometryResultOptions", geometryResultOptions); IJSONWriter jsonWriter = new JSONWriterClass(); jsonWriter.WriteToString(); IJSONSerializer jsonSerializer = new JSONSerializerGdbClass(); jsonSerializer.InitSerializer(jsonWriter, null); jsonSerializer.WriteObject(recordset, propertySet); Console.Write(Encoding.UTF8.GetString(jsonWriter.GetStringBuffer())); Console.Read();
Da json features a feature class:
string jsonFeatures = "{\"displayFieldName\":\"\",\"fieldAliases\":{\"OBJECTID\":\"OBJECTID\",\"Indirizzo\":\"Indirizzo\"},\"geometryType\":\"esriGeometryPoint\",\"spatialReference\":{\"wkid\":102100},\"fields\":[{\"name\":\"OBJECTID\",\"type\":\"esriFieldTypeOID\",\"alias\":\"OBJECTID\"},{\"name\":\"Indirizzo\",\"type\":\"esriFieldTypeString\",\"alias\":\"Indirizzo\",\"length\":50}],\"features\":[" + "{" + "\"geometry\": {" + "\"x\": 940411.3699657875," + "\"y\": 5643498.120243863," + "\"spatialReference\": {\"wkid\": 102100}" + "}," + "\"attributes\": {" + "\"OBJECTID\": 1," + "\"Indirizzo\": \"VIA SORDI, 1\"" + "}" + "}]}"; IJSONReader jsonReader = new JSONReaderClass(); jsonReader.ReadFromString(jsonFeatures); IJSONConverterGdb JSONConverterGdb = new JSONConverterGdbClass(); IPropertySet originalToNewFieldMap; IRecordSet recorset; JSONConverterGdb.ReadRecordSet(jsonReader, null, null, out recorset, out originalToNewFieldMap); Type factoryType = Type.GetTypeFromProgID("esriDataSourcesGDB.FileGDBWorkspaceFactory"); IWorkspaceFactory workspaceFactory = (IWorkspaceFactory)Activator.CreateInstance(factoryType); IWorkspace workspace = workspaceFactory.OpenFromFile(@"C:\Temp\testsd\sd.gdb", 0); IRecordSet2 recordSet2 = recorset as IRecordSet2; recordSet2.SaveAsTable(workspace, "Test");
Ricordarsi di utilizzare l'Activator per oggetti singleton (SpatialReferenceEnvironmental e FileGDBWorkspaceFactory).
Gli shortcut a questi metodi li potete trovare anche nell'assembly ESRI.ArcGIS.SOESupport nella classe Conversion con i metodi ToGeometry, ToJson e ToSpatialReference. Sempre in questo assembly potete utilizzare i metodi della classe JsonObject per serializzare e deserializzare:
Esempio di deserializzazione
JsonObject jsonPoint; if (!operationInput.TryGetJsonObject("location", out jsonPoint)) throw new ArgumentNullException("location"); IPoint location = Conversion.ToGeometry(jsonPoint, esriGeometryType.esriGeometryPoint) as IPoint;
Esempio di serializzazione
List<JsonObject> jsonGeometries = new List<JsonObject>(); JsonObject jsonResultsGeometry = Conversion.ToJsonObject(resultsGeometry); jsonGeometries.Add(jsonResultsGeometry); JsonObject resultJsonObject = new JsonObject(); resultJsonObject.AddArray("geometries", jsonGeometries.ToArray()); byte[] result = Encoding.UTF8.GetBytes(resultJsonObject.ToJson()); return result;
Con il MapServer possiamo utilizzare i metodi dell'interfaccia IMapServer3 che ci consentono agevolmente di avere dei risultati in JSON (mediante l'interfaccia IQueryResult) o Recordset da convertire in JSON da query che filtrano e riproiettano anche con datum differente (vedi IQueryResultsOptions)
IQueryResultOptions queryResultOptions = new QueryResultOptions(); queryResultOptions.Format = esriQueryResultFormat.esriQueryResultRecordSetAsObject; IMapServer3 mapServer = serverObjectHelper.ServerObject as IMapServer3; IRecordSet rs = MapServer.QueryFeatureData2(mapServer.DefaultMapName, aLayerDescription, aspatialFilterOut, queryResultOptions).Object as IRecordSet; return Conversion.ToJson(rs);
IQueryResultOptions resultOptions = new QueryResultOptionsClass(); resultOptions.Format = esriQueryResultFormat.esriQueryResultJsonAsMime; IMapTableDescription tableDesc = GetTableDesc(mapServer, layerID); IQueryResult result = mapServer.QueryData(mapServer.DefaultMapName, tableDesc, filter, resultOptions); return result.MimeData;