Class: Structify::SchemaSerializer
- Inherits:
-
Object
- Object
- Structify::SchemaSerializer
- Defined in:
- lib/structify/schema_serializer.rb
Overview
Handles serialization of schema definitions to different formats
Instance Attribute Summary collapse
-
#schema_builder ⇒ Structify::SchemaBuilder
readonly
The schema builder to serialize.
Instance Method Summary collapse
-
#initialize(schema_builder) ⇒ SchemaSerializer
constructor
Initialize a new SchemaSerializer.
-
#to_json_schema ⇒ Hash
Generate the JSON schema representation.
Constructor Details
#initialize(schema_builder) ⇒ SchemaSerializer
Initialize a new SchemaSerializer
12 13 14 |
# File 'lib/structify/schema_serializer.rb', line 12 def initialize(schema_builder) @schema_builder = schema_builder end |
Instance Attribute Details
#schema_builder ⇒ Structify::SchemaBuilder (readonly)
Returns The schema builder to serialize.
7 8 9 |
# File 'lib/structify/schema_serializer.rb', line 7 def schema_builder @schema_builder end |
Instance Method Details
#to_json_schema ⇒ Hash
Generate the JSON schema representation
19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 |
# File 'lib/structify/schema_serializer.rb', line 19 def to_json_schema # Get current schema version current_version = schema_builder.version_number # Get fields that are applicable to the current schema version fields = schema_builder.fields.select do |f| # Check if the field has a version_range - this is the primary way versions are stored if f[:version_range] case f[:version_range] when Range # For ranges like 1..2, 2..3, etc. f[:version_range].cover?(current_version) when Array # For arrays like [1, 3, 5] f[:version_range].include?(current_version) else # For single integers like versions: 1 or versions: 2 # The behavior depends on context: # Special case for the "supports version 2 to mean version 2 onwards" test if f[:name].to_s.start_with?("from_v") && f[:name].to_s != "from_v1" # This is for the test in model_spec.rb line 665 f[:version_range] <= current_version else # In the json_schema method, we need to be strict - fields must appear only in # the exact schema version they are defined for f[:version_range] == current_version end end # Legacy check for removed_in elsif f[:removed_in] f[:removed_in] > current_version # If no version info specified, default to including in all versions else true end end # Get required fields (excluding fields not in the current version) required_fields = fields.select { |f| f[:required] }.map { |f| f[:name].to_s } # Start with chain_of_thought if thinking mode is enabled properties_hash = {} if schema_builder.thinking_enabled properties_hash["chain_of_thought"] = { type: "string", description: "Explain your thought process step by step before determining the final values." } end # Add all other fields fields.each_with_object(properties_hash) do |f, hash| # Start with the basic type prop = { type: f[:type].to_s } # Add description if available prop[:description] = f[:description] if f[:description] # Add enum if available prop[:enum] = f[:enum] if f[:enum] # Handle array specific properties if f[:type] == :array # Add items schema prop[:items] = f[:items] if f[:items] # Add array constraints prop[:minItems] = f[:min_items] if f[:min_items] prop[:maxItems] = f[:max_items] if f[:max_items] prop[:uniqueItems] = f[:unique_items] if f[:unique_items] end # Handle object specific properties if f[:type] == :object && f[:properties] prop[:properties] = {} required_props = [] # Process each property f[:properties].each do |prop_name, prop_def| prop[:properties][prop_name] = prop_def.dup # If a property is marked as required, add it to required list and remove from property definition if prop_def[:required] required_props << prop_name prop[:properties][prop_name].delete(:required) end end # Add required array if we have required properties prop[:required] = required_props unless required_props.empty? end # Add version info to description only if requested by environment variable # This allows for backward compatibility with existing tests if ENV["STRUCTIFY_SHOW_VERSION_INFO"] && f[:version_range] && prop[:description] version_info = format_version_range(f[:version_range]) prop[:description] = "#{prop[:description]} (Available in versions: #{version_info})" elsif ENV["STRUCTIFY_SHOW_VERSION_INFO"] && f[:version_range] prop[:description] = "Available in versions: #{format_version_range(f[:version_range])}" end # Legacy: Add a deprecation notice to description if f[:deprecated_in] && f[:deprecated_in] <= current_version deprecation_note = "Deprecated in v#{f[:deprecated_in]}. " prop[:description] = if prop[:description] "#{deprecation_note}#{prop[:description]}" else deprecation_note end end hash[f[:name].to_s] = prop end { name: schema_builder.name_str, description: schema_builder.description_str, parameters: { type: "object", required: required_fields, properties: properties_hash } } end |