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" ;
@@ -474,6 +479,59 @@ Result<RenameTableRequest> RenameTableRequestFromJson(const nlohmann::json& json
474479 return request;
475480}
476481
482+ nlohmann::json ToJson (const FieldLabel& field_label) {
483+ nlohmann::json json;
484+ json[kFieldId ] = field_label.field_id ;
485+ json[kLabels ] = field_label.labels ;
486+ return json;
487+ }
488+
489+ Result<FieldLabel> FieldLabelFromJson (const nlohmann::json& json) {
490+ if (!json.is_object ()) {
491+ return JsonParseError (" Cannot parse field label from non-object: {}" ,
492+ SafeDumpJson (json));
493+ }
494+ FieldLabel field_label;
495+ ICEBERG_ASSIGN_OR_RAISE (field_label.field_id , GetJsonInteger<int32_t >(json, kFieldId ));
496+ ICEBERG_ASSIGN_OR_RAISE (field_label.labels ,
497+ GetJsonValue<decltype (field_label.labels )>(json, kLabels ));
498+ return field_label;
499+ }
500+
501+ nlohmann::json ToJson (const Labels& labels) {
502+ nlohmann::json json = nlohmann::json::object ();
503+ if (!labels.object_labels .empty ()) {
504+ json[kObjectLabels ] = labels.object_labels ;
505+ }
506+ if (!labels.fields .empty ()) {
507+ nlohmann::json fields = nlohmann::json::array ();
508+ for (const auto & field_label : labels.fields ) {
509+ fields.push_back (ToJson (field_label));
510+ }
511+ json[kFields ] = std::move (fields);
512+ }
513+ return json;
514+ }
515+
516+ // A non-object value is treated as absent labels rather than failing the load.
517+ Result<Labels> LabelsFromJson (const nlohmann::json& json) {
518+ Labels labels;
519+ ICEBERG_ASSIGN_OR_RAISE (
520+ labels.object_labels ,
521+ GetJsonValueOrDefault<decltype (labels.object_labels )>(json, kObjectLabels ));
522+ if (auto it = json.find (kFields ); it != json.end () && !it->is_null ()) {
523+ if (!it->is_array ()) {
524+ return JsonParseError (" Cannot parse '{}' from non-array: {}" , kFields ,
525+ SafeDumpJson (*it));
526+ }
527+ for (const auto & entry : *it) {
528+ ICEBERG_ASSIGN_OR_RAISE (auto field_label, FieldLabelFromJson (entry));
529+ labels.fields .push_back (std::move (field_label));
530+ }
531+ }
532+ return labels;
533+ }
534+
477535// LoadTableResult (used by CreateTableResponse, LoadTableResponse)
478536Result<nlohmann::json> ToJson (const LoadTableResult& result) {
479537 nlohmann::json json;
@@ -488,6 +546,9 @@ Result<nlohmann::json> ToJson(const LoadTableResult& result) {
488546 }
489547 json[kStorageCredentials ] = std::move (creds);
490548 }
549+ if (!result.labels .empty ()) {
550+ json[kLabels ] = ToJson (result.labels );
551+ }
491552 return json;
492553}
493554
@@ -501,6 +562,9 @@ Result<LoadTableResult> LoadTableResultFromJson(const nlohmann::json& json) {
501562 ICEBERG_ASSIGN_OR_RAISE (result.config ,
502563 GetJsonValueOrDefault<decltype (result.config )>(json, kConfig ));
503564 ICEBERG_ASSIGN_OR_RAISE (result.storage_credentials , StorageCredentialsFromJson (json));
565+ if (auto it = json.find (kLabels ); it != json.end () && !it->is_null ()) {
566+ ICEBERG_ASSIGN_OR_RAISE (result.labels , LabelsFromJson (*it));
567+ }
504568 ICEBERG_RETURN_UNEXPECTED (result.Validate ());
505569 return result;
506570}
@@ -983,5 +1047,7 @@ ICEBERG_DEFINE_FROM_JSON(CommitTableResponse)
9831047ICEBERG_DEFINE_FROM_JSON (OAuthTokenResponse)
9841048ICEBERG_DEFINE_FROM_JSON (PlanTableScanRequest)
9851049ICEBERG_DEFINE_FROM_JSON (FetchScanTasksRequest)
1050+ ICEBERG_DEFINE_FROM_JSON (FieldLabel)
1051+ ICEBERG_DEFINE_FROM_JSON (Labels)
9861052
9871053} // namespace iceberg::rest
0 commit comments