Skip to content

Conversation

@imohag9
Copy link

@imohag9 imohag9 commented Oct 13, 2025

Summary

This PR refactors the core serialization and deserialization logic in OpenAPI.jl to leverage the modern features of JSON.jl v1.0 and the StructTypes.jl ecosystem. This change simplifies the codebase, improves maintainability, and enhances performance by removing custom object-mapping machinery in favor of a standardized, declarative approach.

Motivation

The existing implementation relies on JSON.jl v0.21 and uses a custom JSONWrapper struct to handle the omission of nothing fields during serialization. While functional, this approach adds boilerplate and predates the modern object-mapping standards in the Julia ecosystem.

This upgrade provides several key benefits:

  1. Simplicity & Maintainability: Replaces the imperative logic of JSONWrapper with a single, declarative line (StructTypes.omitempties) and removes a significant amount of boilerplate code from src/json.jl.
  2. Performance: Utilizes JSON.read for direct struct deserialization, which avoids allocating an intermediate Dict and can lead to reduced memory usage and faster parsing times.
  3. Robustness: Relies on a well-maintained, standard library (StructTypes.jl) for object mapping, reducing the maintenance burden on OpenAPI.jl itself.

Key Changes

  • Dependency Update:

    • Added StructTypes.jl as a new dependency.
    • Updated the [compat] entry for JSON.jl to 1.
  • Serialization (src/json.jl):

    • The JSONWrapper struct and its associated methods have been completely removed.
    • StructTypes.StructType and StructTypes.omitempties are now defined for APIModel, providing a declarative way to handle struct serialization and omit nothing fields.
  • Deserialization (src/json.jl, src/client.jl, src/server.jl):

    • A StructTypes.construct hook is used to delegate object construction to our existing from_json logic. This preserves all custom handling for date/time types, discriminated unions (oneOf/anyOf), and other special cases.
    • The response function in src/client.jl now uses JSON.read(body, T) for direct, one-step deserialization.
    • Server-side parameter and body parsing in src/server.jl has been updated to use JSON.read.
    • new implementation of stream parsing in src/server.jl that has a significant performance benefit. The original code would parse the JSON, serialize it back to bytes, and then the calling code would parse it again. This new version directly extracts the raw bytes of the JSON chunk, avoiding the unnecessary intermediate steps

Impact on Generated Code

A major advantage of this approach is its minimal impact on the code generated by the OpenAPI Generator. Because the core logic is centralized in the OpenAPI.jl runtime via StructTypes hooks, the individual model_*.jl files and api_*.jl files do not require any changes. The existing generated code will work seamlessly with this updated implementation.

Testing

Full Integration Suite: All existing E2E tests (petstore, forms, allany, etc.) pass successfully. This confirms that the entire client-server request-response lifecycle functions correctly with the new JSON handling.


Contributor Checklist

  • Implemented core logic changes in src/json.jl.
  • Updated src/client.jl and src/server.jl.
  • Added StructTypes.jl to Project.toml and updated JSON.jl compat entry.
  • All existing tests in test/runtests.jl pass successfully.
  • Documentation has been reviewed and does not require updates, as these are internal changes.
  • This PR follows the project's contribution guidelines.

@imohag9 imohag9 closed this Oct 20, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant