Skip to main content

ValueGetExt

Trait ValueGetExt 

Source
pub trait ValueGetExt {
    // Required methods
    fn get_i64(&self, key: &str) -> Option<i64>;
    fn get_str(&self, key: &str) -> Option<&str>;
    fn get_array(&self, key: &str) -> Option<&Vec<Value>>;
    fn get_bool(&self, key: &str) -> Option<bool>;
}
Expand description

Substrate extension trait over serde_json::Value — the ONE substrate owner of the paired .get(<key>).and_then(|v| v.as_<T>()) two-link READ chain every downstream projection walks to pull a typed leaf off a Kubernetes-status blob (or an equivalent rendered-resource JSON object) without asserting the slot is present, without asserting its variant, and without asserting the slot fits the target scalar type.

The trait carries ONE method per typed READ axis; the axis-family is Self::get_i64 (integer counters) + Self::get_str (string slots) + Self::get_array (JSON array slots) + Self::get_bool (boolean flags). Adding a further axis (a get_object for Value::Object, a get_f64 for Value::Number truncated to f64) lands as ONE new method here

  • ONE impl arm per receiver shape, inheriting the naming, #[must_use], and inline discipline the existing axes pin. Never open a peer trait for a new axis — keep every READ projection on the ONE substrate owner so a caller who imports ValueGetExt reaches every axis through the same trait handle.

READ-side counterpart to the three MUTATION-side siblings already in this module — ValueObjectExt::as_object_mut_or, JsonMapStrExt::insert_str, JsonMapObjectEntryExt::object_slot_mut_or — partitioning the substrate along the (read, mutate) axis on the same serde_json::Value / serde_json::Map<String, Value> carrier pair.

Pre-lift the two-link chain was hand-authored at THREE adjacent slots inside tatara-reconciler::boundary::fetch_job_status, each projecting one batch/v1::Job status.<counter> field out of the fetched serde_json::Value object into a private JobStatusView row past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold:

  • status.get("succeeded").and_then(|v| v.as_i64()) — the Job-completion counter every JobAttested + ClosedLoopAuth postcondition evaluator gates on (succeeded < 1 short-circuits to Satisfaction::Unsatisfied("… still running (…)")).
  • status.get("failed").and_then(|v| v.as_i64()) — the Job-failure counter the same evaluators gate on (failed > 0 short-circuits to Satisfaction::Unsatisfied("… failed (status.failed={n})")).
  • status.get("active").and_then(|v| v.as_i64()) — the Job-in-flight counter the “still running” diagnostic tail reports as (succeeded={s}, active={a}).

All THREE sites walked the SAME two-link chain — .get(<key>) on a serde_json::Value already known to be the status object, then .and_then(|v| v.as_i64()) on the returned Option<&Value> — and each was followed by an if let Some(...) write into the [JobStatusView] row initialised from Default::default(). Post- lift each callsite reads status.get_i64(<key>) and the two-link READ chain lives at ONE substrate owner here.

§Naming — get_i64, not as_i64 or i64_at

Same discipline as the three sibling traits above — the trait method deliberately does NOT collide with serde_json::Value::as_i64 (the inherent projection on a single Value handle) nor with serde_json::Value::get (the inherent slot-lookup returning Option<&Value>). A name collision would let a caller who has ValueGetExt in scope resolve to one of the inherent methods by accident (inherent methods win over trait methods in method resolution) and silently drop half of the paired chain. The get_i64(<key>) shape names the intent: look up the slot at <key>, project the returned handle to i64, in ONE call.

§#[must_use]

Every consumer either binds the returned Option<i64> into a downstream if let Some(n) = ... / .unwrap_or_default() / struct- field construction. Dropping the return silently discards the projection entirely, which is never the intended semantic at the three pre-lift consumers (each downstream write depends on the returned counter).

