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:
Danila Poyarkov
2026-07-02 17:29:24 +03:00
parent 53b98d76c4
commit 116e40cbdf
+71 -2
View File
@@ -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{};
} }