Skip to content

fix: handle integer:"string" tags in map values during JSON unmarshal#106

Open
c1-dev-bot[bot] wants to merge 1 commit into
mainfrom
fix/iga-731-escalation-expiration-unmarshal
Open

fix: handle integer:"string" tags in map values during JSON unmarshal#106
c1-dev-bot[bot] wants to merge 1 commit into
mainfrom
fix/iga-731-escalation-expiration-unmarshal

Conversation

@c1-dev-bot
Copy link
Copy Markdown

@c1-dev-bot c1-dev-bot Bot commented Apr 7, 2026

Summary

Fixes the root cause of the Escalation.Expiration JSON unmarshaling failure (IGA-731).

The unmarshalValue function's map handling fell through to standard json.Unmarshal for maps with struct value types (like map[string]PolicySteps). Standard json doesn't understand the integer:"string" struct tag, so nested structs like Escalation with string-encoded int64 fields failed with:

json: cannot unmarshal string into Go struct field Escalation.steps.approval.escalation.expiration of type int64

Root cause

In pkg/utils/json.go, the unmarshalValue map case checked isComplexValueType (time.Time, big.Int, types.Date) to decide whether to use the recursive custom unmarshal path or fall through to standard json.Unmarshal. Struct types (model types) were not considered "complex", so maps with struct values always used standard json, which doesn't respect custom tags like integer:"string".

Fix

Extended the condition to also use the recursive unmarshal path when the map value type is a model type (struct). This ensures custom struct tags are respected throughout the entire unmarshal chain, matching how slices/arrays already handle this correctly.

Also added pointer dereferencing in the map recursive path (matching the existing slice/array pattern) to handle cases where the map value is behind a pointer.

Test plan

  • Added TestUnmarshalMapWithNestedStringInt64 that reproduces the exact error from the issue
  • Added TestUnmarshalMapWithNestedStringInt64_NumericValue for string-encoded ints in direct map values
  • Added TestMarshalMapWithNestedStringInt64 to verify marshal round-trip
  • All existing tests pass (31 tests in pkg/utils, full suite green)

The unmarshalValue function's map handling fell through to standard
json.Unmarshal for maps with struct value types. Standard json doesn't
understand the integer:"string" struct tag, so nested structs like
Escalation with string-encoded int64 fields (e.g., expiration: "3600")
failed to unmarshal.

This fix extends the recursive unmarshal path (already used for complex
types like time.Time) to also handle model types (structs), ensuring
custom struct tags are respected throughout the entire unmarshal chain.

Fixes IGA-731
@linear
Copy link
Copy Markdown

linear Bot commented Apr 7, 2026

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.

0 participants