# Parse a Boolean String Value: Truthy/Falsy Conventions

Source: https://www.techinterview.org/post/3233459765/boolean-string-value/
Updated: 2026-04-27 · techinterview.org

## Parse a Boolean String Value: Truthy/Falsy Conventions Across Languages

"Parse a string into a boolean value" sounds trivial — just check if it equals "true" or "false." In practice, configuration parsers, environment variable handling, JSON parsing, and CLI argument processing all need to handle "yes/no", "1/0", "T/F", case variations, and edge cases. This guide covers the standard conventions, the language-specific quirks, and the safe parsing patterns interviewers expect when this question comes up.

## The Problem

Given a string, return a boolean. Handle:

- Standard literals: "true", "false"

- Case variations: "True", "TRUE", "FALSE", "False"

- Numeric: "1", "0"

- Yes/no: "yes", "no", "y", "n"

- On/off: "on", "off"

- Whitespace: "  true  " should still parse

- Edge cases: "", "null", "undefined", non-boolean strings

## Approach 1: Strict Match

Accept only exact "true" or "false" (lowercase, trimmed). Reject everything else.


```
def parse_bool_strict(s: str) -> bool:
    """Strict parse — only 'true' or 'false'."""
    if s is None:
        raise ValueError("None input")
    s = s.strip().lower()
    if s == "true":
        return True
    if s == "false":
        return False
    raise ValueError(f"Cannot parse '{s}' as boolean")


# Tests
print(parse_bool_strict("true"))    # True
print(parse_bool_strict("True"))    # True
print(parse_bool_strict("FALSE"))   # False
# parse_bool_strict("1")  # raises
```


Strict parsing is appropriate when the input format is well-defined (e.g., JSON booleans). Use this in API contracts where ambiguity should be an error.

## Approach 2: Permissive Match (Common in Config Parsers)

Accept any common truthy / falsy variant. Default behavior in environment variable handling, CLI argument parsing, and most config libraries.


```
def parse_bool(s: str) -> bool:
    """Permissive parse for common truthy/falsy strings."""
    if s is None:
        return False
    s = s.strip().lower()
    if s in {"true", "t", "yes", "y", "on", "1"}:
        return True
    if s in {"false", "f", "no", "n", "off", "0", ""}:
        return False
    raise ValueError(f"Cannot parse '{s}' as boolean")


# Tests
print(parse_bool("yes"))    # True
print(parse_bool("Off"))    # False
print(parse_bool("1"))      # True
print(parse_bool(""))       # False (treated as falsy)
# parse_bool("maybe")  # raises
```


Common in environment variable parsers (e.g., `distutils.util.strtobool`, `python-dotenv`, similar libraries in other languages).

## Approach 3: Distutils-Style

Python's standard library `distutils.util.strtobool` (deprecated in 3.12 but the pattern persists in many libraries) accepts a specific set:


```
def strtobool(s: str) -> int:
    """Mimics distutils.util.strtobool (returns 1 or 0)."""
    val = s.strip().lower()
    if val in ("y", "yes", "t", "true", "on", "1"):
        return 1
    elif val in ("n", "no", "f", "false", "off", "0"):
        return 0
    else:
        raise ValueError(f"Invalid truth value {val!r}")
```


## Language-Specific Conventions

### Python's bool(s)

Python's built-in `bool(s)` on strings returns `True` for any non-empty string, even `"false"` and `"0"`. This catches new Python developers off-guard:


```
print(bool("false"))    # True (non-empty string)
print(bool(""))         # False (empty string)
print(bool("0"))        # True (non-empty)
```


Don't use `bool(s)` for parsing user-provided strings; use a custom parser.

### JavaScript's Boolean(s) and !!s

Same trap: `Boolean("false")` is `true` because the string is non-empty. Same for `!!s`.


```
// JavaScript
console.log(Boolean("false"));  // true
console.log(Boolean(""));       // false
console.log(Boolean("0"));      // true
```


