Private/ConvertTo-JsonSchema.ps1

function _TreatJsonSchemaObjectProprs {
    param(
        [Object]$SchemaObj,
        [bool]$RemoveUnsupportedKeyWords = $true
    )
    # Probably, there is more polished methods. (ISchemaProcessor?)

    # https://platform.openai.com/docs/guides/structured-outputs/some-type-specific-keywords-are-not-yet-supported
    $UnsupportedKeyWords = @(
        'minLength', 'maxLength', 'pattern', 'format',
        'minimum', 'maximum', 'multipleOf',
        'patternProperties', 'unevaluatedProperties', 'propertyNames', 'minProperties', 'maxProperties',
        'unevaluatedItems', 'contains', 'minContains', 'maxContains', 'minItems', 'maxItems', 'uniqueItems', 'maxContains', 'maxContains', 'maxContains'
    )

    try {
        $SchemaObj.PSObject.Properties.Remove('$schema')
        $SchemaObj.PSObject.Properties.Remove('title')
    }
    catch {}

    if ($SchemaObj.properties) {
        $props = [string[]]($SchemaObj.properties | Get-Member -MemberType NoteProperty).Name
        $SchemaObj | Add-Member -MemberType NoteProperty -Name 'required' -Value $props -Force

        if ($RemoveUnsupportedKeyWords) {
            foreach ($p in $props) {
                # Use the trick to improve the response accuracy of the model by giving a description instead of keywords.
                if ($SchemaObj.properties.$p.'format' -eq 'date-time') {
                    $SchemaObj.properties.$p | Add-Member -MemberType NoteProperty -Name 'description' -Value 'Parsable date-time format string. For example, "2018-11-13T08:20:39"' -Force
                }
                elseif ($SchemaObj.properties.$p.'format' -eq 'date') {
                    $SchemaObj.properties.$p | Add-Member -MemberType NoteProperty -Name 'description' -Value 'It represents a date in the following format: "YYYY-MM-DD"' -Force
                }
                elseif ($SchemaObj.properties.$p.'format' -eq 'time') {
                    $SchemaObj.properties.$p | Add-Member -MemberType NoteProperty -Name 'description' -Value 'It represents a time in the following format: "hh:mm:ss.s"' -Force
                }
                elseif ($SchemaObj.properties.$p.'format' -eq 'regex') {
                    $SchemaObj.properties.$p | Add-Member -MemberType NoteProperty -Name 'description' -Value 'This property should be a valid regular expression string.' -Force
                }
                elseif ($SchemaObj.properties.$p.'format' -eq 'email') {
                    $SchemaObj.properties.$p | Add-Member -MemberType NoteProperty -Name 'description' -Value 'This property should be a valid e-mail address format.' -Force
                }
                elseif ($SchemaObj.properties.$p.'format' -eq 'uri') {
                    $SchemaObj.properties.$p | Add-Member -MemberType NoteProperty -Name 'description' -Value 'This property should be a valid URI' -Force
                }
                elseif ($SchemaObj.properties.$p.'format' -eq 'ipv4') {
                    $SchemaObj.properties.$p | Add-Member -MemberType NoteProperty -Name 'description' -Value 'It represents a IPv4 address.' -Force
                }
                elseif ($SchemaObj.properties.$p.'format' -eq 'ipv6') {
                    $SchemaObj.properties.$p | Add-Member -MemberType NoteProperty -Name 'description' -Value 'It represents a IPv6 address.' -Force
                }

                $UnsupportedKeyWords.ForEach({
                        $SchemaObj.properties.$p.PSObject.Properties.Remove($_)
                    })
            }
        }
    }

    if ($SchemaObj.Definitions) {
        foreach ($def in ($SchemaObj.Definitions | Get-Member -MemberType NoteProperty).Name) {
            _TreatJsonSchemaObjectProprs -SchemaObj $SchemaObj.Definitions.$def
        }
    }
}

function ConvertTo-JsonSchema {
    [CmdletBinding()]
    param (
        [Parameter(Mandatory, Position = 0)]
        [type]$Type
    )

    begin {
        if (-not ('NJsonSchema.JsonSchema' -as [type])) {
            $LibsPath = Join-Path $PSScriptRoot '..\Libs\NJsonSchema\netstandard2.0'
            if (-not ('Newtonsoft.Json.Schema.JsonSchema' -as [type])) {
                Add-Type -Path (Join-Path $LibsPath 'Newtonsoft.Json.dll')
            }
            Add-Type -Path (Join-Path $LibsPath 'Namotion.Reflection.dll')
            Add-Type -Path (Join-Path $LibsPath 'NJsonSchema.dll')
        }

        $setting = [NJsonSchema.Generation.JsonSchemaGeneratorSettings]::new()
        $setting.DefaultEnumHandling = [NJsonSchema.Generation.EnumHandling]::String
        $generator = [NJsonSchema.Generation.JsonSchemaGenerator]::new($setting)
    }

    process {
        $typeSchemaRef = $generator.Generate($Type)
        $typeSchemaObj = $typeSchemaRef.ToJson() | ConvertFrom-Json
        _TreatJsonSchemaObjectProprs -SchemaObj $typeSchemaObj -RemoveUnsupportedKeyWords $true
        $typeSchemaObj
    }

    end {
    }
}