Wiki 9Minecraft Wiki 9Minecraft

JSON UI Type Conversion and Data Casting

How to convert between strings, numbers, and booleans inside Minecraft Bedrock JSON UI bindings.

5Sections
4Code examples
3Known errors

Minecraft Bedrock's JSON UI engine is strictly typed when evaluating data bindings, meaning a control expecting a boolean or string will fail if handed a raw integer or float. Because the engine lacks explicit casting functions like `int()` or `str()`, developers must use expression operators and string manipulation tricks to convert data types on the fly. You will reach for these techniques whenever you need to display numeric scoreboard values as text, parse raw server strings into numbers for progress bars, or toggle visibility based on non-boolean properties.

Data Types in JSON UI Bindings

Before converting data, it helps to understand how the UI engine categorizes values inside the `bindings` array. Unlike Molang, which treats almost everything as a floating-point number, JSON UI expressions recognize four primary primitives: booleans, integers, floats, and strings. Hardcoded properties retrieved from the game engine (typically prefixed with `#`) carry a strict internal type.

When you write a binding expression (by enclosing the logic in parentheses), the final output of that expression must match the exact data type required by the target property (`binding_name_override`). For example, `#visible` and `#enabled` strictly require a boolean result, `#text` requires a string, and `#clip_ratio` requires a float between 0.0 and 1.0. Feeding an integer straight into `#text` or a string of digits into `#clip_ratio` will cause the binding to silently fail or render blank.

TypeCommon Target PropertiesCoercion Rule
String#text, #textureConcatenate with an empty string ('') to force conversion from numbers.
Integer / Float#clip_ratio, #size_binding_xMultiply by 1 or 1.0 to strip strings of their text type and parse digits.
Boolean#visible, #enabled, #toggle_stateUse comparison operators (=, <, >) or the 'not' operator to evaluate truthiness.

Converting Numbers and Booleans to Strings

The most common conversion needed in custom interfaces is turning a numeric binding (like `#player_level` or a slider value) into a string so a `label` control can render it. If you bind a numeric property directly to `#text` without an expression, the game will often refuse to render it because of a type mismatch.

To cast a number or boolean into a string, concatenate it with an empty string literal (`''`) using the `+` operator. In JSON UI expressions, single quotes denote a string literal, and when one side of the `+` operator is a string, the engine automatically converts the other operand into its string representation. Note that converting a float to a string this way may expose raw decimal places, so it is best used with integer bindings or pre-formatted values.

RP/ui/hud_screen.json
{
  "namespace": "hud",
  "level_readout_label": {
    "type": "label",
    "text": "#text",
    "bindings": [
      {
        "binding_name": "#level_number",
        "binding_name_override": "#level_raw"
      },
      {
        "binding_type": "view",
        "source_property_name": "('Level: ' + #level_raw)",
        "target_property_name": "#text"
      }
    ]
  }
}

Parsing Strings into Numbers

When building custom server forms, scoreboards, or reading data passed through custom title strings, your only data source is often a string such as `#title_text` or `#form_button_text`. If you want to use a numeric value hidden inside that text to drive a health bar's `#clip_ratio` or dynamically resize an element, you have to convert the string into a number.

You can force the UI engine to parse a string of digits into an integer or float by performing arithmetic on it—specifically, multiplying it by `1` (for an integer) or `1.0` (for a float), or adding `0` to it. If the string contains non-numeric characters (such as formatting codes, spaces, or letters), the conversion will fail and evaluate to zero. Because of this, you commonly pair string-to-number casting with `-` (which acts as string removal when used between two strings) to strip out unwanted prefixes before multiplying.

RP/ui/server_form.json
{
  "namespace": "server_form",
  "custom_mana_bar": {
    "type": "image",
    "texture": "textures/ui/mana_full",
    "clip_direction": "left",
    "bindings": [
      {
        "binding_name": "#form_button_text",
        "binding_name_override": "#raw_text"
      },
      {
        "binding_type": "view",
        "source_property_name": "(((#raw_text - 'mana:') * 1.0) / 100.0)",
        "target_property_name": "#clip_ratio"
      }
    ]
  }
}

