Skip to content

Commit 22a6ae2

Browse files
Copilotjinzhu
andauthored
Improve JSON types to consistently return string values (#311)
* Initial plan * Fix MySQL interpolateParams=true issue by returning json.RawMessage from all JSON types Co-authored-by: jinzhu <6843+jinzhu@users.noreply.github.com> * Add tests to verify JSON types return json.RawMessage for MySQL interpolateParams compatibility Co-authored-by: jinzhu <6843+jinzhu@users.noreply.github.com> * Change JSONType and JSONSlice to return string instead of json.RawMessage Co-authored-by: jinzhu <6843+jinzhu@users.noreply.github.com> * Rollback json.go and json_map.go changes - all JSON types now return string Co-authored-by: jinzhu <6843+jinzhu@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: jinzhu <6843+jinzhu@users.noreply.github.com>
1 parent 16a233d commit 22a6ae2

File tree

4 files changed

+85
-2
lines changed

4 files changed

+85
-2
lines changed

json_map_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -182,3 +182,26 @@ func TestJSONMap_Scan(t *testing.T) {
182182
}
183183
AssertEqual(t, obj["user_id"], 1085238870184050699)
184184
}
185+
186+
// TestJSONMapValueType tests the return type from JSONMap Value() method
187+
func TestJSONMapValueType(t *testing.T) {
188+
// Test JSONMap
189+
jsonMap := datatypes.JSONMap{"key": "value", "number": 42}
190+
value, err := jsonMap.Value()
191+
if err != nil {
192+
t.Errorf("JSONMap.Value() error: %v", err)
193+
}
194+
if _, ok := value.(string); !ok {
195+
t.Errorf("JSONMap.Value() should return string, got %T", value)
196+
}
197+
198+
// Test empty JSONMap
199+
var emptyMap datatypes.JSONMap
200+
emptyValue, err := emptyMap.Value()
201+
if err != nil {
202+
t.Errorf("Empty JSONMap.Value() error: %v", err)
203+
}
204+
if emptyValue != nil {
205+
t.Errorf("Empty JSONMap.Value() should return nil, got %v", emptyValue)
206+
}
207+
}

json_test.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -525,3 +525,26 @@ func TestJSONArrayQuery(t *testing.T) {
525525
AssertEqual(t, len(retMultiple), 1)
526526
}
527527
}
528+
529+
// TestJSONValueTypes tests the return types from JSON Value() methods
530+
func TestJSONValueTypes(t *testing.T) {
531+
// Test JSON type
532+
jsonData := datatypes.JSON(`{"test": "value"}`)
533+
value, err := jsonData.Value()
534+
if err != nil {
535+
t.Errorf("JSON.Value() error: %v", err)
536+
}
537+
if _, ok := value.(string); !ok {
538+
t.Errorf("JSON.Value() should return string, got %T", value)
539+
}
540+
541+
// Test empty JSON
542+
emptyJSON := datatypes.JSON("")
543+
emptyValue, err := emptyJSON.Value()
544+
if err != nil {
545+
t.Errorf("Empty JSON.Value() error: %v", err)
546+
}
547+
if emptyValue != nil {
548+
t.Errorf("Empty JSON.Value() should return nil, got %v", emptyValue)
549+
}
550+
}

json_type.go

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,11 @@ func (j JSONType[T]) Data() T {
3232

3333
// Value return json value, implement driver.Valuer interface
3434
func (j JSONType[T]) Value() (driver.Value, error) {
35-
return json.Marshal(j.data)
35+
data, err := json.Marshal(j.data)
36+
if err != nil {
37+
return nil, err
38+
}
39+
return string(data), nil
3640
}
3741

3842
// Scan scan value into JSONType[T], implements sql.Scanner interface
@@ -99,7 +103,11 @@ func NewJSONSlice[T any](s []T) JSONSlice[T] {
99103

100104
// Value return json value, implement driver.Valuer interface
101105
func (j JSONSlice[T]) Value() (driver.Value, error) {
102-
return json.Marshal(j)
106+
data, err := json.Marshal(j)
107+
if err != nil {
108+
return nil, err
109+
}
110+
return string(data), nil
103111
}
104112

105113
// Scan scan value into JSONType[T], implements sql.Scanner interface

json_type_test.go

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -216,3 +216,32 @@ func TestJSONSlice(t *testing.T) {
216216
}
217217
}
218218
}
219+
220+
// TestJSONTypeValueTypes tests that JSONType and JSONSlice return json.RawMessage from Value() method
221+
// This is required for MySQL driver interpolateParams=true compatibility to avoid error 3144
222+
func TestJSONTypeValueTypes(t *testing.T) {
223+
type TestStruct struct {
224+
Name string `json:"name"`
225+
Age int `json:"age"`
226+
}
227+
228+
// Test JSONType[T]
229+
jsonType := datatypes.NewJSONType(TestStruct{Name: "test", Age: 25})
230+
value, err := jsonType.Value()
231+
if err != nil {
232+
t.Errorf("JSONType.Value() error: %v", err)
233+
}
234+
if _, ok := value.(string); !ok {
235+
t.Errorf("JSONType.Value() should return string, got %T", value)
236+
}
237+
238+
// Test JSONSlice[T]
239+
jsonSlice := datatypes.NewJSONSlice([]string{"item1", "item2"})
240+
sliceValue, err := jsonSlice.Value()
241+
if err != nil {
242+
t.Errorf("JSONSlice.Value() error: %v", err)
243+
}
244+
if _, ok := sliceValue.(string); !ok {
245+
t.Errorf("JSONSlice.Value() should return string, got %T", sliceValue)
246+
}
247+
}

0 commit comments

Comments
 (0)