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}