-----------------------------------

Acquista i software ArcGIS tramite Studio A&T srl, rivenditore autorizzato dei prodotti Esri.

I migliori software GIS, il miglior supporto tecnico!

I migliori software GIS, il miglior supporto tecnico!
Azienda operante nel settore GIS dal 2001, specializzata nell’utilizzo della tecnologia ArcGIS e aderente ai programmi Esri Italia Business Network ed Esri Partner Network

-----------------------------------



domenica 29 aprile 2012

Json & ArcObjects

Con ArcGIS 10 sono state introdotte nuove classi che permettono di serializzare e deserializzare in JSON.
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 ITablenull);
 
            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, nullnullout 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;

1 commento:

sjb ha detto...

Thanks for posting this. I wouldn't have figured out how to convert a shape to JSON without it.

Simon