Skip to content

v.what.rast: Add JSON support #6140

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion vector/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -824,7 +824,8 @@ build_program_in_subdir(
grass_dbmidriver
grass_gis
grass_raster
grass_vector)
grass_vector
grass_parson)

build_program_in_subdir(
v.what.rast3
Expand Down
2 changes: 1 addition & 1 deletion vector/v.what.rast/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ MODULE_TOPDIR = ../..

PGM=v.what.rast

LIBES = $(VECTORLIB) $(DBMILIB) $(RASTERLIB) $(GISLIB)
LIBES = $(VECTORLIB) $(DBMILIB) $(RASTERLIB) $(GISLIB) $(PARSONLIB)
DEPENDENCIES = $(VECTORDEP) $(DBMIDEP) $(RASTERDEP) $(GISDEP)
EXTRA_INC = $(VECT_INC)
EXTRA_CFLAGS = $(VECT_CFLAGS)
Expand Down
2 changes: 2 additions & 0 deletions vector/v.what.rast/local_proto.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,8 @@ struct order {
DCELL dvalue; /* used for FCELL and DCELL */
};

enum OutputFormat { PLAIN, CSV, JSON };

/* search.c */
int by_row_col(const void *, const void *);
int by_cat(const void *, const void *);
Expand Down
151 changes: 133 additions & 18 deletions vector/v.what.rast/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <grass/gjson.h>
#include <grass/raster.h>
#include <grass/dbmi.h>
#include <grass/vector.h>
Expand All @@ -40,7 +41,7 @@ int main(int argc, char *argv[])
int row, col;
char buf[DB_SQL_MAX];
struct {
struct Option *vect, *rast, *field, *type, *col, *where;
struct Option *vect, *rast, *field, *type, *col, *where, *sep, *format;
} opt;
struct Flag *interp_flag, *print_flag;
int Cache_size;
Expand All @@ -64,6 +65,12 @@ int main(int argc, char *argv[])
dbDriver *driver;
int select, norec_cnt, update_cnt, upderr_cnt, col_type;

char *sep;
enum OutputFormat format;
JSON_Value *root_value = NULL, *cat_value = NULL;
JSON_Array *root_array = NULL;
JSON_Object *cat_object = NULL;

G_gisinit(argv[0]);

module = G_define_module();
Expand Down Expand Up @@ -99,6 +106,17 @@ int main(int argc, char *argv[])

opt.where = G_define_standard_option(G_OPT_DB_WHERE);

opt.sep = G_define_standard_option(G_OPT_F_SEP);
opt.sep->answer = "comma";
opt.sep->label = _("Field separator for CSV style output");
opt.sep->guisection = _("Print");

opt.format = G_define_standard_option(G_OPT_F_FORMAT);
opt.format->options = "plain,csv,json";
opt.format->descriptions = ("plain;Human readable text output;"
"csv;CSV (Comma Separated Values);"
"json;JSON (JavaScript Object Notation);");

interp_flag = G_define_flag();
interp_flag->key = 'i';
interp_flag->description =
Expand All @@ -119,6 +137,29 @@ int main(int argc, char *argv[])
if (!print_flag->answer && !opt.col->answer)
G_fatal_error(_("Required parameter <%s> not set"), opt.col->key);

if (strcmp(opt.format->answer, "json") == 0) {
format = JSON;
root_value = G_json_value_init_array();
if (root_value == NULL) {
G_fatal_error(_("Failed to initialize JSON array. Out of memory?"));
}
root_array = G_json_array(root_value);
}
else if (strcmp(opt.format->answer, "csv") == 0) {
format = CSV;
}
else {
format = PLAIN;
}

sep = G_option_to_separator(opt.sep);

if (format != PLAIN && !print_flag->answer) {
G_json_value_free(root_value);
G_fatal_error(_("The format option can only be used with -%c flag"),
print_flag->key);
}

G_get_window(&window);
Vect_region_box(&window, &box); /* T and B set to +/- PORT_DOUBLE_MAX */

Expand Down Expand Up @@ -549,11 +590,19 @@ int main(int argc, char *argv[])

if (print_flag->answer) {
dupl_cnt = 0;

if (Fi)
G_message("%s|value", Fi->key);
else
G_message("cat|value");
if (format == PLAIN) {
if (Fi)
G_message("%s|value", Fi->key);
else
G_message("cat|value");
}
else if (format == CSV) {
/* CSV Header */
if (Fi)
fprintf(stdout, "%s%svalue\n", Fi->key, sep);
else
fprintf(stdout, "cat%svalue\n", sep);
}

for (point = 0; point < point_cnt; point++) {
if (cache[point].count > 1) {
Expand All @@ -564,25 +613,91 @@ int main(int argc, char *argv[])
dupl_cnt++;
}

fprintf(stdout, "%d|", cache[point].cat);
switch (format) {
case PLAIN:
fprintf(stdout, "%d|", cache[point].cat);
break;

case CSV:
fprintf(stdout, "%d%s", cache[point].cat, sep);
break;

case JSON:
cat_value = G_json_value_init_object();
if (cat_value == NULL) {
G_fatal_error(_("Failed to initialize JSON object. "
"Out of memory?"));
}
cat_object = G_json_object(cat_value);

G_json_object_set_number(cat_object, "category",
cache[point].cat);
break;
}

if (out_type == CELL_TYPE) {
if (cache[point].count > 1 ||
Rast_is_c_null_value(&cache[point].value)) {
fprintf(stdout, "*");
switch (format) {
case PLAIN:
case CSV:
if (cache[point].count > 1 ||
Rast_is_c_null_value(&cache[point].value)) {
fprintf(stdout, "*");
}
else
fprintf(stdout, "%d", cache[point].value);
break;

case JSON:
if (cache[point].count > 1 ||
Rast_is_c_null_value(&cache[point].value)) {
G_json_object_set_null(cat_object, "value");
}
else
G_json_object_set_number(cat_object, "value",
cache[point].value);
break;
}
else
fprintf(stdout, "%d", cache[point].value);
}
else { /* FCELL or DCELL */
if (cache[point].count > 1 ||
Rast_is_d_null_value(&cache[point].dvalue)) {
fprintf(stdout, "*");
switch (format) {
case PLAIN:
case CSV:
if (cache[point].count > 1 ||
Rast_is_d_null_value(&cache[point].dvalue)) {
fprintf(stdout, "*");
}
else
fprintf(stdout, "%.*g", width, cache[point].dvalue);
break;

case JSON:
if (cache[point].count > 1 ||
Rast_is_d_null_value(&cache[point].dvalue)) {
G_json_object_set_null(cat_object, "value");
}
else
G_json_object_set_number(cat_object, "value",
cache[point].dvalue);
break;
}
else
fprintf(stdout, "%.*g", width, cache[point].dvalue);
}
fprintf(stdout, "\n");
if (format != JSON)
fprintf(stdout, "\n");
else
G_json_array_append_value(root_array, cat_value);
}

if (format == JSON) {
char *json_string = G_json_serialize_to_string_pretty(root_value);
if (!json_string) {
G_json_value_free(root_value);
G_fatal_error(_("Failed to serialize JSON to pretty format."));
}

puts(json_string);

G_json_free_serialized_string(json_string);
G_json_value_free(root_value);
}
}
else {
Expand Down
Loading
Loading