{"record":{"id":"b18d60e855e3ae74","repo":"nautechsystems/nautilus_trader","slug":"data-type-must-be-a-json-object","errorCode":null,"errorMessage":"data_type must be a JSON object","messagePattern":"data_type must be a JSON object","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/data/mod.rs","lineNumber":808,"sourceCode":"                \"identifier\".to_string(),\n                serde_json::Value::String(id.clone()),\n            );\n        }\n        serde_json::to_string(&serde_json::Value::Object(map))\n    }\n\n    /// Deserializes from JSON produced by `to_persistence_json`.\n    /// Accepts legacy JSON with `topic` (ignored); topic is rebuilt from `type_name` + metadata.\n    ///\n    /// # Errors\n    ///\n    /// Returns an error if the string is not valid JSON or missing required fields.\n    pub fn from_persistence_json(s: &str) -> Result<Self, anyhow::Error> {\n        let value: serde_json::Value =\n            serde_json::from_str(s).map_err(|e| anyhow::anyhow!(\"Invalid data_type JSON: {e}\"))?;\n        let obj = value\n            .as_object()\n            .ok_or_else(|| anyhow::anyhow!(\"data_type must be a JSON object\"))?;\n        let type_name = obj\n            .get(\"type_name\")\n            .and_then(|v| v.as_str())\n            .ok_or_else(|| anyhow::anyhow!(\"data_type must have type_name\"))?;\n        let metadata = obj.get(\"metadata\").and_then(|m| {\n            if m.is_null() {\n                None\n            } else {\n                let p: Params = serde_json::from_value(m.clone()).ok()?;\n                if p.is_empty() { None } else { Some(p) }\n            }\n        });\n        let identifier = obj\n            .get(\"identifier\")\n            .and_then(|v| v.as_str())\n            .map(String::from);\n        Ok(Self::new(type_name, metadata, identifier))\n    }","sourceCodeStart":790,"sourceCodeEnd":826,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/data/mod.rs#L790-L826","documentation":"After the JSON parses, `from_persistence_json` requires the top-level value to be a JSON object (a map of fields for the DataType). If the string parses to a scalar, array, or null instead, this error is raised.","triggerScenarios":"Passing JSON like `\"SomeType\"`, `[\"a\",\"b\"]`, `123`, or `null` to `DataType::from_persistence_json` — anything that is valid JSON but not an object.","commonSituations":"Persisting only the type_name string and trying to reload it as a full DataType; a serialization change between versions that wrote arrays/scalars; slicing the wrong portion of a JSON document.","solutions":["Ensure the persisted form is a full object: `{\"type_name\": \"...\", \"metadata\": {...}}`, not just the type name.","Re-persist the DataType with the current library's serializer so the on-disk format matches.","Check that you're loading the whole record and not an inner field of it.","Validate the parsed value's shape before calling, e.g. `serde_json::from_str::<serde_json::Value>(s)?.is_object()`."],"exampleFix":"// before\nlet dt = DataType::from_persistence_json(r#\"\"QuoteTick\"\"#)?;\n\n// after\nlet dt = DataType::from_persistence_json(r#\"{\"type_name\": \"QuoteTick\"}\"#)?;","handlingStrategy":"type-guard","validationCode":"fn is_object_json(s: &str) -> bool {\n    serde_json::from_str::<serde_json::Value>(s).map(|v| v.is_object()).unwrap_or(false)\n}","typeGuard":"fn as_datatype_object(v: &serde_json::Value) -> Option<&serde_json::Map<String, serde_json::Value>> {\n    v.as_object()\n}","tryCatchPattern":null,"preventionTips":["Always serialize the full DataType object, not just its type name string.","Round-trip test your persistence format across versions.","Validate the parsed shape before handing the string to from_persistence_json."],"tags":["rust","json","schema","persistence"],"backgroundTag":"schema-validation-failed","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T00:17:10.932Z"}