Skip to content

Commit cdcb9bd

Browse files
author
junoberryferry
committed
adjust jsonv2 output to become similar to v1
1 parent a65bff4 commit cdcb9bd

File tree

5 files changed

+55
-9
lines changed

5 files changed

+55
-9
lines changed

models/webhook/webhook.go

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,14 @@ func init() {
150150
// AfterLoad updates the webhook object upon setting a column
151151
func (w *Webhook) AfterLoad() {
152152
w.HookEvent = &webhook_module.HookEvent{}
153-
if err := json.Unmarshal([]byte(w.Events), w.HookEvent); err != nil {
153+
154+
events := w.Events
155+
if events == "" {
156+
// jsonv2 is unable to unmarshal an empty string
157+
return
158+
}
159+
160+
if err := json.Unmarshal([]byte(events), w.HookEvent); err != nil {
154161
log.Error("Unmarshal[%d]: %v", w.ID, err)
155162
}
156163
}

modules/json/json.go

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -174,7 +174,7 @@ func Indent(dst *bytes.Buffer, src []byte, prefix, indent string) error {
174174

175175
// MarshalIndent copied from encoding/json
176176
func MarshalIndent(v any, prefix, indent string) ([]byte, error) {
177-
b, err := Marshal(v)
177+
b, err := DefaultJSONHandler.Marshal(v)
178178
if err != nil {
179179
return nil, err
180180
}
@@ -200,6 +200,12 @@ func UnmarshalHandleDoubleEncode(bs []byte, v any) error {
200200
// To be consistent, we should treat all empty inputs as success
201201
return nil
202202
}
203+
204+
trimmed := bytes.TrimSpace(bs)
205+
if len(trimmed) == 0 {
206+
return nil
207+
}
208+
203209
err := DefaultJSONHandler.Unmarshal(bs, v)
204210
if err != nil {
205211
ok := true

modules/json/jsonv2.go

Lines changed: 37 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
package json
77

88
import (
9+
"bytes"
910
jsonv2 "encoding/json/v2" //nolint:depguard // this package wraps it
1011
"io"
1112
)
@@ -15,18 +16,38 @@ func isJSONv2Available() bool {
1516
return true
1617
}
1718

18-
// marshalV2 uses JSON v2 marshal with v1 compatibility options
19-
func marshalV2(v any) ([]byte, error) {
19+
// marshalV2Internal uses JSON v2 marshal with v1 compatibility options (no trailing newline)
20+
func marshalV2Internal(v any) ([]byte, error) {
2021
opts := jsonv2.JoinOptions(
2122
jsonv2.MatchCaseInsensitiveNames(true),
2223
jsonv2.FormatNilSliceAsNull(true),
2324
jsonv2.FormatNilMapAsNull(true),
25+
jsonv2.Deterministic(true),
2426
)
2527
return jsonv2.Marshal(v, opts)
2628
}
2729

30+
// marshalV2 uses JSON v2 marshal with v1 compatibility options (with trailing newline for compatibility with standard library)
31+
func marshalV2(v any) ([]byte, error) {
32+
result, err := marshalV2Internal(v)
33+
if err != nil {
34+
return nil, err
35+
}
36+
37+
return append(result, '\n'), nil
38+
}
39+
2840
// unmarshalV2 uses JSON v2 unmarshal with v1 compatibility options
2941
func unmarshalV2(data []byte, v any) error {
42+
if len(data) == 0 {
43+
return nil
44+
}
45+
46+
data = bytes.TrimSpace(data)
47+
if len(data) == 0 {
48+
return nil
49+
}
50+
3051
opts := jsonv2.JoinOptions(
3152
jsonv2.MatchCaseInsensitiveNames(true),
3253
)
@@ -40,7 +61,13 @@ type encoderV2 struct {
4061
}
4162

4263
func (e *encoderV2) Encode(v any) error {
43-
return jsonv2.MarshalWrite(e.writer, v, e.opts)
64+
err := jsonv2.MarshalWrite(e.writer, v, e.opts)
65+
if err != nil {
66+
return err
67+
}
68+
69+
_, err = e.writer.Write([]byte{'\n'})
70+
return err
4471
}
4572

4673
// newEncoderV2 creates a new JSON v2 streaming encoder
@@ -49,6 +76,7 @@ func newEncoderV2(writer io.Writer) Encoder {
4976
jsonv2.MatchCaseInsensitiveNames(true),
5077
jsonv2.FormatNilSliceAsNull(true),
5178
jsonv2.FormatNilMapAsNull(true),
79+
jsonv2.Deterministic(true),
5280
)
5381
return &encoderV2{writer: writer, opts: opts}
5482
}
@@ -60,7 +88,12 @@ type decoderV2 struct {
6088
}
6189

6290
func (d *decoderV2) Decode(v any) error {
63-
return jsonv2.UnmarshalRead(d.reader, v, d.opts)
91+
err := jsonv2.UnmarshalRead(d.reader, v, d.opts)
92+
// Handle EOF more gracefully to match standard library behavior
93+
if err != nil && err.Error() == "unexpected EOF" {
94+
return io.EOF
95+
}
96+
return err
6497
}
6598

6699
// newDecoderV2 creates a new JSON v2 streaming decoder

services/webhook/deliver_test.go

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -142,13 +142,13 @@ func TestWebhookDeliverHookTask(t *testing.T) {
142142
assert.NoError(t, err)
143143
assert.Equal(t, `{"data": 42}`, string(body))
144144

145-
case "/webhook/6db5dc1e282529a8c162c7fe93dd2667494eeb51":
145+
case "/webhook/4ddf3b1533e54f082ae6eadfc1b5530be36c8893":
146146
// Version 2
147147
assert.Equal(t, "push", r.Header.Get("X-GitHub-Event"))
148148
assert.Equal(t, "application/json", r.Header.Get("Content-Type"))
149149
body, err := io.ReadAll(r.Body)
150150
assert.NoError(t, err)
151-
assert.Len(t, body, 2147)
151+
assert.Len(t, body, 2047)
152152

153153
default:
154154
w.WriteHeader(http.StatusNotFound)

services/webhook/matrix_test.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -216,7 +216,7 @@ func TestMatrixJSONPayload(t *testing.T) {
216216
require.NoError(t, err)
217217

218218
assert.Equal(t, "PUT", req.Method)
219-
assert.Equal(t, "/_matrix/client/r0/rooms/ROOM_ID/send/m.room.message/6db5dc1e282529a8c162c7fe93dd2667494eeb51", req.URL.Path)
219+
assert.Equal(t, "/_matrix/client/r0/rooms/ROOM_ID/send/m.room.message/4ddf3b1533e54f082ae6eadfc1b5530be36c8893", req.URL.Path)
220220
assert.Equal(t, "sha256=", req.Header.Get("X-Hub-Signature-256"))
221221
assert.Equal(t, "application/json", req.Header.Get("Content-Type"))
222222
var body MatrixPayload

0 commit comments

Comments
 (0)