JavaScript developers commonly use libraries (lodash's `toLower` + custom logic, or `JSON.parse` for JSON-format booleans).

### Java's Boolean.parseBoolean

Java's `Boolean.parseBoolean(s)` returns true only for the string "true" (case-insensitive); everything else is false:


```
// Java
Boolean.parseBoolean("true");    // true
Boolean.parseBoolean("True");    // true
Boolean.parseBoolean("yes");     // false
Boolean.parseBoolean("1");       // false
Boolean.parseBoolean("");        // false
```


Strict but doesn't throw on invalid input. Some prefer `Boolean.valueOf(s)` which has identical semantics but returns Boolean object.

### Go's strconv.ParseBool

Go's standard library accepts: 1, t, T, TRUE, true, True; 0, f, F, FALSE, false, False. Anything else returns an error.


```
// Go
v, err := strconv.ParseBool("yes")  // error: invalid syntax
v, err := strconv.ParseBool("1")    // true, nil
v, err := strconv.ParseBool("t")    // true, nil
```


### Rust's str.parse::<bool>()

Rust accepts only "true" and "false" exactly (case-sensitive). Returns Err for anything else.

## Common Mistakes

- **Using language built-in `bool(s)`.** In Python and JavaScript, this returns True for any non-empty string, including "false". Always write a custom parser for user input.

- **Not handling None / null / empty.** Decide explicitly: is None False, or an error? Empty string False, or an error? Document and stick to it.

- **Inconsistent case handling.** Some languages are case-insensitive (Java, Go); others aren't (Rust). Pick one convention and apply consistently.

- **Forgetting whitespace.** "  true  " from environment variables or YAML files should parse correctly. Always trim before comparing.

- **Returning the wrong type on error.** Some implementations silently return False on invalid input; others raise. Document the contract; raise for production parsers where ambiguity is dangerous.

- **Treating "0" as falsy in JSON contexts.** JSON booleans are strictly "true" and "false"; "0" is a number. Mixing these conventions causes subtle bugs.

## Common Variations

### Three-state parsing (true / false / null)

Useful for "unknown" or "default" cases. Return Optional[bool] or three-state enum.

### Locale-specific parsing

"Sí/No" (Spanish), "Oui/Non" (French), etc. Most production code sticks to English; locale-aware parsing is rare and error-prone.

### JSON boolean parsing

Use json.loads(s) for JSON-format booleans. Strict; only "true" and "false" accepted.

### YAML boolean parsing

YAML 1.1 accepts "yes", "no", "y", "n", "on", "off" as booleans. YAML 1.2 narrowed to just "true"/"false". Major source of bugs in YAML 1.1 parsers (the famous "Norway problem" — country code "NO" parses to false).

## Frequently Asked Questions

### What's the expected interview answer?

  Permissive parser: accept "true"/"false", "yes"/"no", "1"/"0", "on"/"off", case-insensitive, with whitespace trimming. Raise on unrecognized values. Walk through edge cases: None, empty string, "0" (truthy or falsy depending on convention). Strong candidates discuss the language-specific quirks (Python bool() returning True for "false") and library-vs-manual trade-offs.

### Why is bool(s) in Python wrong for parsing?

  Because Python's bool() on strings returns True for any non-empty string. `bool("false")` is True. `bool("0")` is True. `bool("")` is False. The only reliable Pythonic way is to compare against known truthy/falsy strings explicitly.

### What's the YAML "Norway problem"?

  YAML 1.1 parses "NO" as a boolean false. Country code lists with "NO" (Norway) get silently converted to False. This caused real bugs in production YAML parsers. YAML 1.2 fixed it by restricting to "true"/"false". Strong candidates know this anecdote when discussing config parsing pitfalls.

### How do production parsers handle the choice between strict and permissive?

  API responses (JSON): strict. Environment variables: permissive (accept "1", "true", "yes"). Config files: permissive. CLI flags: depends on framework (Click in Python is permissive; argparse with type=bool is broken — use a custom type=parse_bool). Document the choice; align with platform conventions.

### Should I support locale-specific values?

  Generally no. Stick to English. Programs talking to programs use English anyway. Programs talking to users typically rely on UI affordances (checkboxes, radio buttons), not free-text boolean parsing. Locale-specific parsing introduces bugs without much benefit.

See also: [Remove a Character from a String](/post/3233459622/removing-a-character-from-a-string/) • [Detect Missing Country Code](/post/3233459746/missing-country-code/) • [Print String Permutations](/post/3233459701/print-string-permutations/)