§Composability

  • Key slot is &str — matches every pre-lift .get("<literal>") callsite and the inherent serde_json::Value::get’s primary str-index arm. A caller with a runtime-computed key (a String produced by a template composer) reaches through .get_i64(&s) mechanically via Deref<Target = str>.
  • Returns Option<i64> matching the composed inherent chain’s own return; a consumer wanting the “absent or non-integer → 0” fallback composes .unwrap_or_default() (or .unwrap_or(0)) at the callsite, keeping the “should this counter default to 0 or fail loud” decision at the caller rather than baking it into the primitive.
  • Non-object receivers (a Value::String, a Value::Null) return None verbatim via the inherent Value::get’s own non-object- arm behaviour, matching the pre-lift chain’s semantics on the corner where the caller’s status blob is malformed.

A future normalization — a per-fleet clamp that rejects negative counters (the K8s API server never emits them, but a fixture authoring bug could), a Value::Number fallback that accepts f64 counters truncated to i64, a checked overflow arm that promotes an out-of-range integer to a diagnostic rather than a silent None — lands at THIS ONE substrate primitive and every downstream Job-status / Deployment-replica / HPA-desired-count counter reader inherits the upgrade mechanically. No per-site edit at any of the 3 listed callers or at future consumers (a Deployment readyReplicas projection, an HPA currentReplicas gate, a StatefulSet updatedReplicas freshness check).

Theory anchor: THEORY.md §VI.1 (generation over composition — the two-link .get(<key>).and_then(|v| v.as_i64()) chain recurred at three hand-authored sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger, and is lifted to ONE substrate owner here). THEORY.md §II.1 invariant 5 (composition preserves proofs — a regression that drifted the projection axis at ONE site — a swap of as_i64 for as_u64 narrowing the accepted range, a swap of .get(<key>) for .pointer("<key>") losing the direct-child semantics — would silently pass every downstream JobStatusView composition and surface as a wrong counter at operator-facing diagnostic wording; post-lift the projection lives at ONE typed owner so a regression surfaces at [tests::get_i64_null_arm_returns_none] / peers rather than as silent operator-facing drift).

Required Methods§

Source

fn get_i64(&self, key: &str) -> Option<i64>

Look up key on this JSON object and project the returned handle to i64; returns None when the slot is absent, when the receiver is not a JSON object, or when the slot’s variant is not integer-shaped.

Source

fn get_str(&self, key: &str) -> Option<&str>

Look up key on this JSON object and project the returned handle to &str; returns None when the slot is absent, when the receiver is not a JSON object, or when the slot’s variant is not Value::String.

String-axis sibling of Self::get_i64 on the same .get(<key>).and_then(|v| v.as_<T>()) READ-chain lift. Pre-lift the two-link chain was hand-authored at SEVEN production sites across two crates past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold:

  • tatara-process::status::RenderedResourceCoords::from_json — FOUR paired reads (apiVersion, kind, metadata.name, metadata.namespace) that project the four rendered-resource coordinate slots off a serde_json::Value rendered manifest into the typed RenderedResourceCoords row; the required three (apiVersion / kind / metadata.name) compose with .ok_or_else(|| anyhow!("rendered resource missing X"))? .to_string(), and the optional metadata.namespace composes with .map(str::to_string).
  • tatara-reconciler::ssapply::ready_condition_value — THREE paired reads (type, status, message) inside the condition-walker’s per-condition classifier, each pulling a Value::String slot off a K8s Condition object off the status.conditions[] array.

All seven sites walked the SAME two-link chain — .get(<key>) on a serde_json::Value already known to be an object, then .and_then(|v| v.as_str()) on the returned Option<&Value> — and each composed different downstream tails (fallible .ok_or_else(...)?.to_string(), optional .map(String::from), pattern-match Some("True") / Some("False") / _). Post-lift each callsite reads <value>.get_str(<key>) and the two-link READ chain lives at ONE substrate owner here.

§Naming — get_str, not as_str or str_at

Same discipline as Self::get_i64 — the trait method deliberately does NOT collide with serde_json::Value::as_str (the inherent projection on a single Value handle) nor with serde_json::Value::get (the inherent slot-lookup returning Option<&Value>). A name collision would let a caller who has ValueGetExt in scope resolve to one of the inherent methods by accident (inherent methods win over trait methods in method resolution) and silently drop half of the paired chain. The get_str(<key>) shape names the intent: look up the slot at <key>, project the returned handle to &str, in ONE call.

§#[must_use]

