This is an automated email from the ASF dual-hosted git repository.
Jefffrey pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/arrow-rs.git
The following commit(s) were added to refs/heads/main by this push:
new 7d9bdfd8a8 fix(arrow-integration-test): preserve field metadata in
JSON (#10811)
7d9bdfd8a8 is described below
commit 7d9bdfd8a83eb66672826757c324e6fc73d20d53
Author: Stefan Wang <[email protected]>
AuthorDate: Tue Aug 25 01:48:12 2026 -0400
fix(arrow-integration-test): preserve field metadata in JSON (#10811)
# Which issue does this PR close?
- Closes #6700.
# Rationale for this change
Converting an Arrow schema to integration JSON and reading it back
silently drops metadata attached to fields. The emitted field metadata
is `null` instead of the original key-value map.
# What changes are included in this PR?
`field_to_json` now adds non-empty metadata after constructing either an
ordinary or dictionary field. Fields without metadata keep their
existing JSON shape.
# Are these changes tested?
Yes. Ordinary and dictionary field metadata tests fail on `origin/main`
and pass with this change. The full crate suite also passes.
<details>
<summary>Raw logs</summary>
Before (`origin/main` at `cd7c6b83abd6605a83014b3d043930a592542510`):
```console
$ cargo test -p arrow-integration-test schema::tests::field_metadata_json
-- --exact
test schema::tests::field_metadata_json ... FAILED
left: Null
right: Object {"key": String("value")}
test result: FAILED. 0 passed; 1 failed
$ cargo test -p arrow-integration-test
schema::tests::dictionary_field_metadata_json -- --exact
test schema::tests::dictionary_field_metadata_json ... FAILED
left: Null
right: Object {"dictionary_key": String("dictionary_value")}
test result: FAILED. 0 passed; 1 failed
```
After:
```console
$ cargo test -p arrow-integration-test schema::tests::field_metadata_json
-- --exact
test schema::tests::field_metadata_json ... ok
test result: ok. 1 passed; 0 failed
$ cargo test -p arrow-integration-test
schema::tests::dictionary_field_metadata_json -- --exact
test schema::tests::dictionary_field_metadata_json ... ok
test result: ok. 1 passed; 0 failed
$ cargo test -p arrow-integration-test
test result: ok. 13 passed; 0 failed
```
</details>
Hygiene: `cargo fmt --check` and `cargo clippy -p arrow-integration-test
--all-targets --all-features -- -D warnings` pass.
# Are there any user-facing changes?
Yes. Integration JSON now preserves non-empty metadata on ordinary and
dictionary fields. There is no public API or breaking change.
Signed-off-by: 1fanwang <[email protected]>
---
arrow-integration-test/src/field.rs | 12 ++++++++++-
arrow-integration-test/src/schema.rs | 41 ++++++++++++++++++++++++++++++++++++
2 files changed, 52 insertions(+), 1 deletion(-)
diff --git a/arrow-integration-test/src/field.rs
b/arrow-integration-test/src/field.rs
index 253ab6fe76..da30217431 100644
--- a/arrow-integration-test/src/field.rs
+++ b/arrow-integration-test/src/field.rs
@@ -306,7 +306,7 @@ pub fn field_to_json(field: &Field) -> serde_json::Value {
_ => vec![],
};
- match field.data_type() {
+ let mut json = match field.data_type() {
DataType::Dictionary(index_type, value_type) => {
#[expect(deprecated)]
let dict_id = field.dict_id().unwrap();
@@ -328,7 +328,17 @@ pub fn field_to_json(field: &Field) -> serde_json::Value {
"type": data_type_to_json(field.data_type()),
"children": children
}),
+ };
+
+ if !field.metadata().is_empty() {
+ json["metadata"] = field
+ .metadata()
+ .iter()
+ .map(|(key, value)| (key.clone(), value.clone()))
+ .collect();
}
+
+ json
}
#[cfg(test)]
diff --git a/arrow-integration-test/src/schema.rs
b/arrow-integration-test/src/schema.rs
index c43c8bb126..28e67c851c 100644
--- a/arrow-integration-test/src/schema.rs
+++ b/arrow-integration-test/src/schema.rs
@@ -728,4 +728,45 @@ mod tests {
let schema = schema_from_json(&value).unwrap();
assert!(schema.metadata.is_empty());
}
+
+ #[test]
+ fn field_metadata_json() {
+ let schema = Schema::new(vec![
+ Field::new("field", DataType::Utf8, false)
+ .with_metadata(HashMap::from([("key".to_string(),
"value".to_string())])),
+ ]);
+
+ let json = schema_to_json(&schema);
+
+ assert_eq!(
+ json["fields"][0]["metadata"],
+ serde_json::json!({"key": "value"})
+ );
+ assert_eq!(schema_from_json(&json).unwrap(), schema);
+ }
+
+ #[test]
+ fn dictionary_field_metadata_json() {
+ #[expect(deprecated)]
+ let field = Field::new_dict(
+ "dictionary",
+ DataType::Dictionary(Box::new(DataType::Int32),
Box::new(DataType::Utf8)),
+ true,
+ 42,
+ false,
+ )
+ .with_metadata(HashMap::from([(
+ "dictionary_key".to_string(),
+ "dictionary_value".to_string(),
+ )]));
+ let schema = Schema::new(vec![field]);
+
+ let json = schema_to_json(&schema);
+
+ assert_eq!(
+ json["fields"][0]["metadata"],
+ serde_json::json!({"dictionary_key": "dictionary_value"})
+ );
+ assert_eq!(schema_from_json(&json).unwrap(), schema);
+ }
}