Skip to content

Semantic mismatch: JSON Schema allows empty strings, ActiveModel presence rejects them #114

@sergiobayona

Description

@sergiobayona

Summary

There is a semantic mismatch between JSON Schema validation and ActiveModel validation for required string properties:

  • JSON Schema: type: "string" allows empty strings ""
  • ActiveModel: presence: true rejects empty strings

This causes the validations to disagree on whether data is valid.

Steps to Reproduce

class User
  include EasyTalk::Model

  define_schema do
    property :name, String
  end
end

user = User.new(name: "")

# JSON Schema validation (using json_schemer)
schema = User.json_schema
# => { "type" => "object", "properties" => { "name" => { "type" => "string" } }, "required" => ["name"] }

schemer = JSONSchemer.schema(schema)
schemer.valid?({ "name" => "" })
# => true (empty string is valid for type: "string")

# ActiveModel validation  
user.valid?
# => false (presence: true rejects empty strings)
user.errors[:name]
# => ["can't be blank"]

Expected Behavior

Validations should be consistent. Either:

  1. JSON Schema should include minLength: 1 for required string properties, OR
  2. ActiveModel should allow empty strings for type validation (only using presence where explicitly requested)

Analysis

This is a semantic difference rather than a bug. Both behaviors are technically correct for their respective systems:

  • JSON Schema's required means "key must be present" not "value must be non-empty"
  • ActiveModel's presence: true means "value must not be blank"

Options to Consider

  1. Add minLength: 1 to JSON Schema for required strings (breaking change for schema consumers)
  2. Make presence validation opt-in with a constraint like presence: true or blank: false
  3. Document the difference and accept that the two validation systems have different semantics
  4. Add configuration option to control this behavior

Verification

This gap was identified using the new have_matching_validations_for RSpec matcher:

# This test correctly detects the mismatch
expect(User).not_to have_matching_validations_for(name: '')

Impact

  • APIs that validate against JSON Schema may accept empty strings that Rails controllers reject
  • This could cause confusion when debugging validation issues
  • LLM function calling responses may include empty strings that fail Rails validation

🤖 Generated with Claude Code

Metadata

Metadata

Assignees

No one assigned

    Labels

    priority: criticalMust fix - bugs breaking core functionality

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions