1 : /******************************************************************************
2 : * $Id: ogresrijsonreader.cpp 22281 2011-05-01 17:57:55Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implementation of OGRESRIJSONReader class (OGR ESRIJSON Driver)
6 : * to read ESRI Feature Service REST data
7 : * Author: Even Rouault, even dot rouault at mines dash paris dot org
8 : *
9 : ******************************************************************************
10 : * Copyright (c) 2010, Even Rouault
11 : * Copyright (c) 2007, Mateusz Loskot
12 : *
13 : * Permission is hereby granted, free of charge, to any person obtaining a
14 : * copy of this software and associated documentation files (the "Software"),
15 : * to deal in the Software without restriction, including without limitation
16 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
17 : * and/or sell copies of the Software, and to permit persons to whom the
18 : * Software is furnished to do so, subject to the following conditions:
19 : *
20 : * The above copyright notice and this permission notice shall be included
21 : * in all copies or substantial portions of the Software.
22 : *
23 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
24 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
25 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
26 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
27 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
28 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
29 : * DEALINGS IN THE SOFTWARE.
30 : ****************************************************************************/
31 :
32 : #include "ogrgeojsonreader.h"
33 : #include "ogrgeojsonutils.h"
34 : #include "ogr_geojson.h"
35 : #include <jsonc/json.h> // JSON-C
36 : #include <jsonc/json_object_private.h> // json_object_iter, complete type required
37 : #include <ogr_api.h>
38 :
39 : /************************************************************************/
40 : /* OGRESRIJSONReader() */
41 : /************************************************************************/
42 :
43 8 : OGRESRIJSONReader::OGRESRIJSONReader()
44 8 : : poGJObject_( NULL ), poLayer_( NULL )
45 : {
46 : // Take a deep breath and get to work.
47 8 : }
48 :
49 : /************************************************************************/
50 : /* ~OGRESRIJSONReader() */
51 : /************************************************************************/
52 :
53 8 : OGRESRIJSONReader::~OGRESRIJSONReader()
54 : {
55 8 : if( NULL != poGJObject_ )
56 : {
57 8 : json_object_put(poGJObject_);
58 : }
59 :
60 8 : poGJObject_ = NULL;
61 8 : poLayer_ = NULL;
62 8 : }
63 :
64 : /************************************************************************/
65 : /* Parse() */
66 : /************************************************************************/
67 :
68 8 : OGRErr OGRESRIJSONReader::Parse( const char* pszText )
69 : {
70 8 : if( NULL != pszText )
71 : {
72 8 : json_tokener* jstok = NULL;
73 8 : json_object* jsobj = NULL;
74 :
75 8 : jstok = json_tokener_new();
76 8 : jsobj = json_tokener_parse_ex(jstok, pszText, -1);
77 8 : if( jstok->err != json_tokener_success)
78 : {
79 : CPLError( CE_Failure, CPLE_AppDefined,
80 : "ESRIJSON parsing error: %s (at offset %d)",
81 0 : json_tokener_errors[jstok->err], jstok->char_offset);
82 :
83 0 : json_tokener_free(jstok);
84 0 : return OGRERR_CORRUPT_DATA;
85 : }
86 8 : json_tokener_free(jstok);
87 :
88 : /* JSON tree is shared for while lifetime of the reader object
89 : * and will be released in the destructor.
90 : */
91 8 : poGJObject_ = jsobj;
92 : }
93 :
94 8 : return OGRERR_NONE;
95 : }
96 :
97 : /************************************************************************/
98 : /* ReadLayer() */
99 : /************************************************************************/
100 :
101 8 : OGRGeoJSONLayer* OGRESRIJSONReader::ReadLayer( const char* pszName,
102 : OGRGeoJSONDataSource* poDS )
103 : {
104 8 : CPLAssert( NULL == poLayer_ );
105 :
106 8 : if( NULL == poGJObject_ )
107 : {
108 : CPLDebug( "ESRIJSON",
109 0 : "Missing parset ESRIJSON data. Forgot to call Parse()?" );
110 0 : return NULL;
111 : }
112 :
113 : poLayer_ = new OGRGeoJSONLayer( pszName, NULL,
114 : OGRESRIJSONGetGeometryType(poGJObject_),
115 8 : NULL, poDS );
116 :
117 8 : if( !GenerateLayerDefn() )
118 : {
119 : CPLError( CE_Failure, CPLE_AppDefined,
120 0 : "Layer schema generation failed." );
121 :
122 0 : delete poLayer_;
123 0 : return NULL;
124 : }
125 :
126 8 : OGRGeoJSONLayer* poThisLayer = NULL;
127 8 : poThisLayer = ReadFeatureCollection( poGJObject_ );
128 8 : if (poThisLayer == NULL)
129 : {
130 0 : delete poLayer_;
131 0 : return NULL;
132 : }
133 :
134 8 : OGRSpatialReference* poSRS = NULL;
135 8 : poSRS = OGRESRIJSONReadSpatialReference( poGJObject_ );
136 8 : if (poSRS != NULL )
137 : {
138 4 : poLayer_->SetSpatialRef( poSRS );
139 4 : delete poSRS;
140 : }
141 :
142 8 : return poLayer_;
143 : }
144 :
145 : /************************************************************************/
146 : /* GenerateFeatureDefn() */
147 : /************************************************************************/
148 :
149 8 : bool OGRESRIJSONReader::GenerateLayerDefn()
150 : {
151 8 : CPLAssert( NULL != poGJObject_ );
152 8 : CPLAssert( NULL != poLayer_->GetLayerDefn() );
153 8 : CPLAssert( 0 == poLayer_->GetLayerDefn()->GetFieldCount() );
154 :
155 8 : bool bSuccess = true;
156 :
157 : /* -------------------------------------------------------------------- */
158 : /* Scan all features and generate layer definition. */
159 : /* -------------------------------------------------------------------- */
160 8 : json_object* poObjFeatures = NULL;
161 :
162 8 : poObjFeatures = OGRGeoJSONFindMemberByName( poGJObject_, "fields" );
163 8 : if( NULL != poObjFeatures && json_type_array == json_object_get_type( poObjFeatures ) )
164 : {
165 8 : json_object* poObjFeature = NULL;
166 8 : const int nFeatures = json_object_array_length( poObjFeatures );
167 24 : for( int i = 0; i < nFeatures; ++i )
168 : {
169 16 : poObjFeature = json_object_array_get_idx( poObjFeatures, i );
170 16 : if( !GenerateFeatureDefn( poObjFeature ) )
171 : {
172 0 : CPLDebug( "GeoJSON", "Create feature schema failure." );
173 0 : bSuccess = false;
174 : }
175 : }
176 : }
177 : else
178 : {
179 0 : poObjFeatures = OGRGeoJSONFindMemberByName( poGJObject_, "fieldAliases" );
180 0 : if( NULL != poObjFeatures )
181 : {
182 0 : OGRFeatureDefn* poDefn = poLayer_->GetLayerDefn();
183 : json_object_iter it;
184 0 : it.key = NULL;
185 0 : it.val = NULL;
186 0 : it.entry = NULL;
187 0 : json_object_object_foreachC( poObjFeatures, it )
188 : {
189 0 : OGRFieldDefn fldDefn( it.key, OFTString );
190 0 : poDefn->AddFieldDefn( &fldDefn );
191 : }
192 : }
193 : else
194 : {
195 : CPLError( CE_Failure, CPLE_AppDefined,
196 : "Invalid FeatureCollection object. "
197 0 : "Missing \'fields\' member." );
198 0 : bSuccess = false;
199 : }
200 : }
201 :
202 8 : return bSuccess;
203 : }
204 :
205 : /************************************************************************/
206 : /* GenerateFeatureDefn() */
207 : /************************************************************************/
208 :
209 16 : bool OGRESRIJSONReader::GenerateFeatureDefn( json_object* poObj )
210 : {
211 16 : OGRFeatureDefn* poDefn = poLayer_->GetLayerDefn();
212 16 : CPLAssert( NULL != poDefn );
213 :
214 16 : bool bSuccess = false;
215 :
216 : /* -------------------------------------------------------------------- */
217 : /* Read collection of properties. */
218 : /* -------------------------------------------------------------------- */
219 16 : json_object* poObjName = OGRGeoJSONFindMemberByName( poObj, "name" );
220 16 : json_object* poObjType = OGRGeoJSONFindMemberByName( poObj, "type" );
221 16 : if( NULL != poObjName && NULL != poObjType )
222 : {
223 16 : OGRFieldType eFieldType = OFTString;
224 16 : if (EQUAL(json_object_get_string(poObjType), "esriFieldTypeOID"))
225 : {
226 4 : eFieldType = OFTInteger;
227 4 : poLayer_->SetFIDColumn(json_object_get_string(poObjName));
228 : }
229 12 : else if (EQUAL(json_object_get_string(poObjType), "esriFieldTypeDouble"))
230 : {
231 4 : eFieldType = OFTReal;
232 : }
233 8 : else if (EQUAL(json_object_get_string(poObjType), "esriFieldTypeSmallInteger") ||
234 : EQUAL(json_object_get_string(poObjType), "esriFieldTypeInteger") )
235 : {
236 4 : eFieldType = OFTInteger;
237 : }
238 : OGRFieldDefn fldDefn( json_object_get_string(poObjName),
239 16 : eFieldType);
240 :
241 16 : json_object* poObjLength = OGRGeoJSONFindMemberByName( poObj, "length" );
242 16 : if (poObjLength != NULL && json_object_get_type(poObjLength) == json_type_int )
243 : {
244 8 : fldDefn.SetWidth(json_object_get_int(poObjLength));
245 : }
246 :
247 16 : poDefn->AddFieldDefn( &fldDefn );
248 :
249 16 : bSuccess = true; // SUCCESS
250 : }
251 16 : return bSuccess;
252 : }
253 :
254 : /************************************************************************/
255 : /* AddFeature */
256 : /************************************************************************/
257 :
258 8 : bool OGRESRIJSONReader::AddFeature( OGRFeature* poFeature )
259 : {
260 8 : bool bAdded = false;
261 :
262 8 : if( NULL != poFeature )
263 : {
264 8 : poLayer_->AddFeature( poFeature );
265 8 : bAdded = true;
266 8 : delete poFeature;
267 : }
268 :
269 8 : return bAdded;
270 : }
271 :
272 : /************************************************************************/
273 : /* ReadGeometry() */
274 : /************************************************************************/
275 :
276 8 : OGRGeometry* OGRESRIJSONReader::ReadGeometry( json_object* poObj )
277 : {
278 8 : OGRGeometry* poGeometry = NULL;
279 :
280 8 : OGRwkbGeometryType eType = poLayer_->GetGeomType();
281 8 : if (eType == wkbPoint)
282 2 : poGeometry = OGRESRIJSONReadPoint( poObj );
283 6 : else if (eType == wkbLineString)
284 2 : poGeometry = OGRESRIJSONReadLineString( poObj );
285 4 : else if (eType == wkbPolygon)
286 2 : poGeometry = OGRESRIJSONReadPolygon( poObj );
287 2 : else if (eType == wkbMultiPoint)
288 2 : poGeometry = OGRESRIJSONReadMultiPoint( poObj );
289 :
290 8 : return poGeometry;
291 : }
292 :
293 : /************************************************************************/
294 : /* ReadFeature() */
295 : /************************************************************************/
296 :
297 8 : OGRFeature* OGRESRIJSONReader::ReadFeature( json_object* poObj )
298 : {
299 8 : CPLAssert( NULL != poObj );
300 8 : CPLAssert( NULL != poLayer_ );
301 :
302 8 : OGRFeature* poFeature = NULL;
303 8 : poFeature = new OGRFeature( poLayer_->GetLayerDefn() );
304 :
305 : /* -------------------------------------------------------------------- */
306 : /* Translate ESRIJSON "attributes" object to feature attributes. */
307 : /* -------------------------------------------------------------------- */
308 8 : CPLAssert( NULL != poFeature );
309 :
310 8 : json_object* poObjProps = NULL;
311 8 : poObjProps = OGRGeoJSONFindMemberByName( poObj, "attributes" );
312 8 : if( NULL != poObjProps )
313 : {
314 8 : int nField = -1;
315 8 : OGRFieldDefn* poFieldDefn = NULL;
316 : json_object_iter it;
317 8 : it.key = NULL;
318 8 : it.val = NULL;
319 8 : it.entry = NULL;
320 24 : json_object_object_foreachC( poObjProps, it )
321 : {
322 16 : nField = poFeature->GetFieldIndex(it.key);
323 16 : poFieldDefn = poFeature->GetFieldDefnRef(nField);
324 16 : if (poFieldDefn && it.val != NULL )
325 : {
326 16 : if ( EQUAL( it.key, poLayer_->GetFIDColumn() ) )
327 4 : poFeature->SetFID( json_object_get_int( it.val ) );
328 16 : poFeature->SetField( nField, json_object_get_string(it.val) );
329 : }
330 : }
331 : }
332 :
333 8 : OGRwkbGeometryType eType = poLayer_->GetGeomType();
334 8 : if (eType == wkbNone)
335 0 : return poFeature;
336 :
337 : /* -------------------------------------------------------------------- */
338 : /* Translate geometry sub-object of ESRIJSON Feature. */
339 : /* -------------------------------------------------------------------- */
340 8 : json_object* poObjGeom = NULL;
341 :
342 8 : json_object* poTmp = poObj;
343 :
344 : json_object_iter it;
345 8 : it.key = NULL;
346 8 : it.val = NULL;
347 8 : it.entry = NULL;
348 24 : json_object_object_foreachC(poTmp, it)
349 : {
350 16 : if( EQUAL( it.key, "geometry" ) ) {
351 8 : if (it.val != NULL)
352 8 : poObjGeom = it.val;
353 : // we're done. They had 'geometry':null
354 : else
355 0 : return poFeature;
356 : }
357 : }
358 :
359 8 : if( NULL != poObjGeom )
360 : {
361 8 : OGRGeometry* poGeometry = ReadGeometry( poObjGeom );
362 8 : if( NULL != poGeometry )
363 : {
364 8 : poFeature->SetGeometryDirectly( poGeometry );
365 : }
366 : }
367 : else
368 : {
369 : CPLError( CE_Failure, CPLE_AppDefined,
370 : "Invalid Feature object. "
371 0 : "Missing \'geometry\' member." );
372 0 : delete poFeature;
373 0 : return NULL;
374 : }
375 :
376 8 : return poFeature;
377 : }
378 :
379 : /************************************************************************/
380 : /* ReadFeatureCollection() */
381 : /************************************************************************/
382 :
383 : OGRGeoJSONLayer*
384 8 : OGRESRIJSONReader::ReadFeatureCollection( json_object* poObj )
385 : {
386 8 : CPLAssert( NULL != poLayer_ );
387 :
388 8 : json_object* poObjFeatures = NULL;
389 8 : poObjFeatures = OGRGeoJSONFindMemberByName( poObj, "features" );
390 8 : if( NULL == poObjFeatures )
391 : {
392 : CPLError( CE_Failure, CPLE_AppDefined,
393 : "Invalid FeatureCollection object. "
394 0 : "Missing \'features\' member." );
395 0 : return NULL;
396 : }
397 :
398 8 : if( json_type_array == json_object_get_type( poObjFeatures ) )
399 : {
400 8 : bool bAdded = false;
401 8 : OGRFeature* poFeature = NULL;
402 8 : json_object* poObjFeature = NULL;
403 :
404 8 : const int nFeatures = json_object_array_length( poObjFeatures );
405 16 : for( int i = 0; i < nFeatures; ++i )
406 : {
407 8 : poObjFeature = json_object_array_get_idx( poObjFeatures, i );
408 8 : poFeature = OGRESRIJSONReader::ReadFeature( poObjFeature );
409 8 : bAdded = AddFeature( poFeature );
410 : //CPLAssert( bAdded );
411 : }
412 : //CPLAssert( nFeatures == poLayer_->GetFeatureCount() );
413 : }
414 :
415 : // We're returning class member to follow the same pattern of
416 : // Read* functions call convention.
417 8 : CPLAssert( NULL != poLayer_ );
418 8 : return poLayer_;
419 : }
420 :
421 : /************************************************************************/
422 : /* OGRESRIJSONGetType() */
423 : /************************************************************************/
424 :
425 8 : OGRwkbGeometryType OGRESRIJSONGetGeometryType( json_object* poObj )
426 : {
427 8 : if( NULL == poObj )
428 0 : return wkbUnknown;
429 :
430 8 : json_object* poObjType = NULL;
431 8 : poObjType = OGRGeoJSONFindMemberByName( poObj, "geometryType" );
432 8 : if( NULL == poObjType )
433 : {
434 0 : return wkbNone;
435 : }
436 :
437 8 : const char* name = json_object_get_string( poObjType );
438 8 : if( EQUAL( name, "esriGeometryPoint" ) )
439 2 : return wkbPoint;
440 6 : else if( EQUAL( name, "esriGeometryPolyline" ) )
441 2 : return wkbLineString;
442 4 : else if( EQUAL( name, "esriGeometryPolygon" ) )
443 2 : return wkbPolygon;
444 2 : else if( EQUAL( name, "esriGeometryMultiPoint" ) )
445 2 : return wkbMultiPoint;
446 : else
447 0 : return wkbUnknown;
448 : }
449 :
450 : /************************************************************************/
451 : /* OGRESRIJSONReadPoint() */
452 : /************************************************************************/
453 :
454 2 : OGRPoint* OGRESRIJSONReadPoint( json_object* poObj)
455 : {
456 2 : CPLAssert( NULL != poObj );
457 :
458 2 : json_object* poObjX = OGRGeoJSONFindMemberByName( poObj, "x" );
459 2 : if( NULL == poObjX )
460 : {
461 : CPLError( CE_Failure, CPLE_AppDefined,
462 : "Invalid Point object. "
463 0 : "Missing \'x\' member." );
464 0 : return NULL;
465 : }
466 :
467 2 : int iTypeX = json_object_get_type(poObjX);
468 2 : if ( (json_type_double != iTypeX) && (json_type_int != iTypeX) )
469 : {
470 : CPLError( CE_Failure, CPLE_AppDefined,
471 : "Invalid X coordinate. Type is not double or integer for \'%s\'.",
472 0 : json_object_to_json_string(poObjX) );
473 0 : return NULL;
474 : }
475 :
476 2 : json_object* poObjY = OGRGeoJSONFindMemberByName( poObj, "y" );
477 2 : if( NULL == poObjY )
478 : {
479 : CPLError( CE_Failure, CPLE_AppDefined,
480 : "Invalid Point object. "
481 0 : "Missing \'y\' member." );
482 0 : return NULL;
483 : }
484 :
485 2 : int iTypeY = json_object_get_type(poObjY);
486 2 : if ( (json_type_double != iTypeY) && (json_type_int != iTypeY) )
487 : {
488 : CPLError( CE_Failure, CPLE_AppDefined,
489 : "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
490 0 : json_object_to_json_string(poObjY) );
491 0 : return NULL;
492 : }
493 :
494 : double dfX, dfY;
495 2 : if (iTypeX == json_type_double)
496 0 : dfX = json_object_get_double( poObjX );
497 : else
498 2 : dfX = json_object_get_int( poObjX );
499 2 : if (iTypeY == json_type_double)
500 0 : dfY = json_object_get_double( poObjY );
501 : else
502 2 : dfY = json_object_get_int( poObjY );
503 :
504 2 : return new OGRPoint(dfX, dfY);
505 : }
506 :
507 : /************************************************************************/
508 : /* OGRESRIJSONReadLineString() */
509 : /************************************************************************/
510 :
511 2 : OGRLineString* OGRESRIJSONReadLineString( json_object* poObj)
512 : {
513 2 : CPLAssert( NULL != poObj );
514 :
515 2 : OGRLineString* poLine = NULL;
516 :
517 2 : json_object* poObjPaths = OGRGeoJSONFindMemberByName( poObj, "paths" );
518 2 : if( NULL == poObjPaths )
519 : {
520 : CPLError( CE_Failure, CPLE_AppDefined,
521 : "Invalid LineString object. "
522 0 : "Missing \'paths\' member." );
523 0 : return NULL;
524 : }
525 :
526 2 : if( json_type_array != json_object_get_type( poObjPaths ) )
527 : {
528 : CPLError( CE_Failure, CPLE_AppDefined,
529 : "Invalid LineString object. "
530 0 : "Invalid \'paths\' member." );
531 0 : return NULL;
532 : }
533 :
534 2 : poLine = new OGRLineString();
535 2 : const int nPaths = json_object_array_length( poObjPaths );
536 4 : for(int iPath = 0; iPath < nPaths; iPath ++)
537 : {
538 2 : json_object* poObjPath = json_object_array_get_idx( poObjPaths, iPath );
539 2 : if ( poObjPath == NULL ||
540 : json_type_array != json_object_get_type( poObjPath ) )
541 : {
542 0 : delete poLine;
543 : CPLDebug( "ESRIJSON",
544 0 : "LineString: got non-array object." );
545 0 : return NULL;
546 : }
547 :
548 2 : const int nPoints = json_object_array_length( poObjPath );
549 6 : for(int i = 0; i < nPoints; i++)
550 : {
551 4 : json_object* poObjCoords = NULL;
552 :
553 4 : poObjCoords = json_object_array_get_idx( poObjPath, i );
554 4 : if (poObjCoords == NULL)
555 : {
556 0 : delete poLine;
557 : CPLDebug( "ESRIJSON",
558 0 : "LineString: got null object." );
559 0 : return NULL;
560 : }
561 4 : if( json_type_array != json_object_get_type( poObjCoords ) ||
562 : json_object_array_length( poObjCoords ) != 2 )
563 : {
564 0 : delete poLine;
565 : CPLDebug( "ESRIJSON",
566 0 : "LineString: got non-array object." );
567 0 : return NULL;
568 : }
569 :
570 : json_object* poObjCoord;
571 : int iType;
572 : double dfX, dfY;
573 :
574 : // Read X coordinate
575 4 : poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
576 4 : if (poObjCoord == NULL)
577 : {
578 0 : CPLDebug( "ESRIJSON", "LineString: got null object." );
579 0 : delete poLine;
580 0 : return NULL;
581 : }
582 :
583 4 : iType = json_object_get_type(poObjCoord);
584 4 : if ( (json_type_double != iType) && (json_type_int != iType) )
585 : {
586 : CPLError( CE_Failure, CPLE_AppDefined,
587 : "Invalid X coordinate. Type is not double or integer for \'%s\'.",
588 0 : json_object_to_json_string(poObjCoord) );
589 0 : delete poLine;
590 0 : return NULL;
591 : }
592 :
593 4 : if (iType == json_type_double)
594 0 : dfX = json_object_get_double( poObjCoord );
595 : else
596 4 : dfX = json_object_get_int( poObjCoord );
597 :
598 : // Read Y coordinate
599 4 : poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
600 4 : if (poObjCoord == NULL)
601 : {
602 0 : CPLDebug( "ESRIJSON", "LineString: got null object." );
603 0 : delete poLine;
604 0 : return NULL;
605 : }
606 :
607 4 : iType = json_object_get_type(poObjCoord);
608 4 : if ( (json_type_double != iType) && (json_type_int != iType) )
609 : {
610 : CPLError( CE_Failure, CPLE_AppDefined,
611 : "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
612 0 : json_object_to_json_string(poObjCoord) );
613 0 : delete poLine;
614 0 : return NULL;
615 : }
616 :
617 4 : if (iType == json_type_double)
618 0 : dfY = json_object_get_double( poObjCoord );
619 : else
620 4 : dfY = json_object_get_int( poObjCoord );
621 :
622 4 : poLine->addPoint( dfX, dfY );
623 : }
624 : }
625 :
626 2 : return poLine;
627 : }
628 :
629 : /************************************************************************/
630 : /* OGRESRIJSONReadPolygon() */
631 : /************************************************************************/
632 :
633 2 : OGRPolygon* OGRESRIJSONReadPolygon( json_object* poObj)
634 : {
635 2 : CPLAssert( NULL != poObj );
636 :
637 2 : OGRPolygon* poPoly = NULL;
638 :
639 2 : json_object* poObjRings = OGRGeoJSONFindMemberByName( poObj, "rings" );
640 2 : if( NULL == poObjRings )
641 : {
642 : CPLError( CE_Failure, CPLE_AppDefined,
643 : "Invalid Polygon object. "
644 0 : "Missing \'rings\' member." );
645 0 : return NULL;
646 : }
647 :
648 2 : if( json_type_array != json_object_get_type( poObjRings ) )
649 : {
650 : CPLError( CE_Failure, CPLE_AppDefined,
651 : "Invalid Polygon object. "
652 0 : "Invalid \'rings\' member." );
653 0 : return NULL;
654 : }
655 :
656 2 : poPoly = new OGRPolygon();
657 :
658 2 : const int nRings = json_object_array_length( poObjRings );
659 4 : for(int iRing = 0; iRing < nRings; iRing ++)
660 : {
661 2 : json_object* poObjRing = json_object_array_get_idx( poObjRings, iRing );
662 2 : if ( poObjRing == NULL ||
663 : json_type_array != json_object_get_type( poObjRing ) )
664 : {
665 0 : delete poPoly;
666 : CPLDebug( "ESRIJSON",
667 0 : "Polygon: got non-array object." );
668 0 : return NULL;
669 : }
670 :
671 2 : OGRLinearRing* poLine = new OGRLinearRing();
672 2 : poPoly->addRingDirectly(poLine);
673 :
674 2 : const int nPoints = json_object_array_length( poObjRing );
675 12 : for(int i = 0; i < nPoints; i++)
676 : {
677 10 : json_object* poObjCoords = NULL;
678 :
679 10 : poObjCoords = json_object_array_get_idx( poObjRing, i );
680 10 : if (poObjCoords == NULL)
681 : {
682 0 : delete poPoly;
683 : CPLDebug( "ESRIJSON",
684 0 : "Polygon: got null object." );
685 0 : return NULL;
686 : }
687 10 : if( json_type_array != json_object_get_type( poObjCoords ) ||
688 : json_object_array_length( poObjCoords ) != 2 )
689 : {
690 0 : delete poPoly;
691 : CPLDebug( "ESRIJSON",
692 0 : "Polygon: got non-array object." );
693 0 : return NULL;
694 : }
695 :
696 : json_object* poObjCoord;
697 : int iType;
698 : double dfX, dfY;
699 :
700 : // Read X coordinate
701 10 : poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
702 10 : if (poObjCoord == NULL)
703 : {
704 0 : CPLDebug( "ESRIJSON", "Polygon: got null object." );
705 0 : delete poPoly;
706 0 : return NULL;
707 : }
708 :
709 10 : iType = json_object_get_type(poObjCoord);
710 10 : if ( (json_type_double != iType) && (json_type_int != iType) )
711 : {
712 : CPLError( CE_Failure, CPLE_AppDefined,
713 : "Invalid X coordinate. Type is not double or integer for \'%s\'.",
714 0 : json_object_to_json_string(poObjCoord) );
715 0 : delete poPoly;
716 0 : return NULL;
717 : }
718 :
719 10 : if (iType == json_type_double)
720 0 : dfX = json_object_get_double( poObjCoord );
721 : else
722 10 : dfX = json_object_get_int( poObjCoord );
723 :
724 : // Read Y coordinate
725 10 : poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
726 10 : if (poObjCoord == NULL)
727 : {
728 0 : CPLDebug( "ESRIJSON", "Polygon: got null object." );
729 0 : delete poPoly;
730 0 : return NULL;
731 : }
732 :
733 10 : iType = json_object_get_type(poObjCoord);
734 10 : if ( (json_type_double != iType) && (json_type_int != iType) )
735 : {
736 : CPLError( CE_Failure, CPLE_AppDefined,
737 : "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
738 0 : json_object_to_json_string(poObjCoord) );
739 0 : delete poPoly;
740 0 : return NULL;
741 : }
742 :
743 10 : if (iType == json_type_double)
744 0 : dfY = json_object_get_double( poObjCoord );
745 : else
746 10 : dfY = json_object_get_int( poObjCoord );
747 :
748 10 : poLine->addPoint( dfX, dfY );
749 : }
750 : }
751 :
752 2 : return poPoly;
753 : }
754 :
755 : /************************************************************************/
756 : /* OGRESRIJSONReadMultiPoint() */
757 : /************************************************************************/
758 :
759 2 : OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj)
760 : {
761 2 : CPLAssert( NULL != poObj );
762 :
763 2 : OGRMultiPoint* poMulti = NULL;
764 :
765 2 : json_object* poObjPoints = OGRGeoJSONFindMemberByName( poObj, "points" );
766 2 : if( NULL == poObjPoints )
767 : {
768 : CPLError( CE_Failure, CPLE_AppDefined,
769 : "Invalid LineString object. "
770 0 : "Missing \'points\' member." );
771 0 : return NULL;
772 : }
773 :
774 2 : if( json_type_array != json_object_get_type( poObjPoints ) )
775 : {
776 : CPLError( CE_Failure, CPLE_AppDefined,
777 : "Invalid LineString object. "
778 0 : "Invalid \'points\' member." );
779 0 : return NULL;
780 : }
781 :
782 2 : poMulti = new OGRMultiPoint();
783 :
784 2 : const int nPoints = json_object_array_length( poObjPoints );
785 12 : for(int i = 0; i < nPoints; i++)
786 : {
787 4 : json_object* poObjCoords = NULL;
788 :
789 4 : poObjCoords = json_object_array_get_idx( poObjPoints, i );
790 4 : if (poObjCoords == NULL)
791 : {
792 0 : delete poMulti;
793 : CPLDebug( "ESRIJSON",
794 0 : "MultiPoint: got null object." );
795 0 : return NULL;
796 : }
797 4 : if( json_type_array != json_object_get_type( poObjCoords ) ||
798 : json_object_array_length( poObjCoords ) != 2 )
799 : {
800 0 : delete poMulti;
801 : CPLDebug( "ESRIJSON",
802 0 : "MultiPoint: got non-array object." );
803 0 : return NULL;
804 : }
805 :
806 : json_object* poObjCoord;
807 : int iType;
808 : double dfX, dfY;
809 :
810 : // Read X coordinate
811 4 : poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
812 4 : if (poObjCoord == NULL)
813 : {
814 0 : CPLDebug( "ESRIJSON", "MultiPoint: got null object." );
815 0 : delete poMulti;
816 0 : return NULL;
817 : }
818 :
819 4 : iType = json_object_get_type(poObjCoord);
820 4 : if ( (json_type_double != iType) && (json_type_int != iType) )
821 : {
822 : CPLError( CE_Failure, CPLE_AppDefined,
823 : "Invalid X coordinate. Type is not double or integer for \'%s\'.",
824 0 : json_object_to_json_string(poObjCoord) );
825 0 : delete poMulti;
826 0 : return NULL;
827 : }
828 :
829 4 : if (iType == json_type_double)
830 0 : dfX = json_object_get_double( poObjCoord );
831 : else
832 4 : dfX = json_object_get_int( poObjCoord );
833 :
834 : // Read Y coordinate
835 4 : poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
836 4 : if (poObjCoord == NULL)
837 : {
838 0 : CPLDebug( "ESRIJSON", "MultiPoint: got null object." );
839 0 : delete poMulti;
840 0 : return NULL;
841 : }
842 :
843 4 : iType = json_object_get_type(poObjCoord);
844 4 : if ( (json_type_double != iType) && (json_type_int != iType) )
845 : {
846 : CPLError( CE_Failure, CPLE_AppDefined,
847 : "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
848 0 : json_object_to_json_string(poObjCoord) );
849 0 : delete poMulti;
850 0 : return NULL;
851 : }
852 :
853 4 : if (iType == json_type_double)
854 0 : dfY = json_object_get_double( poObjCoord );
855 : else
856 4 : dfY = json_object_get_int( poObjCoord );
857 :
858 4 : poMulti->addGeometryDirectly( new OGRPoint(dfX, dfY) );
859 : }
860 :
861 2 : return poMulti;
862 : }
863 :
864 : /************************************************************************/
865 : /* OGRESRIJSONReadSpatialReference() */
866 : /************************************************************************/
867 :
868 8 : OGRSpatialReference* OGRESRIJSONReadSpatialReference( json_object* poObj )
869 : {
870 : /* -------------------------------------------------------------------- */
871 : /* Read spatial reference definition. */
872 : /* -------------------------------------------------------------------- */
873 8 : OGRSpatialReference* poSRS = NULL;
874 :
875 8 : json_object* poObjSrs = OGRGeoJSONFindMemberByName( poObj, "spatialReference" );
876 8 : if( NULL != poObjSrs )
877 : {
878 4 : json_object* poObjWkid = OGRGeoJSONFindMemberByName( poObjSrs, "wkid" );
879 4 : if (poObjWkid == NULL)
880 : {
881 0 : json_object* poObjWkt = OGRGeoJSONFindMemberByName( poObjSrs, "wkt" );
882 0 : if (poObjWkt == NULL)
883 0 : return NULL;
884 :
885 0 : char* pszWKT = (char*) json_object_get_string( poObjWkt );
886 0 : poSRS = new OGRSpatialReference();
887 0 : if( OGRERR_NONE != poSRS->importFromWkt( &pszWKT ) ||
888 : poSRS->morphFromESRI() != OGRERR_NONE )
889 : {
890 0 : delete poSRS;
891 0 : poSRS = NULL;
892 : }
893 :
894 0 : return poSRS;
895 : }
896 :
897 4 : int nEPSG = json_object_get_int( poObjWkid );
898 :
899 4 : poSRS = new OGRSpatialReference();
900 4 : if( OGRERR_NONE != poSRS->importFromEPSG( nEPSG ) )
901 : {
902 0 : delete poSRS;
903 0 : poSRS = NULL;
904 : }
905 : }
906 :
907 8 : return poSRS;
908 : }
|