Every pre-lift consumer binds the returned Option<&str> into a downstream .ok_or_else(...)?.to_string() / .map(String::from) / .map(str::to_string) / pattern-match arm. Dropping the return silently discards the projection entirely, which is never the intended semantic at any of the seven pre-lift consumers.

§Return lifetime

The &str borrows the same buffer the underlying Value::String variant owns; the Option<&str> is bounded by the receiver’s lifetime (&'_ self), so a caller holding onto the returned slice keeps the receiver borrowed. Matches the pre-lift chain’s own borrow shape (v.as_str() borrows through the &Value).

A future normalization on the projection — a Unicode normalization pass (NFC-folding annotation values), a per-fleet trim of leading/trailing whitespace, a rejection of empty-string arms as “the caller meant absent” — lands at THIS ONE substrate primitive and every downstream apiVersion / kind / metadata.name / K8s-condition-string reader inherits the upgrade mechanically.

Theory anchor: THEORY.md §VI.1 (generation over composition — the two-link .get(<key>).and_then(|v| v.as_str()) chain recurred at SEVEN production sites across two crates past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger, and is lifted to ONE substrate owner here on the string axis of the same READ-chain axis-family the get_i64 sibling opened for the integer axis). THEORY.md §II.1 invariant 5 (composition preserves proofs — a regression that drifted the projection axis at ONE site would silently pass every downstream composition and surface as a wrong slot at operator-facing diagnostic wording; post-lift the projection lives at ONE typed owner so a regression surfaces at [tests::get_str_present_string_slot_returns_the_slice] / peers rather than as silent operator-facing drift).

Source

fn get_array(&self, key: &str) -> Option<&Vec<Value>>

Look up key on this JSON object and project the returned handle to &Vec<Value>; returns None when the slot is absent, when the receiver is not a JSON object, or when the slot’s variant is not Value::Array.

Array-axis sibling of Self::get_i64 + Self::get_str on the same .get(<key>).and_then(|v| v.as_<T>()) READ-chain axis-family. Pre-lift the two-link chain was hand-authored at TWO production sites across two crates past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold:

  • tatara-reconciler::ssapply::ready_condition_value — the tail of the data.get("status").and_then(|s| s.get("conditions")).and_then(|c| c.as_array()) walker that opens the K8s Condition classifier every DynamicObject readiness probe rides through.
  • tatara-closed-loop-probe::probe::count_jwks_keys — the JWKS-response walker that counts issuer-side public keys off the keys slot for the closed-loop probe’s per-run jwks_key_count diagnostic.

Both sites walked the SAME two-link chain — .get(<key>) on a serde_json::Value already known to be an object, then .and_then(|v| v.as_array()) on the returned Option<&Value> — and composed different downstream tails (Some(conditions) pattern-match on the reconciler side, .map(|xs| xs.len() as u64) on the probe side). Post-lift each callsite reads <value>.get_array(<key>) and the two-link READ chain lives at ONE substrate owner here. The probe-side variant additionally sheds the pre-lift .get("keys").cloned() allocation because this primitive borrows through the receiver rather than cloning.

§Naming — get_array, not as_array or array_at

Same discipline as Self::get_i64 + Self::get_str — the trait method deliberately does NOT collide with serde_json::Value::as_array (the inherent projection on a single Value handle) nor with serde_json::Value::get (the inherent slot-lookup returning Option<&Value>). A name collision would let a caller who has ValueGetExt in scope resolve to one of the inherent methods by accident (inherent methods win over trait methods in method resolution) and silently drop half of the paired chain. The get_array(<key>) shape names the intent: look up the slot at <key>, project the returned handle to &Vec<Value>, in ONE call.

§#[must_use]

Every pre-lift consumer binds the returned Option<&Vec<Value>> into a downstream let Some(...) = ... else { return ... } short-circuit or a .map(|xs| xs.len() as u64).unwrap_or(0) counter composition. Dropping the return silently discards the projection entirely, which is never the intended semantic at either pre-lift consumer.

§Return lifetime

The &Vec<Value> borrows the same buffer the underlying Value::Array variant owns; the Option<&Vec<Value>> is bounded by the receiver’s lifetime (&'_ self), so a caller iterating the returned slice keeps the receiver borrowed. Matches the pre-lift chain’s own borrow shape (v.as_array() borrows through the &Value), and in the probe.rs case eliminates the pre-lift .cloned() on the intermediate Value that only existed to sidestep the borrow.

A future normalization on the projection — a rejection of empty arrays as “the caller meant absent”, an accept-scalar coercion (a Value::String promoted to a one-element array), a per-fleet cap on array length that short-circuits pathological payloads — lands at THIS ONE substrate primitive and every downstream K8s-Condition classifier / JWKS-array counter / future array-slot reader inherits the upgrade mechanically.

Theory anchor: THEORY.md §VI.1 (generation over composition — the two-link .get(<key>).and_then(|v| v.as_array()) chain recurred at two production sites across two crates past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger, and is lifted to ONE substrate owner here on the array axis of the same READ-chain axis-family the get_i64 + get_str siblings already own). THEORY.md §II.1 invariant 5 (composition preserves proofs — a regression that drifted the projection axis at ONE site would silently pass every downstream composition and surface as a wrong slot at operator-facing diagnostic wording; post-lift the projection lives at ONE typed owner so a regression surfaces at [tests::get_array_present_array_slot_returns_the_slice] / peers rather than as silent operator-facing drift).

Source

fn get_bool(&self, key: &str) -> Option<bool>

Look up key on this JSON object and project the returned handle to bool; returns None when the slot is absent, when the receiver is not a JSON object, or when the slot’s variant is not Value::Bool.

Boolean-axis sibling of Self::get_i64 / Self::get_str / Self::get_array on the same .get(<key>).and_then(|v| v.as_<T>()) READ-chain axis-family. Completes the axis-family coverage over the four most-common Value scalar / collection shapes an operator reads out of a K8s status / spec blob or a rendered-resource JSON object: integer counter (succeeded, failed, active, replicas), string slot (apiVersion, kind, metadata.name, type, status, message), array slot (conditions, finalizers, keys), and boolean flag (controller, blockOwnerDeletion, spec.suspended, hostNetwork, automountServiceAccountToken, identity.name_override).

The axis was named as the next extension point in the ValueGetExt docstring’s own guidance (“Adding a new axis (a get_bool for Value::Bool, …) lands as ONE new method here + ONE impl arm”), and this method opens it. A future consumer walking a blockOwnerDeletion / controller bit off a K8s OwnerReference JSON, an identity.name_override flag off a phase_status_with(phase, "identity", …) patch body, or a spec.suspended gate off a SIGSTOP-driven spec toggle reaches this substrate rather than re-authoring the two-link .get(<key>).and_then(|v| v.as_bool()) chain by hand.

§Naming — get_bool, not as_bool or bool_at

Same discipline as the three sibling axes — the trait method deliberately does NOT collide with serde_json::Value::as_bool (the inherent projection on a single Value handle) nor with serde_json::Value::get (the inherent slot-lookup returning Option<&Value>). A name collision would let a caller who has ValueGetExt in scope resolve to one of the inherent methods by accident (inherent methods win over trait methods in method resolution) and silently drop half of the paired chain. The get_bool(<key>) shape names the intent: look up the slot at <key>, project the returned handle to bool, in ONE call.

§#[must_use]

Every consumer either binds the returned Option<bool> into a downstream if let Some(b) = ... gate, a .unwrap_or_default() / .unwrap_or(false) fallback, or a pattern-match arm. Dropping the return silently discards the projection entirely, which is never the intended semantic at any downstream boolean-flag consumer.

§Composability
  • Key slot is &str — matches the sibling axes verbatim; &'static str literals and runtime-composed String handles both coerce.
  • Returns Option<bool> matching the composed inherent chain’s own return; a consumer wanting the “absent or non-bool → false” fallback composes .unwrap_or_default() (or .unwrap_or(false)) at the callsite, keeping the “should this flag default to false or fail loud” decision at the caller rather than baking it into the primitive.
  • Non-object receivers (a Value::String, a Value::Null) return None verbatim via the inherent Value::get’s own non-object-arm behaviour, matching the pre-lift chain’s semantics on the corner where the caller’s status blob is malformed.

A future normalization on the projection — a stricter Value::String("true") / Value::String("false") coercion for K8s wire-form drift (K8s occasionally serialises booleans as stringified values in edge cases), a per-fleet default policy for the absent-slot corner, a checked corner that fails loud on Value::Number(0) / Value::Number(1) coercion attempts — lands at THIS ONE substrate primitive and every downstream boolean-flag reader inherits the upgrade mechanically. No per-site edit at any consumer that adopts this primitive.

Theory anchor: THEORY.md §II.1 invariant 5 (composition preserves proofs — the projection lives at ONE typed owner on the same axis-family the three sibling axes already open; a regression that drifted the projection axis at ONE site would silently pass every downstream composition and surface as a wrong flag at operator-facing gate wording). THEORY.md §III (typescape — the axis-family completes coverage over the four most-common Value shapes any K8s status / spec / manifest reader projects, so a caller who imports ValueGetExt reaches integer counters, string slots, array slots, AND boolean flags through ONE trait handle).

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementations on Foreign Types§

Source§

impl ValueGetExt for Map<String, Value>

Receiver-shape widening of the READ-projection axis-family — the same three methods extended from Value (the Value::Object arm’s walker) to Map<String, Value> (the object interior itself), closing the receiver-shape gap so a caller who already holds an &Map<String, Value> handle (via .as_object().unwrap(), via ValueObjectExt::as_object_mut_or, via the two JsonMap*Ext siblings’ returns, or via a helper like ssapply::ownership_kv_pair that composes and returns a Map directly) reaches the SAME get_i64 / get_str / get_array methods without a Value::Object(m) rewrap detour.

Pre-lift the .get(<key>).and_then(Value::as_<T>) two-link chain was hand-authored at 30 Map<String, Value>-receiver sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold — 19 in tatara-reconciler::patch tests (the phase-status wire-shape pins walking obj = v.as_object().unwrap() and metadata = obj.get( "metadata").and_then(Value::as_object).unwrap() receivers) plus 11 in tatara-reconciler::ssapply tests (the ownership-tag + composed-coord pins walking the Map handles returned by ownership_annotations / ownership_labels / ownership_annotations_by_coord). Post-lift each callsite reads <map>.get_str(<key>) / <map>.get_array(<key>) and the READ chain rides through the SAME substrate owner the Value-receiver callers already threaded through.

The axis-family invariant (a caller who imports ValueGetExt reaches every axis through the same trait handle — pinned at [tests::get_array_axis_family_reaches_i64_str_and_array_through_one_trait_import], its get_str sibling, and the fourth-axis sibling [tests::get_bool_axis_family_reaches_i64_str_array_and_bool_through_one_trait_import]) extends verbatim to the Map receiver: a single use tatara_process::json_object::ValueGetExt; unlocks every axis on both receiver shapes. A future new axis (e.g. a get_object for Value::Object slots, a get_f64 for Value::Number truncated to f64) adds one method on the trait and inherits both impls; there is no separate MapGetExt peer to keep in sync.

Theory anchor: THEORY.md §VI.1 (generation over composition — the two-link chain recurred at 30 Map-receiver sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger, and rides through the same substrate owner the pre-existing Value-receiver impl above already pinned). THEORY.md §II.1 invariant 5 (composition preserves proofs — the receiver-shape widening carries the axis-family invariant across without splitting it into two traits).

Source§

fn get_i64(&self, key: &str) -> Option<i64>

Source§

fn get_str(&self, key: &str) -> Option<&str>

Source§

fn get_array(&self, key: &str) -> Option<&Vec<Value>>

Source§

fn get_bool(&self, key: &str) -> Option<bool>

Source§

impl ValueGetExt for Option<&Value>

Receiver-shape widening of the READ-projection axis-family — the same four methods extended from Value / Map<String, Value> to Option<&Value>, closing the outer-optionality gap so a caller who has already threaded an inherent Value::get(<key>) → Option<&Value> walk into a nested slot (or otherwise holds an Option<&Value> from a prior projection) reaches the SAME get_i64 / get_str / get_array / get_bool methods through the SAME trait handle without an intermediate .and_then(|v| v.get_<T>(<key>)) closure.

Pre-lift the <opt>.and_then(|v| v.get_<T>(<key>)) outer- optionality closure was hand-authored at THREE production callsites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication threshold:

  • tatara-process::status::RenderedResourceCoords::from_json — the metadata.and_then(|m| m.get_str("namespace")) walk that projects the optional metadata.namespace slot off a rendered manifest’s metadata handle (metadata: Option<&Value>, since a K8s manifest MAY omit the metadata slot altogether — a cluster- scoped resource, a template-authored intermediate spec).
  • tatara-process::status::RenderedResourceCoords::required_str — the private required-extract helper’s v.and_then(|x| x.get_str(key)) walk (v: Option<&Value>), the sink every apiVersion / kind / metadata.name required extract fans through.
  • tatara-reconciler::ssapply::ready_condition_value — the data.get("status").and_then(|s| s.get_array("conditions")) walk that opens the K8s Condition classifier every DynamicObject readiness probe rides through; the outer Option<&Value> comes from the inherent Value::get("status") step.

All three sites walked the SAME .and_then(|<v>| <v>.get_<T> (<key>)) closure shape, differing only in the axis (get_str at two sites, get_array at the third), the slot name, and the closure-argument binding. Post-lift each callsite reads <opt> .get_<T>(<key>) and the outer-optionality unwrap-then-project lives at ONE substrate owner here — the closure disappears, the method-call surface stays identical to the two pre-existing receiver-shape impls.

§Composability
  • Chains directly off an inherent Value::get(<key>) step — data.get("status").get_array("conditions") reads as one left-to-right walk, no nested closure.
  • Composes bytewise with the pre-lift .and_then(|v| v.get_<T> (<key>)) chain — the impl body IS (*self).and_then(|v| v.get_<T>(key)), so the returned Option is bit-for-bit what the pre-lift closure produced.
  • Option<&Value> is Copy (every &T is Copy, so Option<&Value>: Copy), so the (*self) deref inside the impl is a bare bitwise copy — no clone, no additional allocation.
§Return lifetime

The returned Option<&str> / Option<&Vec<Value>> borrows through the underlying &Value handle that lived inside the outer Option; the lifetime is bounded by &self (elided per the trait method signatures), matching the two pre-existing receiver impls. A caller that consumes the borrow before the outer Option<&Value> handle expires sees no observable difference in borrow scope from the pre-lift .and_then(|v| v.get_<T>(<key>)) chain.

§Axis-family invariant

The axis-family invariant carries verbatim from the two pre-existing impls: a single use tatara_process::json_object::ValueGetExt; unlocks every axis (get_i64 / get_str / get_array / get_bool) on all three receiver shapes (Value, Map<String, Value>, Option<&Value>). A future new axis (get_object for Value::Object slots, get_f64 for Value::Number truncated to f64) adds ONE method on the trait and inherits all three impls; there is no separate OptGetExt peer to keep in sync. Pinned at [tests::option_ref_value_axis_family_reaches_all_four_axes_through_one_trait_import].

Theory anchor: THEORY.md §VI.1 (generation over composition — the outer-optionality .and_then(|v| v.get_<T>(<key>)) closure recurred at three production sites past the ★★ PRIME-DIRECTIVE ≥ 2 duplication trigger, and is lifted to ONE substrate owner here). THEORY.md §II.1 invariant 5 (composition preserves proofs — the receiver-shape widening carries the axis-family invariant across without splitting it into two traits; a regression that specialised one axis at ONE receiver but not the other would silently split the three receiver shapes’ behaviour and break the “widening preserves semantics” invariant at [tests::option_ref_value_get_str_matches_value_arm_bytewise_when_some] and its per-axis peers).

Source§

fn get_i64(&self, key: &str) -> Option<i64>

Source§

fn get_str(&self, key: &str) -> Option<&str>

Source§

fn get_array(&self, key: &str) -> Option<&Vec<Value>>

Source§

fn get_bool(&self, key: &str) -> Option<bool>

Source§

impl ValueGetExt for Value

Source§

fn get_i64(&self, key: &str) -> Option<i64>

Source§

fn get_str(&self, key: &str) -> Option<&str>

Source§

fn get_array(&self, key: &str) -> Option<&Vec<Value>>

Source§

fn get_bool(&self, key: &str) -> Option<bool>

Implementors§