]> granicus.if.org Git - postgis/commitdiff
Add lwgeom_from_geojson to liblwgeom, add cunit test, fix memory leak
authorSandro Santilli <strk@keybit.net>
Thu, 28 Feb 2013 17:04:44 +0000 (17:04 +0000)
committerSandro Santilli <strk@keybit.net>
Thu, 28 Feb 2013 17:04:44 +0000 (17:04 +0000)
git-svn-id: http://svn.osgeo.org/postgis/trunk@11119 b70326c6-7e19-0410-871a-916f4a2858ee

NEWS
configure.ac
liblwgeom/Makefile.in
liblwgeom/cunit/Makefile.in
liblwgeom/cunit/cu_in_geojson.c [new file with mode: 0644]
liblwgeom/cunit/cu_tester.c
liblwgeom/liblwgeom.h.in
liblwgeom/lwin_geojson.c [new file with mode: 0644]
postgis/lwgeom_in_geojson.c

diff --git a/NEWS b/NEWS
index 44da35448fdbd527c83d725df943f736e2583ec5..297c6244644e65f6e5ba981516ef4973830ed07a 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -68,6 +68,7 @@ PostGIS 2.1.0
   - #945, improved join selectivity, N-D selectivity calculations, user
     accessible selectivity and stats reader functions for testing
   - #2210, ST_MinConvexHull(raster)
+  - lwgeom_from_geojson in liblwgeom (Sandro Santilli / Vizzuality)
 
 * Enhancements *
   - #823,  tiger geocoder: Make loader_generate_script download portion 
index f904246df1461dc6642e244c470ef5c54c94ad67..929d2e8fd0ebc46f5787bed86d65fda3264b14ec 100644 (file)
@@ -840,7 +840,7 @@ dnl Always enable use of ANALYZE statistics by default
 AC_DEFINE_UNQUOTED([POSTGIS_USE_STATS], [1], [Enable use of ANALYZE statistics])
 
 
-CPPFLAGS="$PGSQL_CPPFLAGS $GEOS_CPPFLAGS $PROJ_CPPFLAGS $JSON_CPPFLAGS $XML2_CPPFLAGS"
+CPPFLAGS="$PGSQL_CPPFLAGS $GEOS_CPPFLAGS $PROJ_CPPFLAGS $XML2_CPPFLAGS"
 dnl AC_MSG_RESULT([CPPFLAGS: $CPPFLAGS])
 
 SHLIB_LINK="$PGSQL_LDFLAGS $GEOS_LDFLAGS $PROJ_LDFLAGS -lgeos_c -lproj $JSON_LDFLAGS $XML2_LDFLAGS"
index cad453d8fec009f1b336602acccd2e9d6d594db3..7ee6bd2ef12c8000fc4847b58e02e2ed67c4392b 100644 (file)
@@ -11,8 +11,8 @@
 # **********************************************************************
 
 CC = @CC@
-CFLAGS = @CFLAGS@ @PICFLAGS@ @WARNFLAGS@ @GEOS_CPPFLAGS@ @PROJ_CPPFLAGS@
-LDFLAGS = @LDFLAGS@ @GEOS_LDFLAGS@ -lgeos_c @PROJ_LDFLAGS@ -lproj
+CFLAGS = @CFLAGS@ @PICFLAGS@ @WARNFLAGS@ @GEOS_CPPFLAGS@ @PROJ_CPPFLAGS@ @JSON_CPPFLAGS@
+LDFLAGS = @LDFLAGS@ @GEOS_LDFLAGS@ -lgeos_c @PROJ_LDFLAGS@ -lproj @JSON_LDFLAGS@
 NUMERICFLAGS = @NUMERICFLAGS@
 top_builddir = @top_builddir@
 prefix = @prefix@
@@ -57,6 +57,7 @@ SA_OBJS = \
        lwpsurface.o \
        lwtin.o \
        lwout_wkb.o \
+       lwin_geojson.o \
        lwin_wkb.o \
        lwout_wkt.o \
        lwin_wkt_parse.o \
index fc3f399f9c081569bb9e7f5088c151d9e0208eae..e5723aeb14e19ed62630604faee14b1bca8f2465 100644 (file)
@@ -46,6 +46,7 @@ OBJS= \
        cu_out_svg.o \
        cu_surface.o \
        cu_out_x3d.o \
+       cu_in_geojson.o \
        cu_in_wkb.o \
        cu_in_wkt.o \
        cu_tester.o 
