HashMap<String, T> for Dynamic JSON Keys

Use HashMap<String, T> when JSON object keys are not known in advance. Covers serde_json::Value, typed maps, and BTreeMap alternatives.

Type Mapping

Detailed Explanation

Handling Dynamic Keys with HashMap

When a JSON object's keys are not known at compile time — feature flags, metric names, dynamic labels — you cannot define a struct. Instead, use HashMap<String, T>.

Example JSON

{
  "metrics": {
    "cpu_usage": 72.5,
    "memory_usage": 85.3,
    "disk_io": 45.1
  },
  "labels": {
    "env": "production",
    "region": "us-east-1"
  }
}

Recommended Rust

use std::collections::HashMap;

#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct Root {
    pub metrics: HashMap<String, f64>,
    pub labels: HashMap<String, String>,
}

The auto-converter cannot infer that an object should be a HashMap from a single sample. After pasting, replace the generated nested struct with HashMap<String, T> when you know the keys are dynamic.

Mixed value types

If values have different types ({ "theme": "dark", "fontSize": 14 }), use HashMap<String, serde_json::Value> and pattern-match on the variant at runtime:

match settings.get("theme") {
    Some(serde_json::Value::String(s)) => println!("Theme: {}", s),
    _ => {}
}

Ordered iteration

HashMap iteration order is unspecified. If you need deterministic output (for diffing, snapshot testing, or stable CLI output), use BTreeMap<String, T> instead — it iterates in sorted key order with the same serde derive support.

When to prefer a struct

If the same set of keys always appears, define a struct. Maps are slower at runtime, lose autocomplete, and bypass compile-time checks. Reach for HashMap only when the keys really do vary.

Use Case

Monitoring dashboards, feature flag systems, and Kubernetes-style label maps return arbitrary key/value pairs. Modeling them as HashMap lets you ingest the data without an explosion of one-off struct definitions.

Try It — JSON to Rust Struct Converter

Open full tool