Skip to content

Reserved Keywords in JSON Property Names Generate Backticks Instead of JsonPropertyName Attributes #58

@houstonhaynes

Description

@houstonhaynes

When OpenAPI schemas contain properties that are F# reserved keywords (like namespace, type, end), Hawaii correctly escapes them with backticks. However, for F# record types, using [<JsonPropertyName>] attributes would provide better developer experience while maintaining correct JSON serialization.

OpenAPI Source

# From Cloudflare Vectorize V2 OpenAPI spec
vectorizeindex-get-vectors-by-id-responseArrayItem:
  type: object
  properties:
    id:
      type: string
      description: Identifier for a Vector
    metadata:
      type: object
    namespace:     # 'namespace' is an F# reserved keyword
      type: string
    values:
      type: array
      items:
        type: number

Current Hawaii Output

// From CloudflareFS: src/Management/CloudFlare.Management.Vectorize/Types.fs (line 9)
type ``vectorizeindex-get-vectors-by-id-responseArrayItem`` =
    { id: Option<``vectorizevector-identifier``>
      metadata: Option<Newtonsoft.Json.Linq.JObject>
      ``namespace``: Option<string>      // Backtick escaping
      values: Option<list<float>> }

Impact on User Code

// Users must use backticks in their code
let vectorResult = {
    id = Some "vector-123"
    metadata = None
    ``namespace`` = Some "my-namespace"  // Awkward!
    values = Some [1.0; 2.0; 3.0]
}

// Accessing the field
let ns = vectorResult.``namespace``      // Exhausting!

Proposed Improvement

type ``vectorizeindex-get-vectors-by-id-responseArrayItem`` =
    { id: Option<``vectorizevector-identifier``>
      metadata: Option<Newtonsoft.Json.Linq.JObject>
      [<System.Text.Json.Serialization.JsonPropertyName("namespace")>]
      Namespace: Option<string>          // Clean F# name!
      values: Option<list<float>> }

Benefits

// Users write clean F# code
let vectorResult = {
    id = Some "vector-123"
    metadata = None
    Namespace = Some "my-namespace"  // Clean!
    values = Some [1.0; 2.0; 3.0]
}

// Accessing the field
let ns = vectorResult.Namespace      // Idiomatic!

// JSON serialization still produces:
// { "namespace": "my-namespace" }

Implementation Suggestion

  1. Detect when a property name is an F# reserved keyword
  2. Generate [<System.Text.Json.Serialization.JsonPropertyName("original_name")>] attribute
  3. Transform property name to PascalCase (e.g., namespaceNamespace, typeType)
  4. This works with System.Text.Json (already used by Hawaii) and Newtonsoft.Json

CloudflareFS Workaround

We accept the backticks in generated code and document that users must use backtick syntax when working with these properties. This is suboptimal but functional.

Additional Examples from CloudflareFS

// From Vectorize Types.fs (line 404)
type ``vectorizeindex-query-v2-responseMatches`` =
    { id: Option<``vectorizevector-identifier``>
      metadata: Option<Newtonsoft.Json.Linq.JObject>
      ``namespace``: Option<string>          // Reserved keyword
      score: Option<float>
      values: Option<list<float>> }

Reserved Keywords to Consider

Common F# keywords that appear in API schemas:

  • namespace, type, end, function, let, match, module, new, null, return, static, then, when, with, yield

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions