Skip to content
← escentmachine field notes

How to Distinguish Null, Empty Strings, and Missing JSON Properties

On this page
AI-generated illustration; not taken on location · Conceptual comparison of a property containing null, a property containing an empty string, and an omitted property.
AI-generated illustration; not taken on location · A three-panel diagram separates property presence from the value a property contains.AI-generated illustration

In {"name":null}, the name member exists and contains null. In {"name":""}, it exists and contains a string with zero characters. In {}, the member is absent. Distinguish these representations by asking two separate questions: was the member supplied, and what value does it contain?

This distinction makes an error report actionable. “Name is empty” could describe inputs that require different corrections: adding a missing member, replacing null, or supplying text instead of an empty string. A useful report identifies what arrived and explains which requirement it fails.

The examples below compare the JSON representations and develop precise inspection and validation rules. Whether omission means “leave unchanged,” null means “clear,” or an empty string is acceptable depends on the application’s field contract.

Three small payloads, three distinct states

A JSON object member pairs a quoted property name with a value. Both null and strings are permitted JSON values. Consequently, {"name":null} and {"name":""} each include a member named name; {} includes no such name-value pair.

Payload Is name present? Supplied value JSON value kind
{"name":null} Yes null Null
{"name":""} Yes "" String
{} No No member value supplied No value to classify

An empty string contains zero characters, but it remains a supplied string. Its lack of characters does not remove the surrounding name-value pair. Similarly, null is a value explicitly included in the payload; it is different from omitting the member.

These observations describe representation without assigning intent. One application might accept null as a request to clear a saved name. Another might reject it. Neither interpretation follows from the payload alone.

The distinction also improves comparisons between requests. Changing {} to {"name":null} adds a member. Changing {"name":null} to {"name":""} changes an existing member’s value. A report that calls both edits “name became empty” loses information about the actual change.

Before correcting an input, establish which representation the receiving application expects. Converting every blank-looking field to the same representation can erase distinctions that its contract deliberately preserves.

Check property presence explicitly

Begin with the structural question: does the supplied JSON object include a member named name? Answer that question independently of any judgment about its value.

For {"name":null}, the inspection record should say name: present; value: null. For {"name":""}, it should say name: present; value: empty string. For {}, report name: absent; there is no supplied member value to describe.

Keep the inspection questions separate

A practical inspection sequence is:

  1. Identify the object being inspected.
  2. Determine whether the requested member appears in that object.
  3. If it appears, record its supplied value.
  4. Apply the field’s acceptance rules separately.

This sequence gives an error report enough information to distinguish adding a member from changing an existing member. A presence observation alone does not establish whether the supplied value is acceptable.

Parsed JSON objects support ordinary JavaScript dot and bracket notation, such as obj.name and obj['name'], for accessing their members. When implementing an inspector, verify the chosen presence-checking operation separately from the expressions used to access values.

Ask “Was the member supplied?” before asking “Is its value acceptable?” For example, a contract might require name to appear while allowing either null or a string. That contract needs a presence decision and an acceptance decision, even when both contribute to one final validation result.

Classify values with strict comparisons

Specify the intended categories before choosing comparison expressions. For this inspection task, the categories are missing, null, empty string, and other.

The following table describes the required classification of the JSON representations. It provides review cases for an implementation without depending on a particular JavaScript operator or membership function.

Payload Reporting category Reason
{} missing No name member is supplied
{"name":null} null The supplied member contains null
{"name":""} empty string The supplied member contains a string with zero characters
{"name":"Ada"} other The supplied string falls outside the three preceding categories

Resolve presence before classifying a supplied value. Otherwise, the report risks assigning a value category where the payload contains no member value at all.

Classification is separate from acceptance

Keep the other outcome because these three special states do not cover every possible field value. A supplied name containing text falls outside them, but may still need the application’s content checks.

Neither other nor any named category automatically establishes validity. A contract may accept null or an empty string. Conversely, a value classified as other may fail the field’s requirements.

Use the category to explain the observation, then apply the contract. For example, “name contains an empty string; this field requires at least one character” is appropriate only when that character requirement is documented. Review the implementation against each table row before relying on its diagnostics.

Show what a truthiness check loses

Before using a truthiness check to produce an “empty field” message, specify which observations the message must preserve. Review the actual language behavior separately; a broad label should not stand in for a documented field rule.

Consider a diagnostic design that gives all three example payloads the same message: name is empty. That design discards the distinction between an absent member and two different supplied values.

Payload Observation hidden by the shared message Correction to consider
{} The member is absent Add it if the contract requires presence
{"name":null} The member contains null Replace it if null is disallowed
{"name":""} The member contains an empty string Supply acceptable text if required

