1 : /******************************************************************************
2 : * $Id: ogresrijsonreader.cpp 24923 2012-09-16 09:46:59Z 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 : 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 : json_object_get_type(poObjFeatures) == json_type_object )
182 : {
183 0 : OGRFeatureDefn* poDefn = poLayer_->GetLayerDefn();
184 : json_object_iter it;
185 0 : it.key = NULL;
186 0 : it.val = NULL;
187 0 : it.entry = NULL;
188 0 : json_object_object_foreachC( poObjFeatures, it )
189 : {
190 0 : OGRFieldDefn fldDefn( it.key, OFTString );
191 0 : poDefn->AddFieldDefn( &fldDefn );
192 : }
193 : }
194 : else
195 : {
196 : CPLError( CE_Failure, CPLE_AppDefined,
197 : "Invalid FeatureCollection object. "
198 0 : "Missing \'fields\' member." );
199 0 : bSuccess = false;
200 : }
201 : }
202 :
203 8 : return bSuccess;
204 : }
205 :
206 : /************************************************************************/
207 : /* GenerateFeatureDefn() */
208 : /************************************************************************/
209 :
210 16 : bool OGRESRIJSONReader::GenerateFeatureDefn( json_object* poObj )
211 : {
212 16 : OGRFeatureDefn* poDefn = poLayer_->GetLayerDefn();
213 16 : CPLAssert( NULL != poDefn );
214 :
215 16 : bool bSuccess = false;
216 :
217 : /* -------------------------------------------------------------------- */
218 : /* Read collection of properties. */
219 : /* -------------------------------------------------------------------- */
220 16 : json_object* poObjName = OGRGeoJSONFindMemberByName( poObj, "name" );
221 16 : json_object* poObjType = OGRGeoJSONFindMemberByName( poObj, "type" );
222 16 : if( NULL != poObjName && NULL != poObjType )
223 : {
224 16 : OGRFieldType eFieldType = OFTString;
225 16 : if (EQUAL(json_object_get_string(poObjType), "esriFieldTypeOID"))
226 : {
227 4 : eFieldType = OFTInteger;
228 4 : poLayer_->SetFIDColumn(json_object_get_string(poObjName));
229 : }
230 12 : else if (EQUAL(json_object_get_string(poObjType), "esriFieldTypeDouble"))
231 : {
232 4 : eFieldType = OFTReal;
233 : }
234 8 : else if (EQUAL(json_object_get_string(poObjType), "esriFieldTypeSmallInteger") ||
235 : EQUAL(json_object_get_string(poObjType), "esriFieldTypeInteger") )
236 : {
237 4 : eFieldType = OFTInteger;
238 : }
239 : OGRFieldDefn fldDefn( json_object_get_string(poObjName),
240 16 : eFieldType);
241 :
242 16 : json_object* poObjLength = OGRGeoJSONFindMemberByName( poObj, "length" );
243 16 : if (poObjLength != NULL && json_object_get_type(poObjLength) == json_type_int )
244 : {
245 8 : fldDefn.SetWidth(json_object_get_int(poObjLength));
246 : }
247 :
248 16 : poDefn->AddFieldDefn( &fldDefn );
249 :
250 16 : bSuccess = true; // SUCCESS
251 : }
252 16 : return bSuccess;
253 : }
254 :
255 : /************************************************************************/
256 : /* AddFeature */
257 : /************************************************************************/
258 :
259 8 : bool OGRESRIJSONReader::AddFeature( OGRFeature* poFeature )
260 : {
261 8 : bool bAdded = false;
262 :
263 8 : if( NULL != poFeature )
264 : {
265 8 : poLayer_->AddFeature( poFeature );
266 8 : bAdded = true;
267 8 : delete poFeature;
268 : }
269 :
270 8 : return bAdded;
271 : }
272 :
273 : /************************************************************************/
274 : /* ReadGeometry() */
275 : /************************************************************************/
276 :
277 8 : OGRGeometry* OGRESRIJSONReader::ReadGeometry( json_object* poObj )
278 : {
279 8 : OGRGeometry* poGeometry = NULL;
280 :
281 8 : OGRwkbGeometryType eType = poLayer_->GetGeomType();
282 8 : if (eType == wkbPoint)
283 2 : poGeometry = OGRESRIJSONReadPoint( poObj );
284 6 : else if (eType == wkbLineString)
285 2 : poGeometry = OGRESRIJSONReadLineString( poObj );
286 4 : else if (eType == wkbPolygon)
287 2 : poGeometry = OGRESRIJSONReadPolygon( poObj );
288 2 : else if (eType == wkbMultiPoint)
289 2 : poGeometry = OGRESRIJSONReadMultiPoint( poObj );
290 :
291 8 : return poGeometry;
292 : }
293 :
294 : /************************************************************************/
295 : /* ReadFeature() */
296 : /************************************************************************/
297 :
298 8 : OGRFeature* OGRESRIJSONReader::ReadFeature( json_object* poObj )
299 : {
300 8 : CPLAssert( NULL != poObj );
301 8 : CPLAssert( NULL != poLayer_ );
302 :
303 8 : OGRFeature* poFeature = NULL;
304 8 : poFeature = new OGRFeature( poLayer_->GetLayerDefn() );
305 :
306 : /* -------------------------------------------------------------------- */
307 : /* Translate ESRIJSON "attributes" object to feature attributes. */
308 : /* -------------------------------------------------------------------- */
309 8 : CPLAssert( NULL != poFeature );
310 :
311 8 : json_object* poObjProps = NULL;
312 8 : poObjProps = OGRGeoJSONFindMemberByName( poObj, "attributes" );
313 8 : if( NULL != poObjProps &&
314 : json_object_get_type(poObjProps) == json_type_object )
315 : {
316 8 : int nField = -1;
317 8 : OGRFieldDefn* poFieldDefn = NULL;
318 : json_object_iter it;
319 8 : it.key = NULL;
320 8 : it.val = NULL;
321 8 : it.entry = NULL;
322 24 : json_object_object_foreachC( poObjProps, it )
323 : {
324 16 : nField = poFeature->GetFieldIndex(it.key);
325 16 : poFieldDefn = poFeature->GetFieldDefnRef(nField);
326 16 : if (poFieldDefn && it.val != NULL )
327 : {
328 16 : if ( EQUAL( it.key, poLayer_->GetFIDColumn() ) )
329 4 : poFeature->SetFID( json_object_get_int( it.val ) );
330 16 : if ( poLayer_->GetLayerDefn()->GetFieldDefn(nField)->GetType() == OFTReal )
331 4 : poFeature->SetField( nField, CPLAtofM(json_object_get_string(it.val)) );
332 : else
333 12 : poFeature->SetField( nField, json_object_get_string(it.val) );
334 : }
335 : }
336 : }
337 :
338 8 : OGRwkbGeometryType eType = poLayer_->GetGeomType();
339 8 : if (eType == wkbNone)
340 0 : return poFeature;
341 :
342 : /* -------------------------------------------------------------------- */
343 : /* Translate geometry sub-object of ESRIJSON Feature. */
344 : /* -------------------------------------------------------------------- */
345 8 : json_object* poObjGeom = NULL;
346 :
347 8 : json_object* poTmp = poObj;
348 :
349 : json_object_iter it;
350 8 : it.key = NULL;
351 8 : it.val = NULL;
352 8 : it.entry = NULL;
353 24 : json_object_object_foreachC(poTmp, it)
354 : {
355 16 : if( EQUAL( it.key, "geometry" ) ) {
356 8 : if (it.val != NULL)
357 8 : poObjGeom = it.val;
358 : // we're done. They had 'geometry':null
359 : else
360 0 : return poFeature;
361 : }
362 : }
363 :
364 8 : if( NULL != poObjGeom )
365 : {
366 8 : OGRGeometry* poGeometry = ReadGeometry( poObjGeom );
367 8 : if( NULL != poGeometry )
368 : {
369 8 : poFeature->SetGeometryDirectly( poGeometry );
370 : }
371 : }
372 : else
373 : {
374 : CPLError( CE_Failure, CPLE_AppDefined,
375 : "Invalid Feature object. "
376 0 : "Missing \'geometry\' member." );
377 0 : delete poFeature;
378 0 : return NULL;
379 : }
380 :
381 8 : return poFeature;
382 : }
383 :
384 : /************************************************************************/
385 : /* ReadFeatureCollection() */
386 : /************************************************************************/
387 :
388 : OGRGeoJSONLayer*
389 8 : OGRESRIJSONReader::ReadFeatureCollection( json_object* poObj )
390 : {
391 8 : CPLAssert( NULL != poLayer_ );
392 :
393 8 : json_object* poObjFeatures = NULL;
394 8 : poObjFeatures = OGRGeoJSONFindMemberByName( poObj, "features" );
395 8 : if( NULL == poObjFeatures )
396 : {
397 : CPLError( CE_Failure, CPLE_AppDefined,
398 : "Invalid FeatureCollection object. "
399 0 : "Missing \'features\' member." );
400 0 : return NULL;
401 : }
402 :
403 8 : if( json_type_array == json_object_get_type( poObjFeatures ) )
404 : {
405 8 : bool bAdded = false;
406 8 : OGRFeature* poFeature = NULL;
407 8 : json_object* poObjFeature = NULL;
408 :
409 8 : const int nFeatures = json_object_array_length( poObjFeatures );
410 16 : for( int i = 0; i < nFeatures; ++i )
411 : {
412 8 : poObjFeature = json_object_array_get_idx( poObjFeatures, i );
413 8 : if (poObjFeature != NULL &&
414 : json_object_get_type(poObjFeature) == json_type_object)
415 : {
416 8 : poFeature = OGRESRIJSONReader::ReadFeature( poObjFeature );
417 8 : bAdded = AddFeature( poFeature );
418 : }
419 : //CPLAssert( bAdded );
420 : }
421 : //CPLAssert( nFeatures == poLayer_->GetFeatureCount() );
422 : }
423 :
424 : // We're returning class member to follow the same pattern of
425 : // Read* functions call convention.
426 8 : CPLAssert( NULL != poLayer_ );
427 8 : return poLayer_;
428 : }
429 :
430 : /************************************************************************/
431 : /* OGRESRIJSONGetType() */
432 : /************************************************************************/
433 :
434 8 : OGRwkbGeometryType OGRESRIJSONGetGeometryType( json_object* poObj )
435 : {
436 8 : if( NULL == poObj )
437 0 : return wkbUnknown;
438 :
439 8 : json_object* poObjType = NULL;
440 8 : poObjType = OGRGeoJSONFindMemberByName( poObj, "geometryType" );
441 8 : if( NULL == poObjType )
442 : {
443 0 : return wkbNone;
444 : }
445 :
446 8 : const char* name = json_object_get_string( poObjType );
447 8 : if( EQUAL( name, "esriGeometryPoint" ) )
448 2 : return wkbPoint;
449 6 : else if( EQUAL( name, "esriGeometryPolyline" ) )
450 2 : return wkbLineString;
451 4 : else if( EQUAL( name, "esriGeometryPolygon" ) )
452 2 : return wkbPolygon;
453 2 : else if( EQUAL( name, "esriGeometryMultiPoint" ) )
454 2 : return wkbMultiPoint;
455 : else
456 0 : return wkbUnknown;
457 : }
458 :
459 : /************************************************************************/
460 : /* OGRESRIJSONReadPoint() */
461 : /************************************************************************/
462 :
463 2 : OGRPoint* OGRESRIJSONReadPoint( json_object* poObj)
464 : {
465 2 : CPLAssert( NULL != poObj );
466 :
467 2 : json_object* poObjX = OGRGeoJSONFindMemberByName( poObj, "x" );
468 2 : if( NULL == poObjX )
469 : {
470 : CPLError( CE_Failure, CPLE_AppDefined,
471 : "Invalid Point object. "
472 0 : "Missing \'x\' member." );
473 0 : return NULL;
474 : }
475 :
476 2 : int iTypeX = json_object_get_type(poObjX);
477 2 : if ( (json_type_double != iTypeX) && (json_type_int != iTypeX) )
478 : {
479 : CPLError( CE_Failure, CPLE_AppDefined,
480 : "Invalid X coordinate. Type is not double or integer for \'%s\'.",
481 0 : json_object_to_json_string(poObjX) );
482 0 : return NULL;
483 : }
484 :
485 2 : json_object* poObjY = OGRGeoJSONFindMemberByName( poObj, "y" );
486 2 : if( NULL == poObjY )
487 : {
488 : CPLError( CE_Failure, CPLE_AppDefined,
489 : "Invalid Point object. "
490 0 : "Missing \'y\' member." );
491 0 : return NULL;
492 : }
493 :
494 2 : int iTypeY = json_object_get_type(poObjY);
495 2 : if ( (json_type_double != iTypeY) && (json_type_int != iTypeY) )
496 : {
497 : CPLError( CE_Failure, CPLE_AppDefined,
498 : "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
499 0 : json_object_to_json_string(poObjY) );
500 0 : return NULL;
501 : }
502 :
503 : double dfX, dfY;
504 2 : if (iTypeX == json_type_double)
505 0 : dfX = json_object_get_double( poObjX );
506 : else
507 2 : dfX = json_object_get_int( poObjX );
508 2 : if (iTypeY == json_type_double)
509 0 : dfY = json_object_get_double( poObjY );
510 : else
511 2 : dfY = json_object_get_int( poObjY );
512 :
513 2 : return new OGRPoint(dfX, dfY);
514 : }
515 :
516 : /************************************************************************/
517 : /* OGRESRIJSONReadLineString() */
518 : /************************************************************************/
519 :
520 2 : OGRLineString* OGRESRIJSONReadLineString( json_object* poObj)
521 : {
522 2 : CPLAssert( NULL != poObj );
523 :
524 2 : OGRLineString* poLine = NULL;
525 :
526 2 : json_object* poObjPaths = OGRGeoJSONFindMemberByName( poObj, "paths" );
527 2 : if( NULL == poObjPaths )
528 : {
529 : CPLError( CE_Failure, CPLE_AppDefined,
530 : "Invalid LineString object. "
531 0 : "Missing \'paths\' member." );
532 0 : return NULL;
533 : }
534 :
535 2 : if( json_type_array != json_object_get_type( poObjPaths ) )
536 : {
537 : CPLError( CE_Failure, CPLE_AppDefined,
538 : "Invalid LineString object. "
539 0 : "Invalid \'paths\' member." );
540 0 : return NULL;
541 : }
542 :
543 2 : poLine = new OGRLineString();
544 2 : const int nPaths = json_object_array_length( poObjPaths );
545 4 : for(int iPath = 0; iPath < nPaths; iPath ++)
546 : {
547 2 : json_object* poObjPath = json_object_array_get_idx( poObjPaths, iPath );
548 2 : if ( poObjPath == NULL ||
549 : json_type_array != json_object_get_type( poObjPath ) )
550 : {
551 0 : delete poLine;
552 : CPLDebug( "ESRIJSON",
553 0 : "LineString: got non-array object." );
554 0 : return NULL;
555 : }
556 :
557 2 : const int nPoints = json_object_array_length( poObjPath );
558 6 : for(int i = 0; i < nPoints; i++)
559 : {
560 4 : json_object* poObjCoords = NULL;
561 :
562 4 : poObjCoords = json_object_array_get_idx( poObjPath, i );
563 4 : if (poObjCoords == NULL)
564 : {
565 0 : delete poLine;
566 : CPLDebug( "ESRIJSON",
567 0 : "LineString: got null object." );
568 0 : return NULL;
569 : }
570 4 : if( json_type_array != json_object_get_type( poObjCoords ) ||
571 : json_object_array_length( poObjCoords ) != 2 )
572 : {
573 0 : delete poLine;
574 : CPLDebug( "ESRIJSON",
575 0 : "LineString: got non-array object." );
576 0 : return NULL;
577 : }
578 :
579 : json_object* poObjCoord;
580 : int iType;
581 : double dfX, dfY;
582 :
583 : // Read X coordinate
584 4 : poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
585 4 : if (poObjCoord == NULL)
586 : {
587 0 : CPLDebug( "ESRIJSON", "LineString: got null object." );
588 0 : delete poLine;
589 0 : return NULL;
590 : }
591 :
592 4 : iType = json_object_get_type(poObjCoord);
593 4 : if ( (json_type_double != iType) && (json_type_int != iType) )
594 : {
595 : CPLError( CE_Failure, CPLE_AppDefined,
596 : "Invalid X coordinate. Type is not double or integer for \'%s\'.",
597 0 : json_object_to_json_string(poObjCoord) );
598 0 : delete poLine;
599 0 : return NULL;
600 : }
601 :
602 4 : if (iType == json_type_double)
603 0 : dfX = json_object_get_double( poObjCoord );
604 : else
605 4 : dfX = json_object_get_int( poObjCoord );
606 :
607 : // Read Y coordinate
608 4 : poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
609 4 : if (poObjCoord == NULL)
610 : {
611 0 : CPLDebug( "ESRIJSON", "LineString: got null object." );
612 0 : delete poLine;
613 0 : return NULL;
614 : }
615 :
616 4 : iType = json_object_get_type(poObjCoord);
617 4 : if ( (json_type_double != iType) && (json_type_int != iType) )
618 : {
619 : CPLError( CE_Failure, CPLE_AppDefined,
620 : "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
621 0 : json_object_to_json_string(poObjCoord) );
622 0 : delete poLine;
623 0 : return NULL;
624 : }
625 :
626 4 : if (iType == json_type_double)
627 0 : dfY = json_object_get_double( poObjCoord );
628 : else
629 4 : dfY = json_object_get_int( poObjCoord );
630 :
631 4 : poLine->addPoint( dfX, dfY );
632 : }
633 : }
634 :
635 2 : return poLine;
636 : }
637 :
638 : /************************************************************************/
639 : /* OGRESRIJSONReadPolygon() */
640 : /************************************************************************/
641 :
642 2 : OGRPolygon* OGRESRIJSONReadPolygon( json_object* poObj)
643 : {
644 2 : CPLAssert( NULL != poObj );
645 :
646 2 : OGRPolygon* poPoly = NULL;
647 :
648 2 : json_object* poObjRings = OGRGeoJSONFindMemberByName( poObj, "rings" );
649 2 : if( NULL == poObjRings )
650 : {
651 : CPLError( CE_Failure, CPLE_AppDefined,
652 : "Invalid Polygon object. "
653 0 : "Missing \'rings\' member." );
654 0 : return NULL;
655 : }
656 :
657 2 : if( json_type_array != json_object_get_type( poObjRings ) )
658 : {
659 : CPLError( CE_Failure, CPLE_AppDefined,
660 : "Invalid Polygon object. "
661 0 : "Invalid \'rings\' member." );
662 0 : return NULL;
663 : }
664 :
665 2 : poPoly = new OGRPolygon();
666 :
667 2 : const int nRings = json_object_array_length( poObjRings );
668 4 : for(int iRing = 0; iRing < nRings; iRing ++)
669 : {
670 2 : json_object* poObjRing = json_object_array_get_idx( poObjRings, iRing );
671 2 : if ( poObjRing == NULL ||
672 : json_type_array != json_object_get_type( poObjRing ) )
673 : {
674 0 : delete poPoly;
675 : CPLDebug( "ESRIJSON",
676 0 : "Polygon: got non-array object." );
677 0 : return NULL;
678 : }
679 :
680 2 : OGRLinearRing* poLine = new OGRLinearRing();
681 2 : poPoly->addRingDirectly(poLine);
682 :
683 2 : const int nPoints = json_object_array_length( poObjRing );
684 12 : for(int i = 0; i < nPoints; i++)
685 : {
686 10 : json_object* poObjCoords = NULL;
687 :
688 10 : poObjCoords = json_object_array_get_idx( poObjRing, i );
689 10 : if (poObjCoords == NULL)
690 : {
691 0 : delete poPoly;
692 : CPLDebug( "ESRIJSON",
693 0 : "Polygon: got null object." );
694 0 : return NULL;
695 : }
696 10 : if( json_type_array != json_object_get_type( poObjCoords ) ||
697 : json_object_array_length( poObjCoords ) != 2 )
698 : {
699 0 : delete poPoly;
700 : CPLDebug( "ESRIJSON",
701 0 : "Polygon: got non-array object." );
702 0 : return NULL;
703 : }
704 :
705 : json_object* poObjCoord;
706 : int iType;
707 : double dfX, dfY;
708 :
709 : // Read X coordinate
710 10 : poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
711 10 : if (poObjCoord == NULL)
712 : {
713 0 : CPLDebug( "ESRIJSON", "Polygon: got null object." );
714 0 : delete poPoly;
715 0 : return NULL;
716 : }
717 :
718 10 : iType = json_object_get_type(poObjCoord);
719 10 : if ( (json_type_double != iType) && (json_type_int != iType) )
720 : {
721 : CPLError( CE_Failure, CPLE_AppDefined,
722 : "Invalid X coordinate. Type is not double or integer for \'%s\'.",
723 0 : json_object_to_json_string(poObjCoord) );
724 0 : delete poPoly;
725 0 : return NULL;
726 : }
727 :
728 10 : if (iType == json_type_double)
729 0 : dfX = json_object_get_double( poObjCoord );
730 : else
731 10 : dfX = json_object_get_int( poObjCoord );
732 :
733 : // Read Y coordinate
734 10 : poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
735 10 : if (poObjCoord == NULL)
736 : {
737 0 : CPLDebug( "ESRIJSON", "Polygon: got null object." );
738 0 : delete poPoly;
739 0 : return NULL;
740 : }
741 :
742 10 : iType = json_object_get_type(poObjCoord);
743 10 : if ( (json_type_double != iType) && (json_type_int != iType) )
744 : {
745 : CPLError( CE_Failure, CPLE_AppDefined,
746 : "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
747 0 : json_object_to_json_string(poObjCoord) );
748 0 : delete poPoly;
749 0 : return NULL;
750 : }
751 :
752 10 : if (iType == json_type_double)
753 0 : dfY = json_object_get_double( poObjCoord );
754 : else
755 10 : dfY = json_object_get_int( poObjCoord );
756 :
757 10 : poLine->addPoint( dfX, dfY );
758 : }
759 : }
760 :
761 2 : return poPoly;
762 : }
763 :
764 : /************************************************************************/
765 : /* OGRESRIJSONReadMultiPoint() */
766 : /************************************************************************/
767 :
768 2 : OGRMultiPoint* OGRESRIJSONReadMultiPoint( json_object* poObj)
769 : {
770 2 : CPLAssert( NULL != poObj );
771 :
772 2 : OGRMultiPoint* poMulti = NULL;
773 :
774 2 : json_object* poObjPoints = OGRGeoJSONFindMemberByName( poObj, "points" );
775 2 : if( NULL == poObjPoints )
776 : {
777 : CPLError( CE_Failure, CPLE_AppDefined,
778 : "Invalid LineString object. "
779 0 : "Missing \'points\' member." );
780 0 : return NULL;
781 : }
782 :
783 2 : if( json_type_array != json_object_get_type( poObjPoints ) )
784 : {
785 : CPLError( CE_Failure, CPLE_AppDefined,
786 : "Invalid LineString object. "
787 0 : "Invalid \'points\' member." );
788 0 : return NULL;
789 : }
790 :
791 2 : poMulti = new OGRMultiPoint();
792 :
793 2 : const int nPoints = json_object_array_length( poObjPoints );
794 12 : for(int i = 0; i < nPoints; i++)
795 : {
796 4 : json_object* poObjCoords = NULL;
797 :
798 4 : poObjCoords = json_object_array_get_idx( poObjPoints, i );
799 4 : if (poObjCoords == NULL)
800 : {
801 0 : delete poMulti;
802 : CPLDebug( "ESRIJSON",
803 0 : "MultiPoint: got null object." );
804 0 : return NULL;
805 : }
806 4 : if( json_type_array != json_object_get_type( poObjCoords ) ||
807 : json_object_array_length( poObjCoords ) != 2 )
808 : {
809 0 : delete poMulti;
810 : CPLDebug( "ESRIJSON",
811 0 : "MultiPoint: got non-array object." );
812 0 : return NULL;
813 : }
814 :
815 : json_object* poObjCoord;
816 : int iType;
817 : double dfX, dfY;
818 :
819 : // Read X coordinate
820 4 : poObjCoord = json_object_array_get_idx( poObjCoords, 0 );
821 4 : if (poObjCoord == NULL)
822 : {
823 0 : CPLDebug( "ESRIJSON", "MultiPoint: got null object." );
824 0 : delete poMulti;
825 0 : return NULL;
826 : }
827 :
828 4 : iType = json_object_get_type(poObjCoord);
829 4 : if ( (json_type_double != iType) && (json_type_int != iType) )
830 : {
831 : CPLError( CE_Failure, CPLE_AppDefined,
832 : "Invalid X coordinate. Type is not double or integer for \'%s\'.",
833 0 : json_object_to_json_string(poObjCoord) );
834 0 : delete poMulti;
835 0 : return NULL;
836 : }
837 :
838 4 : if (iType == json_type_double)
839 0 : dfX = json_object_get_double( poObjCoord );
840 : else
841 4 : dfX = json_object_get_int( poObjCoord );
842 :
843 : // Read Y coordinate
844 4 : poObjCoord = json_object_array_get_idx( poObjCoords, 1 );
845 4 : if (poObjCoord == NULL)
846 : {
847 0 : CPLDebug( "ESRIJSON", "MultiPoint: got null object." );
848 0 : delete poMulti;
849 0 : return NULL;
850 : }
851 :
852 4 : iType = json_object_get_type(poObjCoord);
853 4 : if ( (json_type_double != iType) && (json_type_int != iType) )
854 : {
855 : CPLError( CE_Failure, CPLE_AppDefined,
856 : "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
857 0 : json_object_to_json_string(poObjCoord) );
858 0 : delete poMulti;
859 0 : return NULL;
860 : }
861 :
862 4 : if (iType == json_type_double)
863 0 : dfY = json_object_get_double( poObjCoord );
864 : else
865 4 : dfY = json_object_get_int( poObjCoord );
866 :
867 4 : poMulti->addGeometryDirectly( new OGRPoint(dfX, dfY) );
868 : }
869 :
870 2 : return poMulti;
871 : }
872 :
873 : /************************************************************************/
874 : /* OGRESRIJSONReadSpatialReference() */
875 : /************************************************************************/
876 :
877 8 : OGRSpatialReference* OGRESRIJSONReadSpatialReference( json_object* poObj )
878 : {
879 : /* -------------------------------------------------------------------- */
880 : /* Read spatial reference definition. */
881 : /* -------------------------------------------------------------------- */
882 8 : OGRSpatialReference* poSRS = NULL;
883 :
884 8 : json_object* poObjSrs = OGRGeoJSONFindMemberByName( poObj, "spatialReference" );
885 8 : if( NULL != poObjSrs )
886 : {
887 4 : json_object* poObjWkid = OGRGeoJSONFindMemberByName( poObjSrs, "wkid" );
888 4 : if (poObjWkid == NULL)
889 : {
890 0 : json_object* poObjWkt = OGRGeoJSONFindMemberByName( poObjSrs, "wkt" );
891 0 : if (poObjWkt == NULL)
892 0 : return NULL;
893 :
894 0 : char* pszWKT = (char*) json_object_get_string( poObjWkt );
895 0 : poSRS = new OGRSpatialReference();
896 0 : if( OGRERR_NONE != poSRS->importFromWkt( &pszWKT ) ||
897 : poSRS->morphFromESRI() != OGRERR_NONE )
898 : {
899 0 : delete poSRS;
900 0 : poSRS = NULL;
901 : }
902 :
903 0 : return poSRS;
904 : }
905 :
906 4 : int nEPSG = json_object_get_int( poObjWkid );
907 :
908 4 : poSRS = new OGRSpatialReference();
909 4 : if( OGRERR_NONE != poSRS->importFromEPSG( nEPSG ) )
910 : {
911 0 : delete poSRS;
912 0 : poSRS = NULL;
913 : }
914 : }
915 :
916 8 : return poSRS;
917 : }
|