diff --git a/internal/message/content.go b/internal/message/content.go index b3021c48cc60247e016181e7d79134cdeca3c856..e226034f574b9561a3b0d2ea4adaf3b0267608f3 100644 --- a/internal/message/content.go +++ b/internal/message/content.go @@ -2,6 +2,7 @@ package message import ( "encoding/base64" + "encoding/json" "slices" "time" @@ -142,6 +143,51 @@ type Message struct { UpdatedAt int64 `json:"updated_at"` } +// MarshalJSON implements the [json.Marshaler] interface. +func (m Message) MarshalJSON() ([]byte, error) { + // We need to handle the Parts specially since they're ContentPart interfaces + // which can't be directly marshaled by the standard JSON package. + parts, err := marshallParts(m.Parts) + if err != nil { + return nil, err + } + + // Create an alias to avoid infinite recursion + type Alias Message + return json.Marshal(&struct { + Parts json.RawMessage `json:"parts"` + *Alias + }{ + Parts: json.RawMessage(parts), + Alias: (*Alias)(&m), + }) +} + +// UnmarshalJSON implements the [json.Unmarshaler] interface. +func (m *Message) UnmarshalJSON(data []byte) error { + // Create an alias to avoid infinite recursion + type Alias Message + aux := &struct { + Parts json.RawMessage `json:"parts"` + *Alias + }{ + Alias: (*Alias)(m), + } + + if err := json.Unmarshal(data, &aux); err != nil { + return err + } + + // Unmarshal the parts using our custom function + parts, err := unmarshallParts([]byte(aux.Parts)) + if err != nil { + return err + } + + m.Parts = parts + return nil +} + func (m *Message) Content() TextContent { for _, part := range m.Parts { if c, ok := part.(TextContent); ok {