Project: YugabyteDB (App Definition and Development / Database)
File: typecast-operators.md

title: "::jsonb and ::json and ::text (JSON typecast)" headerTitle: "::jsonb and ::json and ::text (typecast)" linkTitle: "::jsonb, ::json, ::text (typecast)" description: Typecast between any pair of text, json, and jsonb values. menu: v2.18: identifier: typecast-operators parent: json-functions-operators weight: 10 type: docs Purpose: Typecast between any pair of `text`, `json`, and `jsonb` values in both directions. Signature for the `jsonb` overload of `::text`: ```ebnf input value: jsonb return value: text ``` Notes: You can use the `::text` operator on both a `jsonb` value and a `json` value; you can use the `::jsonb` operator on both a `text` value and a `json` value; and you can use the `::json` operator on both a `jsonb` value and a `text` value. Consider this round trip: ```ebnf newrfc7159text := (origrfc7159text::jsonb)::text ``` The round trip is, in general, literally, but not semantically, lossy because "origrfc7159text" can contain arbitrary occurrences of whitespace characters but "newrfc7159text" has conventionally defined whitespace use: there are no newlines; and single spaces are used according to a rule. ```plpgsql do $body$ declare origrfc7159_text constant text := ' { "a": 1, "b": {"x": 1, "y": 19}, "c": true }'; expectednewrfc7159text constant text := '{"a": 1, "b": {"x": 1, "y": 19}, "c": true}'; j constant jsonb := origrfc7159_text::jsonb; newrfc7159_text constant text := j::text; begin assert newrfc7159text = expectednewrfc7159_text, 'unexpected'; end; $body$; ``` In contrast, this: ```ebnf newrfc7159text := (origrfc7159text::json)::text ``` is literally non-lossy because `json` stores the actual Unicode text, as is, that defines the JSON value. ```plpgsql do $body$ declare origrfc7159_text constant text := ' { "a": 1, "b": {"x": 1, "y": 19}, "c": true }'; j constant json := origrfc7159_text::json; newrfc7159_text constant text := j::text; begin assert newrfc7159text = origrfc7159text, 'unexpected'; end; $body$; ``` This example illustrates the point dramatically: ```plpgsql do $body$ declare origrfc7159_text constant text := '{"a": 42, "b": 17, "a": 99}'; jjson constant json := origrfc7159text::json; jjsonb constant jsonb := origrfc7159text::jsonb; textfromjson constant text := j_json::text; textfromjsonb constant text := j_jsonb::text; expectedtextfrom_jsonb constant text := '{"a": 99, "b": 17}'; begin assert (textfromjson = origrfc7159_text) and (textfromjsonb = expectedtextfrom_jsonb), 'unexpected'; end; $body$; ``` The `jsonb` representation is semantics-aware, and so it applies the "rightmost mention wins" rule to overwrite the first value establishment for the key "a" (the JSON number 42) with the second value establishment for that key (the JSON number 92). But the `json` representation is not semantics-aware; it merely applies a syntax-check before accepting the content. This last example shows that the round trip: ```ebnf newjsonvalue := (json_value::jsonb)::json; ``` is lossy because the `json` representation stores the text definition of the JSON value. ```plpgsql do $body$ declare orig_json constant json := ' { "a": 1, "b": {"x": 1, "y": 19}, "c": true }'::json; jsonbfromjson constant jsonb := orig_json::jsonb; jsonfromjsonb constant json := jsonbfromjson::json; begin assert not (jsonfromjsonb::text = orig_json::text), 'unexpected'; end; $body$; ``` The predicate for the assert has to use `::text` operator on both sides of the `=` operator because this has a `jsonb` overload but not a `json` overload.