diff --git a/liblwgeom/cunit/cu_in_geojson.c b/liblwgeom/cunit/cu_in_geojson.c
new file mode 100644 (file)
index 0000000..5ecbf23
--- /dev/null
@@ -0,0 +1,228 @@
+/**********************************************************************
+ * $Id$
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ * http://postgis.refractions.net
+ *
+ * Copyright 2013 Sandro Santilli <strk@keybit.net>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include "CUnit/Basic.h"
+
+#include "liblwgeom_internal.h"
+#include "cu_tester.h"
+
+static void do_geojson_test(const char * exp, char * in, char * exp_srs, int precision, int has_bbox)
+{
+       LWGEOM *g;
+       char * h = NULL;
+  char * srs = NULL;
+  size_t size;
+
+  has_bbox = has_bbox; /* unused */
+
+       g = lwgeom_from_geojson(in, &srs);
+       h = lwgeom_to_wkt(g, WKT_EXTENDED, 15, &size);
+
+       if (strcmp(h, exp)) {
+               fprintf(stderr, "\nIn:   %s\nExp:  %s\nObt: %s\n", in, exp, h);
+         CU_ASSERT_STRING_EQUAL(h, exp);
+  }
+
+  if ( exp_srs ) {
+    if ( ! srs ) {
+      fprintf(stderr, "\nIn:   %s\nExp:  %s\nObt: (null)\n", in, exp_srs);
+           CU_ASSERT_EQUAL(srs, exp_srs);
+    }
+    else if (strcmp(srs, exp_srs)) {
+      fprintf(stderr, "\nIn:   %s\nExp:  %s\nObt: %s\n", in, exp_srs, srs);
+           CU_ASSERT_STRING_EQUAL(srs, exp_srs);
+    }
+  } else if ( srs ) {
+    fprintf(stderr, "\nIn:   %s\nExp:  (null)\nObt: %s\n", in, srs);
+         CU_ASSERT_EQUAL(srs, exp_srs);
+  }
+
+       lwgeom_free(g);
+       if ( h ) lwfree(h);
+  if ( srs ) lwfree(srs);
+}
+
+
+static void do_geojson_unsupported(char * in, char * exp)
+{
+       LWGEOM *g;
+       char * h = NULL;
+  char * srs = NULL;
+  size_t size;
+
+       g = lwgeom_from_geojson(in, &srs);
+
+  if ( g ) {
+         h = lwgeom_to_wkt(g, WKT_ISO, 1, &size);
+    fprintf(stderr, "\nIn:   %s\nExp:  %s\nObt: %s\n",
+              in, exp, h);
+    CU_ASSERT(!g);
+  } else {
+
+    if (strcmp(cu_error_msg, exp))
+      fprintf(stderr, "\nIn:   %s\nExp:  %s\nObt: %s\n",
+              in, exp, cu_error_msg);
+    CU_ASSERT_STRING_EQUAL(in, cu_error_msg);
+  }
+
+  cu_error_msg_reset();
+
+  if ( srs ) lwfree(srs);
+  if ( h ) lwfree(h);
+       lwgeom_free(g);
+}
+
+static void in_geojson_test_srid(void)
+{
+       /* Linestring */
+       do_geojson_test(
+           "LINESTRING(0 1,2 3,4 5)",
+           "{\"type\":\"LineString\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}},\"coordinates\":[[0,1],[2,3],[4,5]]}",
+           "EPSG:4326", 0, 0);
+
+       /* Polygon */
+       do_geojson_test(
+           "POLYGON((0 1,2 3,4 5,0 1))",
+           "{\"type\":\"Polygon\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}},\"coordinates\":[[[0,1],[2,3],[4,5],[0,1]]]}",
+           "EPSG:4326", 0, 0);
+
+       /* Polygon - with internal ring */
+       do_geojson_test(
+           "POLYGON((0 1,2 3,4 5,0 1),(6 7,8 9,10 11,6 7))",
+           "{\"type\":\"Polygon\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}},\"coordinates\":[[[0,1],[2,3],[4,5],[0,1]],[[6,7],[8,9],[10,11],[6,7]]]}",
+           "EPSG:4326", 0, 0);
+
+       /* Multiline */
+       do_geojson_test(
+           "MULTILINESTRING((0 1,2 3,4 5),(6 7,8 9,10 11))",
+           "{\"type\":\"MultiLineString\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}},\"coordinates\":[[[0,1],[2,3],[4,5]],[[6,7],[8,9],[10,11]]]}",
+           "EPSG:4326", 0, 0);
+
+       /* MultiPolygon */
+       do_geojson_test(
+           "MULTIPOLYGON(((0 1,2 3,4 5,0 1)),((6 7,8 9,10 11,6 7)))",
+           "{\"type\":\"MultiPolygon\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}},\"coordinates\":[[[[0,1],[2,3],[4,5],[0,1]]],[[[6,7],[8,9],[10,11],[6,7]]]]}",
+           "EPSG:4326", 0, 0);
+
+       /* Empty GeometryCollection */
+       do_geojson_test(
+           "GEOMETRYCOLLECTION EMPTY",
+           "{\"type\":\"GeometryCollection\",\"crs\":{\"type\":\"name\",\"properties\":{\"name\":\"EPSG:4326\"}},\"geometries\":[]}",
+           "EPSG:4326", 0, 0);
+}
+
+static void in_geojson_test_bbox(void)
+{
+       /* Linestring */
+       do_geojson_test(
+           "LINESTRING(0 1,2 3,4 5)",
+           "{\"type\":\"LineString\",\"bbox\":[0,1,4,5],\"coordinates\":[[0,1],[2,3],[4,5]]}",
+           NULL, 0, 1);
+
+       /* Polygon */
+       do_geojson_test(
+           "POLYGON((0 1,2 3,4 5,0 1))",
+           "{\"type\":\"Polygon\",\"bbox\":[0,1,4,5],\"coordinates\":[[[0,1],[2,3],[4,5],[0,1]]]}",
+           NULL, 0, 1);
+
+       /* Polygon - with internal ring */
+       do_geojson_test(
+           "POLYGON((0 1,2 3,4 5,0 1),(6 7,8 9,10 11,6 7))",
+           "{\"type\":\"Polygon\",\"bbox\":[0,1,4,5],\"coordinates\":[[[0,1],[2,3],[4,5],[0,1]],[[6,7],[8,9],[10,11],[6,7]]]}",
+           NULL, 0, 1);
+
+       /* Multiline */
+       do_geojson_test(
+           "MULTILINESTRING((0 1,2 3,4 5),(6 7,8 9,10 11))",
+           "{\"type\":\"MultiLineString\",\"bbox\":[0,1,10,11],\"coordinates\":[[[0,1],[2,3],[4,5]],[[6,7],[8,9],[10,11]]]}",
+           NULL, 0, 1);
+
+       /* MultiPolygon */
+       do_geojson_test(
+           "MULTIPOLYGON(((0 1,2 3,4 5,0 1)),((6 7,8 9,10 11,6 7)))",
+           "{\"type\":\"MultiPolygon\",\"bbox\":[0,1,10,11],\"coordinates\":[[[[0,1],[2,3],[4,5],[0,1]]],[[[6,7],[8,9],[10,11],[6,7]]]]}",
+           NULL, 0, 1);
+
+       /* GeometryCollection */
+       do_geojson_test(
+           "GEOMETRYCOLLECTION(LINESTRING(0 1,-1 3),LINESTRING(2 3,4 5))",
+           "{\"type\":\"GeometryCollection\",\"bbox\":[-1,1,4,5],\"geometries\":[{\"type\":\"LineString\",\"coordinates\":[[0,1],[-1,3]]},{\"type\":\"LineString\",\"coordinates\":[[2,3],[4,5]]}]}",
+           NULL, 0, 1);
+
+       /* Empty GeometryCollection */
+       do_geojson_test(
+           "GEOMETRYCOLLECTION EMPTY",
+           "{\"type\":\"GeometryCollection\",\"geometries\":[]}",
+           NULL, 0, 1);
+}
+
+static void in_geojson_test_geoms(void)
+{
+       /* Linestring */
+       do_geojson_test(
+           "LINESTRING(0 1,2 3,4 5)",
+           "{\"type\":\"LineString\",\"coordinates\":[[0,1],[2,3],[4,5]]}",
+           NULL, 0, 0);
+
+       /* Polygon */
+       do_geojson_test(
+           "POLYGON((0 1,2 3,4 5,0 1))",
+           "{\"type\":\"Polygon\",\"coordinates\":[[[0,1],[2,3],[4,5],[0,1]]]}",
+           NULL, 0, 0);
+
+       /* Polygon - with internal ring */
+       do_geojson_test(
+           "POLYGON((0 1,2 3,4 5,0 1),(6 7,8 9,10 11,6 7))",
+           "{\"type\":\"Polygon\",\"coordinates\":[[[0,1],[2,3],[4,5],[0,1]],[[6,7],[8,9],[10,11],[6,7]]]}",
+           NULL, 0, 0);
+
+       /* Multiline */
+       do_geojson_test(
+           "MULTILINESTRING((0 1,2 3,4 5),(6 7,8 9,10 11))",
+           "{\"type\":\"MultiLineString\",\"coordinates\":[[[0,1],[2,3],[4,5]],[[6,7],[8,9],[10,11]]]}",
+           NULL, 0, 0);
+
+       /* MultiPolygon */
+       do_geojson_test(
+           "MULTIPOLYGON(((0 1,2 3,4 5,0 1)),((6 7,8 9,10 11,6 7)))",
+           "{\"type\":\"MultiPolygon\",\"coordinates\":[[[[0,1],[2,3],[4,5],[0,1]]],[[[6,7],[8,9],[10,11],[6,7]]]]}",
+           NULL, 0, 0);
+
+       /* GeometryCollection */
+       do_geojson_test(
+           "GEOMETRYCOLLECTION(POINT(0 1),LINESTRING(2 3,4 5))",
+           "{\"type\":\"GeometryCollection\",\"geometries\":[{\"type\":\"Point\",\"coordinates\":[0,1]},{\"type\":\"LineString\",\"coordinates\":[[2,3],[4,5]]}]}",
+           NULL, 0, 0);
+
+       /* Empty GeometryCollection */
+       do_geojson_test(
+           "GEOMETRYCOLLECTION EMPTY",
+           "{\"type\":\"GeometryCollection\",\"geometries\":[]}",
+           NULL, 0, 0);
+
+}
+
+/*
+** Used by test harness to register the tests in this file.
+*/
+CU_TestInfo in_geojson_tests[] =
+{
+       PG_TEST(in_geojson_test_srid),
+       PG_TEST(in_geojson_test_bbox),
+       PG_TEST(in_geojson_test_geoms),
+       CU_TEST_INFO_NULL
+};
+CU_SuiteInfo in_geojson_suite = {"in_geojson",  NULL,  NULL, in_geojson_tests};
index 3dc8677dab10414c64c75fe8616225c358d955f3..4fc8ffe85a65d2d637da51003fe7bebd0c1f683f 100644 (file)
@@ -40,6 +40,7 @@ extern CU_SuiteInfo geos_suite;
 extern CU_SuiteInfo tree_suite;
 extern CU_SuiteInfo triangulate_suite;
 extern CU_SuiteInfo homogenize_suite;