Evaluating to Booleans for Visibility

Controlling whether a UI panel is shown or hidden relies on the `#visible` property, which exclusively accepts a boolean. You cannot pass a string or an integer straight into `#visible` and expect C-style truthiness (where `1` is true and `0` is false) to work reliably across all control types.

To convert a number into a boolean, compare it against a literal number using `=`, `>`, or `<`. For strings, compare the binding against an empty string `''` or a known keyword. If you need an 'is not equal to' check, wrap an equality check in the `not` operator, such as `(not (#item_name = ''))`. You can also convert a boolean back into an integer (1 or 0) for math operations by multiplying the boolean expression by `1`, which lets you build branchless conditional math inside a single view binding.

RP/ui/inventory_screen.json
{
  "namespace": "crafting",
  "conditional_warning_panel": {
    "type": "panel",
    "bindings": [
      {
        "binding_name": "#hover_text",
        "binding_name_override": "#item_info"
      },
      {
        "binding_type": "view",
        "source_property_name": "(not (#item_info = ''))",
        "target_property_name": "#visible"
      }
    ]
  }
}

Multi-Step Conversion Chains

Complex UI modifications often require chaining multiple conversions together across separate `view` bindings on the same control. Trying to strip a string, cast it to a float, divide it, and compare it to a threshold inside one massive `source_property_name` string quickly becomes unreadable and can trip up the expression parser.

Instead, break the conversion into discrete steps using custom intermediate property names (any arbitrary name starting with `#`). First, extract and clean the string into an intermediate property. Second, cast that property into a number by multiplying by `1.0`. Finally, feed that numeric property into your target calculation. The UI engine resolves these view bindings in the order they are needed, keeping your JSON clean and easy to debug.

RP/ui/hud_screen.json
{
  "namespace": "hud",
  "parsed_data_bar": {
    "type": "image",
    "texture": "textures/ui/bar_fill",
    "clip_direction": "left",
    "bindings": [
      {
        "binding_name": "#title_text",
        "binding_name_override": "#raw_title"
      },
      {
        "binding_type": "view",
        "source_property_name": "(#raw_title - 'HP:')",
        "target_property_name": "#clean_str"
      },
      {
        "binding_type": "view",
        "source_property_name": "(#clean_str * 1.0)",
        "target_property_name": "#hp_float"
      },
      {
        "binding_type": "view",
        "source_property_name": "(#hp_float / 20.0)",
        "target_property_name": "#clip_ratio"
      },
      {
        "binding_type": "view",
        "source_property_name": "(#hp_float > 0.0)",
        "target_property_name": "#visible"
      }
    ]
  }
}

Which versions this applies to

Applies to all modern Minecraft Bedrock versions (1.16.0 and above). JSON UI is a stable resource pack system and requires no experimental toggles.

When it does not work

What you seeWhyThe fix
A label control is completely blank or shows the literal binding name (like '#level_raw') on screen instead of the value.You either forgot to wrap the `source_property_name` expression in outer parentheses `(...)`, or you passed a raw integer/float binding directly to `#text` without converting it to a string first.Ensure the entire expression is enclosed in parentheses and concatenate an empty string in single quotes: `('' + #my_number_binding)`.
A custom progress bar using `#clip_ratio` is stuck at 0% (invisible) or 100% (full) even though the source value is changing.Both numbers in your division expression are integers (or strings cast to integers via `* 1`), causing the JSON UI engine to perform integer division, which truncates `50 / 100` down to `0`.Force floating-point division by multiplying your string or integer by `1.0` instead of `1`, and always include `.0` on your divisor (for example, `((#val * 1.0) / 100.0)`).
String-to-number conversion via `* 1` always evaluates to 0 when reading text from a server or scoreboard.The source string contains hidden formatting codes (such as `§r` or `§f`) or whitespace, which causes the numeric parser to abort and return 0.Strip out any known color codes or prefixes using the string subtraction operator (`#raw_text - '§r'`) before multiplying by `1`, or send clean, unformatted digits from your script.

Reference, straight from the game files

Read out of the game itself, so the ids match the version you are building for.