1 : /******************************************************************************
2 : * $Id: ogrgeojsonreader.cpp 19506 2010-04-22 21:54:13Z rouault $
3 : *
4 : * Project: OpenGIS Simple Features Reference Implementation
5 : * Purpose: Implementation of OGRGeoJSONReader class (OGR GeoJSON Driver).
6 : * Author: Mateusz Loskot, mateusz@loskot.net
7 : *
8 : ******************************************************************************
9 : * Copyright (c) 2007, Mateusz Loskot
10 : *
11 : * Permission is hereby granted, free of charge, to any person obtaining a
12 : * copy of this software and associated documentation files (the "Software"),
13 : * to deal in the Software without restriction, including without limitation
14 : * the rights to use, copy, modify, merge, publish, distribute, sublicense,
15 : * and/or sell copies of the Software, and to permit persons to whom the
16 : * Software is furnished to do so, subject to the following conditions:
17 : *
18 : * The above copyright notice and this permission notice shall be included
19 : * in all copies or substantial portions of the Software.
20 : *
21 : * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
22 : * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23 : * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
24 : * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25 : * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26 : * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27 : * DEALINGS IN THE SOFTWARE.
28 : ****************************************************************************/
29 : #include "ogrgeojsonreader.h"
30 : #include "ogrgeojsonutils.h"
31 : #include "ogr_geojson.h"
32 : #include <jsonc/json.h> // JSON-C
33 : #include <jsonc/json_object_private.h> // json_object_iter, complete type required
34 : #include <ogr_api.h>
35 :
36 : /************************************************************************/
37 : /* OGRGeoJSONReader */
38 : /************************************************************************/
39 :
40 22 : OGRGeoJSONReader::OGRGeoJSONReader()
41 : : poGJObject_( NULL ), poLayer_( NULL ),
42 : bGeometryPreserve_( true ),
43 22 : bAttributesSkip_( false )
44 : {
45 : // Take a deep breath and get to work.
46 22 : }
47 :
48 : /************************************************************************/
49 : /* ~OGRGeoJSONReader */
50 : /************************************************************************/
51 :
52 22 : OGRGeoJSONReader::~OGRGeoJSONReader()
53 : {
54 22 : if( NULL != poGJObject_ )
55 : {
56 22 : json_object_put(poGJObject_);
57 : }
58 :
59 22 : poGJObject_ = NULL;
60 22 : poLayer_ = NULL;
61 22 : }
62 :
63 : /************************************************************************/
64 : /* Parse */
65 : /************************************************************************/
66 :
67 22 : OGRErr OGRGeoJSONReader::Parse( const char* pszText )
68 : {
69 22 : if( NULL != pszText )
70 : {
71 22 : json_tokener* jstok = NULL;
72 22 : json_object* jsobj = NULL;
73 :
74 22 : jstok = json_tokener_new();
75 22 : jsobj = json_tokener_parse_ex(jstok, pszText, -1);
76 22 : if( jstok->err != json_tokener_success)
77 : {
78 : CPLError( CE_Failure, CPLE_AppDefined,
79 : "GeoJSON parsing error: %s (at offset %d)",
80 0 : json_tokener_errors[jstok->err], jstok->char_offset);
81 :
82 0 : json_tokener_free(jstok);
83 0 : return OGRERR_CORRUPT_DATA;
84 : }
85 22 : json_tokener_free(jstok);
86 :
87 : /* JSON tree is shared for while lifetime of the reader object
88 : * and will be released in the destructor.
89 : */
90 22 : poGJObject_ = jsobj;
91 : }
92 :
93 22 : return OGRERR_NONE;
94 : }
95 :
96 : /************************************************************************/
97 : /* ReadLayer */
98 : /************************************************************************/
99 :
100 : OGRGeoJSONLayer* OGRGeoJSONReader::ReadLayer( const char* pszName,
101 22 : OGRGeoJSONDataSource* poDS )
102 : {
103 22 : CPLAssert( NULL == poLayer_ );
104 :
105 22 : if( NULL == poGJObject_ )
106 : {
107 : CPLDebug( "GeoJSON",
108 0 : "Missing parset GeoJSON data. Forgot to call Parse()?" );
109 0 : return NULL;
110 : }
111 :
112 : poLayer_ = new OGRGeoJSONLayer( pszName, NULL,
113 : OGRGeoJSONLayer::DefaultGeometryType,
114 22 : NULL, poDS );
115 :
116 22 : if( !GenerateLayerDefn() )
117 : {
118 : CPLError( CE_Failure, CPLE_AppDefined,
119 0 : "Layer schema generation failed." );
120 :
121 0 : delete poLayer_;
122 0 : return NULL;
123 : }
124 :
125 : /* -------------------------------------------------------------------- */
126 : /* Translate single geometry-only Feature object. */
127 : /* -------------------------------------------------------------------- */
128 22 : GeoJSONObject::Type objType = OGRGeoJSONGetType( poGJObject_ );
129 :
130 31 : if( GeoJSONObject::ePoint == objType
131 : || GeoJSONObject::eMultiPoint == objType
132 : || GeoJSONObject::eLineString == objType
133 : || GeoJSONObject::eMultiLineString == objType
134 : || GeoJSONObject::ePolygon == objType
135 : || GeoJSONObject::eMultiPolygon == objType
136 : || GeoJSONObject::eGeometryCollection == objType )
137 : {
138 9 : OGRGeometry* poGeometry = NULL;
139 9 : poGeometry = ReadGeometry( poGJObject_ );
140 9 : if( !AddFeature( poGeometry ) )
141 : {
142 : CPLDebug( "GeoJSON",
143 0 : "Translation of single geometry failed." );
144 0 : delete poLayer_;
145 0 : return NULL;
146 : }
147 : }
148 : /* -------------------------------------------------------------------- */
149 : /* Translate single but complete Feature object. */
150 : /* -------------------------------------------------------------------- */
151 13 : else if( GeoJSONObject::eFeature == objType )
152 : {
153 0 : OGRFeature* poFeature = NULL;
154 0 : poFeature = ReadFeature( poGJObject_ );
155 0 : if( !AddFeature( poFeature ) )
156 : {
157 : CPLDebug( "GeoJSON",
158 0 : "Translation of single feature failed." );
159 :
160 0 : delete poLayer_;
161 0 : return NULL;
162 : }
163 : }
164 : /* -------------------------------------------------------------------- */
165 : /* Translate multi-feature FeatureCollection object. */
166 : /* -------------------------------------------------------------------- */
167 13 : else if( GeoJSONObject::eFeatureCollection == objType )
168 : {
169 13 : OGRGeoJSONLayer* poThisLayer = NULL;
170 13 : poThisLayer = ReadFeatureCollection( poGJObject_ );
171 13 : CPLAssert( poLayer_ == poThisLayer );
172 : }
173 : else
174 : {
175 : CPLError( CE_Failure, CPLE_AppDefined,
176 0 : "Unrecognized GeoJSON structure." );
177 :
178 0 : delete poLayer_;
179 0 : return NULL;
180 : }
181 :
182 22 : OGRSpatialReference* poSRS = NULL;
183 22 : poSRS = OGRGeoJSONReadSpatialReference( poGJObject_ );
184 22 : if (poSRS == NULL ) {
185 : // If there is none defined, we use 4326
186 21 : poSRS = new OGRSpatialReference();
187 21 : if( OGRERR_NONE != poSRS->importFromEPSG( 4326 ) )
188 : {
189 0 : delete poSRS;
190 0 : poSRS = NULL;
191 : }
192 21 : poLayer_->SetSpatialRef( poSRS );
193 21 : delete poSRS;
194 : }
195 : else {
196 1 : poLayer_->SetSpatialRef( poSRS );
197 1 : delete poSRS;
198 : }
199 :
200 : // TODO: FeatureCollection
201 :
202 22 : return poLayer_;
203 : }
204 :
205 24 : OGRSpatialReference* OGRGeoJSONReadSpatialReference( json_object* poObj) {
206 :
207 : /* -------------------------------------------------------------------- */
208 : /* Read spatial reference definition. */
209 : /* -------------------------------------------------------------------- */
210 24 : OGRSpatialReference* poSRS = NULL;
211 :
212 24 : json_object* poObjSrs = OGRGeoJSONFindMemberByName( poObj, "crs" );
213 24 : if( NULL != poObjSrs )
214 : {
215 3 : json_object* poObjSrsType = OGRGeoJSONFindMemberByName( poObjSrs, "type" );
216 3 : const char* pszSrsType = json_object_get_string( poObjSrsType );
217 :
218 : // TODO: Add URL and URN types support
219 3 : if( EQUALN( pszSrsType, "NAME", 4 ) )
220 : {
221 3 : json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
222 3 : CPLAssert( NULL != poObjSrsProps );
223 :
224 3 : json_object* poNameURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "name" );
225 3 : CPLAssert( NULL != poNameURL );
226 :
227 3 : const char* pszName = json_object_get_string( poNameURL );
228 :
229 3 : poSRS = new OGRSpatialReference();
230 3 : if( OGRERR_NONE != poSRS->SetFromUserInput( pszName ) )
231 : {
232 0 : delete poSRS;
233 0 : poSRS = NULL;
234 : }
235 : }
236 :
237 3 : if( EQUALN( pszSrsType, "EPSG", 4 ) )
238 : {
239 0 : json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
240 0 : CPLAssert( NULL != poObjSrsProps );
241 :
242 0 : json_object* poObjCode = OGRGeoJSONFindMemberByName( poObjSrsProps, "code" );
243 0 : CPLAssert( NULL != poObjCode );
244 :
245 0 : int nEPSG = json_object_get_int( poObjCode );
246 :
247 0 : poSRS = new OGRSpatialReference();
248 0 : if( OGRERR_NONE != poSRS->importFromEPSG( nEPSG ) )
249 : {
250 0 : delete poSRS;
251 0 : poSRS = NULL;
252 : }
253 : }
254 3 : if( EQUALN( pszSrsType, "URL", 3 ) || EQUALN( pszSrsType, "LINK", 4 ) )
255 : {
256 0 : json_object* poObjSrsProps = OGRGeoJSONFindMemberByName( poObjSrs, "properties" );
257 0 : CPLAssert( NULL != poObjSrsProps );
258 :
259 0 : json_object* poObjURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "url" );
260 :
261 0 : if (NULL == poObjURL) {
262 0 : poObjURL = OGRGeoJSONFindMemberByName( poObjSrsProps, "href" );
263 : }
264 0 : CPLAssert( NULL != poObjURL );
265 :
266 0 : const char* pszURL = json_object_get_string( poObjURL );
267 :
268 0 : poSRS = new OGRSpatialReference();
269 0 : if( OGRERR_NONE != poSRS->importFromUrl( pszURL ) )
270 : {
271 0 : delete poSRS;
272 0 : poSRS = NULL;
273 :
274 : }
275 : }
276 : }
277 :
278 24 : return poSRS;
279 : }
280 : /************************************************************************/
281 : /* SetPreserveGeometryType */
282 : /************************************************************************/
283 :
284 0 : void OGRGeoJSONReader::SetPreserveGeometryType( bool bPreserve )
285 : {
286 0 : bGeometryPreserve_ = bPreserve;
287 0 : }
288 :
289 : /************************************************************************/
290 : /* SetSkipAttributes */
291 : /************************************************************************/
292 :
293 0 : void OGRGeoJSONReader::SetSkipAttributes( bool bSkip )
294 : {
295 0 : bAttributesSkip_ = bSkip;
296 0 : }
297 :
298 : /************************************************************************/
299 : /* GenerateFeatureDefn */
300 : /************************************************************************/
301 :
302 22 : bool OGRGeoJSONReader::GenerateLayerDefn()
303 : {
304 22 : CPLAssert( NULL != poGJObject_ );
305 22 : CPLAssert( NULL != poLayer_->GetLayerDefn() );
306 22 : CPLAssert( 0 == poLayer_->GetLayerDefn()->GetFieldCount() );
307 :
308 22 : bool bSuccess = true;
309 :
310 22 : if( bAttributesSkip_ )
311 0 : return true;
312 :
313 : /* -------------------------------------------------------------------- */
314 : /* Scan all features and generate layer definition. */
315 : /* -------------------------------------------------------------------- */
316 22 : GeoJSONObject::Type objType = OGRGeoJSONGetType( poGJObject_ );
317 22 : if( GeoJSONObject::eFeature == objType )
318 : {
319 0 : bSuccess = GenerateFeatureDefn( poGJObject_ );
320 : }
321 22 : else if( GeoJSONObject::eFeatureCollection == objType )
322 : {
323 13 : json_object* poObjFeatures = NULL;
324 13 : poObjFeatures = OGRGeoJSONFindMemberByName( poGJObject_, "features" );
325 13 : if( NULL != poObjFeatures
326 : && json_type_array == json_object_get_type( poObjFeatures ) )
327 : {
328 13 : json_object* poObjFeature = NULL;
329 13 : const int nFeatures = json_object_array_length( poObjFeatures );
330 48 : for( int i = 0; i < nFeatures; ++i )
331 : {
332 35 : poObjFeature = json_object_array_get_idx( poObjFeatures, i );
333 35 : if( !GenerateFeatureDefn( poObjFeature ) )
334 : {
335 0 : CPLDebug( "GeoJSON", "Create feature schema failure." );
336 0 : bSuccess = false;
337 : }
338 : }
339 : }
340 : else
341 : {
342 : CPLError( CE_Failure, CPLE_AppDefined,
343 : "Invalid FeatureCollection object. "
344 0 : "Missing \'features\' member." );
345 0 : bSuccess = false;
346 : }
347 : }
348 :
349 : /* -------------------------------------------------------------------- */
350 : /* Validate and add FID column if necessary. */
351 : /* -------------------------------------------------------------------- */
352 22 : OGRFeatureDefn* poLayerDefn = poLayer_->GetLayerDefn();
353 22 : CPLAssert( NULL != poLayerDefn );
354 :
355 22 : bool bHasFID = false;
356 :
357 46 : for( int i = 0; i < poLayerDefn->GetFieldCount(); ++i )
358 : {
359 24 : OGRFieldDefn* poDefn = poLayerDefn->GetFieldDefn(i);
360 24 : if( EQUAL( poDefn->GetNameRef(), OGRGeoJSONLayer::DefaultFIDColumn )
361 : && OFTInteger == poDefn->GetType() )
362 : {
363 0 : poLayer_->SetFIDColumn( poDefn->GetNameRef() );
364 0 : bHasFID = true;
365 0 : break;
366 : }
367 : }
368 :
369 : // TODO - mloskot: This is wrong! We want to add only FID field if
370 : // found in source layer (by default name or by FID_PROPERTY= specifier,
371 : // the latter has to be implemented).
372 : /*
373 : if( !bHasFID )
374 : {
375 : OGRFieldDefn fldDefn( OGRGeoJSONLayer::DefaultFIDColumn, OFTInteger );
376 : poLayerDefn->AddFieldDefn( &fldDefn );
377 : poLayer_->SetFIDColumn( fldDefn.GetNameRef() );
378 : }
379 : */
380 :
381 22 : return bSuccess;
382 : }
383 :
384 35 : bool OGRGeoJSONReader::GenerateFeatureDefn( json_object* poObj )
385 : {
386 35 : OGRFeatureDefn* poDefn = poLayer_->GetLayerDefn();
387 35 : CPLAssert( NULL != poDefn );
388 :
389 35 : bool bSuccess = false;
390 :
391 : /* -------------------------------------------------------------------- */
392 : /* Read collection of properties. */
393 : /* -------------------------------------------------------------------- */
394 35 : json_object* poObjProps = NULL;
395 35 : poObjProps = OGRGeoJSONFindMemberByName( poObj, "properties" );
396 35 : if( NULL != poObjProps )
397 : {
398 : json_object_iter it;
399 35 : it.key = NULL;
400 35 : it.val = NULL;
401 35 : it.entry = NULL;
402 59 : json_object_object_foreachC( poObjProps, it )
403 : {
404 24 : if( -1 == poDefn->GetFieldIndex( it.key ) )
405 : {
406 : OGRFieldDefn fldDefn( it.key,
407 24 : GeoJSONPropertyToFieldType( it.val ) );
408 24 : poDefn->AddFieldDefn( &fldDefn );
409 : }
410 : }
411 :
412 35 : bSuccess = true; // SUCCESS
413 : }
414 : else
415 : {
416 : CPLError( CE_Failure, CPLE_AppDefined,
417 : "Invalid Feature object. "
418 0 : "Missing \'properties\' member." );
419 : }
420 :
421 35 : return bSuccess;
422 : }
423 :
424 : /************************************************************************/
425 : /* AddFeature */
426 : /************************************************************************/
427 :
428 9 : bool OGRGeoJSONReader::AddFeature( OGRGeometry* poGeometry )
429 : {
430 9 : bool bAdded = false;
431 :
432 : // TODO: Should we check if geometry is of type of
433 : // wkbGeometryCollection ?
434 :
435 9 : if( NULL != poGeometry )
436 : {
437 9 : OGRFeature* poFeature = NULL;
438 9 : poFeature = new OGRFeature( poLayer_->GetLayerDefn() );
439 9 : poFeature->SetGeometryDirectly( poGeometry );
440 :
441 9 : bAdded = AddFeature( poFeature );
442 : }
443 :
444 9 : return bAdded;
445 : }
446 :
447 : /************************************************************************/
448 : /* AddFeature */
449 : /************************************************************************/
450 :
451 44 : bool OGRGeoJSONReader::AddFeature( OGRFeature* poFeature )
452 : {
453 44 : bool bAdded = false;
454 :
455 44 : if( NULL != poFeature )
456 : {
457 43 : poLayer_->AddFeature( poFeature );
458 43 : bAdded = true;
459 43 : delete poFeature;
460 : }
461 :
462 44 : return bAdded;
463 : }
464 :
465 : /************************************************************************/
466 : /* ReadGeometry */
467 : /************************************************************************/
468 :
469 43 : OGRGeometry* OGRGeoJSONReader::ReadGeometry( json_object* poObj )
470 : {
471 43 : OGRGeometry* poGeometry = NULL;
472 :
473 43 : poGeometry = OGRGeoJSONReadGeometry( poObj );
474 :
475 : /* -------------------------------------------------------------------- */
476 : /* Wrap geometry with GeometryCollection as a common denominator. */
477 : /* Sometimes a GeoJSON text may consist of objects of different */
478 : /* geometry types. Users may request wrapping all geometries with */
479 : /* OGRGeometryCollection type by using option */
480 : /* GEOMETRY_AS_COLLECTION=NO|YES (NO is default). */
481 : /* -------------------------------------------------------------------- */
482 43 : if( NULL != poGeometry )
483 : {
484 33 : if( !bGeometryPreserve_
485 : && wkbGeometryCollection != poGeometry->getGeometryType() )
486 : {
487 0 : OGRGeometryCollection* poMetaGeometry = NULL;
488 0 : poMetaGeometry = new OGRGeometryCollection();
489 0 : poMetaGeometry->addGeometryDirectly( poGeometry );
490 0 : return poMetaGeometry;
491 : }
492 : }
493 :
494 43 : return poGeometry;
495 : }
496 :
497 : /************************************************************************/
498 : /* ReadFeature() */
499 : /************************************************************************/
500 :
501 35 : OGRFeature* OGRGeoJSONReader::ReadFeature( json_object* poObj )
502 : {
503 35 : CPLAssert( NULL != poObj );
504 35 : CPLAssert( NULL != poLayer_ );
505 :
506 35 : OGRFeature* poFeature = NULL;
507 35 : poFeature = new OGRFeature( poLayer_->GetLayerDefn() );
508 :
509 : /* -------------------------------------------------------------------- */
510 : /* Translate GeoJSON "properties" object to feature attributes. */
511 : /* -------------------------------------------------------------------- */
512 35 : CPLAssert( NULL != poFeature );
513 :
514 35 : json_object* poObjProps = NULL;
515 35 : poObjProps = OGRGeoJSONFindMemberByName( poObj, "properties" );
516 35 : if( !bAttributesSkip_ && NULL != poObjProps )
517 : {
518 35 : int nField = -1;
519 35 : OGRFieldDefn* poFieldDefn = NULL;
520 : json_object_iter it;
521 35 : it.key = NULL;
522 35 : it.val = NULL;
523 35 : it.entry = NULL;
524 59 : json_object_object_foreachC( poObjProps, it )
525 : {
526 24 : nField = poFeature->GetFieldIndex(it.key);
527 24 : poFieldDefn = poFeature->GetFieldDefnRef(nField);
528 24 : CPLAssert( NULL != poFieldDefn );
529 :
530 : /* Unset FID. */
531 24 : poFeature->SetFID( -1 );
532 :
533 24 : if( OFTInteger == poFieldDefn->GetType() )
534 : {
535 0 : poFeature->SetField( nField, json_object_get_int(it.val) );
536 :
537 : /* Check if FID available and set correct value. */
538 0 : if( EQUAL( it.key, poLayer_->GetFIDColumn() ) )
539 0 : poFeature->SetFID( json_object_get_int(it.val) );
540 : }
541 24 : else if( OFTReal == poFieldDefn->GetType() )
542 : {
543 12 : poFeature->SetField( nField, json_object_get_double(it.val) );
544 : }
545 : else
546 : {
547 12 : poFeature->SetField( nField, json_object_get_string(it.val) );
548 : }
549 : }
550 : }
551 :
552 : /* -------------------------------------------------------------------- */
553 : /* If FID not set, try to use feature-level ID if available */
554 : /* and of integral type. Otherwise, leave unset (-1) then index */
555 : /* in features sequence will be used as FID. */
556 : /* -------------------------------------------------------------------- */
557 35 : if( -1 == poFeature->GetFID() )
558 : {
559 35 : json_object* poObjId = NULL;
560 35 : poObjId = OGRGeoJSONFindMemberByName( poObj, OGRGeoJSONLayer::DefaultFIDColumn );
561 35 : if( NULL != poObjId
562 : && EQUAL( OGRGeoJSONLayer::DefaultFIDColumn, poLayer_->GetFIDColumn() )
563 : && OFTInteger == GeoJSONPropertyToFieldType( poObjId ) )
564 : {
565 0 : poFeature->SetFID( json_object_get_int( poObjId ) );
566 0 : int nField = poFeature->GetFieldIndex( poLayer_->GetFIDColumn() );
567 0 : if( -1 != nField )
568 0 : poFeature->SetField( nField, (int) poFeature->GetFID() );
569 : }
570 : }
571 :
572 : /* -------------------------------------------------------------------- */
573 : /* Translate geometry sub-object of GeoJSON Feature. */
574 : /* -------------------------------------------------------------------- */
575 35 : json_object* poObjGeom = NULL;
576 :
577 35 : json_object* poTmp = poObj;
578 :
579 : json_object_iter it;
580 35 : it.key = NULL;
581 35 : it.val = NULL;
582 35 : it.entry = NULL;
583 139 : json_object_object_foreachC(poTmp, it)
584 : {
585 104 : if( EQUAL( it.key, "geometry" ) ) {
586 34 : if (it.val != NULL)
587 34 : poObjGeom = it.val;
588 : // we're done. They had 'geometry':null
589 : else
590 0 : return poFeature;
591 : }
592 : }
593 :
594 35 : if( NULL != poObjGeom )
595 : {
596 : // NOTE: If geometry can not be parsed or read correctly
597 : // then NULL geometry is assigned to a feature and
598 : // geometry type for layer is classified as wkbUnknown.
599 34 : OGRGeometry* poGeometry = ReadGeometry( poObjGeom );
600 34 : if( NULL != poGeometry )
601 : {
602 24 : poFeature->SetGeometryDirectly( poGeometry );
603 : }
604 : }
605 : else
606 : {
607 : CPLError( CE_Failure, CPLE_AppDefined,
608 : "Invalid Feature object. "
609 1 : "Missing \'geometry\' member." );
610 1 : delete poFeature;
611 1 : return NULL;
612 : }
613 :
614 34 : return poFeature;
615 : }
616 :
617 : /************************************************************************/
618 : /* ReadFeatureCollection() */
619 : /************************************************************************/
620 :
621 : OGRGeoJSONLayer*
622 13 : OGRGeoJSONReader::ReadFeatureCollection( json_object* poObj )
623 : {
624 13 : CPLAssert( NULL != poLayer_ );
625 :
626 13 : json_object* poObjFeatures = NULL;
627 13 : poObjFeatures = OGRGeoJSONFindMemberByName( poObj, "features" );
628 13 : if( NULL == poObjFeatures )
629 : {
630 : CPLError( CE_Failure, CPLE_AppDefined,
631 : "Invalid FeatureCollection object. "
632 0 : "Missing \'features\' member." );
633 0 : return NULL;
634 : }
635 :
636 13 : if( json_type_array == json_object_get_type( poObjFeatures ) )
637 : {
638 13 : bool bAdded = false;
639 13 : OGRFeature* poFeature = NULL;
640 13 : json_object* poObjFeature = NULL;
641 :
642 13 : const int nFeatures = json_object_array_length( poObjFeatures );
643 48 : for( int i = 0; i < nFeatures; ++i )
644 : {
645 35 : poObjFeature = json_object_array_get_idx( poObjFeatures, i );
646 35 : poFeature = OGRGeoJSONReader::ReadFeature( poObjFeature );
647 35 : bAdded = AddFeature( poFeature );
648 : //CPLAssert( bAdded );
649 : }
650 : //CPLAssert( nFeatures == poLayer_->GetFeatureCount() );
651 : }
652 :
653 : // We're returning class member to follow the same pattern of
654 : // Read* functions call convention.
655 13 : CPLAssert( NULL != poLayer_ );
656 13 : return poLayer_;
657 : }
658 :
659 : /************************************************************************/
660 : /* OGRGeoJSONFindMemberByName */
661 : /************************************************************************/
662 :
663 : json_object* OGRGeoJSONFindMemberByName( json_object* poObj,
664 352 : const char* pszName )
665 : {
666 352 : if( NULL == pszName || NULL == poObj)
667 0 : return NULL;
668 :
669 352 : json_object* poTmp = poObj;
670 :
671 : json_object_iter it;
672 352 : it.key = NULL;
673 352 : it.val = NULL;
674 352 : it.entry = NULL;
675 352 : if( NULL != json_object_get_object(poTmp) )
676 : {
677 352 : CPLAssert( NULL != json_object_get_object(poTmp)->head );
678 :
679 747 : for( it.entry = json_object_get_object(poTmp)->head;
680 : ( it.entry ?
681 : ( it.key = (char*)it.entry->k,
682 : it.val = (json_object*)it.entry->v, it.entry) : 0);
683 : it.entry = it.entry->next)
684 : {
685 645 : if( EQUAL( it.key, pszName ) )
686 250 : return it.val;
687 : }
688 : }
689 :
690 102 : return NULL;
691 : }
692 :
693 : /************************************************************************/
694 : /* OGRGeoJSONGetType */
695 : /************************************************************************/
696 :
697 92 : GeoJSONObject::Type OGRGeoJSONGetType( json_object* poObj )
698 : {
699 92 : if( NULL == poObj )
700 0 : return GeoJSONObject::eUnknown;
701 :
702 92 : json_object* poObjType = NULL;
703 92 : poObjType = OGRGeoJSONFindMemberByName( poObj, "type" );
704 92 : if( NULL == poObjType )
705 0 : return GeoJSONObject::eUnknown;
706 :
707 92 : const char* name = json_object_get_string( poObjType );
708 92 : if( EQUAL( name, "Point" ) )
709 12 : return GeoJSONObject::ePoint;
710 80 : else if( EQUAL( name, "LineString" ) )
711 11 : return GeoJSONObject::eLineString;
712 69 : else if( EQUAL( name, "Polygon" ) )
713 9 : return GeoJSONObject::ePolygon;
714 60 : else if( EQUAL( name, "MultiPoint" ) )
715 8 : return GeoJSONObject::eMultiPoint;
716 52 : else if( EQUAL( name, "MultiLineString" ) )
717 8 : return GeoJSONObject::eMultiLineString;
718 44 : else if( EQUAL( name, "MultiPolygon" ) )
719 9 : return GeoJSONObject::eMultiPolygon;
720 35 : else if( EQUAL( name, "GeometryCollection" ) )
721 9 : return GeoJSONObject::eGeometryCollection;
722 26 : else if( EQUAL( name, "Feature" ) )
723 0 : return GeoJSONObject::eFeature;
724 26 : else if( EQUAL( name, "FeatureCollection" ) )
725 26 : return GeoJSONObject::eFeatureCollection;
726 : else
727 0 : return GeoJSONObject::eUnknown;
728 : }
729 :
730 : /************************************************************************/
731 : /* OGRGeoJSONReadGeometry */
732 : /************************************************************************/
733 :
734 48 : OGRGeometry* OGRGeoJSONReadGeometry( json_object* poObj )
735 : {
736 48 : OGRGeometry* poGeometry = NULL;
737 :
738 48 : GeoJSONObject::Type objType = OGRGeoJSONGetType( poObj );
739 48 : if( GeoJSONObject::ePoint == objType )
740 8 : poGeometry = OGRGeoJSONReadPoint( poObj );
741 40 : else if( GeoJSONObject::eMultiPoint == objType )
742 6 : poGeometry = OGRGeoJSONReadMultiPoint( poObj );
743 34 : else if( GeoJSONObject::eLineString == objType )
744 9 : poGeometry = OGRGeoJSONReadLineString( poObj );
745 25 : else if( GeoJSONObject::eMultiLineString == objType )
746 6 : poGeometry = OGRGeoJSONReadMultiLineString( poObj );
747 19 : else if( GeoJSONObject::ePolygon == objType )
748 7 : poGeometry = OGRGeoJSONReadPolygon( poObj );
749 12 : else if( GeoJSONObject::eMultiPolygon == objType )
750 7 : poGeometry = OGRGeoJSONReadMultiPolygon( poObj );
751 5 : else if( GeoJSONObject::eGeometryCollection == objType )
752 5 : poGeometry = OGRGeoJSONReadGeometryCollection( poObj );
753 : else
754 : {
755 : CPLDebug( "GeoJSON",
756 : "Unsupported geometry type detected. "
757 0 : "Feature gets NULL geometry assigned." );
758 : }
759 : // If we have a crs object in the current object, let's try and
760 : // set it too.
761 :
762 48 : json_object* poObjSrs = OGRGeoJSONFindMemberByName( poObj, "crs" );
763 48 : if (poObjSrs != NULL) {
764 2 : OGRSpatialReference* poSRS = OGRGeoJSONReadSpatialReference(poObj);
765 2 : if (poSRS != NULL) {
766 2 : poGeometry->assignSpatialReference(poSRS);
767 2 : poSRS->Release();
768 : }
769 : }
770 48 : return poGeometry;
771 : }
772 :
773 : /************************************************************************/
774 : /* OGRGeoJSONReadRawPoint */
775 : /************************************************************************/
776 :
777 113 : bool OGRGeoJSONReadRawPoint( json_object* poObj, OGRPoint& point )
778 : {
779 113 : CPLAssert( NULL != poObj );
780 :
781 113 : if( json_type_array == json_object_get_type( poObj ) )
782 : {
783 113 : const int nSize = json_object_array_length( poObj );
784 113 : int iType = 0;
785 :
786 113 : if( nSize != GeoJSONObject::eMinCoordinateDimension
787 : && nSize != GeoJSONObject::eMaxCoordinateDimension )
788 : {
789 : CPLDebug( "GeoJSON",
790 1 : "Invalid coord dimension. Only 2D and 3D supported." );
791 1 : return false;
792 : }
793 :
794 112 : json_object* poObjCoord = NULL;
795 :
796 : // Read X coordinate
797 112 : poObjCoord = json_object_array_get_idx( poObj, 0 );
798 :
799 112 : iType = json_object_get_type(poObjCoord);
800 112 : if ( (json_type_double != iType) && (json_type_int != iType) )
801 : {
802 : CPLError( CE_Failure, CPLE_AppDefined,
803 : "Invalid X coordinate. Type is not double or integer for \'%s\'.",
804 0 : json_object_to_json_string(poObj) );
805 0 : return false;
806 : }
807 :
808 112 : if (iType == json_type_double)
809 98 : point.setX(json_object_get_double( poObjCoord ));
810 : else
811 14 : point.setX(json_object_get_int( poObjCoord ));
812 :
813 : // Read Y coordiante
814 112 : poObjCoord = json_object_array_get_idx( poObj, 1 );
815 :
816 112 : iType = json_object_get_type(poObjCoord);
817 112 : if ( (json_type_double != iType) && (json_type_int != iType) )
818 : {
819 : CPLError( CE_Failure, CPLE_AppDefined,
820 : "Invalid Y coordinate. Type is not double or integer for \'%s\'.",
821 0 : json_object_to_json_string(poObj) );
822 0 : return false;
823 : }
824 :
825 112 : if (iType == json_type_double)
826 98 : point.setY(json_object_get_double( poObjCoord ));
827 : else
828 14 : point.setY(json_object_get_int( poObjCoord ));
829 :
830 : // Read Z coordinate
831 112 : if( nSize == GeoJSONObject::eMaxCoordinateDimension )
832 : {
833 : // Don't *expect* mixed-dimension geometries, although the
834 : // spec doesn't explicitly forbid this.
835 0 : poObjCoord = json_object_array_get_idx( poObj, 2 );
836 :
837 0 : iType = json_object_get_type(poObjCoord);
838 0 : if ( (json_type_double != iType) && (json_type_int != iType) )
839 : {
840 : CPLError( CE_Failure, CPLE_AppDefined,
841 : "Invalid Z coordinate. Type is not double or integer for \'%s\'.",
842 0 : json_object_to_json_string(poObj) );
843 0 : return false;
844 : }
845 :
846 0 : if (iType == json_type_double)
847 0 : point.setZ(json_object_get_double( poObjCoord ));
848 : else
849 0 : point.setZ(json_object_get_int( poObjCoord ));
850 : }
851 : else
852 : {
853 112 : point.flattenTo2D();
854 : }
855 112 : return true;
856 : }
857 :
858 0 : return false;
859 : }
860 :
861 : /************************************************************************/
862 : /* OGRGeoJSONReadPoint */
863 : /************************************************************************/
864 :
865 8 : OGRPoint* OGRGeoJSONReadPoint( json_object* poObj )
866 : {
867 8 : CPLAssert( NULL != poObj );
868 :
869 8 : json_object* poObjCoords = NULL;
870 8 : poObjCoords = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
871 8 : if( NULL == poObjCoords )
872 : {
873 : CPLError( CE_Failure, CPLE_AppDefined,
874 1 : "Invalid Point object. Missing \'coordinates\' member." );
875 1 : return NULL;
876 : }
877 :
878 7 : OGRPoint* poPoint = new OGRPoint();
879 7 : if( !OGRGeoJSONReadRawPoint( poObjCoords, *poPoint ) )
880 : {
881 1 : CPLDebug( "GeoJSON", "Point: raw point parsing failure." );
882 1 : delete poPoint;
883 1 : return NULL;
884 : }
885 :
886 6 : return poPoint;
887 : }
888 :
889 : /************************************************************************/
890 : /* OGRGeoJSONReadMultiPoint */
891 : /************************************************************************/
892 :
893 6 : OGRMultiPoint* OGRGeoJSONReadMultiPoint( json_object* poObj )
894 : {
895 6 : CPLAssert( NULL != poObj );
896 :
897 6 : OGRMultiPoint* poMultiPoint = NULL;
898 :
899 6 : json_object* poObjPoints = NULL;
900 6 : poObjPoints = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
901 6 : if( NULL == poObjPoints )
902 : {
903 : CPLError( CE_Failure, CPLE_AppDefined,
904 : "Invalid MultiPoint object. "
905 1 : "Missing \'coordinates\' member." );
906 1 : return NULL;
907 : }
908 :
909 5 : if( json_type_array == json_object_get_type( poObjPoints ) )
910 : {
911 5 : const int nPoints = json_object_array_length( poObjPoints );
912 :
913 5 : poMultiPoint = new OGRMultiPoint();
914 :
915 16 : for( int i = 0; i < nPoints; ++i)
916 : {
917 11 : json_object* poObjCoords = NULL;
918 11 : poObjCoords = json_object_array_get_idx( poObjPoints, i );
919 :
920 11 : OGRPoint pt;
921 11 : if( poObjCoords != NULL && !OGRGeoJSONReadRawPoint( poObjCoords, pt ) )
922 : {
923 0 : delete poMultiPoint;
924 : CPLDebug( "GeoJSON",
925 0 : "LineString: raw point parsing failure." );
926 0 : return NULL;
927 : }
928 11 : poMultiPoint->addGeometry( &pt );
929 : }
930 : }
931 :
932 5 : return poMultiPoint;
933 : }
934 :
935 : /************************************************************************/
936 : /* OGRGeoJSONReadLineString */
937 : /************************************************************************/
938 :
939 18 : OGRLineString* OGRGeoJSONReadLineString( json_object* poObj , bool bRaw)
940 : {
941 18 : CPLAssert( NULL != poObj );
942 :
943 18 : OGRLineString* poLine = NULL;
944 18 : json_object* poObjPoints = NULL;
945 :
946 18 : if( !bRaw )
947 : {
948 9 : poObjPoints = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
949 9 : if( NULL == poObjPoints )
950 : {
951 : CPLError( CE_Failure, CPLE_AppDefined,
952 : "Invalid LineString object. "
953 1 : "Missing \'coordinates\' member." );
954 1 : return NULL;
955 : }
956 : }
957 : else
958 : {
959 9 : poObjPoints = poObj;
960 : }
961 :
962 17 : if( json_type_array == json_object_get_type( poObjPoints ) )
963 : {
964 17 : const int nPoints = json_object_array_length( poObjPoints );
965 :
966 17 : poLine = new OGRLineString();
967 17 : poLine->setNumPoints( nPoints );
968 :
969 45 : for( int i = 0; i < nPoints; ++i)
970 : {
971 32 : json_object* poObjCoords = NULL;
972 32 : poObjCoords = json_object_array_get_idx( poObjPoints, i );
973 32 : if (poObjCoords == NULL)
974 : {
975 4 : delete poLine;
976 : CPLDebug( "GeoJSON",
977 4 : "LineString: got null object." );
978 4 : return NULL;
979 : }
980 :
981 28 : OGRPoint pt;
982 28 : if( !OGRGeoJSONReadRawPoint( poObjCoords, pt ) )
983 : {
984 0 : delete poLine;
985 : CPLDebug( "GeoJSON",
986 0 : "LineString: raw point parsing failure." );
987 0 : return NULL;
988 : }
989 28 : if (pt.getCoordinateDimension() == 2) {
990 28 : poLine->setPoint( i, pt.getX(), pt.getY());
991 : } else {
992 0 : poLine->setPoint( i, pt.getX(), pt.getY(), pt.getZ() );
993 : }
994 :
995 : }
996 : }
997 :
998 13 : return poLine;
999 : }
1000 :
1001 : /************************************************************************/
1002 : /* OGRGeoJSONReadMultiLineString */
1003 : /************************************************************************/
1004 :
1005 6 : OGRMultiLineString* OGRGeoJSONReadMultiLineString( json_object* poObj )
1006 : {
1007 6 : CPLAssert( NULL != poObj );
1008 :
1009 6 : OGRMultiLineString* poMultiLine = NULL;
1010 :
1011 6 : json_object* poObjLines = NULL;
1012 6 : poObjLines = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
1013 6 : if( NULL == poObjLines )
1014 : {
1015 : CPLError( CE_Failure, CPLE_AppDefined,
1016 : "Invalid MultiLineString object. "
1017 1 : "Missing \'coordinates\' member." );
1018 1 : return NULL;
1019 : }
1020 :
1021 5 : if( json_type_array == json_object_get_type( poObjLines ) )
1022 : {
1023 5 : const int nLines = json_object_array_length( poObjLines );
1024 :
1025 5 : poMultiLine = new OGRMultiLineString();
1026 :
1027 16 : for( int i = 0; i < nLines; ++i)
1028 : {
1029 11 : json_object* poObjLine = NULL;
1030 11 : poObjLine = json_object_array_get_idx( poObjLines, i );
1031 :
1032 : OGRLineString* poLine;
1033 11 : if (poObjLine != NULL)
1034 9 : poLine = OGRGeoJSONReadLineString( poObjLine , true );
1035 : else
1036 2 : poLine = new OGRLineString();
1037 :
1038 11 : if( NULL != poLine )
1039 : {
1040 9 : poMultiLine->addGeometryDirectly( poLine );
1041 : }
1042 : }
1043 : }
1044 :
1045 5 : return poMultiLine;
1046 : }
1047 :
1048 : /************************************************************************/
1049 : /* OGRGeoJSONReadLinearRing */
1050 : /************************************************************************/
1051 :
1052 15 : OGRLinearRing* OGRGeoJSONReadLinearRing( json_object* poObj )
1053 : {
1054 15 : CPLAssert( NULL != poObj );
1055 :
1056 15 : OGRLinearRing* poRing = NULL;
1057 :
1058 15 : if( json_type_array == json_object_get_type( poObj ) )
1059 : {
1060 15 : const int nPoints = json_object_array_length( poObj );
1061 :
1062 15 : poRing= new OGRLinearRing();
1063 15 : poRing->setNumPoints( nPoints );
1064 :
1065 85 : for( int i = 0; i < nPoints; ++i)
1066 : {
1067 70 : json_object* poObjCoords = NULL;
1068 70 : poObjCoords = json_object_array_get_idx( poObj, i );
1069 70 : if (poObjCoords == NULL)
1070 : {
1071 0 : delete poRing;
1072 : CPLDebug( "GeoJSON",
1073 0 : "LinearRing: got null object." );
1074 0 : return NULL;
1075 : }
1076 :
1077 70 : OGRPoint pt;
1078 70 : if( !OGRGeoJSONReadRawPoint( poObjCoords, pt ) )
1079 : {
1080 0 : delete poRing;
1081 : CPLDebug( "GeoJSON",
1082 0 : "LinearRing: raw point parsing failure." );
1083 0 : return NULL;
1084 : }
1085 :
1086 70 : if( 2 == pt.getCoordinateDimension() )
1087 70 : poRing->setPoint( i, pt.getX(), pt.getY());
1088 : else
1089 0 : poRing->setPoint( i, pt.getX(), pt.getY(), pt.getZ() );
1090 : }
1091 : }
1092 :
1093 15 : return poRing;
1094 : }
1095 :
1096 : /************************************************************************/
1097 : /* OGRGeoJSONReadPolygon */
1098 : /************************************************************************/
1099 :
1100 18 : OGRPolygon* OGRGeoJSONReadPolygon( json_object* poObj , bool bRaw )
1101 : {
1102 18 : CPLAssert( NULL != poObj );
1103 :
1104 18 : OGRPolygon* poPolygon = NULL;
1105 :
1106 18 : json_object* poObjRings = NULL;
1107 :
1108 18 : if( !bRaw )
1109 : {
1110 7 : poObjRings = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
1111 7 : if( NULL == poObjRings )
1112 : {
1113 : CPLError( CE_Failure, CPLE_AppDefined,
1114 : "Invalid Polygon object. "
1115 1 : "Missing \'coordinates\' member." );
1116 1 : return NULL;
1117 : }
1118 : }
1119 : else
1120 : {
1121 11 : poObjRings = poObj;
1122 : }
1123 :
1124 17 : if( json_type_array == json_object_get_type( poObjRings ) )
1125 : {
1126 17 : const int nRings = json_object_array_length( poObjRings );
1127 17 : if( nRings > 0 )
1128 : {
1129 15 : json_object* poObjPoints = NULL;
1130 15 : poObjPoints = json_object_array_get_idx( poObjRings, 0 );
1131 15 : if (poObjPoints == NULL)
1132 : {
1133 2 : poPolygon = new OGRPolygon();
1134 4 : poPolygon->addRingDirectly( new OGRLinearRing() );
1135 : }
1136 : else
1137 : {
1138 13 : OGRLinearRing* poRing = OGRGeoJSONReadLinearRing( poObjPoints );
1139 13 : if( NULL != poRing )
1140 : {
1141 13 : poPolygon = new OGRPolygon();
1142 13 : poPolygon->addRingDirectly( poRing );
1143 : }
1144 : }
1145 :
1146 18 : for( int i = 1; i < nRings && NULL != poPolygon; ++i )
1147 : {
1148 3 : poObjPoints = json_object_array_get_idx( poObjRings, i );
1149 3 : if (poObjPoints == NULL)
1150 : {
1151 1 : poPolygon->addRingDirectly( new OGRLinearRing() );
1152 : }
1153 : else
1154 : {
1155 2 : OGRLinearRing* poRing = OGRGeoJSONReadLinearRing( poObjPoints );
1156 2 : if( NULL != poRing )
1157 : {
1158 2 : poPolygon->addRingDirectly( poRing );
1159 : }
1160 : }
1161 : }
1162 : }
1163 : }
1164 :
1165 17 : return poPolygon;
1166 : }
1167 :
1168 : /************************************************************************/
1169 : /* OGRGeoJSONReadMultiPolygon */
1170 : /************************************************************************/
1171 :
1172 7 : OGRMultiPolygon* OGRGeoJSONReadMultiPolygon( json_object* poObj )
1173 : {
1174 7 : CPLAssert( NULL != poObj );
1175 :
1176 7 : OGRMultiPolygon* poMultiPoly = NULL;
1177 :
1178 7 : json_object* poObjPolys = NULL;
1179 7 : poObjPolys = OGRGeoJSONFindMemberByName( poObj, "coordinates" );
1180 7 : if( NULL == poObjPolys )
1181 : {
1182 : CPLError( CE_Failure, CPLE_AppDefined,
1183 : "Invalid MultiPolygon object. "
1184 1 : "Missing \'coordinates\' member." );
1185 1 : return NULL;
1186 : }
1187 :
1188 6 : if( json_type_array == json_object_get_type( poObjPolys ) )
1189 : {
1190 6 : const int nPolys = json_object_array_length( poObjPolys );
1191 :
1192 6 : poMultiPoly = new OGRMultiPolygon();
1193 :
1194 20 : for( int i = 0; i < nPolys; ++i)
1195 : {
1196 :
1197 14 : json_object* poObjPoly = NULL;
1198 14 : poObjPoly = json_object_array_get_idx( poObjPolys, i );
1199 14 : if (poObjPoly == NULL)
1200 : {
1201 3 : poMultiPoly->addGeometryDirectly( new OGRPolygon() );
1202 : }
1203 : else
1204 : {
1205 11 : OGRPolygon* poPoly = OGRGeoJSONReadPolygon( poObjPoly , true );
1206 11 : if( NULL != poPoly )
1207 : {
1208 9 : poMultiPoly->addGeometryDirectly( poPoly );
1209 : }
1210 : }
1211 : }
1212 : }
1213 :
1214 6 : return poMultiPoly;
1215 : }
1216 : /************************************************************************/
1217 : /* OGRGeoJSONReadGeometryCollection */
1218 : /************************************************************************/
1219 :
1220 5 : OGRGeometryCollection* OGRGeoJSONReadGeometryCollection( json_object* poObj )
1221 : {
1222 5 : CPLAssert( NULL != poObj );
1223 :
1224 5 : OGRGeometry* poGeometry = NULL;
1225 5 : OGRGeometryCollection* poCollection = NULL;
1226 :
1227 5 : json_object* poObjGeoms = NULL;
1228 5 : poObjGeoms = OGRGeoJSONFindMemberByName( poObj, "geometries" );
1229 5 : if( NULL == poObjGeoms )
1230 : {
1231 : CPLError( CE_Failure, CPLE_AppDefined,
1232 : "Invalid GeometryCollection object. "
1233 1 : "Missing \'geometries\' member." );
1234 1 : return NULL;
1235 : }
1236 :
1237 4 : if( json_type_array == json_object_get_type( poObjGeoms ) )
1238 : {
1239 4 : const int nGeoms = json_object_array_length( poObjGeoms );
1240 4 : if( nGeoms > 0 )
1241 : {
1242 4 : poCollection = new OGRGeometryCollection();
1243 : }
1244 :
1245 4 : json_object* poObjGeom = NULL;
1246 12 : for( int i = 0; i < nGeoms; ++i )
1247 : {
1248 8 : poObjGeom = json_object_array_get_idx( poObjGeoms, i );
1249 8 : if (poObjGeom == NULL)
1250 : {
1251 3 : CPLDebug( "GeoJSON", "Skipping null sub-geometry");
1252 3 : continue;
1253 : }
1254 :
1255 5 : poGeometry = OGRGeoJSONReadGeometry( poObjGeom );
1256 5 : if( NULL != poGeometry )
1257 : {
1258 5 : poCollection->addGeometryDirectly( poGeometry );
1259 : }
1260 : }
1261 : }
1262 :
1263 4 : return poCollection;
1264 : }
1265 :
1266 : /************************************************************************/
1267 : /* OGR_G_ExportToJson */
1268 : /************************************************************************/
1269 :
1270 0 : OGRGeometryH OGR_G_CreateGeometryFromJson( const char* pszJson )
1271 : {
1272 0 : VALIDATE_POINTER1( pszJson, "OGR_G_CreateGeometryFromJson", NULL );
1273 :
1274 0 : if( NULL != pszJson )
1275 : {
1276 0 : json_tokener* jstok = NULL;
1277 0 : json_object* poObj = NULL;
1278 :
1279 0 : jstok = json_tokener_new();
1280 0 : poObj = json_tokener_parse_ex(jstok, pszJson, -1);
1281 0 : if( jstok->err != json_tokener_success)
1282 : {
1283 : CPLError( CE_Failure, CPLE_AppDefined,
1284 : "GeoJSON parsing error: %s (at offset %d)",
1285 0 : json_tokener_errors[jstok->err], jstok->char_offset);
1286 0 : json_tokener_free(jstok);
1287 0 : return NULL;
1288 : }
1289 0 : json_tokener_free(jstok);
1290 :
1291 0 : OGRGeometry* poGeometry = NULL;
1292 0 : poGeometry = OGRGeoJSONReadGeometry( poObj );
1293 :
1294 : /* Release JSON tree. */
1295 0 : json_object_put( poObj );
1296 :
1297 0 : return (OGRGeometryH)poGeometry;
1298 : }
1299 :
1300 : /* Translation failed */
1301 0 : return NULL;
1302 : }
1303 :
|