+extern CU_SuiteInfo in_geojson_suite;
 extern CU_SuiteInfo stringbuffer_suite;
 extern CU_SuiteInfo surface_suite;
 extern CU_SuiteInfo out_gml_suite;
@@ -79,6 +80,7 @@ int main(int argc, char *argv[])
                stringbuffer_suite,
                surface_suite,
                homogenize_suite,
+               in_geojson_suite,
                out_gml_suite,
                out_kml_suite,
                out_geojson_suite,
index 1cf353766f2619fb83b09aff1260236ce4713b38..84c698f134f7bcea545374f245530b8f771e4ec2 100644 (file)
@@ -1349,6 +1349,17 @@ extern char* lwgeom_to_geojson(const LWGEOM *geo, char *srs, int precision, int
 extern char* lwgeom_to_svg(const LWGEOM *geom, int precision, int relative);
 extern char* lwgeom_to_x3d3(const LWGEOM *geom, char *srs, int precision, int opts, const char *defid);
 
+/**
+ * Create an LWGEOM object from a GeoJSON representation
+ *
+ * @param geojson the GeoJSON input
+ * @param srs output parameter. Will be set to a newly allocated
+ *            string holding the spatial reference string, or NULL
+ *            if no such parameter is found in input.
+ *            If not null, the pointer must be freed with lwfree.
+ */
+extern LWGEOM* lwgeom_from_geojson(const char *geojson, char **srs);
+
 /**
 * Initialize a spheroid object for use in geodetic functions.
 */
diff --git a/liblwgeom/lwin_geojson.c b/liblwgeom/lwin_geojson.c
new file mode 100644 (file)
index 0000000..7e0d95f
--- /dev/null
@@ -0,0 +1,555 @@
+/**********************************************************************
+ *
+ * PostGIS - Spatial Types for PostgreSQL
+ *
+ * Copyright 2013 Sandro Santilli <strk@keybit.net>
+ * Copyright 2011 Kashif Rasul <kashif.rasul@gmail.com>
+ *
+ * This is free software; you can redistribute and/or modify it under
+ * the terms of the GNU General Public Licence. See the COPYING file.
+ *
+ **********************************************************************/
+
+#include <assert.h>
+#include "liblwgeom.h"
+#include "lwgeom_log.h"
+#include "../postgis_config.h"
+
+#ifdef HAVE_LIBJSON
+
+#include <json/json.h>
+#include <json/json_object_private.h>
+#include <string.h>
+
+static void geojson_lwerror(char *msg, int error_code)
+{
+       LWDEBUGF(3, "lwgeom_from_geojson ERROR %i", error_code);
+       lwerror("%s", msg);
+}
+
+/* Prototype */
+static LWGEOM* parse_geojson(json_object *geojson, int *hasz,  int root_srid);
+
+static json_object*
+findMemberByName(json_object* poObj, const char* pszName )
+{
+       json_object* poTmp;
+       json_object_iter it;
+
+       poTmp = poObj;
+
+       if( NULL == pszName || NULL == poObj)
+               return NULL;
+
+       it.key = NULL;
+       it.val = NULL;
+       it.entry = NULL;
+
+       if( NULL != json_object_get_object(poTmp) )
+       {
+               assert( NULL != json_object_get_object(poTmp)->head );
+
+               for( it.entry = json_object_get_object(poTmp)->head;
+                       ( it.entry ?
+                         ( it.key = (char*)it.entry->k,
+                           it.val = (json_object*)it.entry->v, it.entry) : 0);
+                       it.entry = it.entry->next)
+               {
+                       if( strcasecmp((char *)it.key, pszName )==0 )
+                               return it.val;
+               }
+       }
+
+       return NULL;
+}
+
+
+static int
+parse_geojson_coord(json_object *poObj, int *hasz, POINTARRAY *pa)
+{
+       POINT4D pt;
+       int iType = 0;
+
+       LWDEBUGF(3, "parse_geojson_coord called for object %s.", json_object_to_json_string( poObj ) );
+
+       if( json_type_array == json_object_get_type( poObj ) )
+       {
+
+               json_object* poObjCoord = NULL;
+               const int nSize = json_object_array_length( poObj );
+               LWDEBUGF(3, "parse_geojson_coord called for array size %d.", nSize );
+
+
+               // Read X coordinate
+               poObjCoord = json_object_array_get_idx( poObj, 0 );
+               iType = json_object_get_type(poObjCoord);
+               if (iType == json_type_double)
+                       pt.x = json_object_get_double( poObjCoord );
+               else
+                       pt.x = json_object_get_int( poObjCoord );
+               LWDEBUGF(3, "parse_geojson_coord pt.x = %f.", pt.x );
+
+               // Read Y coordiante
+               poObjCoord = json_object_array_get_idx( poObj, 1 );
+               if (iType == json_type_double)
+                       pt.y = json_object_get_double( poObjCoord );
+               else
+                       pt.y = json_object_get_int( poObjCoord );
+               LWDEBUGF(3, "parse_geojson_coord pt.y = %f.", pt.y );
+
+               if( nSize == 3 ) /* should this be >= 3 ? */
+               {
+                       // Read Z coordiante
+                       poObjCoord = json_object_array_get_idx( poObj, 2 );
+                       if (iType == 3)
+                               pt.z = json_object_get_double( poObjCoord );
+                       else
+                               pt.z = json_object_get_int( poObjCoord );
+                       LWDEBUGF(3, "parse_geojson_coord pt.z = %f.", pt.z );
+                       *hasz = LW_TRUE;
+               }
+               else
+               {
+                       *hasz = LW_FALSE;
+                       /* Initialize Z coordinate, if required */
+                       if ( FLAGS_GET_Z(pa->flags) ) pt.z = 0.0;
+               }
+
+               /* TODO: should we account for nSize > 3 ? */
+
+               /* Initialize M coordinate, if required */
+               if ( FLAGS_GET_M(pa->flags) ) pt.m = 0.0;
+
+       }
+
+       return ptarray_append_point(pa, &pt, LW_FALSE);
+}
+
+static LWGEOM*
+parse_geojson_point(json_object *geojson, int *hasz,  int root_srid)
+{
+       LWGEOM *geom;
+       POINTARRAY *pa;
+       json_object* coords = NULL;
+
+       LWDEBUGF(3, "parse_geojson_point called with root_srid = %d.", root_srid );
+
+       coords = findMemberByName( geojson, "coordinates" );
+       if ( ! coords ) {
+               geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
+    return NULL;
+  }
+       
+       pa = ptarray_construct_empty(1, 0, 1);
+       parse_geojson_coord(coords, hasz, pa);
+
+       geom = (LWGEOM *) lwpoint_construct(root_srid, NULL, pa);
+       LWDEBUG(2, "parse_geojson_point finished.");
+       return geom;
+}
+
+static LWGEOM*
+parse_geojson_linestring(json_object *geojson, int *hasz,  int root_srid)
+{
+       LWGEOM *geom;
+       POINTARRAY *pa;
+       json_object* points = NULL;
+       int i = 0;
+
+       LWDEBUG(2, "parse_geojson_linestring called.");
+
+       points = findMemberByName( geojson, "coordinates" );
+       if ( ! points ) {
+               geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
+    return NULL;
+  }
+
+       pa = ptarray_construct_empty(1, 0, 1);
+
+       if( json_type_array == json_object_get_type( points ) )
+       {
+               const int nPoints = json_object_array_length( points );
+               for(i = 0; i < nPoints; ++i)
+               {
+                       json_object* coords = NULL;
+                       coords = json_object_array_get_idx( points, i );
+                       parse_geojson_coord(coords, hasz, pa);
+               }
+       }
+
+       geom = (LWGEOM *) lwline_construct(root_srid, NULL, pa);
+
+       LWDEBUG(2, "parse_geojson_linestring finished.");
+       return geom;
+}
+
+static LWGEOM*
+parse_geojson_polygon(json_object *geojson, int *hasz,  int root_srid)
+{
+       LWGEOM *geom;
+       POINTARRAY **ppa;
+       json_object* rings = NULL;
+       int i = 0, j = 0;
+       int ring = 0;
+
+       rings = findMemberByName( geojson, "coordinates" );
+       if ( ! rings ) {
+               geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
+    return NULL;
+  }
+
+       ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));
+
+       if( json_type_array == json_object_get_type( rings ) )
+       {
+               int nPoints;
+               json_object* points = NULL;
+               ppa[0] = ptarray_construct_empty(1, 0, 1);
+               ring = json_object_array_length( rings );
+               points = json_object_array_get_idx( rings, 0 );
+               nPoints = json_object_array_length( points );
+
+               for (i=0; i < nPoints; i++ )
+               {
+                       json_object* coords = NULL;
+                       coords = json_object_array_get_idx( points, i );
+                       parse_geojson_coord(coords, hasz, ppa[0]);
+               }
+
+               for(i = 1; i < ring; ++i)
+               {
+                       int nPoints;
+                       ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa, sizeof(POINTARRAY*) * (i + 1));
+                       ppa[i] = ptarray_construct_empty(1, 0, 1);
+                       points = json_object_array_get_idx( rings, i );
+                       nPoints = json_object_array_length( points );
+                       for (j=0; j < nPoints; j++ )
+                       {
+                               json_object* coords = NULL;
+                               coords = json_object_array_get_idx( points, j );
+                               parse_geojson_coord(coords, hasz, ppa[i]);
+                       }
+               }
+       }
+
+       geom = (LWGEOM *) lwpoly_construct(root_srid, NULL, ring, ppa);
+       return geom;
+}
+
+static LWGEOM*
+parse_geojson_multipoint(json_object *geojson, int *hasz,  int root_srid)
+{
+       LWGEOM *geom;
+       int i = 0;
+       json_object* poObjPoints = NULL;
+
+       if (!root_srid)
+       {
+               geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOINTTYPE, root_srid, 1, 0);
+       }
+       else
+       {
+               geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOINTTYPE, -1, 1, 0);
+       }
+
+       poObjPoints = findMemberByName( geojson, "coordinates" );
+       if ( ! poObjPoints ) {
+               geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
+    return NULL;
+  }
+
+       if( json_type_array == json_object_get_type( poObjPoints ) )
+       {
+               const int nPoints = json_object_array_length( poObjPoints );
+               for( i = 0; i < nPoints; ++i)
+               {
+                       POINTARRAY *pa;
+                       json_object* poObjCoords = NULL;
+                       poObjCoords = json_object_array_get_idx( poObjPoints, i );
+
+                       pa = ptarray_construct_empty(1, 0, 1);
+                       parse_geojson_coord(poObjCoords, hasz, pa);
+
+                       geom = (LWGEOM*)lwmpoint_add_lwpoint((LWMPOINT*)geom,
+                                                            (LWPOINT*)lwpoint_construct(root_srid, NULL, pa));
+               }
+       }
+
+       return geom;
+}
+
+static LWGEOM*
+parse_geojson_multilinestring(json_object *geojson, int *hasz,  int root_srid)
+{
+       LWGEOM *geom = NULL;
+       int i, j;
+       json_object* poObjLines = NULL;
+
+       if (!root_srid)
+       {
+               geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, root_srid, 1, 0);
+       }
+       else
+       {
+               geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, -1, 1, 0);
+       }
+
+       poObjLines = findMemberByName( geojson, "coordinates" );
+       if ( ! poObjLines ) {
+               geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
+    return NULL;
+  }
+
+       if( json_type_array == json_object_get_type( poObjLines ) )
+       {
+               const int nLines = json_object_array_length( poObjLines );
+               for( i = 0; i < nLines; ++i)
+               {
+                       POINTARRAY *pa = NULL;
+                       json_object* poObjLine = NULL;
+                       poObjLine = json_object_array_get_idx( poObjLines, i );
+                       pa = ptarray_construct_empty(1, 0, 1);
+
+                       if( json_type_array == json_object_get_type( poObjLine ) )
+                       {
+                               const int nPoints = json_object_array_length( poObjLine );
+                               for(j = 0; j < nPoints; ++j)
+                               {
+                                       json_object* coords = NULL;
+                                       coords = json_object_array_get_idx( poObjLine, j );
+                                       parse_geojson_coord(coords, hasz, pa);
+                               }
+
+                               geom = (LWGEOM*)lwmline_add_lwline((LWMLINE*)geom,
+                                                                  (LWLINE*)lwline_construct(root_srid, NULL, pa));
+                       }
+               }
+       }
+
+       return geom;
+}
+
+static LWGEOM*
+parse_geojson_multipolygon(json_object *geojson, int *hasz,  int root_srid)
+{
+       LWGEOM *geom = NULL;
+       int i, j, k;
+       json_object* poObjPolys = NULL;
+
+       if (!root_srid)
+       {
+               geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, root_srid, 1, 0);
+       }
+       else
+       {
+               geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, -1, 1, 0);
+       }
+
+       poObjPolys = findMemberByName( geojson, "coordinates" );
+       if ( ! poObjPolys ) {
+               geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
+    return NULL;
+  }
+
+       if( json_type_array == json_object_get_type( poObjPolys ) )
+       {
+               const int nPolys = json_object_array_length( poObjPolys );
+
+               for(i = 0; i < nPolys; ++i)
+               {
+                       POINTARRAY **ppa;
+                       json_object* poObjPoly = NULL;
+                       poObjPoly = json_object_array_get_idx( poObjPolys, i );
+
+                       ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));
+
+                       if( json_type_array == json_object_get_type( poObjPoly ) )
+                       {
+                               int nPoints;
+                               json_object* points = NULL;
+                               int ring = json_object_array_length( poObjPoly );
+                               ppa[0] = ptarray_construct_empty(1, 0, 1);
+
+                               points = json_object_array_get_idx( poObjPoly, 0 );
+                               nPoints = json_object_array_length( points );
+
+                               for (j=0; j < nPoints; j++ )
+                               {
+                                       json_object* coords = NULL;
+                                       coords = json_object_array_get_idx( points, j );
+                                       parse_geojson_coord(coords, hasz, ppa[0]);
+                               }
+
+                               for(j = 1; j < ring; ++j)
+                               {
+                                       int nPoints;
+                                       ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa, sizeof(POINTARRAY*) * (j + 1));
+                                       ppa[j] = ptarray_construct_empty(1, 0, 1);
+                                       points = json_object_array_get_idx( poObjPoly, j );
+
+                                       nPoints = json_object_array_length( points );
+                                       for (k=0; k < nPoints; k++ )
+                                       {
+                                               json_object* coords = NULL;
+                                               coords = json_object_array_get_idx( points, k );
+                                               parse_geojson_coord(coords, hasz, ppa[i]);
+                                       }
+                               }
+
+                               geom = (LWGEOM*)lwmpoly_add_lwpoly((LWMPOLY*)geom,
+                                                                  (LWPOLY*)lwpoly_construct(root_srid, NULL, ring, ppa));
+                       }
+               }
+       }
+
+       return geom;
+}
+
+static LWGEOM*
+parse_geojson_geometrycollection(json_object *geojson, int *hasz,  int root_srid)
+{
+       LWGEOM *geom = NULL;
+       int i;
+       json_object* poObjGeoms = NULL;
+
+       if (!root_srid)
+       {
+               geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, root_srid, 1, 0);
+       }
+       else
+       {
+               geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, -1, 1, 0);
+       }
+
+       poObjGeoms = findMemberByName( geojson, "geometries" );
+       if ( ! poObjGeoms ) {
+               geojson_lwerror("Unable to find 'geometries' in GeoJSON string", 4);
+    return NULL;
+  }
+
+       if( json_type_array == json_object_get_type( poObjGeoms ) )
+       {
+               const int nGeoms = json_object_array_length( poObjGeoms );
+               json_object* poObjGeom = NULL;
+               for(i = 0; i < nGeoms; ++i )
+               {
+                       poObjGeom = json_object_array_get_idx( poObjGeoms, i );
+                       geom = (LWGEOM*)lwcollection_add_lwgeom((LWCOLLECTION *)geom,
+                                                               parse_geojson(poObjGeom, hasz, root_srid));
+               }
+       }
+
+       return geom;
+}
+
+static LWGEOM*
+parse_geojson(json_object *geojson, int *hasz,  int root_srid)
+{
+       json_object* type = NULL;
+       const char* name;
+
+       if( NULL == geojson ) {
+               geojson_lwerror("invalid GeoJSON representation", 2);
+    return NULL;
+  }
+
+       type = findMemberByName( geojson, "type" );
+       if( NULL == type ) {
+               geojson_lwerror("unknown GeoJSON type", 3);
+    return NULL;
+  }
+
+       name = json_object_get_string( type );
+
+       if( strcasecmp( name, "Point" )==0 )
+               return parse_geojson_point(geojson, hasz, root_srid);
+
+       if( strcasecmp( name, "LineString" )==0 )
+               return parse_geojson_linestring(geojson, hasz, root_srid);
+
+       if( strcasecmp( name, "Polygon" )==0 )
+               return parse_geojson_polygon(geojson, hasz, root_srid);
+
+       if( strcasecmp( name, "MultiPoint" )==0 )
+               return parse_geojson_multipoint(geojson, hasz, root_srid);
+
+       if( strcasecmp( name, "MultiLineString" )==0 )
+               return parse_geojson_multilinestring(geojson, hasz, root_srid);
+
+       if( strcasecmp( name, "MultiPolygon" )==0 )
+               return parse_geojson_multipolygon(geojson, hasz, root_srid);
+
+       if( strcasecmp( name, "GeometryCollection" )==0 )
+               return parse_geojson_geometrycollection(geojson, hasz, root_srid);
+
+       lwerror("invalid GeoJson representation");
+       return NULL; /* Never reach */
+}
+
+#endif /* HAVE_LIBJSON  */
+
+LWGEOM*
+lwgeom_from_geojson(const char *geojson, char **srs)
+{
+#ifndef HAVE_LIBJSON
+  *srs = NULL;
+       lwerror("You need JSON-C for lwgeom_from_geojson");
+       return NULL;
+#else /* HAVE_LIBJSON  */
+
+       /* size_t geojson_size = strlen(geojson); */
+
+       LWGEOM *lwgeom;
+       int hasz=LW_TRUE;
+       json_tokener* jstok = NULL;
+       json_object* poObj = NULL;
+       json_object* poObjSrs = NULL;
+  *srs = NULL;
+
+       /* Begin to Parse json */
+       jstok = json_tokener_new();
+       poObj = json_tokener_parse_ex(jstok, geojson, -1);
+       if( jstok->err != json_tokener_success)
+       {
+               char err[256];
+               snprintf(err, 256, "%s (at offset %d)", json_tokener_errors[jstok->err], jstok->char_offset);
+               json_tokener_free(jstok);
+    json_object_put(poObj);
+               geojson_lwerror(err, 1);
+    return NULL;
+       }
+       json_tokener_free(jstok);
+
+       poObjSrs = findMemberByName( poObj, "crs" );
+       if (poObjSrs != NULL)
+       {
+               json_object* poObjSrsType = findMemberByName( poObjSrs, "type" );
+               if (poObjSrsType != NULL)
+               {
+                       json_object* poObjSrsProps = findMemberByName( poObjSrs, "properties" );
+                       json_object* poNameURL = findMemberByName( poObjSrsProps, "name" );
+                       const char* pszName = json_object_get_string( poNameURL );
+      *srs = lwalloc(strlen(pszName) + 1);
+      strcpy(*srs, pszName);
+               }
+       }
+
+       lwgeom = parse_geojson(poObj, &hasz, 0);
+  json_object_put(poObj);
+
+       lwgeom_add_bbox(lwgeom);
+
+       if (!hasz)
+       {
+               LWGEOM *tmp = lwgeom_force_2d(lwgeom);
+               lwgeom_free(lwgeom);
+               lwgeom = tmp;
+
+               LWDEBUG(2, "geom_from_geojson called.");
+       }
+
+  return lwgeom;
+#endif /* HAVE_LIBJSON  */
+}
+
+
index f42202e668cdc2238a10ea49b1494efa6f20d622..8a0ddfc94f767a60d92c613788a3b39424c34750 100644 (file)
 #include "../postgis_config.h"
 #include "lwgeom_pg.h"
 #include "liblwgeom.h"
