qubit-json 0.12.2

Resource-aware infrastructure for lenient and strict JSON processing
Documentation
// =============================================================================
//    Copyright (c) 2026 Haixing Hu.
//
//    SPDX-License-Identifier: Apache-2.0
//
//    Licensed under the Apache License, Version 2.0.
// =============================================================================
//! Deserializes JSON values while rejecting duplicate object keys.

use serde::Deserialize;
use serde::Deserializer;
use serde::de::DeserializeSeed;
use serde_json::Value;

mod duplicate_key_rejecting_json_value_seed;
mod internal;

pub use duplicate_key_rejecting_json_value_seed::DuplicateKeyRejectingJsonValueSeed;

/// A JSON value whose deserialization rejects duplicate object keys.
///
/// This wrapper is useful for document formats where accepting the usual
/// last-key-wins object behavior would make the input ambiguous. Native `i64`,
/// `u64`, and finite `f64` events retain their numeric representation. If an
/// upstream deserializer exposes an arbitrary-precision number as map events,
/// this wrapper treats those events as an ordinary object because it cannot
/// determine their provenance. Lexical admission by
/// [`crate::decode::JsonDecoder`] does not change the subsequent Serde event
/// representation. See `doc/number_contract.md` in the repository for the
/// numeric contract.
/// Use [`crate::decode::JsonDecoder::decode_unique_str`] for owned JSON text
/// decoding that preserves native numbers under feature unification.
///
/// # Examples
///
/// ```
/// use qubit_json::value::DuplicateKeyRejectingJsonValue;
///
/// let value: DuplicateKeyRejectingJsonValue = serde_json::from_str(r#"{"ok":true}"#)?;
/// assert_eq!(value.into_inner()["ok"], true);
/// # Ok::<(), serde_json::Error>(())
/// ```
#[derive(Debug, PartialEq)]
pub struct DuplicateKeyRejectingJsonValue(
    /// Fully materialized value that passed duplicate-key validation.
    Value,
);

impl DuplicateKeyRejectingJsonValue {
    /// Returns the validated JSON value.
    ///
    /// # Returns
    ///
    /// The owned serde_json value constructed during deserialization.
    #[must_use]
    #[inline(always)]
    pub fn into_inner(self) -> Value {
        self.0
    }
}

impl<'de> Deserialize<'de> for DuplicateKeyRejectingJsonValue {
    /// Deserializes JSON recursively while rejecting duplicate object keys.
    ///
    /// # Type Parameters
    ///
    /// * `D` is the deserializer that supplies the JSON data and error type.
    ///
    /// # Parameters
    ///
    /// * `deserializer` supplies the JSON data to validate and materialize.
    ///
    /// # Errors
    ///
    /// Returns the deserializer's error if the input is invalid or an object
    /// contains a duplicate key.
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        DuplicateKeyRejectingJsonValueSeed::new().deserialize(deserializer)
    }
}