These corrections are conditional on the contract. An optional field may need no correction when omitted. A field that permits null may need no correction when null is supplied.

Review grouping against permitted values

Include zero and false in the review matrix when those values are relevant to the field. If a numeric field permits zero, its acceptance rules should explicitly account for zero. If a Boolean field permits false, document that acceptance just as clearly.

If the application deliberately groups several states for one decision, retain their separate observations for diagnostics. A useful review question is: do inputs receiving the same error message actually require the same correction? Adding an omitted member and replacing a supplied value are different actions.

Separate missing JSON members from JavaScript undefined

undefined is not a permitted JSON value. The text {"name":undefined} therefore cannot serve as another valid JSON payload alongside the three examples in this guide.

Keep the representation choices explicit:

Intended representation Example
Omit the member {}
Supply null {"name":null}
Supply an empty string {"name":""}

Which choice expresses the intended application meaning is a contract question. The fact that undefined is unavailable in JSON does not make null the correct replacement for every situation.

Ask what the diagnostic describes

If an investigation includes an undefined observation, obtain the original JSON text and identify the stage that produced the observation. Ask whether the report concerns the supplied text, a parsed object, or a later application state. The JSON value rule alone does not explain a runtime observation.

Describe the original payload using what it actually contains. For {}, report that name was omitted. For {"name":null}, report that null was supplied. Avoid rewriting either description to match an unexplained debugger label.

Do not silently substitute null when repairing input. Null has its own valid JSON representation and may have a specific application meaning. Any replacement should follow a documented rule while preserving an accurate account of the original payload.

Inspect nested fields one object at a time

For a path such as profile.name, inspect the parent before evaluating the child. An absent profile, a null profile, and a profile object lacking name describe different structures.

Suppose the contract requires profile to be an object containing a name member. These inputs then call for different observations:

Input Suggested diagnostic
{} profile: member is missing
{"profile":null} profile: contains null; an object is required
{"profile":""} profile: contains an empty string; an object is required
{"profile":{}} profile.name: member is missing
{"profile":{"name":null}} profile.name: contains null
{"profile":{"name":""}} profile.name: contains an empty string

The last two entries record the child’s value. Whether either observation becomes an error depends on the child’s acceptance rules.

Report the path where inspection stops

Check whether the parent exists, then whether its value satisfies the expected object type. For the contract above, the null and empty-string parents fail that structural requirement. Only proceed to the child’s membership and value checks when the parent has the required object structure.

When profile is absent, report profile. When it is an object without name, report profile.name. Calling both situations “empty name” hides the location where the sender needs to make a change.

For deeper paths, repeat this process at each level. Preserve the first structural problem rather than presenting an uninspected child as though it were an independently missing member. Once the containing object is available, apply the same presence-first classification to the final field.

Define presence and acceptable values independently

A useful field contract answers three questions separately: must the member appear, which types or values are permitted, and what string-content rules apply? Requiring presence does not establish whether null or an empty string is acceptable.

Use a matrix like this to expose the decisions the application needs to document:

Input state Member present? Supplied value Contract question
Omission No No member value supplied Must this member appear?
"name":null Yes Null Is null permitted, and what does it mean?
"name":"" Yes String with zero characters Is an empty string acceptable?
"name":" " Yes String containing spaces Are whitespace-only strings acceptable?
"name":0 Yes Zero Are numeric values permitted?
"name":false Yes False Are Boolean values permitted?

A string containing spaces differs from a string containing zero characters. Decide explicitly whether the application accepts either and whether it processes the string before validation. Document that sequence rather than silently treating the two inputs as equivalent.

Apply a concrete contract

Suppose name must appear, must contain a string, and must include at least one character other than whitespace. Under those stated requirements:

  • Omission fails the presence requirement.
  • Null, zero, and false fail the permitted-type requirement.
  • The empty-string and whitespace-only examples fail the content requirement.

These judgments follow from this hypothetical contract. They are not universal rules for JSON fields. A different contract could permit omission, null, or empty strings.

Document behavioral meaning separately, too. If omission means “leave the existing value unchanged,” state that rule. If null requests clearing a value, describe that operation explicitly. JSON representation alone does not supply either meaning.

Keep schema declarations aligned with the contract

In JSON Schema, properties associates named properties with schemas that validate those properties. A declaration under properties can still allow omission, so confirm the presence rules separately.

The payload comparisons above describe representation and diagnostic requirements. When implementing the contract in JSON Schema, confirm any additional keyword semantics before writing rules for required presence, permitted values, or string content. Review the resulting validation against every matrix row.

Make each diagnostic carry both the observation and the violated requirement. “name contains null; this field requires a string” tells the reader what arrived and what must change. Preserve that precision for missing members, empty strings, and nested paths.

Previous note
Next note