This is an automated email from the ASF dual-hosted git repository.

alamb 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 cf0c0895b1 [Variant] Rename `batch_json_string_to_variant` and 
`batch_variant_to_json_string` (#8161)
cf0c0895b1 is described below

commit cf0c0895b151212acb4c388f2e29158d0ed7f659
Author: Liam Bao <liam.zw....@gmail.com>
AuthorDate: Tue Aug 19 10:34:47 2025 -0400

    [Variant] Rename `batch_json_string_to_variant` and 
`batch_variant_to_json_string` (#8161)
    
    # Which issue does this PR close?
    
    We generally require a GitHub issue to be filed for all bug fixes and
    enhancements and this helps us generate change logs for our releases.
    You can link an issue to this PR using the GitHub syntax.
    
    - Closes #8144.
    
    # Rationale for this change
    
    # What changes are included in this PR?
    
    Use extension traits to wrap the json variant conversion function, and
    rename batch function to a more common name.
    
    # Are these changes tested?
    
    Yes
    
    # Are there any user-facing changes?
    
    The APIs of parquet-variant-json are changed
    
    ---------
    
    Co-authored-by: Andrew Lamb <and...@nerdnetworks.org>
---
 parquet-variant-compute/benches/variant_kernels.rs |  10 +-
 parquet-variant-compute/src/from_json.rs           |  20 +-
 parquet-variant-compute/src/lib.rs                 |   8 +-
 parquet-variant-compute/src/to_json.rs             |  12 +-
 parquet-variant-compute/src/variant_get/mod.rs     |   6 +-
 parquet-variant-json/src/from_json.rs              |  49 +-
 parquet-variant-json/src/lib.rs                    |   8 +-
 parquet-variant-json/src/to_json.rs                | 703 +++++++++++----------
 8 files changed, 414 insertions(+), 402 deletions(-)

diff --git a/parquet-variant-compute/benches/variant_kernels.rs 
b/parquet-variant-compute/benches/variant_kernels.rs
index 8fd6af333f..5e97f948b2 100644
--- a/parquet-variant-compute/benches/variant_kernels.rs
+++ b/parquet-variant-compute/benches/variant_kernels.rs
@@ -20,7 +20,7 @@ use arrow::util::test_util::seedable_rng;
 use criterion::{criterion_group, criterion_main, Criterion};
 use parquet_variant::{Variant, VariantBuilder};
 use parquet_variant_compute::variant_get::{variant_get, GetOptions};
-use parquet_variant_compute::{batch_json_string_to_variant, VariantArray, 
VariantArrayBuilder};
+use parquet_variant_compute::{json_to_variant, VariantArray, 
VariantArrayBuilder};
 use rand::distr::Alphanumeric;
 use rand::rngs::StdRng;
 use rand::Rng;
@@ -34,7 +34,7 @@ fn benchmark_batch_json_string_to_variant(c: &mut Criterion) {
         "batch_json_string_to_variant repeated_struct 8k string",
         |b| {
             b.iter(|| {
-                let _ = batch_json_string_to_variant(&array_ref).unwrap();
+                let _ = json_to_variant(&array_ref).unwrap();
             });
         },
     );
@@ -43,7 +43,7 @@ fn benchmark_batch_json_string_to_variant(c: &mut Criterion) {
     let array_ref: ArrayRef = Arc::new(input_array);
     c.bench_function("batch_json_string_to_variant json_list 8k string", |b| {
         b.iter(|| {
-            let _ = batch_json_string_to_variant(&array_ref).unwrap();
+            let _ = json_to_variant(&array_ref).unwrap();
         });
     });
 
@@ -60,7 +60,7 @@ fn benchmark_batch_json_string_to_variant(c: &mut Criterion) {
     let array_ref: ArrayRef = Arc::new(input_array);
     c.bench_function(&id, |b| {
         b.iter(|| {
-            let _ = batch_json_string_to_variant(&array_ref).unwrap();
+            let _ = json_to_variant(&array_ref).unwrap();
         });
     });
 
@@ -77,7 +77,7 @@ fn benchmark_batch_json_string_to_variant(c: &mut Criterion) {
     let array_ref: ArrayRef = Arc::new(input_array);
     c.bench_function(&id, |b| {
         b.iter(|| {
-            let _ = batch_json_string_to_variant(&array_ref).unwrap();
+            let _ = json_to_variant(&array_ref).unwrap();
         });
     });
 }
diff --git a/parquet-variant-compute/src/from_json.rs 
b/parquet-variant-compute/src/from_json.rs
index 644bd8ad6a..8512620f46 100644
--- a/parquet-variant-compute/src/from_json.rs
+++ b/parquet-variant-compute/src/from_json.rs
@@ -21,7 +21,7 @@
 use crate::{VariantArray, VariantArrayBuilder};
 use arrow::array::{Array, ArrayRef, LargeStringArray, StringArray, 
StringViewArray};
 use arrow_schema::ArrowError;
-use parquet_variant_json::json_to_variant;
+use parquet_variant_json::JsonToVariant;
 
 /// Macro to convert string array to variant array
 macro_rules! string_array_to_variant {
@@ -31,7 +31,7 @@ macro_rules! string_array_to_variant {
                 $builder.append_null();
             } else {
                 let mut vb = $builder.variant_builder();
-                json_to_variant($array.value(i), &mut vb)?;
+                vb.append_json($array.value(i))?;
                 vb.finish()
             }
         }
@@ -46,7 +46,7 @@ macro_rules! string_array_to_variant {
 /// - [`StringArray`]
 /// - [`LargeStringArray`]
 /// - [`StringViewArray`]
-pub fn batch_json_string_to_variant(input: &ArrayRef) -> Result<VariantArray, 
ArrowError> {
+pub fn json_to_variant(input: &ArrayRef) -> Result<VariantArray, ArrowError> {
     let mut variant_array_builder = VariantArrayBuilder::new(input.len());
 
     // Try each string array type in sequence
@@ -68,14 +68,14 @@ pub fn batch_json_string_to_variant(input: &ArrayRef) -> 
Result<VariantArray, Ar
 
 #[cfg(test)]
 mod test {
-    use crate::batch_json_string_to_variant;
+    use crate::json_to_variant;
     use arrow::array::{Array, ArrayRef, LargeStringArray, StringArray, 
StringViewArray};
     use arrow_schema::ArrowError;
     use parquet_variant::{Variant, VariantBuilder};
     use std::sync::Arc;
 
     #[test]
-    fn test_batch_json_string_to_variant() -> Result<(), ArrowError> {
+    fn test_json_to_variant() -> Result<(), ArrowError> {
         let input = StringArray::from(vec![
             Some("1"),
             None,
@@ -84,7 +84,7 @@ mod test {
             None,
         ]);
         let array_ref: ArrayRef = Arc::new(input);
-        let variant_array = batch_json_string_to_variant(&array_ref).unwrap();
+        let variant_array = json_to_variant(&array_ref).unwrap();
 
         let metadata_array = variant_array.metadata_field();
         let value_array = variant_array.value_field().expect("value field");
@@ -124,7 +124,7 @@ mod test {
     }
 
     #[test]
-    fn test_batch_json_string_to_variant_large_string() -> Result<(), 
ArrowError> {
+    fn test_json_to_variant_large_string() -> Result<(), ArrowError> {
         let input = LargeStringArray::from(vec![
             Some("1"),
             None,
@@ -133,7 +133,7 @@ mod test {
             None,
         ]);
         let array_ref: ArrayRef = Arc::new(input);
-        let variant_array = batch_json_string_to_variant(&array_ref).unwrap();
+        let variant_array = json_to_variant(&array_ref).unwrap();
 
         let metadata_array = variant_array.metadata_field();
         let value_array = variant_array.value_field().expect("value field");
@@ -173,7 +173,7 @@ mod test {
     }
 
     #[test]
-    fn test_batch_json_string_to_variant_string_view() -> Result<(), 
ArrowError> {
+    fn test_json_to_variant_string_view() -> Result<(), ArrowError> {
         let input = StringViewArray::from(vec![
             Some("1"),
             None,
@@ -182,7 +182,7 @@ mod test {
             None,
         ]);
         let array_ref: ArrayRef = Arc::new(input);
-        let variant_array = batch_json_string_to_variant(&array_ref).unwrap();
+        let variant_array = json_to_variant(&array_ref).unwrap();
 
         let metadata_array = variant_array.metadata_field();
         let value_array = variant_array.value_field().expect("value field");
diff --git a/parquet-variant-compute/src/lib.rs 
b/parquet-variant-compute/src/lib.rs
index de7fc720be..245e344488 100644
--- a/parquet-variant-compute/src/lib.rs
+++ b/parquet-variant-compute/src/lib.rs
@@ -20,8 +20,8 @@
 //! ## Main APIs
 //! - [`VariantArray`] : Represents an array of `Variant` values.
 //! - [`VariantArrayBuilder`]: For building [`VariantArray`]
-//! - [`batch_json_string_to_variant`]: Function to convert a batch of JSON 
strings to a `VariantArray`.
-//! - [`batch_variant_to_json_string`]: Function to convert a `VariantArray` 
to a batch of JSON strings.
+//! - [`json_to_variant`]: Function to convert a batch of JSON strings to a 
`VariantArray`.
+//! - [`variant_to_json`]: Function to convert a `VariantArray` to a batch of 
JSON strings.
 //! - [`cast_to_variant`]: Module to cast other Arrow arrays to `VariantArray`.
 //! - [`variant_get`]: Module to get values from a `VariantArray` using a 
specified [`VariantPath`]
 //!
@@ -45,5 +45,5 @@ pub mod variant_get;
 pub use variant_array::{ShreddingState, VariantArray};
 pub use variant_array_builder::{VariantArrayBuilder, 
VariantArrayVariantBuilder};
 
-pub use from_json::batch_json_string_to_variant;
-pub use to_json::batch_variant_to_json_string;
+pub use from_json::json_to_variant;
+pub use to_json::variant_to_json;
diff --git a/parquet-variant-compute/src/to_json.rs 
b/parquet-variant-compute/src/to_json.rs
index c7c4653ac7..1d6f51ca24 100644
--- a/parquet-variant-compute/src/to_json.rs
+++ b/parquet-variant-compute/src/to_json.rs
@@ -23,11 +23,11 @@ use arrow::buffer::{Buffer, NullBuffer, OffsetBuffer, 
ScalarBuffer};
 use arrow::datatypes::DataType;
 use arrow_schema::ArrowError;
 use parquet_variant::Variant;
-use parquet_variant_json::variant_to_json;
+use parquet_variant_json::VariantToJson;
 
 /// Transform a batch of Variant represented as STRUCT<metadata: BINARY, 
value: BINARY> to a batch
 /// of JSON strings where nulls are preserved. The JSON strings in the input 
must be valid.
-pub fn batch_variant_to_json_string(input: &ArrayRef) -> Result<StringArray, 
ArrowError> {
+pub fn variant_to_json(input: &ArrayRef) -> Result<StringArray, ArrowError> {
     let struct_array = input
         .as_any()
         .downcast_ref::<StructArray>()
@@ -83,7 +83,7 @@ pub fn batch_variant_to_json_string(input: &ArrayRef) -> 
Result<StringArray, Arr
             let value = value_array.value(i);
             let variant = Variant::new(metadata, value);
             let start_len = json_buffer.len();
-            variant_to_json(&mut json_buffer, &variant)?;
+            variant.to_json(&mut json_buffer)?;
             let written = (json_buffer.len() - start_len) as i32;
             current_offset += written;
             offsets.push(current_offset);
@@ -104,7 +104,7 @@ pub fn batch_variant_to_json_string(input: &ArrayRef) -> 
Result<StringArray, Arr
 
 #[cfg(test)]
 mod test {
-    use crate::batch_variant_to_json_string;
+    use crate::variant_to_json;
     use arrow::array::{Array, ArrayRef, BinaryBuilder, BooleanBufferBuilder, 
StructArray};
     use arrow::buffer::NullBuffer;
     use arrow::datatypes::DataType;
@@ -113,7 +113,7 @@ mod test {
     use std::sync::Arc;
 
     #[test]
-    fn test_batch_variant_to_json_string() {
+    fn test_variant_to_json() {
         let mut metadata_builder = BinaryBuilder::new();
         let mut value_builder = BinaryBuilder::new();
 
@@ -161,7 +161,7 @@ mod test {
 
         let input = Arc::new(struct_array) as ArrayRef;
 
-        let result = batch_variant_to_json_string(&input).unwrap();
+        let result = variant_to_json(&input).unwrap();
 
         // Expected output: ["0", null, "{\"a\":32}", "null", null]
         let expected = vec![Some("0"), None, Some("{\"a\":32}"), Some("null"), 
None];
diff --git a/parquet-variant-compute/src/variant_get/mod.rs 
b/parquet-variant-compute/src/variant_get/mod.rs
index cc852bbc32..6812a17483 100644
--- a/parquet-variant-compute/src/variant_get/mod.rs
+++ b/parquet-variant-compute/src/variant_get/mod.rs
@@ -112,7 +112,7 @@ mod test {
     use arrow_schema::{DataType, Field, FieldRef, Fields};
     use parquet_variant::{Variant, VariantPath};
 
-    use crate::batch_json_string_to_variant;
+    use crate::json_to_variant;
     use crate::VariantArray;
 
     use super::{variant_get, GetOptions};
@@ -121,14 +121,14 @@ mod test {
         // Create input array from JSON string
         let input_array_ref: ArrayRef = 
Arc::new(StringArray::from(vec![Some(input_json)]));
         let input_variant_array_ref: ArrayRef =
-            Arc::new(batch_json_string_to_variant(&input_array_ref).unwrap());
+            Arc::new(json_to_variant(&input_array_ref).unwrap());
 
         let result =
             variant_get(&input_variant_array_ref, 
GetOptions::new_with_path(path)).unwrap();
 
         // Create expected array from JSON string
         let expected_array_ref: ArrayRef = 
Arc::new(StringArray::from(vec![Some(expected_json)]));
-        let expected_variant_array = 
batch_json_string_to_variant(&expected_array_ref).unwrap();
+        let expected_variant_array = 
json_to_variant(&expected_array_ref).unwrap();
 
         let result_array: &VariantArray = 
result.as_any().downcast_ref().unwrap();
         assert_eq!(
diff --git a/parquet-variant-json/src/from_json.rs 
b/parquet-variant-json/src/from_json.rs
index 134bafe953..6f6751ede3 100644
--- a/parquet-variant-json/src/from_json.rs
+++ b/parquet-variant-json/src/from_json.rs
@@ -21,7 +21,7 @@ use arrow_schema::ArrowError;
 use parquet_variant::{ListBuilder, ObjectBuilder, Variant, VariantBuilderExt};
 use serde_json::{Number, Value};
 
-/// Converts a JSON string to Variant to a [`VariantBuilderExt`], such as
+/// Converts a JSON string to Variant using a [`VariantBuilderExt`], such as
 /// [`VariantBuilder`].
 ///
 /// The resulting `value` and `metadata` buffers can be
@@ -29,9 +29,6 @@ use serde_json::{Number, Value};
 ///
 /// # Arguments
 /// * `json` - The JSON string to parse as Variant.
-/// * `variant_builder` - Object of type `VariantBuilder` used to build the 
variant from the JSON
-///   string
-///
 ///
 /// # Returns
 ///
@@ -42,25 +39,23 @@ use serde_json::{Number, Value};
 ///
 /// ```rust
 /// # use parquet_variant::VariantBuilder;
-/// # use parquet_variant_json::{
-/// #   json_to_variant, variant_to_json_string, variant_to_json, 
variant_to_json_value
-/// # };
+/// # use parquet_variant_json::{JsonToVariant, VariantToJson};
 ///
 /// let mut variant_builder = VariantBuilder::new();
 /// let person_string = "{\"name\":\"Alice\", \"age\":30, ".to_string()
 /// + "\"email\":\"al...@example.com\", \"is_active\": true, \"score\": 95.7,"
 /// + "\"additional_info\": null}";
-/// json_to_variant(&person_string, &mut variant_builder)?;
+/// variant_builder.append_json(&person_string)?;
 ///
 /// let (metadata, value) = variant_builder.finish();
 ///
 /// let variant = parquet_variant::Variant::try_new(&metadata, &value)?;
 ///
-/// let json_result = variant_to_json_string(&variant)?;
-/// let json_value = variant_to_json_value(&variant)?;
+/// let json_result = variant.to_json_string()?;
+/// let json_value = variant.to_json_value()?;
 ///
 /// let mut buffer = Vec::new();
-/// variant_to_json(&mut buffer, &variant)?;
+/// variant.to_json(&mut buffer)?;
 /// let buffer_result = String::from_utf8(buffer)?;
 /// assert_eq!(json_result, 
"{\"additional_info\":null,\"age\":30,".to_string() +
 /// 
"\"email\":\"al...@example.com\",\"is_active\":true,\"name\":\"Alice\",\"score\":95.7}");
@@ -68,17 +63,19 @@ use serde_json::{Number, Value};
 /// assert_eq!(json_result, serde_json::to_string(&json_value)?);
 /// # Ok::<(), Box<dyn std::error::Error>>(())
 /// ```
-pub fn json_to_variant(json: &str, builder: &mut impl VariantBuilderExt) -> 
Result<(), ArrowError> {
-    let json: Value = serde_json::from_str(json)
-        .map_err(|e| ArrowError::InvalidArgumentError(format!("JSON format 
error: {e}")))?;
-
-    build_json(&json, builder)?;
-    Ok(())
+pub trait JsonToVariant {
+    /// Create a Variant from a JSON string
+    fn append_json(&mut self, json: &str) -> Result<(), ArrowError>;
 }
 
-fn build_json(json: &Value, builder: &mut impl VariantBuilderExt) -> 
Result<(), ArrowError> {
-    append_json(json, builder)?;
-    Ok(())
+impl<T: VariantBuilderExt> JsonToVariant for T {
+    fn append_json(&mut self, json: &str) -> Result<(), ArrowError> {
+        let json: Value = serde_json::from_str(json)
+            .map_err(|e| ArrowError::InvalidArgumentError(format!("JSON format 
error: {e}")))?;
+
+        append_json(&json, self)?;
+        Ok(())
+    }
 }
 
 fn variant_from_number<'m, 'v>(n: &Number) -> Result<Variant<'m, 'v>, 
ArrowError> {
@@ -157,7 +154,7 @@ impl VariantBuilderExt for ObjectFieldBuilder<'_, '_, '_> {
 #[cfg(test)]
 mod test {
     use super::*;
-    use crate::variant_to_json_string;
+    use crate::VariantToJson;
     use arrow_schema::ArrowError;
     use parquet_variant::{
         ShortString, Variant, VariantBuilder, VariantDecimal16, 
VariantDecimal4, VariantDecimal8,
@@ -171,7 +168,7 @@ mod test {
     impl JsonToVariantTest<'_> {
         fn run(self) -> Result<(), ArrowError> {
             let mut variant_builder = VariantBuilder::new();
-            json_to_variant(self.json, &mut variant_builder)?;
+            variant_builder.append_json(self.json)?;
             let (metadata, value) = variant_builder.finish();
             let variant = Variant::try_new(&metadata, &value)?;
             assert_eq!(variant, self.expected);
@@ -622,10 +619,10 @@ mod test {
         );
         // Manually verify raw JSON value size
         let mut variant_builder = VariantBuilder::new();
-        json_to_variant(&json, &mut variant_builder)?;
+        variant_builder.append_json(&json)?;
         let (metadata, value) = variant_builder.finish();
         let v = Variant::try_new(&metadata, &value)?;
-        let output_string = variant_to_json_string(&v)?;
+        let output_string = v.to_json_string()?;
         assert_eq!(output_string, json);
         // Verify metadata size = 1 + 2 + 2 * 497 + 3 * 496
         assert_eq!(metadata.len(), 2485);
@@ -663,10 +660,10 @@ mod test {
     fn test_json_to_variant_unicode() -> Result<(), ArrowError> {
         let json = "{\"爱\":\"अ\",\"a\":1}";
         let mut variant_builder = VariantBuilder::new();
-        json_to_variant(json, &mut variant_builder)?;
+        variant_builder.append_json(json)?;
         let (metadata, value) = variant_builder.finish();
         let v = Variant::try_new(&metadata, &value)?;
-        let output_string = variant_to_json_string(&v)?;
+        let output_string = v.to_json_string()?;
         assert_eq!(output_string, "{\"a\":1,\"爱\":\"अ\"}");
         let mut variant_builder = VariantBuilder::new();
         let mut object_builder = variant_builder.new_object();
diff --git a/parquet-variant-json/src/lib.rs b/parquet-variant-json/src/lib.rs
index bb774c05c1..f24c740818 100644
--- a/parquet-variant-json/src/lib.rs
+++ b/parquet-variant-json/src/lib.rs
@@ -21,8 +21,8 @@
 //! [Variant Binary Encoding]: 
https://github.com/apache/parquet-format/blob/master/VariantEncoding.md
 //! [Apache Parquet]: https://parquet.apache.org/
 //!
-//! * See [`json_to_variant`] for converting a JSON string to a Variant.
-//! * See [`variant_to_json`] for converting a Variant to a JSON string.
+//! * See [`JsonToVariant`] trait for converting a JSON string to a Variant.
+//! * See [`VariantToJson`] trait for converting a Variant to a JSON string.
 //!
 //! ## 🚧 Work In Progress
 //!
@@ -34,5 +34,5 @@
 mod from_json;
 mod to_json;
 
-pub use from_json::json_to_variant;
-pub use to_json::{variant_to_json, variant_to_json_string, 
variant_to_json_value};
+pub use from_json::JsonToVariant;
+pub use to_json::VariantToJson;
diff --git a/parquet-variant-json/src/to_json.rs 
b/parquet-variant-json/src/to_json.rs
index e18f3b327c..4753d6cc96 100644
--- a/parquet-variant-json/src/to_json.rs
+++ b/parquet-variant-json/src/to_json.rs
@@ -23,6 +23,304 @@ use parquet_variant::{Variant, VariantList, VariantObject};
 use serde_json::Value;
 use std::io::Write;
 
+/// Extension trait for converting Variants to JSON
+pub trait VariantToJson {
+    ///
+    /// This function writes JSON directly to any type that implements 
[`Write`],
+    /// making it efficient for streaming or when you want to control the 
output destination.
+    ///
+    /// See [`VariantToJson::to_json_string`] for a convenience function that 
returns a
+    /// JSON string.
+    ///
+    /// # Arguments
+    ///
+    /// * `writer` - Writer to output JSON to
+    /// * `variant` - The Variant value to convert
+    ///
+    /// # Returns
+    ///
+    /// * `Ok(())` if successful
+    /// * `Err` with error details if conversion fails
+    ///
+    /// # Examples
+    ///
+    ///
+    /// ```rust
+    /// # use parquet_variant::{Variant};
+    /// # use parquet_variant_json::VariantToJson;
+    /// # use arrow_schema::ArrowError;
+    /// let variant = Variant::from("Hello, World!");
+    /// let mut buffer = Vec::new();
+    /// variant.to_json(&mut buffer)?;
+    /// assert_eq!(String::from_utf8(buffer).unwrap(), "\"Hello, World!\"");
+    /// # Ok::<(), ArrowError>(())
+    /// ```
+    ///
+    /// # Example: Create a [`Variant::Object`] and convert to JSON
+    /// ```rust
+    /// # use parquet_variant::{Variant, VariantBuilder};
+    /// # use parquet_variant_json::VariantToJson;
+    /// # use arrow_schema::ArrowError;
+    /// let mut builder = VariantBuilder::new();
+    /// // Create an object builder that will write fields to the object
+    /// let mut object_builder = builder.new_object();
+    /// object_builder.insert("first_name", "Jiaying");
+    /// object_builder.insert("last_name", "Li");
+    /// object_builder.finish();
+    /// // Finish the builder to get the metadata and value
+    /// let (metadata, value) = builder.finish();
+    /// // Create the Variant and convert to JSON
+    /// let variant = Variant::try_new(&metadata, &value)?;
+    /// let mut writer = Vec::new();
+    /// variant.to_json(&mut writer)?;
+    /// assert_eq!(br#"{"first_name":"Jiaying","last_name":"Li"}"#, 
writer.as_slice());
+    /// # Ok::<(), ArrowError>(())
+    /// ```
+    fn to_json(&self, buffer: &mut impl Write) -> Result<(), ArrowError>;
+
+    /// Convert [`Variant`] to JSON [`String`]
+    ///
+    /// This is a convenience function that converts a Variant to a JSON 
string.
+    /// This is the same as calling [`VariantToJson::to_json`] with a [`Vec`].
+    /// It's the simplest way to get a JSON representation when you just need 
a String result.
+    ///
+    /// # Arguments
+    ///
+    /// * `variant` - The Variant value to convert
+    ///
+    /// # Returns
+    ///
+    /// * `Ok(String)` containing the JSON representation
+    /// * `Err` with error details if conversion fails
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// # use parquet_variant::{Variant};
+    /// # use parquet_variant_json::VariantToJson;
+    /// # use arrow_schema::ArrowError;
+    /// let variant = Variant::Int32(42);
+    /// let json = variant.to_json_string()?;
+    /// assert_eq!(json, "42");
+    /// # Ok::<(), ArrowError>(())
+    /// ```
+    ///
+    /// # Example: Create a [`Variant::Object`] and convert to JSON
+    ///
+    /// This example shows how to create an object with two fields and convert 
it to JSON:
+    /// ```json
+    /// {
+    ///   "first_name": "Jiaying",
+    ///   "last_name": "Li"
+    /// }
+    /// ```
+    ///
+    /// ```rust
+    /// # use parquet_variant::{Variant, VariantBuilder};
+    /// # use parquet_variant_json::VariantToJson;
+    /// # use arrow_schema::ArrowError;
+    /// let mut builder = VariantBuilder::new();
+    /// // Create an object builder that will write fields to the object
+    /// let mut object_builder = builder.new_object();
+    /// object_builder.insert("first_name", "Jiaying");
+    /// object_builder.insert("last_name", "Li");
+    /// object_builder.finish();
+    /// // Finish the builder to get the metadata and value
+    /// let (metadata, value) = builder.finish();
+    /// // Create the Variant and convert to JSON
+    /// let variant = Variant::try_new(&metadata, &value)?;
+    /// let json = variant.to_json_string()?;
+    /// assert_eq!(r#"{"first_name":"Jiaying","last_name":"Li"}"#, json);
+    /// # Ok::<(), ArrowError>(())
+    /// ```
+    fn to_json_string(&self) -> Result<String, ArrowError>;
+
+    /// Convert [`Variant`] to [`serde_json::Value`]
+    ///
+    /// This function converts a Variant to a [`serde_json::Value`], which is 
useful
+    /// when you need to work with the JSON data programmatically or integrate 
with
+    /// other serde-based JSON processing.
+    ///
+    /// # Arguments
+    ///
+    /// * `variant` - The Variant value to convert
+    ///
+    /// # Returns
+    ///
+    /// * `Ok(Value)` containing the JSON value
+    /// * `Err` with error details if conversion fails
+    ///
+    /// # Examples
+    ///
+    /// ```rust
+    /// # use parquet_variant::{Variant};
+    /// # use parquet_variant_json::VariantToJson;
+    /// # use serde_json::Value;
+    /// # use arrow_schema::ArrowError;
+    /// let variant = Variant::from("hello");
+    /// let json_value = variant.to_json_value()?;
+    /// assert_eq!(json_value, Value::String("hello".to_string()));
+    /// # Ok::<(), ArrowError>(())
+    /// ```
+    fn to_json_value(&self) -> Result<Value, ArrowError>;
+}
+
+impl<'m, 'v> VariantToJson for Variant<'m, 'v> {
+    fn to_json(&self, buffer: &mut impl Write) -> Result<(), ArrowError> {
+        match self {
+            Variant::Null => write!(buffer, "null")?,
+            Variant::BooleanTrue => write!(buffer, "true")?,
+            Variant::BooleanFalse => write!(buffer, "false")?,
+            Variant::Int8(i) => write!(buffer, "{i}")?,
+            Variant::Int16(i) => write!(buffer, "{i}")?,
+            Variant::Int32(i) => write!(buffer, "{i}")?,
+            Variant::Int64(i) => write!(buffer, "{i}")?,
+            Variant::Float(f) => write!(buffer, "{f}")?,
+            Variant::Double(f) => write!(buffer, "{f}")?,
+            Variant::Decimal4(decimal) => write!(buffer, "{decimal}")?,
+            Variant::Decimal8(decimal) => write!(buffer, "{decimal}")?,
+            Variant::Decimal16(decimal) => write!(buffer, "{decimal}")?,
+            Variant::Date(date) => write!(buffer, "\"{}\"", 
format_date_string(date))?,
+            Variant::TimestampMicros(ts) => write!(buffer, "\"{}\"", 
ts.to_rfc3339())?,
+            Variant::TimestampNtzMicros(ts) => {
+                write!(buffer, "\"{}\"", format_timestamp_ntz_string(ts))?
+            }
+            Variant::Time(time) => write!(buffer, "\"{}\"", 
format_time_ntz_str(time))?,
+            Variant::Binary(bytes) => {
+                // Encode binary as base64 string
+                let base64_str = format_binary_base64(bytes);
+                let json_str = serde_json::to_string(&base64_str).map_err(|e| {
+                    ArrowError::InvalidArgumentError(format!("JSON encoding 
error: {e}"))
+                })?;
+                write!(buffer, "{json_str}")?
+            }
+            Variant::String(s) => {
+                // Use serde_json to properly escape the string
+                let json_str = serde_json::to_string(s).map_err(|e| {
+                    ArrowError::InvalidArgumentError(format!("JSON encoding 
error: {e}"))
+                })?;
+                write!(buffer, "{json_str}")?
+            }
+            Variant::ShortString(s) => {
+                // Use serde_json to properly escape the string
+                let json_str = serde_json::to_string(s.as_str()).map_err(|e| {
+                    ArrowError::InvalidArgumentError(format!("JSON encoding 
error: {e}"))
+                })?;
+                write!(buffer, "{json_str}")?
+            }
+            Variant::Object(obj) => {
+                convert_object_to_json(buffer, obj)?;
+            }
+            Variant::List(arr) => {
+                convert_array_to_json(buffer, arr)?;
+            }
+        }
+        Ok(())
+    }
+
+    fn to_json_string(&self) -> Result<String, ArrowError> {
+        let mut buffer = Vec::new();
+        self.to_json(&mut buffer)?;
+        String::from_utf8(buffer)
+            .map_err(|e| ArrowError::InvalidArgumentError(format!("UTF-8 
conversion error: {e}")))
+    }
+
+    fn to_json_value(&self) -> Result<Value, ArrowError> {
+        match self {
+            Variant::Null => Ok(Value::Null),
+            Variant::BooleanTrue => Ok(Value::Bool(true)),
+            Variant::BooleanFalse => Ok(Value::Bool(false)),
+            Variant::Int8(i) => Ok(Value::Number((*i).into())),
+            Variant::Int16(i) => Ok(Value::Number((*i).into())),
+            Variant::Int32(i) => Ok(Value::Number((*i).into())),
+            Variant::Int64(i) => Ok(Value::Number((*i).into())),
+            Variant::Float(f) => serde_json::Number::from_f64((*f).into())
+                .map(Value::Number)
+                .ok_or_else(|| ArrowError::InvalidArgumentError("Invalid float 
value".to_string())),
+            Variant::Double(f) => serde_json::Number::from_f64(*f)
+                .map(Value::Number)
+                .ok_or_else(|| {
+                    ArrowError::InvalidArgumentError("Invalid double 
value".to_string())
+                }),
+            Variant::Decimal4(decimal4) => {
+                let scale = decimal4.scale();
+                let integer = decimal4.integer();
+
+                let integer = if scale == 0 {
+                    integer
+                } else {
+                    let divisor = 10_i32.pow(scale as u32);
+                    if integer % divisor != 0 {
+                        // fall back to floating point
+                        return Ok(Value::from(integer as f64 / divisor as 
f64));
+                    }
+                    integer / divisor
+                };
+                Ok(Value::from(integer))
+            }
+            Variant::Decimal8(decimal8) => {
+                let scale = decimal8.scale();
+                let integer = decimal8.integer();
+
+                let integer = if scale == 0 {
+                    integer
+                } else {
+                    let divisor = 10_i64.pow(scale as u32);
+                    if integer % divisor != 0 {
+                        // fall back to floating point
+                        return Ok(Value::from(integer as f64 / divisor as 
f64));
+                    }
+                    integer / divisor
+                };
+                Ok(Value::from(integer))
+            }
+            Variant::Decimal16(decimal16) => {
+                let scale = decimal16.scale();
+                let integer = decimal16.integer();
+
+                let integer = if scale == 0 {
+                    integer
+                } else {
+                    let divisor = 10_i128.pow(scale as u32);
+                    if integer % divisor != 0 {
+                        // fall back to floating point
+                        return Ok(Value::from(integer as f64 / divisor as 
f64));
+                    }
+                    integer / divisor
+                };
+                // i128 has higher precision than any 64-bit type. Try a 
lossless narrowing cast to
+                // i64 or u64 first, falling back to a lossy narrowing cast to 
f64 if necessary.
+                let value = i64::try_from(integer)
+                    .map(Value::from)
+                    .or_else(|_| u64::try_from(integer).map(Value::from))
+                    .unwrap_or_else(|_| Value::from(integer as f64));
+                Ok(value)
+            }
+            Variant::Date(date) => Ok(Value::String(format_date_string(date))),
+            Variant::TimestampMicros(ts) => Ok(Value::String(ts.to_rfc3339())),
+            Variant::TimestampNtzMicros(ts) => 
Ok(Value::String(format_timestamp_ntz_string(ts))),
+            Variant::Time(time) => 
Ok(Value::String(format_time_ntz_str(time))),
+            Variant::Binary(bytes) => 
Ok(Value::String(format_binary_base64(bytes))),
+            Variant::String(s) => Ok(Value::String(s.to_string())),
+            Variant::ShortString(s) => Ok(Value::String(s.to_string())),
+            Variant::Object(obj) => {
+                let map = obj
+                    .iter()
+                    .map(|(k, v)| v.to_json_value().map(|json_val| 
(k.to_string(), json_val)))
+                    .collect::<Result<_, _>>()?;
+                Ok(Value::Object(map))
+            }
+            Variant::List(arr) => {
+                let vec = arr
+                    .iter()
+                    .map(|element| element.to_json_value())
+                    .collect::<Result<_, _>>()?;
+                Ok(Value::Array(vec))
+            }
+        }
+    }
+}
+
 // Format string constants to avoid duplication and reduce errors
 const DATE_FORMAT: &str = "%Y-%m-%d";
 const TIMESTAMP_NTZ_FORMAT: &str = "%Y-%m-%dT%H:%M:%S%.6f";
@@ -53,109 +351,6 @@ fn format_time_ntz_str(time: &chrono::NaiveTime) -> String 
{
     }
 }
 
-///
-/// This function writes JSON directly to any type that implements [`Write`],
-/// making it efficient for streaming or when you want to control the output 
destination.
-///
-/// See [`variant_to_json_string`] for a convenience function that returns a
-/// JSON string.
-///
-/// # Arguments
-///
-/// * `writer` - Writer to output JSON to
-/// * `variant` - The Variant value to convert
-///
-/// # Returns
-///
-/// * `Ok(())` if successful
-/// * `Err` with error details if conversion fails
-///
-/// # Examples
-///
-///
-/// ```rust
-/// # use parquet_variant::{Variant};
-/// # use parquet_variant_json::variant_to_json;
-/// # use arrow_schema::ArrowError;
-/// let variant = Variant::from("Hello, World!");
-/// let mut buffer = Vec::new();
-/// variant_to_json(&mut buffer, &variant)?;
-/// assert_eq!(String::from_utf8(buffer).unwrap(), "\"Hello, World!\"");
-/// # Ok::<(), ArrowError>(())
-/// ```
-///
-/// # Example: Create a [`Variant::Object`] and convert to JSON
-/// ```rust
-/// # use parquet_variant::{Variant, VariantBuilder};
-/// # use parquet_variant_json::variant_to_json;
-/// # use arrow_schema::ArrowError;
-/// let mut builder = VariantBuilder::new();
-/// // Create an object builder that will write fields to the object
-/// let mut object_builder = builder.new_object();
-/// object_builder.insert("first_name", "Jiaying");
-/// object_builder.insert("last_name", "Li");
-/// object_builder.finish();
-/// // Finish the builder to get the metadata and value
-/// let (metadata, value) = builder.finish();
-/// // Create the Variant and convert to JSON
-/// let variant = Variant::try_new(&metadata, &value)?;
-/// let mut writer = Vec::new();
-/// variant_to_json(&mut writer, &variant,)?;
-/// assert_eq!(br#"{"first_name":"Jiaying","last_name":"Li"}"#, 
writer.as_slice());
-/// # Ok::<(), ArrowError>(())
-/// ```
-pub fn variant_to_json(json_buffer: &mut impl Write, variant: &Variant) -> 
Result<(), ArrowError> {
-    match variant {
-        Variant::Null => write!(json_buffer, "null")?,
-        Variant::BooleanTrue => write!(json_buffer, "true")?,
-        Variant::BooleanFalse => write!(json_buffer, "false")?,
-        Variant::Int8(i) => write!(json_buffer, "{i}")?,
-        Variant::Int16(i) => write!(json_buffer, "{i}")?,
-        Variant::Int32(i) => write!(json_buffer, "{i}")?,
-        Variant::Int64(i) => write!(json_buffer, "{i}")?,
-        Variant::Float(f) => write!(json_buffer, "{f}")?,
-        Variant::Double(f) => write!(json_buffer, "{f}")?,
-        Variant::Decimal4(decimal) => write!(json_buffer, "{decimal}")?,
-        Variant::Decimal8(decimal) => write!(json_buffer, "{decimal}")?,
-        Variant::Decimal16(decimal) => write!(json_buffer, "{decimal}")?,
-        Variant::Date(date) => write!(json_buffer, "\"{}\"", 
format_date_string(date))?,
-        Variant::TimestampMicros(ts) => write!(json_buffer, "\"{}\"", 
ts.to_rfc3339())?,
-        Variant::TimestampNtzMicros(ts) => {
-            write!(json_buffer, "\"{}\"", format_timestamp_ntz_string(ts))?
-        }
-        Variant::Time(time) => write!(json_buffer, "\"{}\"", 
format_time_ntz_str(time))?,
-        Variant::Binary(bytes) => {
-            // Encode binary as base64 string
-            let base64_str = format_binary_base64(bytes);
-            let json_str = serde_json::to_string(&base64_str).map_err(|e| {
-                ArrowError::InvalidArgumentError(format!("JSON encoding error: 
{e}"))
-            })?;
-            write!(json_buffer, "{json_str}")?
-        }
-        Variant::String(s) => {
-            // Use serde_json to properly escape the string
-            let json_str = serde_json::to_string(s).map_err(|e| {
-                ArrowError::InvalidArgumentError(format!("JSON encoding error: 
{e}"))
-            })?;
-            write!(json_buffer, "{json_str}")?
-        }
-        Variant::ShortString(s) => {
-            // Use serde_json to properly escape the string
-            let json_str = serde_json::to_string(s.as_str()).map_err(|e| {
-                ArrowError::InvalidArgumentError(format!("JSON encoding error: 
{e}"))
-            })?;
-            write!(json_buffer, "{json_str}")?
-        }
-        Variant::Object(obj) => {
-            convert_object_to_json(json_buffer, obj)?;
-        }
-        Variant::List(arr) => {
-            convert_array_to_json(json_buffer, arr)?;
-        }
-    }
-    Ok(())
-}
-
 /// Convert object fields to JSON
 fn convert_object_to_json(buffer: &mut impl Write, obj: &VariantObject) -> 
Result<(), ArrowError> {
     write!(buffer, "{{")?;
@@ -176,7 +371,7 @@ fn convert_object_to_json(buffer: &mut impl Write, obj: 
&VariantObject) -> Resul
         write!(buffer, "{json_key}:")?;
 
         // Recursively convert the value
-        variant_to_json(buffer, &value)?;
+        value.to_json(buffer)?;
     }
 
     write!(buffer, "}}")?;
@@ -194,195 +389,13 @@ fn convert_array_to_json(buffer: &mut impl Write, arr: 
&VariantList) -> Result<(
         }
         first = false;
 
-        variant_to_json(buffer, &element)?;
+        element.to_json(buffer)?;
     }
 
     write!(buffer, "]")?;
     Ok(())
 }
 
-/// Convert [`Variant`] to JSON [`String`]
-///
-/// This is a convenience function that converts a Variant to a JSON string.
-/// This is the same as calling [`variant_to_json`] with a [`Vec`].
-/// It's the simplest way to get a JSON representation when you just need a 
String result.
-///
-/// # Arguments
-///
-/// * `variant` - The Variant value to convert
-///
-/// # Returns
-///
-/// * `Ok(String)` containing the JSON representation
-/// * `Err` with error details if conversion fails
-///
-/// # Examples
-///
-/// ```rust
-/// # use parquet_variant::{Variant};
-/// # use parquet_variant_json::variant_to_json_string;
-/// # use arrow_schema::ArrowError;
-/// let variant = Variant::Int32(42);
-/// let json = variant_to_json_string(&variant)?;
-/// assert_eq!(json, "42");
-/// # Ok::<(), ArrowError>(())
-/// ```
-///
-/// # Example: Create a [`Variant::Object`] and convert to JSON
-///
-/// This example shows how to create an object with two fields and convert it 
to JSON:
-/// ```json
-/// {
-///   "first_name": "Jiaying",
-///   "last_name": "Li"
-/// }
-/// ```
-///
-/// ```rust
-/// # use parquet_variant::{Variant, VariantBuilder};
-/// # use parquet_variant_json::variant_to_json_string;
-/// # use arrow_schema::ArrowError;
-/// let mut builder = VariantBuilder::new();
-/// // Create an object builder that will write fields to the object
-/// let mut object_builder = builder.new_object();
-/// object_builder.insert("first_name", "Jiaying");
-/// object_builder.insert("last_name", "Li");
-/// object_builder.finish();
-/// // Finish the builder to get the metadata and value
-/// let (metadata, value) = builder.finish();
-/// // Create the Variant and convert to JSON
-/// let variant = Variant::try_new(&metadata, &value)?;
-/// let json = variant_to_json_string(&variant)?;
-/// assert_eq!(r#"{"first_name":"Jiaying","last_name":"Li"}"#, json);
-/// # Ok::<(), ArrowError>(())
-/// ```
-pub fn variant_to_json_string(variant: &Variant) -> Result<String, ArrowError> 
{
-    let mut buffer = Vec::new();
-    variant_to_json(&mut buffer, variant)?;
-    String::from_utf8(buffer)
-        .map_err(|e| ArrowError::InvalidArgumentError(format!("UTF-8 
conversion error: {e}")))
-}
-
-/// Convert [`Variant`] to [`serde_json::Value`]
-///
-/// This function converts a Variant to a [`serde_json::Value`], which is 
useful
-/// when you need to work with the JSON data programmatically or integrate with
-/// other serde-based JSON processing.
-///
-/// # Arguments
-///
-/// * `variant` - The Variant value to convert
-///
-/// # Returns
-///
-/// * `Ok(Value)` containing the JSON value
-/// * `Err` with error details if conversion fails
-///
-/// # Examples
-///
-/// ```rust
-/// # use parquet_variant::{Variant};
-/// # use parquet_variant_json::variant_to_json_value;
-/// # use serde_json::Value;
-/// # use arrow_schema::ArrowError;
-/// let variant = Variant::from("hello");
-/// let json_value = variant_to_json_value(&variant)?;
-/// assert_eq!(json_value, Value::String("hello".to_string()));
-/// # Ok::<(), ArrowError>(())
-/// ```
-pub fn variant_to_json_value(variant: &Variant) -> Result<Value, ArrowError> {
-    match variant {
-        Variant::Null => Ok(Value::Null),
-        Variant::BooleanTrue => Ok(Value::Bool(true)),
-        Variant::BooleanFalse => Ok(Value::Bool(false)),
-        Variant::Int8(i) => Ok(Value::Number((*i).into())),
-        Variant::Int16(i) => Ok(Value::Number((*i).into())),
-        Variant::Int32(i) => Ok(Value::Number((*i).into())),
-        Variant::Int64(i) => Ok(Value::Number((*i).into())),
-        Variant::Float(f) => serde_json::Number::from_f64((*f).into())
-            .map(Value::Number)
-            .ok_or_else(|| ArrowError::InvalidArgumentError("Invalid float 
value".to_string())),
-        Variant::Double(f) => serde_json::Number::from_f64(*f)
-            .map(Value::Number)
-            .ok_or_else(|| ArrowError::InvalidArgumentError("Invalid double 
value".to_string())),
-        Variant::Decimal4(decimal4) => {
-            let scale = decimal4.scale();
-            let integer = decimal4.integer();
-
-            let integer = if scale == 0 {
-                integer
-            } else {
-                let divisor = 10_i32.pow(scale as u32);
-                if integer % divisor != 0 {
-                    // fall back to floating point
-                    return Ok(Value::from(integer as f64 / divisor as f64));
-                }
-                integer / divisor
-            };
-            Ok(Value::from(integer))
-        }
-        Variant::Decimal8(decimal8) => {
-            let scale = decimal8.scale();
-            let integer = decimal8.integer();
-
-            let integer = if scale == 0 {
-                integer
-            } else {
-                let divisor = 10_i64.pow(scale as u32);
-                if integer % divisor != 0 {
-                    // fall back to floating point
-                    return Ok(Value::from(integer as f64 / divisor as f64));
-                }
-                integer / divisor
-            };
-            Ok(Value::from(integer))
-        }
-        Variant::Decimal16(decimal16) => {
-            let scale = decimal16.scale();
-            let integer = decimal16.integer();
-
-            let integer = if scale == 0 {
-                integer
-            } else {
-                let divisor = 10_i128.pow(scale as u32);
-                if integer % divisor != 0 {
-                    // fall back to floating point
-                    return Ok(Value::from(integer as f64 / divisor as f64));
-                }
-                integer / divisor
-            };
-            // i128 has higher precision than any 64-bit type. Try a lossless 
narrowing cast to
-            // i64 or u64 first, falling back to a lossy narrowing cast to f64 
if necessary.
-            let value = i64::try_from(integer)
-                .map(Value::from)
-                .or_else(|_| u64::try_from(integer).map(Value::from))
-                .unwrap_or_else(|_| Value::from(integer as f64));
-            Ok(value)
-        }
-        Variant::Date(date) => Ok(Value::String(format_date_string(date))),
-        Variant::TimestampMicros(ts) => Ok(Value::String(ts.to_rfc3339())),
-        Variant::TimestampNtzMicros(ts) => 
Ok(Value::String(format_timestamp_ntz_string(ts))),
-        Variant::Time(time) => Ok(Value::String(format_time_ntz_str(time))),
-        Variant::Binary(bytes) => 
Ok(Value::String(format_binary_base64(bytes))),
-        Variant::String(s) => Ok(Value::String(s.to_string())),
-        Variant::ShortString(s) => Ok(Value::String(s.to_string())),
-        Variant::Object(obj) => {
-            let map = obj
-                .iter()
-                .map(|(k, v)| variant_to_json_value(&v).map(|json_val| 
(k.to_string(), json_val)))
-                .collect::<Result<_, _>>()?;
-            Ok(Value::Object(map))
-        }
-        Variant::List(arr) => {
-            let vec = arr
-                .iter()
-                .map(|element| variant_to_json_value(&element))
-                .collect::<Result<_, _>>()?;
-            Ok(Value::Array(vec))
-        }
-    }
-}
-
 #[cfg(test)]
 mod tests {
     use super::*;
@@ -393,12 +406,12 @@ mod tests {
     fn test_decimal_edge_cases() -> Result<(), ArrowError> {
         // Test negative decimal
         let negative_variant = Variant::from(VariantDecimal4::try_new(-12345, 
3)?);
-        let negative_json = variant_to_json_string(&negative_variant)?;
+        let negative_json = negative_variant.to_json_string()?;
         assert_eq!(negative_json, "-12.345");
 
         // Test large scale decimal
         let large_scale_variant = 
Variant::from(VariantDecimal8::try_new(123456789, 6)?);
-        let large_scale_json = variant_to_json_string(&large_scale_variant)?;
+        let large_scale_json = large_scale_variant.to_json_string()?;
         assert_eq!(large_scale_json, "123.456789");
 
         Ok(())
@@ -407,15 +420,15 @@ mod tests {
     #[test]
     fn test_decimal16_to_json() -> Result<(), ArrowError> {
         let variant = Variant::from(VariantDecimal16::try_new(123456789012345, 
4)?);
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
         assert_eq!(json, "12345678901.2345");
 
-        let json_value = variant_to_json_value(&variant)?;
+        let json_value = variant.to_json_value()?;
         assert!(matches!(json_value, Value::Number(_)));
 
         // Test very large number
         let large_variant = 
Variant::from(VariantDecimal16::try_new(999999999999999999, 2)?);
-        let large_json = variant_to_json_string(&large_variant)?;
+        let large_json = large_variant.to_json_string()?;
         // Due to f64 precision limits, very large numbers may lose precision
         assert!(
             large_json.starts_with("9999999999999999")
@@ -428,16 +441,16 @@ mod tests {
     fn test_date_to_json() -> Result<(), ArrowError> {
         let date = NaiveDate::from_ymd_opt(2023, 12, 25).unwrap();
         let variant = Variant::Date(date);
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
         assert_eq!(json, "\"2023-12-25\"");
 
-        let json_value = variant_to_json_value(&variant)?;
+        let json_value = variant.to_json_value()?;
         assert_eq!(json_value, Value::String("2023-12-25".to_string()));
 
         // Test leap year date
         let leap_date = NaiveDate::from_ymd_opt(2024, 2, 29).unwrap();
         let leap_variant = Variant::Date(leap_date);
-        let leap_json = variant_to_json_string(&leap_variant)?;
+        let leap_json = leap_variant.to_json_string()?;
         assert_eq!(leap_json, "\"2024-02-29\"");
         Ok(())
     }
@@ -448,11 +461,11 @@ mod tests {
             .unwrap()
             .with_timezone(&Utc);
         let variant = Variant::TimestampMicros(timestamp);
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
         assert!(json.contains("2023-12-25T10:30:45"));
         assert!(json.starts_with('"') && json.ends_with('"'));
 
-        let json_value = variant_to_json_value(&variant)?;
+        let json_value = variant.to_json_value()?;
         assert!(matches!(json_value, Value::String(_)));
         Ok(())
     }
@@ -463,11 +476,11 @@ mod tests {
             .unwrap()
             .naive_utc();
         let variant = Variant::TimestampNtzMicros(naive_timestamp);
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
         assert!(json.contains("2023-12-25"));
         assert!(json.starts_with('"') && json.ends_with('"'));
 
-        let json_value = variant_to_json_value(&variant)?;
+        let json_value = variant.to_json_value()?;
         assert!(matches!(json_value, Value::String(_)));
         Ok(())
     }
@@ -476,10 +489,10 @@ mod tests {
     fn test_time_to_json() -> Result<(), ArrowError> {
         let naive_time = NaiveTime::from_num_seconds_from_midnight_opt(12345, 
123460708).unwrap();
         let variant = Variant::Time(naive_time);
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
         assert_eq!("\"03:25:45.12346\"", json);
 
-        let json_value = variant_to_json_value(&variant)?;
+        let json_value = variant.to_json_value()?;
         assert!(matches!(json_value, Value::String(_)));
         Ok(())
     }
@@ -488,23 +501,23 @@ mod tests {
     fn test_binary_to_json() -> Result<(), ArrowError> {
         let binary_data = b"Hello, World!";
         let variant = Variant::Binary(binary_data);
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
 
         // Should be base64 encoded and quoted
         assert!(json.starts_with('"') && json.ends_with('"'));
         assert!(json.len() > 2); // Should have content
 
-        let json_value = variant_to_json_value(&variant)?;
+        let json_value = variant.to_json_value()?;
         assert!(matches!(json_value, Value::String(_)));
 
         // Test empty binary
         let empty_variant = Variant::Binary(b"");
-        let empty_json = variant_to_json_string(&empty_variant)?;
+        let empty_json = empty_variant.to_json_string()?;
         assert_eq!(empty_json, "\"\"");
 
         // Test binary with special bytes
         let special_variant = Variant::Binary(&[0, 255, 128, 64]);
-        let special_json = variant_to_json_string(&special_variant)?;
+        let special_json = special_variant.to_json_string()?;
         assert!(special_json.starts_with('"') && special_json.ends_with('"'));
         Ok(())
     }
@@ -512,10 +525,10 @@ mod tests {
     #[test]
     fn test_string_to_json() -> Result<(), ArrowError> {
         let variant = Variant::from("hello world");
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
         assert_eq!(json, "\"hello world\"");
 
-        let json_value = variant_to_json_value(&variant)?;
+        let json_value = variant.to_json_value()?;
         assert_eq!(json_value, Value::String("hello world".to_string()));
         Ok(())
     }
@@ -525,10 +538,10 @@ mod tests {
         use parquet_variant::ShortString;
         let short_string = ShortString::try_new("short")?;
         let variant = Variant::ShortString(short_string);
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
         assert_eq!(json, "\"short\"");
 
-        let json_value = variant_to_json_value(&variant)?;
+        let json_value = variant.to_json_value()?;
         assert_eq!(json_value, Value::String("short".to_string()));
         Ok(())
     }
@@ -536,10 +549,10 @@ mod tests {
     #[test]
     fn test_string_escaping() -> Result<(), ArrowError> {
         let variant = Variant::from("hello\nworld\t\"quoted\"");
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
         assert_eq!(json, "\"hello\\nworld\\t\\\"quoted\\\"\"");
 
-        let json_value = variant_to_json_value(&variant)?;
+        let json_value = variant.to_json_value()?;
         assert_eq!(
             json_value,
             Value::String("hello\nworld\t\"quoted\"".to_string())
@@ -551,7 +564,7 @@ mod tests {
     fn test_json_buffer_writing() -> Result<(), ArrowError> {
         let variant = Variant::Int8(123);
         let mut buffer = Vec::new();
-        variant_to_json(&mut buffer, &variant)?;
+        variant.to_json(&mut buffer)?;
 
         let result = String::from_utf8(buffer)
             .map_err(|e| ArrowError::InvalidArgumentError(e.to_string()))?;
@@ -568,7 +581,9 @@ mod tests {
 
     impl JsonTest {
         fn run(self) {
-            let json_string = variant_to_json_string(&self.variant)
+            let json_string = self
+                .variant
+                .to_json_string()
                 .expect("variant_to_json_string should succeed");
             assert_eq!(
                 json_string, self.expected_json,
@@ -576,8 +591,10 @@ mod tests {
                 self.variant
             );
 
-            let json_value =
-                
variant_to_json_value(&self.variant).expect("variant_to_json_value should 
succeed");
+            let json_value = self
+                .variant
+                .to_json_value()
+                .expect("variant_to_json_value should succeed");
 
             // For floating point numbers, we need special comparison due to 
JSON number representation
             match (&json_value, &self.expected_value) {
@@ -857,20 +874,18 @@ mod tests {
 
     #[test]
     fn test_buffer_writing_variants() -> Result<(), ArrowError> {
-        use crate::variant_to_json;
-
         let variant = Variant::from("test buffer writing");
 
         // Test writing to a Vec<u8>
         let mut buffer = Vec::new();
-        variant_to_json(&mut buffer, &variant)?;
+        variant.to_json(&mut buffer)?;
         let result = String::from_utf8(buffer)
             .map_err(|e| ArrowError::InvalidArgumentError(e.to_string()))?;
         assert_eq!(result, "\"test buffer writing\"");
 
         // Test writing to vec![]
         let mut buffer = vec![];
-        variant_to_json(&mut buffer, &variant)?;
+        variant.to_json(&mut buffer)?;
         let result = String::from_utf8(buffer)
             .map_err(|e| ArrowError::InvalidArgumentError(e.to_string()))?;
         assert_eq!(result, "\"test buffer writing\"");
@@ -896,7 +911,7 @@ mod tests {
 
         let (metadata, value) = builder.finish();
         let variant = Variant::try_new(&metadata, &value)?;
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
 
         // Parse the JSON to verify structure - handle JSON parsing errors 
manually
         let parsed: Value = serde_json::from_str(&json).unwrap();
@@ -908,7 +923,7 @@ mod tests {
         assert_eq!(obj.len(), 4);
 
         // Test variant_to_json_value as well
-        let json_value = variant_to_json_value(&variant)?;
+        let json_value = variant.to_json_value()?;
         assert!(matches!(json_value, Value::Object(_)));
 
         Ok(())
@@ -927,10 +942,10 @@ mod tests {
 
         let (metadata, value) = builder.finish();
         let variant = Variant::try_new(&metadata, &value)?;
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
         assert_eq!(json, "{}");
 
-        let json_value = variant_to_json_value(&variant)?;
+        let json_value = variant.to_json_value()?;
         assert_eq!(json_value, Value::Object(serde_json::Map::new()));
 
         Ok(())
@@ -952,7 +967,7 @@ mod tests {
 
         let (metadata, value) = builder.finish();
         let variant = Variant::try_new(&metadata, &value)?;
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
 
         // Verify that special characters are properly escaped
         assert!(json.contains("Hello \\\"World\\\"\\nWith\\tTabs"));
@@ -983,10 +998,10 @@ mod tests {
 
         let (metadata, value) = builder.finish();
         let variant = Variant::try_new(&metadata, &value)?;
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
         assert_eq!(json, "[1,2,3,4,5]");
 
-        let json_value = variant_to_json_value(&variant)?;
+        let json_value = variant.to_json_value()?;
         let arr = json_value.as_array().expect("expected JSON array");
         assert_eq!(arr.len(), 5);
         assert_eq!(arr[0], Value::Number(1.into()));
@@ -1008,10 +1023,10 @@ mod tests {
 
         let (metadata, value) = builder.finish();
         let variant = Variant::try_new(&metadata, &value)?;
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
         assert_eq!(json, "[]");
 
-        let json_value = variant_to_json_value(&variant)?;
+        let json_value = variant.to_json_value()?;
         assert_eq!(json_value, Value::Array(vec![]));
 
         Ok(())
@@ -1034,7 +1049,7 @@ mod tests {
 
         let (metadata, value) = builder.finish();
         let variant = Variant::try_new(&metadata, &value)?;
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
 
         let parsed: Value = serde_json::from_str(&json).unwrap();
         let arr = parsed.as_array().expect("expected JSON array");
@@ -1065,7 +1080,7 @@ mod tests {
 
         let (metadata, value) = builder.finish();
         let variant = Variant::try_new(&metadata, &value)?;
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
 
         // Parse and verify all fields are present
         let parsed: Value = serde_json::from_str(&json).unwrap();
@@ -1097,7 +1112,7 @@ mod tests {
 
         let (metadata, value) = builder.finish();
         let variant = Variant::try_new(&metadata, &value)?;
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
 
         let parsed: Value = serde_json::from_str(&json).unwrap();
         let arr = parsed.as_array().expect("expected JSON array");
@@ -1132,7 +1147,7 @@ mod tests {
 
         let (metadata, value) = builder.finish();
         let variant = Variant::try_new(&metadata, &value)?;
-        let json = variant_to_json_string(&variant)?;
+        let json = variant.to_json_string()?;
 
         let parsed: Value = serde_json::from_str(&json).unwrap();
         let obj = parsed.as_object().expect("expected JSON object");
@@ -1159,8 +1174,8 @@ mod tests {
             6,
         )?);
 
-        let json_string = variant_to_json_string(&high_precision_decimal8)?;
-        let json_value = variant_to_json_value(&high_precision_decimal8)?;
+        let json_string = high_precision_decimal8.to_json_string()?;
+        let json_value = high_precision_decimal8.to_json_value()?;
 
         // Due to f64 precision limits, we expect precision loss for values > 
2^53
         // Both functions should produce consistent results (even if not exact)
@@ -1173,7 +1188,7 @@ mod tests {
             6,
         )?);
 
-        let json_string_exact = variant_to_json_string(&exact_decimal)?;
+        let json_string_exact = exact_decimal.to_json_string()?;
         assert_eq!(json_string_exact, "1234567.89");
 
         // Test integer case (should be exact)
@@ -1182,7 +1197,7 @@ mod tests {
             6,
         )?);
 
-        let json_string_integer = variant_to_json_string(&integer_decimal)?;
+        let json_string_integer = integer_decimal.to_json_string()?;
         assert_eq!(json_string_integer, "42");
 
         Ok(())
@@ -1192,7 +1207,7 @@ mod tests {
     fn test_float_nan_inf_handling() -> Result<(), ArrowError> {
         // Test NaN handling - should return an error since JSON doesn't 
support NaN
         let nan_variant = Variant::Float(f32::NAN);
-        let nan_result = variant_to_json_value(&nan_variant);
+        let nan_result = nan_variant.to_json_value();
         assert!(nan_result.is_err());
         assert!(nan_result
             .unwrap_err()
@@ -1201,7 +1216,7 @@ mod tests {
 
         // Test positive infinity - should return an error since JSON doesn't 
support Infinity
         let pos_inf_variant = Variant::Float(f32::INFINITY);
-        let pos_inf_result = variant_to_json_value(&pos_inf_variant);
+        let pos_inf_result = pos_inf_variant.to_json_value();
         assert!(pos_inf_result.is_err());
         assert!(pos_inf_result
             .unwrap_err()
@@ -1210,7 +1225,7 @@ mod tests {
 
         // Test negative infinity - should return an error since JSON doesn't 
support -Infinity
         let neg_inf_variant = Variant::Float(f32::NEG_INFINITY);
-        let neg_inf_result = variant_to_json_value(&neg_inf_variant);
+        let neg_inf_result = neg_inf_variant.to_json_value();
         assert!(neg_inf_result.is_err());
         assert!(neg_inf_result
             .unwrap_err()
@@ -1219,7 +1234,7 @@ mod tests {
 
         // Test the same for Double variants
         let nan_double_variant = Variant::Double(f64::NAN);
-        let nan_double_result = variant_to_json_value(&nan_double_variant);
+        let nan_double_result = nan_double_variant.to_json_value();
         assert!(nan_double_result.is_err());
         assert!(nan_double_result
             .unwrap_err()
@@ -1227,7 +1242,7 @@ mod tests {
             .contains("Invalid double value"));
 
         let pos_inf_double_variant = Variant::Double(f64::INFINITY);
-        let pos_inf_double_result = 
variant_to_json_value(&pos_inf_double_variant);
+        let pos_inf_double_result = pos_inf_double_variant.to_json_value();
         assert!(pos_inf_double_result.is_err());
         assert!(pos_inf_double_result
             .unwrap_err()
@@ -1235,7 +1250,7 @@ mod tests {
             .contains("Invalid double value"));
 
         let neg_inf_double_variant = Variant::Double(f64::NEG_INFINITY);
-        let neg_inf_double_result = 
variant_to_json_value(&neg_inf_double_variant);
+        let neg_inf_double_result = neg_inf_double_variant.to_json_value();
         assert!(neg_inf_double_result.is_err());
         assert!(neg_inf_double_result
             .unwrap_err()
@@ -1244,11 +1259,11 @@ mod tests {
 
         // Test normal float values still work
         let normal_float = Variant::Float(std::f32::consts::PI);
-        let normal_result = variant_to_json_value(&normal_float)?;
+        let normal_result = normal_float.to_json_value()?;
         assert!(matches!(normal_result, Value::Number(_)));
 
         let normal_double = Variant::Double(std::f64::consts::E);
-        let normal_double_result = variant_to_json_value(&normal_double)?;
+        let normal_double_result = normal_double.to_json_value()?;
         assert!(matches!(normal_double_result, Value::Number(_)));
 
         Ok(())

Reply via email to