Skip to main content

qubit_json/value/
duplicate_key_rejecting_json_value.rs

1// =============================================================================
2//    Copyright (c) 2026 Haixing Hu.
3//
4//    SPDX-License-Identifier: Apache-2.0
5//
6//    Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Deserializes JSON values while rejecting duplicate object keys.
9
10use serde::Deserialize;
11use serde::Deserializer;
12use serde::de::DeserializeSeed;
13use serde_json::Value;
14
15mod duplicate_key_rejecting_json_value_seed;
16mod internal;
17
18pub use duplicate_key_rejecting_json_value_seed::DuplicateKeyRejectingJsonValueSeed;
19
20/// A JSON value whose deserialization rejects duplicate object keys.
21///
22/// This wrapper is useful for document formats where accepting the usual
23/// last-key-wins object behavior would make the input ambiguous. Native `i64`,
24/// `u64`, and finite `f64` events retain their numeric representation. If an
25/// upstream deserializer exposes an arbitrary-precision number as map events,
26/// this wrapper treats those events as an ordinary object because it cannot
27/// determine their provenance. Lexical admission by
28/// [`crate::decode::JsonDecoder`] does not change the subsequent Serde event
29/// representation. See `doc/number_contract.md` in the repository for the
30/// numeric contract.
31/// Use [`crate::decode::JsonDecoder::decode_unique_str`] for owned JSON text
32/// decoding that preserves native numbers under feature unification.
33///
34/// # Examples
35///
36/// ```
37/// use qubit_json::value::DuplicateKeyRejectingJsonValue;
38///
39/// let value: DuplicateKeyRejectingJsonValue = serde_json::from_str(r#"{"ok":true}"#)?;
40/// assert_eq!(value.into_inner()["ok"], true);
41/// # Ok::<(), serde_json::Error>(())
42/// ```
43#[derive(Debug, PartialEq)]
44pub struct DuplicateKeyRejectingJsonValue(
45    /// Fully materialized value that passed duplicate-key validation.
46    Value,
47);
48
49impl DuplicateKeyRejectingJsonValue {
50    /// Returns the validated JSON value.
51    ///
52    /// # Returns
53    ///
54    /// The owned serde_json value constructed during deserialization.
55    #[must_use]
56    #[inline(always)]
57    pub fn into_inner(self) -> Value {
58        self.0
59    }
60}
61
62impl<'de> Deserialize<'de> for DuplicateKeyRejectingJsonValue {
63    /// Deserializes JSON recursively while rejecting duplicate object keys.
64    ///
65    /// # Errors
66    ///
67    /// Returns the deserializer's error if the input is invalid or an object
68    /// contains a duplicate key.
69    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
70    where
71        D: Deserializer<'de>,
72    {
73        DuplicateKeyRejectingJsonValueSeed::new().deserialize(deserializer)
74    }
75}