mirror of
https://github.com/felt/tippecanoe.git
synced 2026-10-02 08:25:40 +02:00
Support nested JSON properties as MLT STRUCT columns
Detect JSON object strings at MLT output time and convert to STRUCT columns. Nested objects/arrays within are re-stringified. MVT output unchanged.
This commit is contained in:
@@ -1,4 +1,5 @@
|
|||||||
#include "mlt.hpp"
|
#include "mlt.hpp"
|
||||||
|
#include "jsonpull/jsonpull.h"
|
||||||
|
|
||||||
#include <mlt/encoder.hpp>
|
#include <mlt/encoder.hpp>
|
||||||
|
|
||||||
@@ -9,6 +10,68 @@
|
|||||||
|
|
||||||
using Vertex = mlt::Encoder::Vertex;
|
using Vertex = mlt::Encoder::Vertex;
|
||||||
|
|
||||||
|
// Try to parse a JSON object string into MLT STRUCT (flat string children only)
|
||||||
|
static bool try_parse_json_object(const std::string &s, mlt::Encoder::StructValue &out) {
|
||||||
|
if (s.empty() || s[0] != '{') {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_pull *jp = json_begin_string(s.c_str());
|
||||||
|
json_object *obj = json_read_tree(jp);
|
||||||
|
|
||||||
|
if (obj == nullptr || obj->type != JSON_HASH) {
|
||||||
|
json_free(obj);
|
||||||
|
json_end(jp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < obj->value.object.length; i++) {
|
||||||
|
json_object *key = obj->value.object.keys[i];
|
||||||
|
json_object *val = obj->value.object.values[i];
|
||||||
|
|
||||||
|
if (key->type != JSON_STRING) continue;
|
||||||
|
|
||||||
|
std::string child_key = key->value.string.string;
|
||||||
|
std::string child_val;
|
||||||
|
|
||||||
|
switch (val->type) {
|
||||||
|
case JSON_STRING:
|
||||||
|
child_val = val->value.string.string;
|
||||||
|
break;
|
||||||
|
case JSON_NUMBER:
|
||||||
|
if (val->value.number.large_unsigned != 0) {
|
||||||
|
child_val = std::to_string(val->value.number.large_unsigned);
|
||||||
|
} else if (val->value.number.large_signed != 0) {
|
||||||
|
child_val = std::to_string(val->value.number.large_signed);
|
||||||
|
} else {
|
||||||
|
child_val = std::to_string(val->value.number.number);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case JSON_TRUE:
|
||||||
|
child_val = "true";
|
||||||
|
break;
|
||||||
|
case JSON_FALSE:
|
||||||
|
child_val = "false";
|
||||||
|
break;
|
||||||
|
case JSON_NULL:
|
||||||
|
child_val = "null";
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
// Nested object/array - stringify back
|
||||||
|
char *nested = json_stringify(val);
|
||||||
|
child_val = nested;
|
||||||
|
free(nested);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
out[child_key] = child_val;
|
||||||
|
}
|
||||||
|
|
||||||
|
json_free(obj);
|
||||||
|
json_end(jp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
static mlt::Encoder::PropertyValue convert_value(const mvt_value &val) {
|
static mlt::Encoder::PropertyValue convert_value(const mvt_value &val) {
|
||||||
switch (val.type) {
|
switch (val.type) {
|
||||||
case mvt_bool:
|
case mvt_bool:
|
||||||
@@ -32,8 +95,14 @@ static mlt::Encoder::PropertyValue convert_value(const mvt_value &val) {
|
|||||||
return val.numeric_value.float_value;
|
return val.numeric_value.float_value;
|
||||||
case mvt_double:
|
case mvt_double:
|
||||||
return val.numeric_value.double_value;
|
return val.numeric_value.double_value;
|
||||||
case mvt_string:
|
case mvt_string: {
|
||||||
return val.get_string_value();
|
std::string s = val.get_string_value();
|
||||||
|
mlt::Encoder::StructValue struct_val;
|
||||||
|
if (try_parse_json_object(s, struct_val)) {
|
||||||
|
return struct_val;
|
||||||
|
}
|
||||||
|
return s;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
return std::string{};
|
return std::string{};
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user