-
Notifications
You must be signed in to change notification settings - Fork 13
Feature Request: JSON Schema to Ruby Generator (Reverse Engineering) #87
Copy link
Copy link
Open
Labels
priority: lowAdvanced features and enhancementsAdvanced features and enhancements
Description
Description
Create a CLI tool that generates Ruby EasyTalk model classes from existing JSON Schema files.
Current State
The library generates JSON Schema from Ruby code:
# Ruby → JSON Schema ✓
class User
include EasyTalk::Model
define_schema do
property :name, String
end
end
User.json_schema # => { "type": "object", "properties": { "name": { "type": "string" } } }Problem
Developers often start with an existing JSON Schema and need to create Ruby backing models:
- Partner APIs: Received schema definitions from external partners
- Standards compliance: Implementing industry standards (FHIR, OpenAPI, etc.)
- Migration: Converting from other languages/frameworks that use JSON Schema
- Contract-first development: Schema designed before implementation
Currently, developers must manually translate JSON Schema to Ruby, which is:
- Time-consuming for large schemas
- Error-prone (easy to miss constraints or types)
- Tedious for deeply nested structures
Proposed Solution
CLI Tool
# Generate Ruby files from JSON Schema
easy_talk generate schema.json
# Specify output directory
easy_talk generate schema.json --output app/models/
# Generate from URL
easy_talk generate https://example.com/api/schema.json
# Dry run (preview without writing files)
easy_talk generate schema.json --dry-run
# Single file output (all classes in one file)
easy_talk generate schema.json --single-fileInput JSON Schema
{
"$schema": "https://json-schema.org/draft/2020-12/schema",
"$id": "https://example.com/user.schema.json",
"title": "User",
"type": "object",
"properties": {
"id": { "type": "integer" },
"name": { "type": "string", "minLength": 1, "maxLength": 100 },
"email": { "type": "string", "format": "email" },
"age": { "type": "integer", "minimum": 0, "maximum": 150 },
"role": { "type": "string", "enum": ["admin", "user", "guest"] },
"address": {
"type": "object",
"properties": {
"street": { "type": "string" },
"city": { "type": "string" }
},
"required": ["street", "city"]
},
"tags": {
"type": "array",
"items": { "type": "string" },
"minItems": 1,
"maxItems": 10
}
},
"required": ["id", "name", "email"]
}Generated Ruby Output
# app/models/address.rb
class Address
include EasyTalk::Model
define_schema do
property :street, String
property :city, String
end
end
# app/models/user.rb
class User
include EasyTalk::Model
define_schema do
title 'User'
property :id, Integer
property :name, String, min_length: 1, max_length: 100
property :email, String, format: 'email'
property :age, Integer, minimum: 0, maximum: 150, optional: true
property :role, String, enum: %w[admin user guest], optional: true
property :address, Address, optional: true
property :tags, T::Array[String], min_items: 1, max_items: 10, optional: true
end
endType Mapping
| JSON Schema Type | Ruby/EasyTalk Type |
|---|---|
string |
String |
integer |
Integer |
number |
Float |
boolean |
T::Boolean |
null |
NilClass |
array |
T::Array[ItemType] |
object (inline) |
Generates new class |
object (with $ref) |
References existing class |
oneOf |
T::OneOf[A, B, ...] |
anyOf |
T::AnyOf[A, B, ...] |
allOf |
T::AllOf[A, B, ...] |
| Union with null | T.nilable(Type) |
Programmatic API
# Generate Ruby source code as string
source = EasyTalk::Generator.from_schema(json_schema_hash)
# Generate and eval (for dynamic use)
klass = EasyTalk::Generator.create_class(json_schema_hash)
# Generate from file
source = EasyTalk::Generator.from_file('schema.json')Benefits
- Rapid onboarding: Instantly create Ruby models from partner schemas
- Accuracy: Automated translation eliminates human error
- Productivity: Save hours of manual conversion work
- Standards support: Easy adoption of standard schemas
- Round-trip capable: Generate schema → modify → regenerate
Implementation Considerations
- Handle
$refand$defsfor shared definitions - Generate meaningful class names from
$idortitle - Support nested objects (generate separate classes or inline)
- Map JSON Schema constraints to EasyTalk constraints
- Handle
additionalProperties - Support
oneOf,anyOf,allOfcompositions - Preserve descriptions as comments
- Handle conflicting class names
- Support multiple schema files with cross-references
- Consider generating RBS type signatures alongside Ruby files
Reactions are currently unavailable
Metadata
Metadata
Assignees
Labels
priority: lowAdvanced features and enhancementsAdvanced features and enhancements