#include #include #include #include #include #include #include #include #include #include #include #include #include "jsonpull.h" #define GEOM_POINT 0 /* array of positions */ #define GEOM_MULTIPOINT 1 /* array of arrays of positions */ #define GEOM_LINESTRING 2 /* array of arrays of positions */ #define GEOM_MULTILINESTRING 3 /* array of arrays of arrays of positions */ #define GEOM_POLYGON 4 /* array of arrays of arrays of positions */ #define GEOM_MULTIPOLYGON 5 /* array of arrays of arrays of arrays of positions */ #define GEOM_TYPES 6 char *geometry_names[GEOM_TYPES] = { "Point", "MultiPoint", "LineString", "MultiLineString", "Polygon", "MultiPolygon", }; int geometry_within[GEOM_TYPES] = { -1, /* point */ GEOM_POINT, /* multipoint */ GEOM_POINT, /* linestring */ GEOM_LINESTRING, /* multilinestring */ GEOM_LINESTRING, /* polygon */ GEOM_POLYGON, /* multipolygon */ }; /* XXX */ #define META_STRING JSON_STRING #define META_INTEGER JSON_NUMBER #define META_BOOLEAN JSON_TRUE void parse_geometry(int t, json_object *j) { if (j == NULL || j->type != JSON_ARRAY) { fprintf(stderr, "expected array for type %d\n", t); return; } int within = geometry_within[t]; if (within >= 0) { printf("["); int i; for (i = 0; i < j->length; i++) { parse_geometry(within, j->array[i]); } printf("]"); } else { if (j->length == 2 && j->array[0]->type == JSON_NUMBER && j->array[1]->type == JSON_NUMBER) { printf(" %f,%f ", j->array[0]->number, j->array[1]->number); } else { fprintf(stderr, "malformed point"); } } } void read_json(FILE *f) { json_pull *jp = json_begin_file(f); while (1) { json_object *j = json_read(jp); if (j == NULL) { if (jp->error != NULL) { fprintf(stderr, "%d: %s\n", jp->line, jp->error); } json_free(jp->root); break; } json_object *type = json_hash_get(j, "type"); if (type == NULL || type->type != JSON_STRING || strcmp(type->string, "Feature") != 0) { continue; } json_object *geometry = json_hash_get(j, "geometry"); if (geometry == NULL) { fprintf(stderr, "%d: feature with no geometry\n", jp->line); goto next_feature; } json_object *geometry_type = json_hash_get(geometry, "type"); if (geometry_type == NULL || geometry_type->type != JSON_STRING) { fprintf(stderr, "%d: geometry without type string\n", jp->line); goto next_feature; } json_object *properties = json_hash_get(j, "properties"); if (properties == NULL || properties->type != JSON_HASH) { fprintf(stderr, "%d: feature without properties hash\n", jp->line); goto next_feature; } json_object *coordinates = json_hash_get(geometry, "coordinates"); if (coordinates == NULL || coordinates->type != JSON_ARRAY) { fprintf(stderr, "%d: feature without coordinates array\n", jp->line); goto next_feature; } int t; for (t = 0; t < GEOM_TYPES; t++) { if (strcmp(geometry_type->string, geometry_names[t]) == 0) { break; } } if (t >= GEOM_TYPES) { fprintf(stderr, "%d: Can't handle geometry type %s\n", jp->line, geometry_type->string); goto next_feature; } /* scope for variable-length arrays */ { char *metakey[properties->length]; char *metaval[properties->length]; int metatype[properties->length]; int m = 0; int i; for (i = 0; i < properties->length; i++) { if (properties->keys[i]->type == JSON_STRING) { metakey[m] = properties->keys[i]->string; if (properties->values[i] != NULL && properties->values[i]->type == JSON_STRING) { metatype[m] = META_STRING; metaval[m] = properties->values[i]->string; m++; } else if (properties->values[i] != NULL && properties->values[i]->type == JSON_NUMBER) { metatype[m] = META_INTEGER; metaval[m] = properties->values[i]->string; m++; } else if (properties->values[i] != NULL && (properties->values[i]->type == JSON_TRUE || properties->values[i]->type == JSON_FALSE)) { metatype[m] = META_BOOLEAN; metaval[m] = properties->values[i]->string; m++; } else { fprintf(stderr, "%d: Unsupported meta type\n", jp->line); goto next_feature; } } } parse_geometry(t, coordinates); printf("\n"); } next_feature: json_free(j); /* XXX check for any non-features in the outer object */ } json_end(jp); } int main(int argc, char **argv) { if (argc > 1) { int i; for (i = 1; i < argc; i++) { FILE *f = fopen(argv[i], "r"); if (f == NULL) { fprintf(stderr, "%s: %s: %s\n", argv[0], argv[i], strerror(errno)); } else { read_json(f); fclose(f); } } } else { read_json(stdin); } return 0; }