From 8310e8341e76c367d1abcf45e1ec84181f5e829d Mon Sep 17 00:00:00 2001 From: "pulse-triage[bot]" <249995291+pulse-triage[bot]@users.noreply.github.com> Date: Mon, 5 Oct 2026 14:18:18 +0100 Subject: [PATCH] Preserve text marshalers in absent-facet conversion Review of the nil fast path identified named nil collections that implement encoding.TextMarshaler rather than json.Marshaler. Keep the parent representation for both interfaces and retain matching byte-level controls. Contract-Neutral: Conversion work only; retain the exact existing JSON and text-marshaler representations and all broadcast fields and freshness boundaries. Change-source: pulse-maintainer --- internal/monitoring/broadcast_conversion_test.go | 10 ++++++++++ internal/monitoring/monitor.go | 5 ++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/internal/monitoring/broadcast_conversion_test.go b/internal/monitoring/broadcast_conversion_test.go index 51acb44221..0702662cb2 100644 --- a/internal/monitoring/broadcast_conversion_test.go +++ b/internal/monitoring/broadcast_conversion_test.go @@ -22,6 +22,14 @@ type projectionNilMap map[string]string func (projectionNilMap) MarshalJSON() ([]byte, error) { return []byte(`{"custom":true}`), nil } +type projectionNilTextSlice []string + +func (projectionNilTextSlice) MarshalText() ([]byte, error) { return []byte("custom-text"), nil } + +type projectionNilTextMap map[string]string + +func (projectionNilTextMap) MarshalText() ([]byte, error) { return []byte("custom-text"), nil } + type projectionInvalidJSON struct{} func (projectionInvalidJSON) MarshalJSON() ([]byte, error) { return []byte(`{broken`), nil } @@ -53,6 +61,8 @@ func TestBroadcastRawJSONPreservesAbsentEmptyAndFailureSemantics(t *testing.T) { {"empty-slice", []string{}}, {"empty-map", map[string]string{}}, {"named-nil-slice-marshaler", projectionNilSlice(nil)}, {"named-nil-map-marshaler", projectionNilMap(nil)}, + {"named-nil-slice-text-marshaler", projectionNilTextSlice(nil)}, + {"named-nil-map-text-marshaler", projectionNilTextMap(nil)}, {"nil-pointer-marshaler", (*projectionNilSlice)(nil)}, {"invalid-json", projectionInvalidJSON{}}, {"encode-failure", projectionFailedJSON{}}, {"invalid-float", math.NaN()}, {"raw-null", json.RawMessage(`null`)}, diff --git a/internal/monitoring/monitor.go b/internal/monitoring/monitor.go index 57f0c98042..53182cf222 100644 --- a/internal/monitoring/monitor.go +++ b/internal/monitoring/monitor.go @@ -3,6 +3,7 @@ package monitoring import ( "context" "crypto/sha256" + "encoding" "encoding/hex" "encoding/json" stderrors "errors" @@ -6654,7 +6655,9 @@ func monitorRawJSON(value interface{}) json.RawMessage { case reflect.Slice, reflect.Map: if v.IsNil() { if _, custom := value.(json.Marshaler); !custom { - return nil + if _, customText := value.(encoding.TextMarshaler); !customText { + return nil + } } } }