Skip to main content

parquet_variant_json/
to_json.rs

1// Licensed to the Apache Software Foundation (ASF) under one
2// or more contributor license agreements.  See the NOTICE file
3// distributed with this work for additional information
4// regarding copyright ownership.  The ASF licenses this file
5// to you under the Apache License, Version 2.0 (the
6// "License"); you may not use this file except in compliance
7// with the License.  You may obtain a copy of the License at
8//
9//   http://www.apache.org/licenses/LICENSE-2.0
10//
11// Unless required by applicable law or agreed to in writing,
12// software distributed under the License is distributed on an
13// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14// KIND, either express or implied.  See the License for the
15// specific language governing permissions and limitations
16// under the License.
17
18//! Module for converting Variant data to JSON format
19use arrow_schema::ArrowError;
20use base64::{Engine as _, engine::general_purpose};
21use chrono::Timelike;
22use parquet_variant::{Variant, VariantList, VariantObject};
23use serde_json::Value;
24use std::io::Write;
25
26/// Extension trait for converting Variants to JSON
27pub trait VariantToJson {
28    ///
29    /// This function writes JSON directly to any type that implements [`Write`],
30    /// making it efficient for streaming or when you want to control the output destination.
31    ///
32    /// See [`VariantToJson::to_json_string`] for a convenience function that returns a
33    /// JSON string.
34    ///
35    /// # Arguments
36    ///
37    /// * `writer` - Writer to output JSON to
38    /// * `variant` - The Variant value to convert
39    ///
40    /// # Returns
41    ///
42    /// * `Ok(())` if successful
43    /// * `Err` with error details if conversion fails
44    ///
45    /// # Examples
46    ///
47    ///
48    /// ```rust
49    /// # use parquet_variant::{Variant};
50    /// # use parquet_variant_json::VariantToJson;
51    /// # use arrow_schema::ArrowError;
52    /// let variant = Variant::from("Hello, World!");
53    /// let mut buffer = Vec::new();
54    /// variant.to_json(&mut buffer)?;
55    /// assert_eq!(String::from_utf8(buffer).unwrap(), "\"Hello, World!\"");
56    /// # Ok::<(), ArrowError>(())
57    /// ```
58    ///
59    /// # Example: Create a [`Variant::Object`] and convert to JSON
60    /// ```rust
61    /// # use parquet_variant::{Variant, VariantBuilder};
62    /// # use parquet_variant_json::VariantToJson;
63    /// # use arrow_schema::ArrowError;
64    /// let mut builder = VariantBuilder::new();
65    /// // Create an object builder that will write fields to the object
66    /// let mut object_builder = builder.new_object();
67    /// object_builder.insert("first_name", "Jiaying");
68    /// object_builder.insert("last_name", "Li");
69    /// object_builder.finish();
70    /// // Finish the builder to get the metadata and value
71    /// let (metadata, value) = builder.finish();
72    /// // Create the Variant and convert to JSON
73    /// let variant = Variant::try_new(&metadata, &value)?;
74    /// let mut writer = Vec::new();
75    /// variant.to_json(&mut writer)?;
76    /// assert_eq!(br#"{"first_name":"Jiaying","last_name":"Li"}"#, writer.as_slice());
77    /// # Ok::<(), ArrowError>(())
78    /// ```
79    fn to_json(&self, buffer: &mut impl Write) -> Result<(), ArrowError>;
80
81    /// Convert [`Variant`] to JSON [`String`]
82    ///
83    /// This is a convenience function that converts a Variant to a JSON string.
84    /// This is the same as calling [`VariantToJson::to_json`] with a [`Vec`].
85    /// It's the simplest way to get a JSON representation when you just need a String result.
86    ///
87    /// # Arguments
88    ///
89    /// * `variant` - The Variant value to convert
90    ///
91    /// # Returns
92    ///
93    /// * `Ok(String)` containing the JSON representation
94    /// * `Err` with error details if conversion fails
95    ///
96    /// # Examples
97    ///
98    /// ```rust
99    /// # use parquet_variant::{Variant};
100    /// # use parquet_variant_json::VariantToJson;
101    /// # use arrow_schema::ArrowError;
102    /// let variant = Variant::Int32(42);
103    /// let json = variant.to_json_string()?;
104    /// assert_eq!(json, "42");
105    /// # Ok::<(), ArrowError>(())
106    /// ```
107    ///
108    /// # Example: Create a [`Variant::Object`] and convert to JSON
109    ///
110    /// This example shows how to create an object with two fields and convert it to JSON:
111    /// ```json
112    /// {
113    ///   "first_name": "Jiaying",
114    ///   "last_name": "Li"
115    /// }
116    /// ```
117    ///
118    /// ```rust
119    /// # use parquet_variant::{Variant, VariantBuilder};
120    /// # use parquet_variant_json::VariantToJson;
121    /// # use arrow_schema::ArrowError;
122    /// let mut builder = VariantBuilder::new();
123    /// // Create an object builder that will write fields to the object
124    /// let mut object_builder = builder.new_object();
125    /// object_builder.insert("first_name", "Jiaying");
126    /// object_builder.insert("last_name", "Li");
127    /// object_builder.finish();
128    /// // Finish the builder to get the metadata and value
129    /// let (metadata, value) = builder.finish();
130    /// // Create the Variant and convert to JSON
131    /// let variant = Variant::try_new(&metadata, &value)?;
132    /// let json = variant.to_json_string()?;
133    /// assert_eq!(r#"{"first_name":"Jiaying","last_name":"Li"}"#, json);
134    /// # Ok::<(), ArrowError>(())
135    /// ```
136    fn to_json_string(&self) -> Result<String, ArrowError>;
137
138    /// Convert [`Variant`] to [`serde_json::Value`]
139    ///
140    /// This function converts a Variant to a [`serde_json::Value`], which is useful
141    /// when you need to work with the JSON data programmatically or integrate with
142    /// other serde-based JSON processing.
143    ///
144    /// # Arguments
145    ///
146    /// * `variant` - The Variant value to convert
147    ///
148    /// # Returns
149    ///
150    /// * `Ok(Value)` containing the JSON value
151    /// * `Err` with error details if conversion fails
152    ///
153    /// # Examples
154    ///
155    /// ```rust
156    /// # use parquet_variant::{Variant};
157    /// # use parquet_variant_json::VariantToJson;
158    /// # use serde_json::Value;
159    /// # use arrow_schema::ArrowError;
160    /// let variant = Variant::from("hello");
161    /// let json_value = variant.to_json_value()?;
162    /// assert_eq!(json_value, Value::String("hello".to_string()));
163    /// # Ok::<(), ArrowError>(())
164    /// ```
165    fn to_json_value(&self) -> Result<Value, ArrowError>;
166}
167
168impl<'m, 'v> VariantToJson for Variant<'m, 'v> {
169    fn to_json(&self, buffer: &mut impl Write) -> Result<(), ArrowError> {
170        match self {
171            Variant::Null => write!(buffer, "null")?,
172            Variant::BooleanTrue => write!(buffer, "true")?,
173            Variant::BooleanFalse => write!(buffer, "false")?,
174            Variant::Int8(i) => write!(buffer, "{i}")?,
175            Variant::Int16(i) => write!(buffer, "{i}")?,
176            Variant::Int32(i) => write!(buffer, "{i}")?,
177            Variant::Int64(i) => write!(buffer, "{i}")?,
178            Variant::Float(f) => write!(buffer, "{f}")?,
179            Variant::Double(f) => write!(buffer, "{f}")?,
180            Variant::Decimal4(decimal) => write!(buffer, "{decimal}")?,
181            Variant::Decimal8(decimal) => write!(buffer, "{decimal}")?,
182            Variant::Decimal16(decimal) => write!(buffer, "{decimal}")?,
183            Variant::Date(date) => write!(buffer, "\"{}\"", format_date_string(date))?,
184            Variant::TimestampMicros(ts) | Variant::TimestampNanos(ts) => {
185                write!(buffer, "\"{}\"", ts.to_rfc3339())?
186            }
187            Variant::TimestampNtzMicros(ts) => {
188                write!(buffer, "\"{}\"", format_timestamp_ntz_string(ts, 6))?
189            }
190            Variant::TimestampNtzNanos(ts) => {
191                write!(buffer, "\"{}\"", format_timestamp_ntz_string(ts, 9))?
192            }
193            Variant::Time(time) => write!(buffer, "\"{}\"", format_time_ntz_str(time))?,
194            Variant::Binary(bytes) => {
195                // Encode binary as base64 string
196                let base64_str = format_binary_base64(bytes);
197                let json_str = serde_json::to_string(&base64_str).map_err(|e| {
198                    ArrowError::InvalidArgumentError(format!("JSON encoding error: {e}"))
199                })?;
200                write!(buffer, "{json_str}")?
201            }
202            Variant::String(s) => {
203                // Use serde_json to properly escape the string
204                let json_str = serde_json::to_string(s).map_err(|e| {
205                    ArrowError::InvalidArgumentError(format!("JSON encoding error: {e}"))
206                })?;
207                write!(buffer, "{json_str}")?
208            }
209            Variant::ShortString(s) => {
210                // Use serde_json to properly escape the string
211                let json_str = serde_json::to_string(s.as_str()).map_err(|e| {
212                    ArrowError::InvalidArgumentError(format!("JSON encoding error: {e}"))
213                })?;
214                write!(buffer, "{json_str}")?
215            }
216            Variant::Uuid(uuid) => {
217                write!(buffer, "\"{uuid}\"")?;
218            }
219            Variant::Object(obj) => {
220                convert_object_to_json(buffer, obj)?;
221            }
222            Variant::List(arr) => {
223                convert_array_to_json(buffer, arr)?;
224            }
225        }
226        Ok(())
227    }
228
229    fn to_json_string(&self) -> Result<String, ArrowError> {
230        let mut buffer = Vec::new();
231        self.to_json(&mut buffer)?;
232        String::from_utf8(buffer)
233            .map_err(|e| ArrowError::InvalidArgumentError(format!("UTF-8 conversion error: {e}")))
234    }
235
236    fn to_json_value(&self) -> Result<Value, ArrowError> {
237        match self {
238            Variant::Null => Ok(Value::Null),
239            Variant::BooleanTrue => Ok(Value::Bool(true)),
240            Variant::BooleanFalse => Ok(Value::Bool(false)),
241            Variant::Int8(i) => Ok(Value::Number((*i).into())),
242            Variant::Int16(i) => Ok(Value::Number((*i).into())),
243            Variant::Int32(i) => Ok(Value::Number((*i).into())),
244            Variant::Int64(i) => Ok(Value::Number((*i).into())),
245            Variant::Float(f) => serde_json::Number::from_f64((*f).into())
246                .map(Value::Number)
247                .ok_or_else(|| ArrowError::InvalidArgumentError("Invalid float value".to_string())),
248            Variant::Double(f) => serde_json::Number::from_f64(*f)
249                .map(Value::Number)
250                .ok_or_else(|| {
251                    ArrowError::InvalidArgumentError("Invalid double value".to_string())
252                }),
253            Variant::Decimal4(decimal4) => {
254                let scale = decimal4.scale();
255                let integer = decimal4.integer();
256
257                let integer = if scale == 0 {
258                    integer
259                } else {
260                    let divisor = 10_i32.pow(scale as u32);
261                    if integer % divisor != 0 {
262                        // fall back to floating point
263                        return Ok(Value::from(integer as f64 / divisor as f64));
264                    }
265                    integer / divisor
266                };
267                Ok(Value::from(integer))
268            }
269            Variant::Decimal8(decimal8) => {
270                let scale = decimal8.scale();
271                let integer = decimal8.integer();
272
273                let integer = if scale == 0 {
274                    integer
275                } else {
276                    let divisor = 10_i64.pow(scale as u32);
277                    if integer % divisor != 0 {
278                        // fall back to floating point
279                        return Ok(Value::from(integer as f64 / divisor as f64));
280                    }
281                    integer / divisor
282                };
283                Ok(Value::from(integer))
284            }
285            Variant::Decimal16(decimal16) => {
286                let scale = decimal16.scale();
287                let integer = decimal16.integer();
288
289                let integer = if scale == 0 {
290                    integer
291                } else {
292                    let divisor = 10_i128.pow(scale as u32);
293                    if integer % divisor != 0 {
294                        // fall back to floating point
295                        return Ok(Value::from(integer as f64 / divisor as f64));
296                    }
297                    integer / divisor
298                };
299                // i128 has higher precision than any 64-bit type. Try a lossless narrowing cast to
300                // i64 or u64 first, falling back to a lossy narrowing cast to f64 if necessary.
301                let value = i64::try_from(integer)
302                    .map(Value::from)
303                    .or_else(|_| u64::try_from(integer).map(Value::from))
304                    .unwrap_or_else(|_| Value::from(integer as f64));
305                Ok(value)
306            }
307            Variant::Date(date) => Ok(Value::String(format_date_string(date))),
308            Variant::TimestampMicros(ts) | Variant::TimestampNanos(ts) => {
309                Ok(Value::String(ts.to_rfc3339()))
310            }
311            Variant::TimestampNtzMicros(ts) => {
312                Ok(Value::String(format_timestamp_ntz_string(ts, 6)))
313            }
314            Variant::TimestampNtzNanos(ts) => Ok(Value::String(format_timestamp_ntz_string(ts, 9))),
315            Variant::Time(time) => Ok(Value::String(format_time_ntz_str(time))),
316            Variant::Binary(bytes) => Ok(Value::String(format_binary_base64(bytes))),
317            Variant::String(s) => Ok(Value::String(s.to_string())),
318            Variant::ShortString(s) => Ok(Value::String(s.to_string())),
319            Variant::Uuid(uuid) => Ok(Value::String(uuid.to_string())),
320            Variant::Object(obj) => {
321                let map = obj
322                    .iter()
323                    .map(|(k, v)| v.to_json_value().map(|json_val| (k.to_string(), json_val)))
324                    .collect::<Result<_, _>>()?;
325                Ok(Value::Object(map))
326            }
327            Variant::List(arr) => {
328                let vec = arr
329                    .iter()
330                    .map(|element| element.to_json_value())
331                    .collect::<Result<_, _>>()?;
332                Ok(Value::Array(vec))
333            }
334        }
335    }
336}
337
338// Format string constants to avoid duplication and reduce errors
339const DATE_FORMAT: &str = "%Y-%m-%d";
340
341// Helper functions for consistent formatting
342fn format_date_string(date: &chrono::NaiveDate) -> String {
343    date.format(DATE_FORMAT).to_string()
344}
345
346fn format_timestamp_ntz_string(ts: &chrono::NaiveDateTime, precision: usize) -> String {
347    let format_str = format!(
348        "{}",
349        ts.format(&format!("%Y-%m-%dT%H:%M:%S%.{}f", precision))
350    );
351    ts.format(format_str.as_str()).to_string()
352}
353
354fn format_binary_base64(bytes: &[u8]) -> String {
355    general_purpose::STANDARD.encode(bytes)
356}
357
358fn format_time_ntz_str(time: &chrono::NaiveTime) -> String {
359    let base = time.format("%H:%M:%S").to_string();
360    let micros = time.nanosecond() / 1000;
361    match micros {
362        0 => format!("{}.{}", base, 0),
363        _ => {
364            let micros_str = format!("{:06}", micros);
365            let micros_str_trimmed = micros_str.trim_end_matches('0');
366            format!("{}.{}", base, micros_str_trimmed)
367        }
368    }
369}
370
371/// Convert object fields to JSON
372fn convert_object_to_json(buffer: &mut impl Write, obj: &VariantObject) -> Result<(), ArrowError> {
373    write!(buffer, "{{")?;
374
375    // Get all fields from the object
376    let mut first = true;
377
378    for (key, value) in obj.iter() {
379        if !first {
380            write!(buffer, ",")?;
381        }
382        first = false;
383
384        // Write the key (properly escaped)
385        let json_key = serde_json::to_string(key).map_err(|e| {
386            ArrowError::InvalidArgumentError(format!("JSON key encoding error: {e}"))
387        })?;
388        write!(buffer, "{json_key}:")?;
389
390        // Recursively convert the value
391        value.to_json(buffer)?;
392    }
393
394    write!(buffer, "}}")?;
395    Ok(())
396}
397
398/// Convert array elements to JSON
399fn convert_array_to_json(buffer: &mut impl Write, arr: &VariantList) -> Result<(), ArrowError> {
400    write!(buffer, "[")?;
401
402    let mut first = true;
403    for element in arr.iter() {
404        if !first {
405            write!(buffer, ",")?;
406        }
407        first = false;
408
409        element.to_json(buffer)?;
410    }
411
412    write!(buffer, "]")?;
413    Ok(())
414}
415
416#[cfg(test)]
417mod tests {
418    use super::*;
419    use chrono::{DateTime, NaiveDate, NaiveTime, Utc};
420    use parquet_variant::{VariantDecimal4, VariantDecimal8, VariantDecimal16};
421
422    #[test]
423    fn test_decimal_edge_cases() -> Result<(), ArrowError> {
424        // Test negative decimal
425        let negative_variant = Variant::from(VariantDecimal4::try_new(-12345, 3)?);
426        let negative_json = negative_variant.to_json_string()?;
427        assert_eq!(negative_json, "-12.345");
428
429        // Test large scale decimal
430        let large_scale_variant = Variant::from(VariantDecimal8::try_new(123456789, 6)?);
431        let large_scale_json = large_scale_variant.to_json_string()?;
432        assert_eq!(large_scale_json, "123.456789");
433
434        Ok(())
435    }
436
437    #[test]
438    fn test_decimal16_to_json() -> Result<(), ArrowError> {
439        let variant = Variant::from(VariantDecimal16::try_new(123456789012345, 4)?);
440        let json = variant.to_json_string()?;
441        assert_eq!(json, "12345678901.2345");
442
443        let json_value = variant.to_json_value()?;
444        assert!(matches!(json_value, Value::Number(_)));
445
446        // Test very large number
447        let large_variant = Variant::from(VariantDecimal16::try_new(999999999999999999, 2)?);
448        let large_json = large_variant.to_json_string()?;
449        // Due to f64 precision limits, very large numbers may lose precision
450        assert!(
451            large_json.starts_with("9999999999999999")
452                || large_json.starts_with("10000000000000000")
453        );
454        Ok(())
455    }
456
457    #[test]
458    fn test_date_to_json() -> Result<(), ArrowError> {
459        let date = NaiveDate::from_ymd_opt(2023, 12, 25).unwrap();
460        let variant = Variant::Date(date);
461        let json = variant.to_json_string()?;
462        assert_eq!(json, "\"2023-12-25\"");
463
464        let json_value = variant.to_json_value()?;
465        assert_eq!(json_value, Value::String("2023-12-25".to_string()));
466
467        // Test leap year date
468        let leap_date = NaiveDate::from_ymd_opt(2024, 2, 29).unwrap();
469        let leap_variant = Variant::Date(leap_date);
470        let leap_json = leap_variant.to_json_string()?;
471        assert_eq!(leap_json, "\"2024-02-29\"");
472        Ok(())
473    }
474
475    #[test]
476    fn test_timestamp_micros_to_json() -> Result<(), ArrowError> {
477        let timestamp = DateTime::parse_from_rfc3339("2023-12-25T10:30:45Z")
478            .unwrap()
479            .with_timezone(&Utc);
480        let variant = Variant::TimestampMicros(timestamp);
481        let json = variant.to_json_string()?;
482        assert!(json.contains("2023-12-25T10:30:45"));
483        assert!(json.starts_with('"') && json.ends_with('"'));
484
485        let json_value = variant.to_json_value()?;
486        assert!(matches!(json_value, Value::String(_)));
487        Ok(())
488    }
489
490    #[test]
491    fn test_timestamp_ntz_micros_to_json() -> Result<(), ArrowError> {
492        let naive_timestamp = DateTime::from_timestamp(1703505045, 123456)
493            .unwrap()
494            .naive_utc();
495        let variant = Variant::TimestampNtzMicros(naive_timestamp);
496        let json = variant.to_json_string()?;
497        assert!(json.contains("2023-12-25"));
498        assert!(json.starts_with('"') && json.ends_with('"'));
499
500        let json_value = variant.to_json_value()?;
501        assert!(matches!(json_value, Value::String(_)));
502        Ok(())
503    }
504
505    #[test]
506    fn test_time_to_json() -> Result<(), ArrowError> {
507        let naive_time = NaiveTime::from_num_seconds_from_midnight_opt(12345, 123460708).unwrap();
508        let variant = Variant::Time(naive_time);
509        let json = variant.to_json_string()?;
510        assert_eq!("\"03:25:45.12346\"", json);
511
512        let expected = [
513            (10, "00:00:00.00001"),
514            (10010, "00:00:00.01001"),
515            (100000, "00:00:00.1"),
516            (123450, "00:00:00.12345"),
517        ];
518
519        for (micros, expected_json) in expected {
520            let naive_time =
521                NaiveTime::from_num_seconds_from_midnight_opt(0, micros * 1000).unwrap();
522            let variant = Variant::Time(naive_time);
523            let json = variant.to_json_string()?;
524            assert_eq!(format!("\"{expected_json}\""), json);
525        }
526
527        let json_value = variant.to_json_value()?;
528        assert!(matches!(json_value, Value::String(_)));
529        Ok(())
530    }
531
532    #[test]
533    fn test_timestamp_nanos_to_json() -> Result<(), ArrowError> {
534        let timestamp = DateTime::parse_from_rfc3339("2023-12-25T10:30:45.123456789Z")
535            .unwrap()
536            .with_timezone(&Utc);
537        let variant = Variant::TimestampNanos(timestamp);
538        let json = variant.to_json_string()?;
539        assert_eq!(json, "\"2023-12-25T10:30:45.123456789+00:00\"");
540
541        let json_value = variant.to_json_value()?;
542        assert!(matches!(json_value, Value::String(_)));
543        Ok(())
544    }
545
546    #[test]
547    fn test_timestamp_ntz_nanos_to_json() -> Result<(), ArrowError> {
548        let naive_timestamp = DateTime::from_timestamp(1703505045, 123456789)
549            .unwrap()
550            .naive_utc();
551        let variant = Variant::TimestampNtzNanos(naive_timestamp);
552        let json = variant.to_json_string()?;
553        assert_eq!(json, "\"2023-12-25T11:50:45.123456789\"");
554
555        let json_value = variant.to_json_value()?;
556        assert!(matches!(json_value, Value::String(_)));
557        Ok(())
558    }
559
560    #[test]
561    fn test_binary_to_json() -> Result<(), ArrowError> {
562        let binary_data = b"Hello, World!";
563        let variant = Variant::Binary(binary_data);
564        let json = variant.to_json_string()?;
565
566        // Should be base64 encoded and quoted
567        assert!(json.starts_with('"') && json.ends_with('"'));
568        assert!(json.len() > 2); // Should have content
569
570        let json_value = variant.to_json_value()?;
571        assert!(matches!(json_value, Value::String(_)));
572
573        // Test empty binary
574        let empty_variant = Variant::Binary(b"");
575        let empty_json = empty_variant.to_json_string()?;
576        assert_eq!(empty_json, "\"\"");
577
578        // Test binary with special bytes
579        let special_variant = Variant::Binary(&[0, 255, 128, 64]);
580        let special_json = special_variant.to_json_string()?;
581        assert!(special_json.starts_with('"') && special_json.ends_with('"'));
582        Ok(())
583    }
584
585    #[test]
586    fn test_string_to_json() -> Result<(), ArrowError> {
587        let variant = Variant::from("hello world");
588        let json = variant.to_json_string()?;
589        assert_eq!(json, "\"hello world\"");
590
591        let json_value = variant.to_json_value()?;
592        assert_eq!(json_value, Value::String("hello world".to_string()));
593        Ok(())
594    }
595
596    #[test]
597    fn test_short_string_to_json() -> Result<(), ArrowError> {
598        use parquet_variant::ShortString;
599        let short_string = ShortString::try_new("short")?;
600        let variant = Variant::ShortString(short_string);
601        let json = variant.to_json_string()?;
602        assert_eq!(json, "\"short\"");
603
604        let json_value = variant.to_json_value()?;
605        assert_eq!(json_value, Value::String("short".to_string()));
606        Ok(())
607    }
608
609    #[test]
610    fn test_uuid_to_json() -> Result<(), ArrowError> {
611        let uuid = uuid::Uuid::parse_str("123e4567-e89b-12d3-a456-426614174000").unwrap();
612        let variant = Variant::Uuid(uuid);
613        let json = variant.to_json_string()?;
614        assert_eq!(json, "\"123e4567-e89b-12d3-a456-426614174000\"");
615
616        let json_value = variant.to_json_value()?;
617        assert_eq!(
618            json_value,
619            Value::String("123e4567-e89b-12d3-a456-426614174000".to_string())
620        );
621        Ok(())
622    }
623
624    #[test]
625    fn test_string_escaping() -> Result<(), ArrowError> {
626        let variant = Variant::from("hello\nworld\t\"quoted\"");
627        let json = variant.to_json_string()?;
628        assert_eq!(json, "\"hello\\nworld\\t\\\"quoted\\\"\"");
629
630        let json_value = variant.to_json_value()?;
631        assert_eq!(
632            json_value,
633            Value::String("hello\nworld\t\"quoted\"".to_string())
634        );
635        Ok(())
636    }
637
638    #[test]
639    fn test_json_buffer_writing() -> Result<(), ArrowError> {
640        let variant = Variant::Int8(123);
641        let mut buffer = Vec::new();
642        variant.to_json(&mut buffer)?;
643
644        let result = String::from_utf8(buffer)
645            .map_err(|e| ArrowError::InvalidArgumentError(e.to_string()))?;
646        assert_eq!(result, "123");
647        Ok(())
648    }
649
650    /// Reusable test structure for JSON conversion testing
651    struct JsonTest {
652        variant: Variant<'static, 'static>,
653        expected_json: &'static str,
654        expected_value: Value,
655    }
656
657    impl JsonTest {
658        fn run(self) {
659            let json_string = self
660                .variant
661                .to_json_string()
662                .expect("variant_to_json_string should succeed");
663            assert_eq!(
664                json_string, self.expected_json,
665                "JSON string mismatch for variant: {:?}",
666                self.variant
667            );
668
669            let json_value = self
670                .variant
671                .to_json_value()
672                .expect("variant_to_json_value should succeed");
673
674            // For floating point numbers, we need special comparison due to JSON number representation
675            match (&json_value, &self.expected_value) {
676                (Value::Number(actual), Value::Number(expected)) => {
677                    let actual_f64 = actual.as_f64().unwrap_or(0.0);
678                    let expected_f64 = expected.as_f64().unwrap_or(0.0);
679                    assert!(
680                        (actual_f64 - expected_f64).abs() < f64::EPSILON,
681                        "JSON value mismatch for variant: {:?}, got {}, expected {}",
682                        self.variant,
683                        actual_f64,
684                        expected_f64
685                    );
686                }
687                _ => {
688                    assert_eq!(
689                        json_value, self.expected_value,
690                        "JSON value mismatch for variant: {:?}",
691                        self.variant
692                    );
693                }
694            }
695
696            // Verify roundtrip: JSON string should parse to same value
697            let parsed: Value =
698                serde_json::from_str(&json_string).expect("Generated JSON should be valid");
699            // Same floating point handling for roundtrip
700            match (&parsed, &self.expected_value) {
701                (Value::Number(actual), Value::Number(expected)) => {
702                    let actual_f64 = actual.as_f64().unwrap_or(0.0);
703                    let expected_f64 = expected.as_f64().unwrap_or(0.0);
704                    assert!(
705                        (actual_f64 - expected_f64).abs() < f64::EPSILON,
706                        "Parsed JSON mismatch for variant: {:?}, got {}, expected {}",
707                        self.variant,
708                        actual_f64,
709                        expected_f64
710                    );
711                }
712                _ => {
713                    assert_eq!(
714                        parsed, self.expected_value,
715                        "Parsed JSON mismatch for variant: {:?}",
716                        self.variant
717                    );
718                }
719            }
720        }
721    }
722
723    #[test]
724    fn test_primitive_json_conversion() {
725        use parquet_variant::ShortString;
726
727        // Null
728        JsonTest {
729            variant: Variant::Null,
730            expected_json: "null",
731            expected_value: Value::Null,
732        }
733        .run();
734
735        // Booleans
736        JsonTest {
737            variant: Variant::BooleanTrue,
738            expected_json: "true",
739            expected_value: Value::Bool(true),
740        }
741        .run();
742
743        JsonTest {
744            variant: Variant::BooleanFalse,
745            expected_json: "false",
746            expected_value: Value::Bool(false),
747        }
748        .run();
749
750        // Integers - positive and negative edge cases
751        JsonTest {
752            variant: Variant::Int8(42),
753            expected_json: "42",
754            expected_value: Value::Number(42.into()),
755        }
756        .run();
757
758        JsonTest {
759            variant: Variant::Int8(-128),
760            expected_json: "-128",
761            expected_value: Value::Number((-128).into()),
762        }
763        .run();
764
765        JsonTest {
766            variant: Variant::Int16(32767),
767            expected_json: "32767",
768            expected_value: Value::Number(32767.into()),
769        }
770        .run();
771
772        JsonTest {
773            variant: Variant::Int16(-32768),
774            expected_json: "-32768",
775            expected_value: Value::Number((-32768).into()),
776        }
777        .run();
778
779        JsonTest {
780            variant: Variant::Int32(2147483647),
781            expected_json: "2147483647",
782            expected_value: Value::Number(2147483647.into()),
783        }
784        .run();
785
786        JsonTest {
787            variant: Variant::Int32(-2147483648),
788            expected_json: "-2147483648",
789            expected_value: Value::Number((-2147483648).into()),
790        }
791        .run();
792
793        JsonTest {
794            variant: Variant::Int64(9223372036854775807),
795            expected_json: "9223372036854775807",
796            expected_value: Value::Number(9223372036854775807i64.into()),
797        }
798        .run();
799
800        JsonTest {
801            variant: Variant::Int64(-9223372036854775808),
802            expected_json: "-9223372036854775808",
803            expected_value: Value::Number((-9223372036854775808i64).into()),
804        }
805        .run();
806
807        // Floats
808        JsonTest {
809            variant: Variant::Float(3.5),
810            expected_json: "3.5",
811            expected_value: serde_json::Number::from_f64(3.5)
812                .map(Value::Number)
813                .unwrap(),
814        }
815        .run();
816
817        JsonTest {
818            variant: Variant::Float(0.0),
819            expected_json: "0",
820            expected_value: Value::Number(0.into()), // Use integer 0 to match JSON parsing
821        }
822        .run();
823
824        JsonTest {
825            variant: Variant::Float(-1.5),
826            expected_json: "-1.5",
827            expected_value: serde_json::Number::from_f64(-1.5)
828                .map(Value::Number)
829                .unwrap(),
830        }
831        .run();
832
833        JsonTest {
834            variant: Variant::Double(std::f64::consts::E),
835            expected_json: "2.718281828459045",
836            expected_value: serde_json::Number::from_f64(std::f64::consts::E)
837                .map(Value::Number)
838                .unwrap(),
839        }
840        .run();
841
842        // Decimals
843        JsonTest {
844            variant: Variant::from(VariantDecimal4::try_new(12345, 2).unwrap()),
845            expected_json: "123.45",
846            expected_value: serde_json::Number::from_f64(123.45)
847                .map(Value::Number)
848                .unwrap(),
849        }
850        .run();
851
852        JsonTest {
853            variant: Variant::from(VariantDecimal4::try_new(42, 0).unwrap()),
854            expected_json: "42",
855            expected_value: serde_json::Number::from_f64(42.0)
856                .map(Value::Number)
857                .unwrap(),
858        }
859        .run();
860
861        JsonTest {
862            variant: Variant::from(VariantDecimal8::try_new(1234567890, 3).unwrap()),
863            expected_json: "1234567.89",
864            expected_value: serde_json::Number::from_f64(1234567.89)
865                .map(Value::Number)
866                .unwrap(),
867        }
868        .run();
869
870        JsonTest {
871            variant: Variant::from(VariantDecimal16::try_new(123456789012345, 4).unwrap()),
872            expected_json: "12345678901.2345",
873            expected_value: serde_json::Number::from_f64(12345678901.2345)
874                .map(Value::Number)
875                .unwrap(),
876        }
877        .run();
878
879        // Strings
880        JsonTest {
881            variant: Variant::from("hello world"),
882            expected_json: "\"hello world\"",
883            expected_value: Value::String("hello world".to_string()),
884        }
885        .run();
886
887        JsonTest {
888            variant: Variant::from(""),
889            expected_json: "\"\"",
890            expected_value: Value::String("".to_string()),
891        }
892        .run();
893
894        JsonTest {
895            variant: Variant::ShortString(ShortString::try_new("test").unwrap()),
896            expected_json: "\"test\"",
897            expected_value: Value::String("test".to_string()),
898        }
899        .run();
900
901        // Date and timestamps
902        JsonTest {
903            variant: Variant::Date(NaiveDate::from_ymd_opt(2023, 12, 25).unwrap()),
904            expected_json: "\"2023-12-25\"",
905            expected_value: Value::String("2023-12-25".to_string()),
906        }
907        .run();
908
909        // Binary data (base64 encoded)
910        JsonTest {
911            variant: Variant::Binary(b"test"),
912            expected_json: "\"dGVzdA==\"", // base64 encoded "test"
913            expected_value: Value::String("dGVzdA==".to_string()),
914        }
915        .run();
916
917        JsonTest {
918            variant: Variant::Binary(b""),
919            expected_json: "\"\"", // empty base64
920            expected_value: Value::String("".to_string()),
921        }
922        .run();
923
924        JsonTest {
925            variant: Variant::Binary(b"binary data"),
926            expected_json: "\"YmluYXJ5IGRhdGE=\"", // base64 encoded "binary data"
927            expected_value: Value::String("YmluYXJ5IGRhdGE=".to_string()),
928        }
929        .run();
930    }
931
932    #[test]
933    fn test_string_escaping_comprehensive() {
934        // Test comprehensive string escaping scenarios
935        JsonTest {
936            variant: Variant::from("line1\nline2\ttab\"quote\"\\backslash"),
937            expected_json: "\"line1\\nline2\\ttab\\\"quote\\\"\\\\backslash\"",
938            expected_value: Value::String("line1\nline2\ttab\"quote\"\\backslash".to_string()),
939        }
940        .run();
941
942        JsonTest {
943            variant: Variant::from("Hello δΈ–η•Œ 🌍"),
944            expected_json: "\"Hello δΈ–η•Œ 🌍\"",
945            expected_value: Value::String("Hello δΈ–η•Œ 🌍".to_string()),
946        }
947        .run();
948    }
949
950    #[test]
951    fn test_buffer_writing_variants() -> Result<(), ArrowError> {
952        let variant = Variant::from("test buffer writing");
953
954        // Test writing to a Vec<u8>
955        let mut buffer = Vec::new();
956        variant.to_json(&mut buffer)?;
957        let result = String::from_utf8(buffer)
958            .map_err(|e| ArrowError::InvalidArgumentError(e.to_string()))?;
959        assert_eq!(result, "\"test buffer writing\"");
960
961        // Test writing to vec![]
962        let mut buffer = vec![];
963        variant.to_json(&mut buffer)?;
964        let result = String::from_utf8(buffer)
965            .map_err(|e| ArrowError::InvalidArgumentError(e.to_string()))?;
966        assert_eq!(result, "\"test buffer writing\"");
967
968        Ok(())
969    }
970
971    #[test]
972    fn test_simple_object_to_json() -> Result<(), ArrowError> {
973        use parquet_variant::VariantBuilder;
974
975        // Create a simple object with various field types
976        let mut builder = VariantBuilder::new();
977
978        builder
979            .new_object()
980            .with_field("name", "Alice")
981            .with_field("age", 30i32)
982            .with_field("active", true)
983            .with_field("score", 95.5f64)
984            .finish();
985
986        let (metadata, value) = builder.finish();
987        let variant = Variant::try_new(&metadata, &value)?;
988        let json = variant.to_json_string()?;
989
990        // Parse the JSON to verify structure - handle JSON parsing errors manually
991        let parsed: Value = serde_json::from_str(&json).unwrap();
992        let obj = parsed.as_object().expect("expected JSON object");
993        assert_eq!(obj.get("name"), Some(&Value::String("Alice".to_string())));
994        assert_eq!(obj.get("age"), Some(&Value::Number(30.into())));
995        assert_eq!(obj.get("active"), Some(&Value::Bool(true)));
996        assert!(matches!(obj.get("score"), Some(Value::Number(_))));
997        assert_eq!(obj.len(), 4);
998
999        // Test variant_to_json_value as well
1000        let json_value = variant.to_json_value()?;
1001        assert!(matches!(json_value, Value::Object(_)));
1002
1003        Ok(())
1004    }
1005
1006    #[test]
1007    fn test_empty_object_to_json() -> Result<(), ArrowError> {
1008        use parquet_variant::VariantBuilder;
1009
1010        let mut builder = VariantBuilder::new();
1011
1012        {
1013            let obj = builder.new_object();
1014            obj.finish();
1015        }
1016
1017        let (metadata, value) = builder.finish();
1018        let variant = Variant::try_new(&metadata, &value)?;
1019        let json = variant.to_json_string()?;
1020        assert_eq!(json, "{}");
1021
1022        let json_value = variant.to_json_value()?;
1023        assert_eq!(json_value, Value::Object(serde_json::Map::new()));
1024
1025        Ok(())
1026    }
1027
1028    #[test]
1029    fn test_object_with_special_characters_to_json() -> Result<(), ArrowError> {
1030        use parquet_variant::VariantBuilder;
1031
1032        let mut builder = VariantBuilder::new();
1033
1034        builder
1035            .new_object()
1036            .with_field("message", "Hello \"World\"\nWith\tTabs")
1037            .with_field("path", "C:\\Users\\Alice\\Documents")
1038            .with_field("unicode", "πŸ˜€ Smiley")
1039            .finish();
1040
1041        let (metadata, value) = builder.finish();
1042        let variant = Variant::try_new(&metadata, &value)?;
1043        let json = variant.to_json_string()?;
1044
1045        // Verify that special characters are properly escaped
1046        assert!(json.contains("Hello \\\"World\\\"\\nWith\\tTabs"));
1047        assert!(json.contains("C:\\\\Users\\\\Alice\\\\Documents"));
1048        assert!(json.contains("πŸ˜€ Smiley"));
1049
1050        // Verify that the JSON can be parsed back
1051        let parsed: Value = serde_json::from_str(&json).unwrap();
1052        assert!(matches!(parsed, Value::Object(_)));
1053
1054        Ok(())
1055    }
1056
1057    #[test]
1058    fn test_simple_list_to_json() -> Result<(), ArrowError> {
1059        use parquet_variant::VariantBuilder;
1060
1061        let mut builder = VariantBuilder::new();
1062
1063        builder
1064            .new_list()
1065            .with_value(1i32)
1066            .with_value(2i32)
1067            .with_value(3i32)
1068            .with_value(4i32)
1069            .with_value(5i32)
1070            .finish();
1071
1072        let (metadata, value) = builder.finish();
1073        let variant = Variant::try_new(&metadata, &value)?;
1074        let json = variant.to_json_string()?;
1075        assert_eq!(json, "[1,2,3,4,5]");
1076
1077        let json_value = variant.to_json_value()?;
1078        let arr = json_value.as_array().expect("expected JSON array");
1079        assert_eq!(arr.len(), 5);
1080        assert_eq!(arr[0], Value::Number(1.into()));
1081        assert_eq!(arr[4], Value::Number(5.into()));
1082
1083        Ok(())
1084    }
1085
1086    #[test]
1087    fn test_empty_list_to_json() -> Result<(), ArrowError> {
1088        use parquet_variant::VariantBuilder;
1089
1090        let mut builder = VariantBuilder::new();
1091
1092        {
1093            let list = builder.new_list();
1094            list.finish();
1095        }
1096
1097        let (metadata, value) = builder.finish();
1098        let variant = Variant::try_new(&metadata, &value)?;
1099        let json = variant.to_json_string()?;
1100        assert_eq!(json, "[]");
1101
1102        let json_value = variant.to_json_value()?;
1103        assert_eq!(json_value, Value::Array(vec![]));
1104
1105        Ok(())
1106    }
1107
1108    #[test]
1109    fn test_mixed_type_list_to_json() -> Result<(), ArrowError> {
1110        use parquet_variant::VariantBuilder;
1111
1112        let mut builder = VariantBuilder::new();
1113
1114        builder
1115            .new_list()
1116            .with_value("hello")
1117            .with_value(42i32)
1118            .with_value(true)
1119            .with_value(()) // null
1120            .with_value(std::f64::consts::PI)
1121            .finish();
1122
1123        let (metadata, value) = builder.finish();
1124        let variant = Variant::try_new(&metadata, &value)?;
1125        let json = variant.to_json_string()?;
1126
1127        let parsed: Value = serde_json::from_str(&json).unwrap();
1128        let arr = parsed.as_array().expect("expected JSON array");
1129        assert_eq!(arr.len(), 5);
1130        assert_eq!(arr[0], Value::String("hello".to_string()));
1131        assert_eq!(arr[1], Value::Number(42.into()));
1132        assert_eq!(arr[2], Value::Bool(true));
1133        assert_eq!(arr[3], Value::Null);
1134        assert!(matches!(arr[4], Value::Number(_)));
1135
1136        Ok(())
1137    }
1138
1139    #[test]
1140    fn test_object_field_ordering_in_json() -> Result<(), ArrowError> {
1141        use parquet_variant::VariantBuilder;
1142
1143        let mut builder = VariantBuilder::new();
1144
1145        {
1146            let mut obj = builder.new_object();
1147            // Add fields in non-alphabetical order
1148            obj.insert("zebra", "last");
1149            obj.insert("alpha", "first");
1150            obj.insert("beta", "second");
1151            obj.finish();
1152        }
1153
1154        let (metadata, value) = builder.finish();
1155        let variant = Variant::try_new(&metadata, &value)?;
1156        let json = variant.to_json_string()?;
1157
1158        // Parse and verify all fields are present
1159        let parsed: Value = serde_json::from_str(&json).unwrap();
1160        let obj = parsed.as_object().expect("expected JSON object");
1161        assert_eq!(obj.len(), 3);
1162        assert_eq!(obj.get("alpha"), Some(&Value::String("first".to_string())));
1163        assert_eq!(obj.get("beta"), Some(&Value::String("second".to_string())));
1164        assert_eq!(obj.get("zebra"), Some(&Value::String("last".to_string())));
1165
1166        Ok(())
1167    }
1168
1169    #[test]
1170    fn test_list_with_various_primitive_types_to_json() -> Result<(), ArrowError> {
1171        use parquet_variant::VariantBuilder;
1172
1173        let mut builder = VariantBuilder::new();
1174
1175        builder
1176            .new_list()
1177            .with_value("string_value")
1178            .with_value(42i32)
1179            .with_value(true)
1180            .with_value(std::f64::consts::PI)
1181            .with_value(false)
1182            .with_value(()) // null
1183            .with_value(100i64)
1184            .finish();
1185
1186        let (metadata, value) = builder.finish();
1187        let variant = Variant::try_new(&metadata, &value)?;
1188        let json = variant.to_json_string()?;
1189
1190        let parsed: Value = serde_json::from_str(&json).unwrap();
1191        let arr = parsed.as_array().expect("expected JSON array");
1192        assert_eq!(arr.len(), 7);
1193        assert_eq!(arr[0], Value::String("string_value".to_string()));
1194        assert_eq!(arr[1], Value::Number(42.into()));
1195        assert_eq!(arr[2], Value::Bool(true));
1196        assert!(matches!(arr[3], Value::Number(_))); // float
1197        assert_eq!(arr[4], Value::Bool(false));
1198        assert_eq!(arr[5], Value::Null);
1199        assert_eq!(arr[6], Value::Number(100.into()));
1200
1201        Ok(())
1202    }
1203
1204    #[test]
1205    fn test_object_with_various_primitive_types_to_json() -> Result<(), ArrowError> {
1206        use parquet_variant::VariantBuilder;
1207
1208        let mut builder = VariantBuilder::new();
1209
1210        {
1211            let mut obj = builder.new_object();
1212            obj.insert("string_field", "test_string");
1213            obj.insert("int_field", 123i32);
1214            obj.insert("bool_field", true);
1215            obj.insert("float_field", 2.71f64);
1216            obj.insert("null_field", ());
1217            obj.insert("long_field", 999i64);
1218            obj.finish();
1219        }
1220
1221        let (metadata, value) = builder.finish();
1222        let variant = Variant::try_new(&metadata, &value)?;
1223        let json = variant.to_json_string()?;
1224
1225        let parsed: Value = serde_json::from_str(&json).unwrap();
1226        let obj = parsed.as_object().expect("expected JSON object");
1227        assert_eq!(obj.len(), 6);
1228        assert_eq!(
1229            obj.get("string_field"),
1230            Some(&Value::String("test_string".to_string()))
1231        );
1232        assert_eq!(obj.get("int_field"), Some(&Value::Number(123.into())));
1233        assert_eq!(obj.get("bool_field"), Some(&Value::Bool(true)));
1234        assert!(matches!(obj.get("float_field"), Some(Value::Number(_))));
1235        assert_eq!(obj.get("null_field"), Some(&Value::Null));
1236        assert_eq!(obj.get("long_field"), Some(&Value::Number(999.into())));
1237
1238        Ok(())
1239    }
1240
1241    #[test]
1242    fn test_decimal_precision_behavior() -> Result<(), ArrowError> {
1243        // Test case that demonstrates f64 precision limits
1244        // This is a 63-bit precision decimal8 value that f64 cannot represent exactly
1245        let high_precision_decimal8 = Variant::from(VariantDecimal8::try_new(
1246            9007199254740993, // 2^53 + 1, exceeds f64 precision
1247            6,
1248        )?);
1249
1250        let json_string = high_precision_decimal8.to_json_string()?;
1251        let json_value = high_precision_decimal8.to_json_value()?;
1252
1253        // Due to f64 precision limits, we expect precision loss for values > 2^53
1254        // Both functions should produce consistent results (even if not exact)
1255        let parsed: Value = serde_json::from_str(&json_string).unwrap();
1256        assert_eq!(parsed, json_value);
1257
1258        // Test a case that can be exactly represented (integer result)
1259        let exact_decimal = Variant::from(VariantDecimal8::try_new(
1260            1234567890000, // Should result in 1234567.89 (trailing zeros trimmed)
1261            6,
1262        )?);
1263
1264        let json_string_exact = exact_decimal.to_json_string()?;
1265        assert_eq!(json_string_exact, "1234567.89");
1266
1267        // Test integer case (should be exact)
1268        let integer_decimal = Variant::from(VariantDecimal8::try_new(
1269            42000000, // Should result in 42 (integer)
1270            6,
1271        )?);
1272
1273        let json_string_integer = integer_decimal.to_json_string()?;
1274        assert_eq!(json_string_integer, "42");
1275
1276        Ok(())
1277    }
1278
1279    #[test]
1280    fn test_float_nan_inf_handling() -> Result<(), ArrowError> {
1281        // Test NaN handling - should return an error since JSON doesn't support NaN
1282        let nan_variant = Variant::Float(f32::NAN);
1283        let nan_result = nan_variant.to_json_value();
1284        assert!(nan_result.is_err());
1285        assert!(
1286            nan_result
1287                .unwrap_err()
1288                .to_string()
1289                .contains("Invalid float value")
1290        );
1291
1292        // Test positive infinity - should return an error since JSON doesn't support Infinity
1293        let pos_inf_variant = Variant::Float(f32::INFINITY);
1294        let pos_inf_result = pos_inf_variant.to_json_value();
1295        assert!(pos_inf_result.is_err());
1296        assert!(
1297            pos_inf_result
1298                .unwrap_err()
1299                .to_string()
1300                .contains("Invalid float value")
1301        );
1302
1303        // Test negative infinity - should return an error since JSON doesn't support -Infinity
1304        let neg_inf_variant = Variant::Float(f32::NEG_INFINITY);
1305        let neg_inf_result = neg_inf_variant.to_json_value();
1306        assert!(neg_inf_result.is_err());
1307        assert!(
1308            neg_inf_result
1309                .unwrap_err()
1310                .to_string()
1311                .contains("Invalid float value")
1312        );
1313
1314        // Test the same for Double variants
1315        let nan_double_variant = Variant::Double(f64::NAN);
1316        let nan_double_result = nan_double_variant.to_json_value();
1317        assert!(nan_double_result.is_err());
1318        assert!(
1319            nan_double_result
1320                .unwrap_err()
1321                .to_string()
1322                .contains("Invalid double value")
1323        );
1324
1325        let pos_inf_double_variant = Variant::Double(f64::INFINITY);
1326        let pos_inf_double_result = pos_inf_double_variant.to_json_value();
1327        assert!(pos_inf_double_result.is_err());
1328        assert!(
1329            pos_inf_double_result
1330                .unwrap_err()
1331                .to_string()
1332                .contains("Invalid double value")
1333        );
1334
1335        let neg_inf_double_variant = Variant::Double(f64::NEG_INFINITY);
1336        let neg_inf_double_result = neg_inf_double_variant.to_json_value();
1337        assert!(neg_inf_double_result.is_err());
1338        assert!(
1339            neg_inf_double_result
1340                .unwrap_err()
1341                .to_string()
1342                .contains("Invalid double value")
1343        );
1344
1345        // Test normal float values still work
1346        let normal_float = Variant::Float(std::f32::consts::PI);
1347        let normal_result = normal_float.to_json_value()?;
1348        assert!(matches!(normal_result, Value::Number(_)));
1349
1350        let normal_double = Variant::Double(std::f64::consts::E);
1351        let normal_double_result = normal_double.to_json_value()?;
1352        assert!(matches!(normal_double_result, Value::Number(_)));
1353
1354        Ok(())
1355    }
1356}