{"record":{"id":"2d6c9f19872e4782","repo":"pola-rs/polars","slug":"expr-str-json-decode-needs-an-explicitly-given","errorCode":null,"errorMessage":"`Expr.str.json_decode` needs an explicitly given `dtype` otherwise Polars is not able to determine the output type. If you want to eagerly infer datatype you can use `Series.str.json_decode`.","messagePattern":"`Expr\\.str\\.json_decode` needs an explicitly given `dtype` otherwise Polars is not able to determine the output type\\. If you want to eagerly infer datatype you can use `Series\\.str\\.json_decode`\\.","errorType":"exception","errorClass":"TypeError","httpStatus":null,"severity":"error","filePath":"py-polars/src/polars/expr/string.py","lineNumber":1351,"sourceCode":"        >>> df = pl.DataFrame(\n        ...     {\"json\": ['{\"a\":1, \"b\": true}', None, '{\"a\":2, \"b\": false}']}\n        ... )\n        >>> dtype = pl.Struct([pl.Field(\"a\", pl.Int64), pl.Field(\"b\", pl.Boolean)])\n        >>> df.with_columns(decoded=pl.col(\"json\").str.json_decode(dtype))\n        shape: (3, 2)\n        ┌─────────────────────┬───────────┐\n        │ json                ┆ decoded   │\n        │ ---                 ┆ ---       │\n        │ str                 ┆ struct[2] │\n        ╞═════════════════════╪═══════════╡\n        │ {\"a\":1, \"b\": true}  ┆ {1,true}  │\n        │ null                ┆ null      │\n        │ {\"a\":2, \"b\": false} ┆ {2,false} │\n        └─────────────────────┴───────────┘\n        \"\"\"\n        if dtype is None:\n            msg = \"`Expr.str.json_decode` needs an explicitly given `dtype` otherwise Polars is not able to determine the output type. If you want to eagerly infer datatype you can use `Series.str.json_decode`.\"\n            raise TypeError(msg)\n\n        if infer_schema_length is not None:\n            issue_warning(\n                \"`Expr.str.json_decode` with `infer_schema_length` is deprecated and has no effect on execution.\",\n                DeprecationWarning,\n            )\n\n        dtype_expr = parse_into_datatype_expr(dtype)._pydatatype_expr\n        return wrap_expr(self._pyexpr.str_json_decode(dtype_expr))\n\n    def json_path_match(self, json_path: IntoExprColumn) -> Expr:\n        \"\"\"\n        Extract the first match from a JSON string using the provided JSONPath.\n\n        Throws errors if invalid JSON strings are encountered. All return values\n        are cast to :class:`String`, regardless of the original value.\n\n        Documentation on the JSONPath standard can be found","sourceCodeStart":1333,"sourceCodeEnd":1369,"githubUrl":"https://github.com/pola-rs/polars/blob/df599052daf96e7a9cc30a3b0c6bd25d6947e3c0/py-polars/src/polars/expr/string.py#L1333-L1369","documentation":"Expr.str.json_decode executes lazily, so Polars must know the output schema when the query plan is built; the dtype argument is therefore mandatory and a TypeError is raised immediately when it is None. Eager schema inference only exists on the Series counterpart. The infer_schema_length parameter on the Expr version is deprecated and has no effect on execution.","triggerScenarios":"df.select(pl.col('payload').str.json_decode()) with no dtype; porting Series.str.json_decode(s, infer_schema_length=100) code into an expression; a scan/pipe that assumed JSON schema auto-detection like pandas or pyarrow would do.","commonSituations":"JSON columns whose shape is only known at runtime; code migrated from eager notebooks (Series path worked) into lazy pipelines; older Polars versions or other libraries where inference was the default; users adding infer_schema_length to the Expr call and still hitting the error because it is ignored.","solutions":["Pass an explicit dtype: .str.json_decode(dtype=pl.Struct({'a': pl.Int64, 'b': pl.Bool}))","If the schema is unknown, collect the column first and use the eager path: s = df['payload']; s.str.json_decode(infer_schema_length=100), then merge the result back","Learn the schema once from a sample (df['payload'].head().str.json_decode(infer_schema_length=100).dtype) and hard-code it","Drop infer_schema_length from the Expr call; it only emits a deprecation warning and changes nothing"],"exampleFix":"# before\npl.col('payload').str.json_decode()\n\n# after\npl.col('payload').str.json_decode(\n    dtype=pl.Struct({'a': pl.Int64, 'b': pl.Bool})\n)\n\n# unknown schema: infer eagerly on a Series, then reuse\ninferred = df['payload'].str.json_decode(infer_schema_length=100).dtype\ndf.select(pl.col('payload').str.json_decode(dtype=inferred))","handlingStrategy":"validation","validationCode":"dtype = None  # e.g. from caller config\nif dtype is None:\n    # infer once, eagerly, then reuse\n    dtype = df['payload'].str.json_decode(infer_schema_length=100).dtype\nout = df.select(pl.col('payload').str.json_decode(dtype=dtype))","typeGuard":null,"tryCatchPattern":null,"preventionTips":["Always pass an explicit dtype on the lazy/Expr path","Reserve infer_schema_length for the Series (eager) API","Cache the inferred schema once per JSON source instead of re-inferring","Watch deprecation warnings — they flag paths that silently do nothing"],"tags":["polars","json","lazy-evaluation","schema","typeerror"],"backgroundTag":null,"analyzedSha":"df599052daf96e7a9cc30a3b0c6bd25d6947e3c0","analyzedAt":"2026-08-16T12:10:03.978Z","schemaVersion":2},"datasetVersion":"2026-08-16T13:17:31.715Z"}