3333#include " iceberg/expression/json_serde_internal.h"
3434#include " iceberg/file_format.h"
3535#include " iceberg/json_serde_internal.h"
36+ #include " iceberg/labels.h"
3637#include " iceberg/manifest/manifest_entry.h"
3738#include " iceberg/partition_spec.h"
3839#include " iceberg/schema.h"
@@ -72,6 +73,10 @@ constexpr std::string_view kDestination = "destination";
7273constexpr std::string_view kMetadata = " metadata" ;
7374constexpr std::string_view kConfig = " config" ;
7475constexpr std::string_view kStorageCredentials = " storage-credentials" ;
76+ constexpr std::string_view kLabels = " labels" ;
77+ constexpr std::string_view kObjectLabels = " object-labels" ;
78+ constexpr std::string_view kFields = " fields" ;
79+ constexpr std::string_view kFieldId = " field-id" ;
7580constexpr std::string_view kPrefix = " prefix" ;
7681constexpr std::string_view kIdentifiers = " identifiers" ;
7782constexpr std::string_view kOverrides = " overrides" ;
@@ -488,6 +493,59 @@ Result<RenameTableRequest> RenameTableRequestFromJson(const nlohmann::json& json
488493 return request;
489494}
490495
496+ nlohmann::json ToJson (const FieldLabel& field_label) {
497+ nlohmann::json json;
498+ json[kFieldId ] = field_label.field_id ;
499+ json[kLabels ] = field_label.labels ;
500+ return json;
501+ }
502+
503+ Result<FieldLabel> FieldLabelFromJson (const nlohmann::json& json) {
504+ if (!json.is_object ()) {
505+ return JsonParseError (" Cannot parse field label from non-object: {}" ,
506+ SafeDumpJson (json));
507+ }
508+ FieldLabel field_label;
509+ ICEBERG_ASSIGN_OR_RAISE (field_label.field_id , GetJsonInteger<int32_t >(json, kFieldId ));
510+ ICEBERG_ASSIGN_OR_RAISE (field_label.labels ,
511+ GetJsonValue<decltype (field_label.labels )>(json, kLabels ));
512+ return field_label;
513+ }
514+
515+ nlohmann::json ToJson (const Labels& labels) {
516+ nlohmann::json json = nlohmann::json::object ();
517+ if (!labels.object_labels .empty ()) {
518+ json[kObjectLabels ] = labels.object_labels ;
519+ }
520+ if (!labels.fields .empty ()) {
521+ nlohmann::json fields = nlohmann::json::array ();
522+ for (const auto & field_label : labels.fields ) {
523+ fields.push_back (ToJson (field_label));
524+ }
525+ json[kFields ] = std::move (fields);
526+ }
527+ return json;
528+ }
529+
530+ // A non-object value is treated as absent labels rather than failing the load.
531+ Result<Labels> LabelsFromJson (const nlohmann::json& json) {
532+ Labels labels;
533+ ICEBERG_ASSIGN_OR_RAISE (
534+ labels.object_labels ,
535+ GetJsonValueOrDefault<decltype (labels.object_labels )>(json, kObjectLabels ));
536+ if (auto it = json.find (kFields ); it != json.end () && !it->is_null ()) {
537+ if (!it->is_array ()) {
538+ return JsonParseError (" Cannot parse '{}' from non-array: {}" , kFields ,
539+ SafeDumpJson (*it));
540+ }
541+ for (const auto & entry : *it) {
542+ ICEBERG_ASSIGN_OR_RAISE (auto field_label, FieldLabelFromJson (entry));
543+ labels.fields .push_back (std::move (field_label));
544+ }
545+ }
546+ return labels;
547+ }
548+
491549// LoadTableResult (used by CreateTableResponse, LoadTableResponse)
492550Result<nlohmann::json> ToJson (const LoadTableResult& result) {
493551 nlohmann::json json;
@@ -502,6 +560,9 @@ Result<nlohmann::json> ToJson(const LoadTableResult& result) {
502560 }
503561 json[kStorageCredentials ] = std::move (creds);
504562 }
563+ if (!result.labels .empty ()) {
564+ json[kLabels ] = ToJson (result.labels );
565+ }
505566 return json;
506567}
507568
@@ -515,6 +576,9 @@ Result<LoadTableResult> LoadTableResultFromJson(const nlohmann::json& json) {
515576 ICEBERG_ASSIGN_OR_RAISE (result.config ,
516577 GetJsonValueOrDefault<decltype (result.config )>(json, kConfig ));
517578 ICEBERG_ASSIGN_OR_RAISE (result.storage_credentials , StorageCredentialsFromJson (json));
579+ if (auto it = json.find (kLabels ); it != json.end () && !it->is_null ()) {
580+ ICEBERG_ASSIGN_OR_RAISE (result.labels , LabelsFromJson (*it));
581+ }
518582 ICEBERG_RETURN_UNEXPECTED (result.Validate ());
519583 return result;
520584}
@@ -1003,5 +1067,7 @@ ICEBERG_DEFINE_FROM_JSON(CommitTableResponse)
10031067ICEBERG_DEFINE_FROM_JSON (OAuthTokenResponse)
10041068ICEBERG_DEFINE_FROM_JSON (PlanTableScanRequest)
10051069ICEBERG_DEFINE_FROM_JSON (FetchScanTasksRequest)
1070+ ICEBERG_DEFINE_FROM_JSON (FieldLabel)
1071+ ICEBERG_DEFINE_FROM_JSON (Labels)
10061072
10071073} // namespace iceberg::rest
0 commit comments