+#include "lwgeom_export.h"
 
 Datum geom_from_geojson(PG_FUNCTION_ARGS);
 Datum postgis_libjson_version(PG_FUNCTION_ARGS);
 
-static void geojson_lwerror(char *msg, int error_code)
-{
-       POSTGIS_DEBUGF(3, "ST_GeomFromGeoJSON ERROR %i", error_code);
-       lwerror("%s", msg);
-}
-
-#ifdef HAVE_LIBJSON
-
-#include "lwgeom_export.h"
-#include <json/json.h>
-#include <json/json_object_private.h>
-
-/* Prototype */
-LWGEOM* parse_geojson(json_object *geojson, bool *hasz,  int *root_srid);
-
-static json_object*
-findMemberByName(json_object* poObj, const char* pszName )
-{
-       json_object* poTmp;
-       json_object_iter it;
-
-       poTmp = poObj;
-
-       if( NULL == pszName || NULL == poObj)
-               return NULL;
-
-       it.key = NULL;
-       it.val = NULL;
-       it.entry = NULL;
-
-       if( NULL != json_object_get_object(poTmp) )
-       {
-               assert( NULL != json_object_get_object(poTmp)->head );
-
-               for( it.entry = json_object_get_object(poTmp)->head;
-                       ( it.entry ?
-                         ( it.key = (char*)it.entry->k,
-                           it.val = (json_object*)it.entry->v, it.entry) : 0);
-                       it.entry = it.entry->next)
-               {
-                       if( strcasecmp((char *)it.key, pszName )==0 )
-                               return it.val;
-               }
-       }
-
-       return NULL;
-}
-
-
-static int
-parse_geojson_coord(json_object *poObj, bool *hasz, POINTARRAY *pa)
-{
-       POINT4D pt;
-       int iType = 0;
-
-       POSTGIS_DEBUGF(3, "parse_geojson_coord called for object %s.", json_object_to_json_string( poObj ) );
-
-       if( json_type_array == json_object_get_type( poObj ) )
-       {
-
-               json_object* poObjCoord = NULL;
-               const int nSize = json_object_array_length( poObj );
-               POSTGIS_DEBUGF(3, "parse_geojson_coord called for array size %d.", nSize );
-
-
-               // Read X coordinate
-               poObjCoord = json_object_array_get_idx( poObj, 0 );
-               iType = json_object_get_type(poObjCoord);
-               if (iType == json_type_double)
-                       pt.x = json_object_get_double( poObjCoord );
-               else
-                       pt.x = json_object_get_int( poObjCoord );
-               POSTGIS_DEBUGF(3, "parse_geojson_coord pt.x = %f.", pt.x );
-
-               // Read Y coordiante
-               poObjCoord = json_object_array_get_idx( poObj, 1 );
-               if (iType == json_type_double)
-                       pt.y = json_object_get_double( poObjCoord );
-               else
-                       pt.y = json_object_get_int( poObjCoord );
-               POSTGIS_DEBUGF(3, "parse_geojson_coord pt.y = %f.", pt.y );
-
-               if( nSize == 3 ) /* should this be >= 3 ? */
-               {
-                       // Read Z coordiante
-                       poObjCoord = json_object_array_get_idx( poObj, 2 );
-                       if (iType == 3)
-                               pt.z = json_object_get_double( poObjCoord );
-                       else
-                               pt.z = json_object_get_int( poObjCoord );
-                       POSTGIS_DEBUGF(3, "parse_geojson_coord pt.z = %f.", pt.z );
-                       *hasz = true;
-               }
-               else
-               {
-                       *hasz = false;
-                       /* Initialize Z coordinate, if required */
-                       if ( FLAGS_GET_Z(pa->flags) ) pt.z = 0.0;
-               }
-
-               /* TODO: should we account for nSize > 3 ? */
-
-               /* Initialize M coordinate, if required */
-               if ( FLAGS_GET_M(pa->flags) ) pt.m = 0.0;
-
-       }
-
-       return ptarray_append_point(pa, &pt, LW_FALSE);
-}
-
-static LWGEOM*
-parse_geojson_point(json_object *geojson, bool *hasz,  int *root_srid)
-{
-       LWGEOM *geom;
-       POINTARRAY *pa;
-       json_object* coords = NULL;
-
-       POSTGIS_DEBUGF(3, "parse_geojson_point called with root_srid = %d.", *root_srid );
-
-       coords = findMemberByName( geojson, "coordinates" );
-       if ( ! coords )
-               geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
-       
-       pa = ptarray_construct_empty(1, 0, 1);
-       parse_geojson_coord(coords, hasz, pa);
-
-       geom = (LWGEOM *) lwpoint_construct(*root_srid, NULL, pa);
-       POSTGIS_DEBUG(2, "parse_geojson_point finished.");
-       return geom;
-}
-
-static LWGEOM*
-parse_geojson_linestring(json_object *geojson, bool *hasz,  int *root_srid)
-{
-       LWGEOM *geom;
-       POINTARRAY *pa;
-       json_object* points = NULL;
-       int i = 0;
-
-       POSTGIS_DEBUG(2, "parse_geojson_linestring called.");
-
-       points = findMemberByName( geojson, "coordinates" );
-       if ( ! points )
-               geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
-
-       pa = ptarray_construct_empty(1, 0, 1);
-
-       if( json_type_array == json_object_get_type( points ) )
-       {
-               const int nPoints = json_object_array_length( points );
-               for(i = 0; i < nPoints; ++i)
-               {
-                       json_object* coords = NULL;
-                       coords = json_object_array_get_idx( points, i );
-                       parse_geojson_coord(coords, hasz, pa);
-               }
-       }
-
-       geom = (LWGEOM *) lwline_construct(*root_srid, NULL, pa);
-
-       POSTGIS_DEBUG(2, "parse_geojson_linestring finished.");
-       return geom;
-}
-
-static LWGEOM*
-parse_geojson_polygon(json_object *geojson, bool *hasz,  int *root_srid)
-{
-       LWGEOM *geom;
-       POINTARRAY **ppa;
-       json_object* rings = NULL;
-       int i = 0, j = 0;
-       int ring = 0;
-
-       rings = findMemberByName( geojson, "coordinates" );
-       if ( ! rings )
-               geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
-
-       ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));
-
-       if( json_type_array == json_object_get_type( rings ) )
-       {
-               int nPoints;
-               json_object* points = NULL;
-               ppa[0] = ptarray_construct_empty(1, 0, 1);
-               ring = json_object_array_length( rings );
-               points = json_object_array_get_idx( rings, 0 );
-               nPoints = json_object_array_length( points );
-
-               for (i=0; i < nPoints; i++ )
-               {
-                       json_object* coords = NULL;
-                       coords = json_object_array_get_idx( points, i );
-                       parse_geojson_coord(coords, hasz, ppa[0]);
-               }
-
-               for(i = 1; i < ring; ++i)
-               {
-                       int nPoints;
-                       ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa, sizeof(POINTARRAY*) * (i + 1));
-                       ppa[i] = ptarray_construct_empty(1, 0, 1);
-                       points = json_object_array_get_idx( rings, i );
-                       nPoints = json_object_array_length( points );
-                       for (j=0; j < nPoints; j++ )
-                       {
-                               json_object* coords = NULL;
-                               coords = json_object_array_get_idx( points, j );
-                               parse_geojson_coord(coords, hasz, ppa[i]);
-                       }
-               }
-       }
-
-       geom = (LWGEOM *) lwpoly_construct(*root_srid, NULL, ring, ppa);
-       return geom;
-}
-
-static LWGEOM*
-parse_geojson_multipoint(json_object *geojson, bool *hasz,  int *root_srid)
-{
-       LWGEOM *geom;
-       int i = 0;
-       json_object* poObjPoints = NULL;
-
-       if (!*root_srid)
-       {
-               geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOINTTYPE, *root_srid, 1, 0);
-       }
-       else
-       {
-               geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOINTTYPE, -1, 1, 0);
-       }
-
-       poObjPoints = findMemberByName( geojson, "coordinates" );
-       if ( ! poObjPoints )
-               geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
-
-       if( json_type_array == json_object_get_type( poObjPoints ) )
-       {
-               const int nPoints = json_object_array_length( poObjPoints );
-               for( i = 0; i < nPoints; ++i)
-               {
-                       POINTARRAY *pa;
-                       json_object* poObjCoords = NULL;
-                       poObjCoords = json_object_array_get_idx( poObjPoints, i );
-
-                       pa = ptarray_construct_empty(1, 0, 1);
-                       parse_geojson_coord(poObjCoords, hasz, pa);
-
-                       geom = (LWGEOM*)lwmpoint_add_lwpoint((LWMPOINT*)geom,
-                                                            (LWPOINT*)lwpoint_construct(*root_srid, NULL, pa));
-               }
-       }
-
-       return geom;
-}
-
-static LWGEOM*
-parse_geojson_multilinestring(json_object *geojson, bool *hasz,  int *root_srid)
-{
-       LWGEOM *geom = NULL;
-       int i, j;
-       json_object* poObjLines = NULL;
-
-       if (!*root_srid)
-       {
-               geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, *root_srid, 1, 0);
-       }
-       else
-       {
-               geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, -1, 1, 0);
-       }
-
-       poObjLines = findMemberByName( geojson, "coordinates" );
-       if ( ! poObjLines )
-               geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
-
-       if( json_type_array == json_object_get_type( poObjLines ) )
-       {
-               const int nLines = json_object_array_length( poObjLines );
-               for( i = 0; i < nLines; ++i)
-               {
-                       POINTARRAY *pa = NULL;
-                       json_object* poObjLine = NULL;
-                       poObjLine = json_object_array_get_idx( poObjLines, i );
-                       pa = ptarray_construct_empty(1, 0, 1);
-
-                       if( json_type_array == json_object_get_type( poObjLine ) )
-                       {
-                               const int nPoints = json_object_array_length( poObjLine );
-                               for(j = 0; j < nPoints; ++j)
-                               {
-                                       json_object* coords = NULL;
-                                       coords = json_object_array_get_idx( poObjLine, j );
-                                       parse_geojson_coord(coords, hasz, pa);
-                               }
-
-                               geom = (LWGEOM*)lwmline_add_lwline((LWMLINE*)geom,
-                                                                  (LWLINE*)lwline_construct(*root_srid, NULL, pa));
-                       }
-               }
-       }
-
-       return geom;
-}
-
-static LWGEOM*
-parse_geojson_multipolygon(json_object *geojson, bool *hasz,  int *root_srid)
-{
-       LWGEOM *geom = NULL;
-       int i, j, k;
-       json_object* poObjPolys = NULL;
-
-       if (!*root_srid)
-       {
-               geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, *root_srid, 1, 0);
-       }
-       else
-       {
-               geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, -1, 1, 0);
-       }
-
-       poObjPolys = findMemberByName( geojson, "coordinates" );
-       if ( ! poObjPolys )
-               geojson_lwerror("Unable to find 'coordinates' in GeoJSON string", 4);
-
-       if( json_type_array == json_object_get_type( poObjPolys ) )
-       {
-               const int nPolys = json_object_array_length( poObjPolys );
-
-               for(i = 0; i < nPolys; ++i)
-               {
-                       POINTARRAY **ppa;
-                       json_object* poObjPoly = NULL;
-                       poObjPoly = json_object_array_get_idx( poObjPolys, i );
-
-                       ppa = (POINTARRAY**) lwalloc(sizeof(POINTARRAY*));
-
-                       if( json_type_array == json_object_get_type( poObjPoly ) )
-                       {
-                               int nPoints;
-                               json_object* points = NULL;
-                               int ring = json_object_array_length( poObjPoly );
-                               ppa[0] = ptarray_construct_empty(1, 0, 1);
-
-                               points = json_object_array_get_idx( poObjPoly, 0 );
-                               nPoints = json_object_array_length( points );
-
-                               for (j=0; j < nPoints; j++ )
-                               {
-                                       json_object* coords = NULL;
-                                       coords = json_object_array_get_idx( points, j );
-                                       parse_geojson_coord(coords, hasz, ppa[0]);
-                               }
-
-                               for(j = 1; j < ring; ++j)
-                               {
-                                       int nPoints;
-                                       ppa = (POINTARRAY**) lwrealloc((POINTARRAY *) ppa, sizeof(POINTARRAY*) * (j + 1));
-                                       ppa[j] = ptarray_construct_empty(1, 0, 1);
-                                       points = json_object_array_get_idx( poObjPoly, j );
-
-                                       nPoints = json_object_array_length( points );
-                                       for (k=0; k < nPoints; k++ )
-                                       {
-                                               json_object* coords = NULL;
-                                               coords = json_object_array_get_idx( points, k );
-                                               parse_geojson_coord(coords, hasz, ppa[i]);
-                                       }
-                               }
-
-                               geom = (LWGEOM*)lwmpoly_add_lwpoly((LWMPOLY*)geom,
-                                                                  (LWPOLY*)lwpoly_construct(*root_srid, NULL, ring, ppa));
-                       }
-               }
-       }
-
-       return geom;
-}
-
-static LWGEOM*
-parse_geojson_geometrycollection(json_object *geojson, bool *hasz,  int *root_srid)
-{
-       LWGEOM *geom = NULL;
-       int i;
-       json_object* poObjGeoms = NULL;
-
-       if (!*root_srid)
-       {
-               geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, *root_srid, 1, 0);
-       }
-       else
-       {
-               geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, -1, 1, 0);
-       }
-
-       poObjGeoms = findMemberByName( geojson, "geometries" );
-       if ( ! poObjGeoms )
-               geojson_lwerror("Unable to find 'geometries' in GeoJSON string", 4);
-
-       if( json_type_array == json_object_get_type( poObjGeoms ) )
-       {
-               const int nGeoms = json_object_array_length( poObjGeoms );
-               json_object* poObjGeom = NULL;
-               for(i = 0; i < nGeoms; ++i )
-               {
-                       poObjGeom = json_object_array_get_idx( poObjGeoms, i );
-                       geom = (LWGEOM*)lwcollection_add_lwgeom((LWCOLLECTION *)geom,
-                                                               parse_geojson(poObjGeom, hasz, root_srid));
-               }
-       }
-
-       return geom;
-}
-
-LWGEOM*
-parse_geojson(json_object *geojson, bool *hasz,  int *root_srid)
-{
-       json_object* type = NULL;
-       const char* name;
-
-       if( NULL == geojson )
-               geojson_lwerror("invalid GeoJSON representation", 2);
-
-       type = findMemberByName( geojson, "type" );
-       if( NULL == type )
-               geojson_lwerror("unknown GeoJSON type", 3);
-
-       name = json_object_get_string( type );
-
-       if( strcasecmp( name, "Point" )==0 )
-               return parse_geojson_point(geojson, hasz, root_srid);
-
-       if( strcasecmp( name, "LineString" )==0 )
-               return parse_geojson_linestring(geojson, hasz, root_srid);
-
-       if( strcasecmp( name, "Polygon" )==0 )
-               return parse_geojson_polygon(geojson, hasz, root_srid);
-
-       if( strcasecmp( name, "MultiPoint" )==0 )
-               return parse_geojson_multipoint(geojson, hasz, root_srid);
-
-       if( strcasecmp( name, "MultiLineString" )==0 )
-               return parse_geojson_multilinestring(geojson, hasz, root_srid);
-
-       if( strcasecmp( name, "MultiPolygon" )==0 )
-               return parse_geojson_multipolygon(geojson, hasz, root_srid);
-
-       if( strcasecmp( name, "GeometryCollection" )==0 )
-               return parse_geojson_geometrycollection(geojson, hasz, root_srid);
-
-       lwerror("invalid GeoJson representation");
-       return NULL; /* Never reach */
-}
-#endif /* HAVE_LIBJSON  */
-
 PG_FUNCTION_INFO_V1(postgis_libjson_version);
 Datum postgis_libjson_version(PG_FUNCTION_ARGS)
 {
@@ -496,59 +43,25 @@ Datum geom_from_geojson(PG_FUNCTION_ARGS)
        GSERIALIZED *geom;
        LWGEOM *lwgeom;
        text *geojson_input;
-       int geojson_size;
        char *geojson;
-       int root_srid=0;
-       bool hasz=true;
-       json_tokener* jstok = NULL;
-       json_object* poObj = NULL;
-       json_object* poObjSrs = NULL;
+  char *srs = NULL;
 
        /* Get the geojson stream */
        if (PG_ARGISNULL(0)) PG_RETURN_NULL();
        geojson_input = PG_GETARG_TEXT_P(0);
        geojson = text2cstring(geojson_input);
-       geojson_size = VARSIZE(geojson_input) - VARHDRSZ;
-
-       /* Begin to Parse json */
-       jstok = json_tokener_new();
-       poObj = json_tokener_parse_ex(jstok, geojson, -1);
-       if( jstok->err != json_tokener_success)
-       {
-               char err[256];
-               snprintf(err, 256, "%s (at offset %d)", json_tokener_errors[jstok->err], jstok->char_offset);
-               json_tokener_free(jstok);
-               geojson_lwerror(err, 1);
-       }
-       json_tokener_free(jstok);
-
-       poObjSrs = findMemberByName( poObj, "crs" );
-       if (poObjSrs != NULL)
-       {
-               json_object* poObjSrsType = findMemberByName( poObjSrs, "type" );
-               if (poObjSrsType != NULL)
-               {
-                       json_object* poObjSrsProps = findMemberByName( poObjSrs, "properties" );
-                       json_object* poNameURL = findMemberByName( poObjSrsProps, "name" );
-                       const char* pszName = json_object_get_string( poNameURL );
-                       root_srid = getSRIDbySRS(pszName);
-                       POSTGIS_DEBUGF(3, "getSRIDbySRS returned root_srid = %d.", root_srid );
-               }
-       }
-
-       lwgeom = parse_geojson(poObj, &hasz, &root_srid);
-
-       lwgeom_add_bbox(lwgeom);
-       if (root_srid && lwgeom->srid == -1) lwgeom->srid = root_srid;
-
-       if (!hasz)
-       {
-               LWGEOM *tmp = lwgeom_force_2d(lwgeom);
-               lwgeom_free(lwgeom);
-               lwgeom = tmp;
 
-               POSTGIS_DEBUG(2, "geom_from_geojson called.");
-       }
+  lwgeom = lwgeom_from_geojson(geojson, &srs);
+  if ( ! lwgeom ) {
+    /* Shouldn't get here */
+         elog(ERROR, "lwgeom_from_geojson returned NULL");
+    PG_RETURN_NULL();
+  }
+
+  if ( srs ) {
+    lwgeom_set_srid(lwgeom, getSRIDbySRS(srs));
+    lwfree(srs);
+  }
 
        geom = geometry_serialize(lwgeom);
        lwgeom_free(lwgeom);