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 VariantToJson for Variant<'_, '_> {
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!("{}", ts.format(&format!("%Y-%m-%dT%H:%M:%S%.{precision}f")));
348    ts.format(format_str.as_str()).to_string()
349}
350
351fn format_binary_base64(bytes: &[u8]) -> String {
352    general_purpose::STANDARD.encode(bytes)
353}
354
355fn format_time_ntz_str(time: &chrono::NaiveTime) -> String {
356    let base = time.format("%H:%M:%S").to_string();
357    let micros = time.nanosecond() / 1000;
358    match micros {
359        0 => format!("{}.{}", base, 0),
360        _ => {
361            let micros_str = format!("{micros:06}");
362            let micros_str_trimmed = micros_str.trim_end_matches('0');
363            format!("{base}.{micros_str_trimmed}")
364        }
365    }
366}
367
368/// Convert object fields to JSON
369fn convert_object_to_json(buffer: &mut impl Write, obj: &VariantObject) -> Result<(), ArrowError> {
370    write!(buffer, "{{")?;
371
372    // Get all fields from the object
373    let mut first = true;
374
375    for (key, value) in obj.iter() {
376        if !first {
377            write!(buffer, ",")?;
378        }
379        first = false;
380
381        // Write the key (properly escaped)
382        let json_key = serde_json::to_string(key).map_err(|e| {
383            ArrowError::InvalidArgumentError(format!("JSON key encoding error: {e}"))
384        })?;
385        write!(buffer, "{json_key}:")?;
386
387        // Recursively convert the value
388        value.to_json(buffer)?;
389    }
390
391    write!(buffer, "}}")?;
392    Ok(())
393}
394
395/// Convert array elements to JSON
396fn convert_array_to_json(buffer: &mut impl Write, arr: &VariantList) -> Result<(), ArrowError> {
397    write!(buffer, "[")?;
398
399    let mut first = true;
400    for element in arr.iter() {
401        if !first {
402            write!(buffer, ",")?;
403        }
404        first = false;
405
406        element.to_json(buffer)?;
407    }
408
409    write!(buffer, "]")?;
410    Ok(())
411}
412
413#[cfg(test)]
414mod tests {
415    use super::*;
416    use chrono::{DateTime, NaiveDate, NaiveTime, Utc};
417    use parquet_variant::{VariantDecimal4, VariantDecimal8, VariantDecimal16};
418
419    #[test]
420    fn test_decimal_edge_cases() -> Result<(), ArrowError> {
421        // Test negative decimal
422        let negative_variant = Variant::from(VariantDecimal4::try_new(-12345, 3)?);
423        let negative_json = negative_variant.to_json_string()?;
424        assert_eq!(negative_json, "-12.345");
425
426        // Test large scale decimal
427        let large_scale_variant = Variant::from(VariantDecimal8::try_new(123456789, 6)?);
428        let large_scale_json = large_scale_variant.to_json_string()?;
429        assert_eq!(large_scale_json, "123.456789");
430
431        Ok(())
432    }
433
434    #[test]
435    fn test_decimal16_to_json() -> Result<(), ArrowError> {
436        let variant = Variant::from(VariantDecimal16::try_new(123456789012345, 4)?);
437        let json = variant.to_json_string()?;
438        assert_eq!(json, "12345678901.2345");
439
440        let json_value = variant.to_json_value()?;
441        assert!(matches!(json_value, Value::Number(_)));
442
443        // Test very large number
444        let large_variant = Variant::from(VariantDecimal16::try_new(999999999999999999, 2)?);
445        let large_json = large_variant.to_json_string()?;
446        // Due to f64 precision limits, very large numbers may lose precision
447        assert!(
448            large_json.starts_with("9999999999999999")
449                || large_json.starts_with("10000000000000000")
450        );
451        Ok(())
452    }
453
454    #[test]
455    fn test_date_to_json() -> Result<(), ArrowError> {
456        let date = NaiveDate::from_ymd_opt(2023, 12, 25).unwrap();
457        let variant = Variant::Date(date);
458        let json = variant.to_json_string()?;
459        assert_eq!(json, "\"2023-12-25\"");
460
461        let json_value = variant.to_json_value()?;
462        assert_eq!(json_value, Value::String("2023-12-25".to_string()));
463
464        // Test leap year date
465        let leap_date = NaiveDate::from_ymd_opt(2024, 2, 29).unwrap();
466        let leap_variant = Variant::Date(leap_date);
467        let leap_json = leap_variant.to_json_string()?;
468        assert_eq!(leap_json, "\"2024-02-29\"");
469        Ok(())
470    }
471
472    #[test]
473    fn test_timestamp_micros_to_json() -> Result<(), ArrowError> {
474        let timestamp = DateTime::parse_from_rfc3339("2023-12-25T10:30:45Z")
475            .unwrap()
476            .with_timezone(&Utc);
477        let variant = Variant::TimestampMicros(timestamp);
478        let json = variant.to_json_string()?;
479        assert!(json.contains("2023-12-25T10:30:45"));
480        assert!(json.starts_with('"') && json.ends_with('"'));
481
482        let json_value = variant.to_json_value()?;
483        assert!(matches!(json_value, Value::String(_)));
484        Ok(())
485    }
486
487    #[test]
488    fn test_timestamp_ntz_micros_to_json() -> Result<(), ArrowError> {
489        let naive_timestamp = DateTime::from_timestamp(1703505045, 123456)
490            .unwrap()
491            .naive_utc();
492        let variant = Variant::TimestampNtzMicros(naive_timestamp);
493        let json = variant.to_json_string()?;
494        assert!(json.contains("2023-12-25"));
495        assert!(json.starts_with('"') && json.ends_with('"'));
496
497        let json_value = variant.to_json_value()?;
498        assert!(matches!(json_value, Value::String(_)));
499        Ok(())
500    }
501
502    #[test]
503    fn test_time_to_json() -> Result<(), ArrowError> {
504        let naive_time = NaiveTime::from_num_seconds_from_midnight_opt(12345, 123460708).unwrap();
505        let variant = Variant::Time(naive_time);
506        let json = variant.to_json_string()?;
507        assert_eq!("\"03:25:45.12346\"", json);
508
509        let expected = [
510            (10, "00:00:00.00001"),
511            (10010, "00:00:00.01001"),
512            (100000, "00:00:00.1"),
513            (123450, "00:00:00.12345"),
514        ];
515
516        for (micros, expected_json) in expected {
517            let naive_time =
518                NaiveTime::from_num_seconds_from_midnight_opt(0, micros * 1000).unwrap();
519            let variant = Variant::Time(naive_time);
520            let json = variant.to_json_string()?;
521            assert_eq!(format!("\"{expected_json}\""), json);
522        }
523
524        let json_value = variant.to_json_value()?;
525        assert!(matches!(json_value, Value::String(_)));
526        Ok(())
527    }
528
529    #[test]
530    fn test_timestamp_nanos_to_json() -> Result<(), ArrowError> {
531        let timestamp = DateTime::parse_from_rfc3339("2023-12-25T10:30:45.123456789Z")
532            .unwrap()
533            .with_timezone(&Utc);
534        let variant = Variant::TimestampNanos(timestamp);
535        let json = variant.to_json_string()?;
536        assert_eq!(json, "\"2023-12-25T10:30:45.123456789+00:00\"");
537
538        let json_value = variant.to_json_value()?;
539        assert!(matches!(json_value, Value::String(_)));
540        Ok(())
541    }
542
543    #[test]
544    fn test_timestamp_ntz_nanos_to_json() -> Result<(), ArrowError> {
545        let naive_timestamp = DateTime::from_timestamp(1703505045, 123456789)
546            .unwrap()
547            .naive_utc();
548        let variant = Variant::TimestampNtzNanos(naive_timestamp);
549        let json = variant.to_json_string()?;
550        assert_eq!(json, "\"2023-12-25T11:50:45.123456789\"");
551
552        let json_value = variant.to_json_value()?;
553        assert!(matches!(json_value, Value::String(_)));
554        Ok(())
555    }
556
557    #[test]
558    fn test_binary_to_json() -> Result<(), ArrowError> {
559        let binary_data = b"Hello, World!";
560        let variant = Variant::Binary(binary_data);
561        let json = variant.to_json_string()?;
562
563        // Should be base64 encoded and quoted
564        assert!(json.starts_with('"') && json.ends_with('"'));
565        assert!(json.len() > 2); // Should have content
566
567        let json_value = variant.to_json_value()?;
568        assert!(matches!(json_value, Value::String(_)));
569
570        // Test empty binary
571        let empty_variant = Variant::Binary(b"");
572        let empty_json = empty_variant.to_json_string()?;
573        assert_eq!(empty_json, "\"\"");
574
575        // Test binary with special bytes
576        let special_variant = Variant::Binary(&[0, 255, 128, 64]);
577        let special_json = special_variant.to_json_string()?;
578        assert!(special_json.starts_with('"') && special_json.ends_with('"'));
579        Ok(())
580    }
581
582    #[test]
583    fn test_string_to_json() -> Result<(), ArrowError> {
584        let variant = Variant::from("hello world");
585        let json = variant.to_json_string()?;
586        assert_eq!(json, "\"hello world\"");
587
588        let json_value = variant.to_json_value()?;
589        assert_eq!(json_value, Value::String("hello world".to_string()));
590        Ok(())
591    }
592
593    #[test]
594    fn test_short_string_to_json() -> Result<(), ArrowError> {
595        use parquet_variant::ShortString;
596        let short_string = ShortString::try_new("short")?;
597        let variant = Variant::ShortString(short_string);
598        let json = variant.to_json_string()?;
599        assert_eq!(json, "\"short\"");
600
601        let json_value = variant.to_json_value()?;
602        assert_eq!(json_value, Value::String("short".to_string()));
603        Ok(())
604    }
605
606    #[test]
607    fn test_uuid_to_json() -> Result<(), ArrowError> {
608        let uuid = uuid::Uuid::parse_str("123e4567-e89b-12d3-a456-426614174000").unwrap();
609        let variant = Variant::Uuid(uuid);
610        let json = variant.to_json_string()?;
611        assert_eq!(json, "\"123e4567-e89b-12d3-a456-426614174000\"");
612
613        let json_value = variant.to_json_value()?;
614        assert_eq!(
615            json_value,
616            Value::String("123e4567-e89b-12d3-a456-426614174000".to_string())
617        );
618        Ok(())
619    }
620
621    #[test]
622    fn test_string_escaping() -> Result<(), ArrowError> {
623        let variant = Variant::from("hello\nworld\t\"quoted\"");
624        let json = variant.to_json_string()?;
625        assert_eq!(json, "\"hello\\nworld\\t\\\"quoted\\\"\"");
626
627        let json_value = variant.to_json_value()?;
628        assert_eq!(
629            json_value,
630            Value::String("hello\nworld\t\"quoted\"".to_string())
631        );
632        Ok(())
633    }
634
635    #[test]
636    fn test_json_buffer_writing() -> Result<(), ArrowError> {
637        let variant = Variant::Int8(123);
638        let mut buffer = Vec::new();
639        variant.to_json(&mut buffer)?;
640
641        let result = String::from_utf8(buffer)
642            .map_err(|e| ArrowError::InvalidArgumentError(e.to_string()))?;
643        assert_eq!(result, "123");
644        Ok(())
645    }
646
647    /// Reusable test structure for JSON conversion testing
648    struct JsonTest {
649        variant: Variant<'static, 'static>,
650        expected_json: &'static str,
651        expected_value: Value,
652    }
653
654    impl JsonTest {
655        fn run(self) {
656            let json_string = self
657                .variant
658                .to_json_string()
659                .expect("variant_to_json_string should succeed");
660            assert_eq!(
661                json_string, self.expected_json,
662                "JSON string mismatch for variant: {:?}",
663                self.variant
664            );
665
666            let json_value = self
667                .variant
668                .to_json_value()
669                .expect("variant_to_json_value should succeed");
670
671            // For floating point numbers, we need special comparison due to JSON number representation
672            match (&json_value, &self.expected_value) {
673                (Value::Number(actual), Value::Number(expected)) => {
674                    let actual_f64 = actual.as_f64().unwrap_or(0.0);
675                    let expected_f64 = expected.as_f64().unwrap_or(0.0);
676                    assert!(
677                        (actual_f64 - expected_f64).abs() < f64::EPSILON,
678                        "JSON value mismatch for variant: {:?}, got {}, expected {}",
679                        self.variant,
680                        actual_f64,
681                        expected_f64
682                    );
683                }
684                _ => {
685                    assert_eq!(
686                        json_value, self.expected_value,
687                        "JSON value mismatch for variant: {:?}",
688                        self.variant
689                    );
690                }
691            }
692
693            // Verify roundtrip: JSON string should parse to same value
694            let parsed: Value =
695                serde_json::from_str(&json_string).expect("Generated JSON should be valid");
696            // Same floating point handling for roundtrip
697            match (&parsed, &self.expected_value) {
698                (Value::Number(actual), Value::Number(expected)) => {
699                    let actual_f64 = actual.as_f64().unwrap_or(0.0);
700                    let expected_f64 = expected.as_f64().unwrap_or(0.0);
701                    assert!(
702                        (actual_f64 - expected_f64).abs() < f64::EPSILON,
703                        "Parsed JSON mismatch for variant: {:?}, got {}, expected {}",
704                        self.variant,
705                        actual_f64,
706                        expected_f64
707                    );
708                }
709                _ => {
710                    assert_eq!(
711                        parsed, self.expected_value,
712                        "Parsed JSON mismatch for variant: {:?}",
713                        self.variant
714                    );
715                }
716            }
717        }
718    }
719
720    #[test]
721    fn test_primitive_json_conversion() {
722        use parquet_variant::ShortString;
723
724        // Null
725        JsonTest {
726            variant: Variant::Null,
727            expected_json: "null",
728            expected_value: Value::Null,
729        }
730        .run();
731
732        // Booleans
733        JsonTest {
734            variant: Variant::BooleanTrue,
735            expected_json: "true",
736            expected_value: Value::Bool(true),
737        }
738        .run();
739
740        JsonTest {
741            variant: Variant::BooleanFalse,
742            expected_json: "false",
743            expected_value: Value::Bool(false),
744        }
745        .run();
746
747        // Integers - positive and negative edge cases
748        JsonTest {
749            variant: Variant::Int8(42),
750            expected_json: "42",
751            expected_value: Value::Number(42.into()),
752        }
753        .run();
754
755        JsonTest {
756            variant: Variant::Int8(-128),
757            expected_json: "-128",
758            expected_value: Value::Number((-128).into()),
759        }
760        .run();
761
762        JsonTest {
763            variant: Variant::Int16(32767),
764            expected_json: "32767",
765            expected_value: Value::Number(32767.into()),
766        }
767        .run();
768
769        JsonTest {
770            variant: Variant::Int16(-32768),
771            expected_json: "-32768",
772            expected_value: Value::Number((-32768).into()),
773        }
774        .run();
775
776        JsonTest {
777            variant: Variant::Int32(2147483647),
778            expected_json: "2147483647",
779            expected_value: Value::Number(2147483647.into()),
780        }
781        .run();
782
783        JsonTest {
784            variant: Variant::Int32(-2147483648),
785            expected_json: "-2147483648",
786            expected_value: Value::Number((-2147483648).into()),
787        }
788        .run();
789
790        JsonTest {
791            variant: Variant::Int64(9223372036854775807),
792            expected_json: "9223372036854775807",
793            expected_value: Value::Number(9223372036854775807i64.into()),
794        }
795        .run();
796
797        JsonTest {
798            variant: Variant::Int64(-9223372036854775808),
799            expected_json: "-9223372036854775808",
800            expected_value: Value::Number((-9223372036854775808i64).into()),
801        }
802        .run();
803
804        // Floats
805        JsonTest {
806            variant: Variant::Float(3.5),
807            expected_json: "3.5",
808            expected_value: serde_json::Number::from_f64(3.5)
809                .map(Value::Number)
810                .unwrap(),
811        }
812        .run();
813
814        JsonTest {
815            variant: Variant::Float(0.0),
816            expected_json: "0",
817            expected_value: Value::Number(0.into()), // Use integer 0 to match JSON parsing
818        }
819        .run();
820
821        JsonTest {
822            variant: Variant::Float(-1.5),
823            expected_json: "-1.5",
824            expected_value: serde_json::Number::from_f64(-1.5)
825                .map(Value::Number)
826                .unwrap(),
827        }
828        .run();
829
830        JsonTest {
831            variant: Variant::Double(std::f64::consts::E),
832            expected_json: "2.718281828459045",
833            expected_value: serde_json::Number::from_f64(std::f64::consts::E)
834                .map(Value::Number)
835                .unwrap(),
836        }
837        .run();
838
839        // Decimals
840        JsonTest {
841            variant: Variant::from(VariantDecimal4::try_new(12345, 2).unwrap()),
842            expected_json: "123.45",
843            expected_value: serde_json::Number::from_f64(123.45)
844                .map(Value::Number)
845                .unwrap(),
846        }
847        .run();
848
849        JsonTest {
850            variant: Variant::from(VariantDecimal4::try_new(42, 0).unwrap()),
851            expected_json: "42",
852            expected_value: serde_json::Number::from_f64(42.0)
853                .map(Value::Number)
854                .unwrap(),
855        }
856        .run();
857
858        JsonTest {
859            variant: Variant::from(VariantDecimal8::try_new(1234567890, 3).unwrap()),
860            expected_json: "1234567.89",
861            expected_value: serde_json::Number::from_f64(1234567.89)
862                .map(Value::Number)
863                .unwrap(),
864        }
865        .run();
866
867        JsonTest {
868            variant: Variant::from(VariantDecimal16::try_new(123456789012345, 4).unwrap()),
869            expected_json: "12345678901.2345",
870            expected_value: serde_json::Number::from_f64(12345678901.2345)
871                .map(Value::Number)
872                .unwrap(),
873        }
874        .run();
875
876        // Strings
877        JsonTest {
878            variant: Variant::from("hello world"),
879            expected_json: "\"hello world\"",
880            expected_value: Value::String("hello world".to_string()),
881        }
882        .run();
883
884        JsonTest {
885            variant: Variant::from(""),
886            expected_json: "\"\"",
887            expected_value: Value::String(String::new()),
888        }
889        .run();
890
891        JsonTest {
892            variant: Variant::ShortString(ShortString::try_new("test").unwrap()),
893            expected_json: "\"test\"",
894            expected_value: Value::String("test".to_string()),
895        }
896        .run();
897
898        // Date and timestamps
899        JsonTest {
900            variant: Variant::Date(NaiveDate::from_ymd_opt(2023, 12, 25).unwrap()),
901            expected_json: "\"2023-12-25\"",
902            expected_value: Value::String("2023-12-25".to_string()),
903        }
904        .run();
905
906        // Binary data (base64 encoded)
907        JsonTest {
908            variant: Variant::Binary(b"test"),
909            expected_json: "\"dGVzdA==\"", // base64 encoded "test"
910            expected_value: Value::String("dGVzdA==".to_string()),
911        }
912        .run();
913
914        JsonTest {
915            variant: Variant::Binary(b""),
916            expected_json: "\"\"", // empty base64
917            expected_value: Value::String(String::new()),
918        }
919        .run();
920
921        JsonTest {
922            variant: Variant::Binary(b"binary data"),
923            expected_json: "\"YmluYXJ5IGRhdGE=\"", // base64 encoded "binary data"
924            expected_value: Value::String("YmluYXJ5IGRhdGE=".to_string()),
925        }
926        .run();
927    }
928
929    #[test]
930    fn test_string_escaping_comprehensive() {
931        // Test comprehensive string escaping scenarios
932        JsonTest {
933            variant: Variant::from("line1\nline2\ttab\"quote\"\\backslash"),
934            expected_json: "\"line1\\nline2\\ttab\\\"quote\\\"\\\\backslash\"",
935            expected_value: Value::String("line1\nline2\ttab\"quote\"\\backslash".to_string()),
936        }
937        .run();
938
939        JsonTest {
940            variant: Variant::from("Hello δΈ–η•Œ 🌍"),
941            expected_json: "\"Hello δΈ–η•Œ 🌍\"",
942            expected_value: Value::String("Hello δΈ–η•Œ 🌍".to_string()),
943        }
944        .run();
945    }
946
947    #[test]
948    fn test_buffer_writing_variants() -> Result<(), ArrowError> {
949        let variant = Variant::from("test buffer writing");
950
951        // Test writing to a Vec<u8>
952        let mut buffer = Vec::new();
953        variant.to_json(&mut buffer)?;
954        let result = String::from_utf8(buffer)
955            .map_err(|e| ArrowError::InvalidArgumentError(e.to_string()))?;
956        assert_eq!(result, "\"test buffer writing\"");
957
958        // Test writing to vec![]
959        let mut buffer = vec![];
960        variant.to_json(&mut buffer)?;
961        let result = String::from_utf8(buffer)
962            .map_err(|e| ArrowError::InvalidArgumentError(e.to_string()))?;
963        assert_eq!(result, "\"test buffer writing\"");
964
965        Ok(())
966    }
967
968    #[test]
969    fn test_simple_object_to_json() -> Result<(), ArrowError> {
970        use parquet_variant::VariantBuilder;
971
972        // Create a simple object with various field types
973        let mut builder = VariantBuilder::new();
974
975        builder
976            .new_object()
977            .with_field("name", "Alice")
978            .with_field("age", 30i32)
979            .with_field("active", true)
980            .with_field("score", 95.5f64)
981            .finish();
982
983        let (metadata, value) = builder.finish();
984        let variant = Variant::try_new(&metadata, &value)?;
985        let json = variant.to_json_string()?;
986
987        // Parse the JSON to verify structure - handle JSON parsing errors manually
988        let parsed: Value = serde_json::from_str(&json).unwrap();
989        let obj = parsed.as_object().expect("expected JSON object");
990        assert_eq!(obj.get("name"), Some(&Value::String("Alice".to_string())));
991        assert_eq!(obj.get("age"), Some(&Value::Number(30.into())));
992        assert_eq!(obj.get("active"), Some(&Value::Bool(true)));
993        assert!(matches!(obj.get("score"), Some(Value::Number(_))));
994        assert_eq!(obj.len(), 4);
995
996        // Test variant_to_json_value as well
997        let json_value = variant.to_json_value()?;
998        assert!(matches!(json_value, Value::Object(_)));
999
1000        Ok(())
1001    }
1002
1003    #[test]
1004    fn test_empty_object_to_json() -> Result<(), ArrowError> {
1005        use parquet_variant::VariantBuilder;
1006
1007        let mut builder = VariantBuilder::new();
1008
1009        {
1010            let obj = builder.new_object();
1011            obj.finish();
1012        }
1013
1014        let (metadata, value) = builder.finish();
1015        let variant = Variant::try_new(&metadata, &value)?;
1016        let json = variant.to_json_string()?;
1017        assert_eq!(json, "{}");
1018
1019        let json_value = variant.to_json_value()?;
1020        assert_eq!(json_value, Value::Object(serde_json::Map::new()));
1021
1022        Ok(())
1023    }
1024
1025    #[test]
1026    fn test_object_with_special_characters_to_json() -> Result<(), ArrowError> {
1027        use parquet_variant::VariantBuilder;
1028
1029        let mut builder = VariantBuilder::new();
1030
1031        builder
1032            .new_object()
1033            .with_field("message", "Hello \"World\"\nWith\tTabs")
1034            .with_field("path", "C:\\Users\\Alice\\Documents")
1035            .with_field("unicode", "πŸ˜€ Smiley")
1036            .finish();
1037
1038        let (metadata, value) = builder.finish();
1039        let variant = Variant::try_new(&metadata, &value)?;
1040        let json = variant.to_json_string()?;
1041
1042        // Verify that special characters are properly escaped
1043        assert!(json.contains("Hello \\\"World\\\"\\nWith\\tTabs"));
1044        assert!(json.contains("C:\\\\Users\\\\Alice\\\\Documents"));
1045        assert!(json.contains("πŸ˜€ Smiley"));
1046
1047        // Verify that the JSON can be parsed back
1048        let parsed: Value = serde_json::from_str(&json).unwrap();
1049        assert!(matches!(parsed, Value::Object(_)));
1050
1051        Ok(())
1052    }
1053
1054    #[test]
1055    fn test_simple_list_to_json() -> Result<(), ArrowError> {
1056        use parquet_variant::VariantBuilder;
1057
1058        let mut builder = VariantBuilder::new();
1059
1060        builder
1061            .new_list()
1062            .with_value(1i32)
1063            .with_value(2i32)
1064            .with_value(3i32)
1065            .with_value(4i32)
1066            .with_value(5i32)
1067            .finish();
1068
1069        let (metadata, value) = builder.finish();
1070        let variant = Variant::try_new(&metadata, &value)?;
1071        let json = variant.to_json_string()?;
1072        assert_eq!(json, "[1,2,3,4,5]");
1073
1074        let json_value = variant.to_json_value()?;
1075        let arr = json_value.as_array().expect("expected JSON array");
1076        assert_eq!(arr.len(), 5);
1077        assert_eq!(arr[0], Value::Number(1.into()));
1078        assert_eq!(arr[4], Value::Number(5.into()));
1079
1080        Ok(())
1081    }
1082
1083    #[test]
1084    fn test_empty_list_to_json() -> Result<(), ArrowError> {
1085        use parquet_variant::VariantBuilder;
1086
1087        let mut builder = VariantBuilder::new();
1088
1089        {
1090            let list = builder.new_list();
1091            list.finish();
1092        }
1093
1094        let (metadata, value) = builder.finish();
1095        let variant = Variant::try_new(&metadata, &value)?;
1096        let json = variant.to_json_string()?;
1097        assert_eq!(json, "[]");
1098
1099        let json_value = variant.to_json_value()?;
1100        assert_eq!(json_value, Value::Array(vec![]));
1101
1102        Ok(())
1103    }
1104
1105    #[test]
1106    fn test_mixed_type_list_to_json() -> Result<(), ArrowError> {
1107        use parquet_variant::VariantBuilder;
1108
1109        let mut builder = VariantBuilder::new();
1110
1111        builder
1112            .new_list()
1113            .with_value("hello")
1114            .with_value(42i32)
1115            .with_value(true)
1116            .with_value(()) // null
1117            .with_value(std::f64::consts::PI)
1118            .finish();
1119
1120        let (metadata, value) = builder.finish();
1121        let variant = Variant::try_new(&metadata, &value)?;
1122        let json = variant.to_json_string()?;
1123
1124        let parsed: Value = serde_json::from_str(&json).unwrap();
1125        let arr = parsed.as_array().expect("expected JSON array");
1126        assert_eq!(arr.len(), 5);
1127        assert_eq!(arr[0], Value::String("hello".to_string()));
1128        assert_eq!(arr[1], Value::Number(42.into()));
1129        assert_eq!(arr[2], Value::Bool(true));
1130        assert_eq!(arr[3], Value::Null);
1131        assert!(matches!(arr[4], Value::Number(_)));
1132
1133        Ok(())
1134    }
1135
1136    #[test]
1137    fn test_object_field_ordering_in_json() -> Result<(), ArrowError> {
1138        use parquet_variant::VariantBuilder;
1139
1140        let mut builder = VariantBuilder::new();
1141
1142        {
1143            let mut obj = builder.new_object();
1144            // Add fields in non-alphabetical order
1145            obj.insert("zebra", "last");
1146            obj.insert("alpha", "first");
1147            obj.insert("beta", "second");
1148            obj.finish();
1149        }
1150
1151        let (metadata, value) = builder.finish();
1152        let variant = Variant::try_new(&metadata, &value)?;
1153        let json = variant.to_json_string()?;
1154
1155        // Parse and verify all fields are present
1156        let parsed: Value = serde_json::from_str(&json).unwrap();
1157        let obj = parsed.as_object().expect("expected JSON object");
1158        assert_eq!(obj.len(), 3);
1159        assert_eq!(obj.get("alpha"), Some(&Value::String("first".to_string())));
1160        assert_eq!(obj.get("beta"), Some(&Value::String("second".to_string())));
1161        assert_eq!(obj.get("zebra"), Some(&Value::String("last".to_string())));
1162
1163        Ok(())
1164    }
1165
1166    #[test]
1167    fn test_list_with_various_primitive_types_to_json() -> Result<(), ArrowError> {
1168        use parquet_variant::VariantBuilder;
1169
1170        let mut builder = VariantBuilder::new();
1171
1172        builder
1173            .new_list()
1174            .with_value("string_value")
1175            .with_value(42i32)
1176            .with_value(true)
1177            .with_value(std::f64::consts::PI)
1178            .with_value(false)
1179            .with_value(()) // null
1180            .with_value(100i64)
1181            .finish();
1182
1183        let (metadata, value) = builder.finish();
1184        let variant = Variant::try_new(&metadata, &value)?;
1185        let json = variant.to_json_string()?;
1186
1187        let parsed: Value = serde_json::from_str(&json).unwrap();
1188        let arr = parsed.as_array().expect("expected JSON array");
1189        assert_eq!(arr.len(), 7);
1190        assert_eq!(arr[0], Value::String("string_value".to_string()));
1191        assert_eq!(arr[1], Value::Number(42.into()));
1192        assert_eq!(arr[2], Value::Bool(true));
1193        assert!(matches!(arr[3], Value::Number(_))); // float
1194        assert_eq!(arr[4], Value::Bool(false));
1195        assert_eq!(arr[5], Value::Null);
1196        assert_eq!(arr[6], Value::Number(100.into()));
1197
1198        Ok(())
1199    }
1200
1201    #[test]
1202    fn test_object_with_various_primitive_types_to_json() -> Result<(), ArrowError> {
1203        use parquet_variant::VariantBuilder;
1204
1205        let mut builder = VariantBuilder::new();
1206
1207        {
1208            let mut obj = builder.new_object();
1209            obj.insert("string_field", "test_string");
1210            obj.insert("int_field", 123i32);
1211            obj.insert("bool_field", true);
1212            obj.insert("float_field", 2.71f64);
1213            obj.insert("null_field", ());
1214            obj.insert("long_field", 999i64);
1215            obj.finish();
1216        }
1217
1218        let (metadata, value) = builder.finish();
1219        let variant = Variant::try_new(&metadata, &value)?;
1220        let json = variant.to_json_string()?;
1221
1222        let parsed: Value = serde_json::from_str(&json).unwrap();
1223        let obj = parsed.as_object().expect("expected JSON object");
1224        assert_eq!(obj.len(), 6);
1225        assert_eq!(
1226            obj.get("string_field"),
1227            Some(&Value::String("test_string".to_string()))
1228        );
1229        assert_eq!(obj.get("int_field"), Some(&Value::Number(123.into())));
1230        assert_eq!(obj.get("bool_field"), Some(&Value::Bool(true)));
1231        assert!(matches!(obj.get("float_field"), Some(Value::Number(_))));
1232        assert_eq!(obj.get("null_field"), Some(&Value::Null));
1233        assert_eq!(obj.get("long_field"), Some(&Value::Number(999.into())));
1234
1235        Ok(())
1236    }
1237
1238    #[test]
1239    fn test_decimal_precision_behavior() -> Result<(), ArrowError> {
1240        // Test case that demonstrates f64 precision limits
1241        // This is a 63-bit precision decimal8 value that f64 cannot represent exactly
1242        let high_precision_decimal8 = Variant::from(VariantDecimal8::try_new(
1243            9007199254740993, // 2^53 + 1, exceeds f64 precision
1244            6,
1245        )?);
1246
1247        let json_string = high_precision_decimal8.to_json_string()?;
1248        let json_value = high_precision_decimal8.to_json_value()?;
1249
1250        // Due to f64 precision limits, we expect precision loss for values > 2^53
1251        // Both functions should produce consistent results (even if not exact)
1252        let parsed: Value = serde_json::from_str(&json_string).unwrap();
1253        assert_eq!(parsed, json_value);
1254
1255        // Test a case that can be exactly represented (integer result)
1256        let exact_decimal = Variant::from(VariantDecimal8::try_new(
1257            1234567890000, // Should result in 1234567.89 (trailing zeros trimmed)
1258            6,
1259        )?);
1260
1261        let json_string_exact = exact_decimal.to_json_string()?;
1262        assert_eq!(json_string_exact, "1234567.89");
1263
1264        // Test integer case (should be exact)
1265        let integer_decimal = Variant::from(VariantDecimal8::try_new(
1266            42000000, // Should result in 42 (integer)
1267            6,
1268        )?);
1269
1270        let json_string_integer = integer_decimal.to_json_string()?;
1271        assert_eq!(json_string_integer, "42");
1272
1273        Ok(())
1274    }
1275
1276    #[test]
1277    fn test_float_nan_inf_handling() -> Result<(), ArrowError> {
1278        // Test NaN handling - should return an error since JSON doesn't support NaN
1279        let nan_variant = Variant::Float(f32::NAN);
1280        let nan_result = nan_variant.to_json_value();
1281        assert!(nan_result.is_err());
1282        assert!(
1283            nan_result
1284                .unwrap_err()
1285                .to_string()
1286                .contains("Invalid float value")
1287        );
1288
1289        // Test positive infinity - should return an error since JSON doesn't support Infinity
1290        let pos_inf_variant = Variant::Float(f32::INFINITY);
1291        let pos_inf_result = pos_inf_variant.to_json_value();
1292        assert!(pos_inf_result.is_err());
1293        assert!(
1294            pos_inf_result
1295                .unwrap_err()
1296                .to_string()
1297                .contains("Invalid float value")
1298        );
1299
1300        // Test negative infinity - should return an error since JSON doesn't support -Infinity
1301        let neg_inf_variant = Variant::Float(f32::NEG_INFINITY);
1302        let neg_inf_result = neg_inf_variant.to_json_value();
1303        assert!(neg_inf_result.is_err());
1304        assert!(
1305            neg_inf_result
1306                .unwrap_err()
1307                .to_string()
1308                .contains("Invalid float value")
1309        );
1310
1311        // Test the same for Double variants
1312        let nan_double_variant = Variant::Double(f64::NAN);
1313        let nan_double_result = nan_double_variant.to_json_value();
1314        assert!(nan_double_result.is_err());
1315        assert!(
1316            nan_double_result
1317                .unwrap_err()
1318                .to_string()
1319                .contains("Invalid double value")
1320        );
1321
1322        let pos_inf_double_variant = Variant::Double(f64::INFINITY);
1323        let pos_inf_double_result = pos_inf_double_variant.to_json_value();
1324        assert!(pos_inf_double_result.is_err());
1325        assert!(
1326            pos_inf_double_result
1327                .unwrap_err()
1328                .to_string()
1329                .contains("Invalid double value")
1330        );
1331
1332        let neg_inf_double_variant = Variant::Double(f64::NEG_INFINITY);
1333        let neg_inf_double_result = neg_inf_double_variant.to_json_value();
1334        assert!(neg_inf_double_result.is_err());
1335        assert!(
1336            neg_inf_double_result
1337                .unwrap_err()
1338                .to_string()
1339                .contains("Invalid double value")
1340        );
1341
1342        // Test normal float values still work
1343        let normal_float = Variant::Float(std::f32::consts::PI);
1344        let normal_result = normal_float.to_json_value()?;
1345        assert!(matches!(normal_result, Value::Number(_)));
1346
1347        let normal_double = Variant::Double(std::f64::consts::E);
1348        let normal_double_result = normal_double.to_json_value()?;
1349        assert!(matches!(normal_double_result, Value::Number(_)));
1350
1351        Ok(())
1352    }
1353}