Skip to content

struct_to_gts_schema: gts_type field blocks Deserialize for structs #72

@striped-zebra-dev

Description

@striped-zebra-dev

Problem

The struct_to_gts_schema proc macro injects a gts_type: GtsSchemaId field into every struct it processes, with #[serde(skip_serializing)]. This means:

  1. Serialization: gts_type is correctly omitted from JSON output
  2. Deserialization: serde still expects gts_type in the JSON input, causing missing field "gts_type" errors

The macro generates both Serialize and Deserialize impls, but skip_serializing only covers one direction.

Impact

Any struct using #[struct_to_gts_schema] cannot be deserialized from JSON without a workaround. This blocks use cases like:

  • Round-trip serialization/deserialization (e.g., CanonicalError → Problem → CanonicalError)
  • Deserializing context types from HTTP response bodies in SDK clients
  • Testing with JSON fixtures

Current Workaround

Adding default = "dummy_gts_schema_id" to the serde attribute on every struct, with a function that constructs a placeholder GtsSchemaId via serde_json::from_value. This is fragile and pollutes consumer code.

Proposed Fix

Change the macro to emit #[serde(skip)] (which handles both serialization and deserialization) on the gts_type field. This requires one of:

  • Option A: Implement Default for GtsSchemaId (e.g., GtsSchemaId("") or GtsSchemaId::empty()) — then #[serde(skip)] works automatically
  • Option B: Have the macro emit #[serde(skip_serializing, default = "...")] with a generated default function per struct (using Self::gts_schema_id().clone())
  • Option C: Remove the gts_type instance field entirely — the schema ID is already available as Self::gts_schema_id() via the GtsSchema trait. The field is always #[allow(dead_code)] and never read at runtime.

Option C is the cleanest — the field has no runtime purpose.

Environment

  • gts / gts-macros: 0.8.2
  • serde: 1.x

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions