mirror of https://github.com/rocboss/paopao-ce
parent
81ae8c0596
commit
8f834e71a2
@ -1,64 +0,0 @@
|
|||||||
// Copyright 2023 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package types
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql"
|
|
||||||
"database/sql/driver"
|
|
||||||
stdjson "encoding/json"
|
|
||||||
"errors"
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
var (
|
|
||||||
_ stdjson.Marshaler = (*JsonType[any])(nil)
|
|
||||||
_ stdjson.Unmarshaler = (*JsonType[any])(nil)
|
|
||||||
_ driver.Valuer = (*JsonType[any])(nil)
|
|
||||||
_ sql.Scanner = (*JsonType[any])(nil)
|
|
||||||
)
|
|
||||||
|
|
||||||
type JsonType[T any] struct {
|
|
||||||
Data T
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *JsonType[T]) MarshalJSON() ([]byte, error) {
|
|
||||||
if j == nil {
|
|
||||||
return []byte(`null`), nil
|
|
||||||
}
|
|
||||||
return json.Marshal(j.Data)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *JsonType[T]) UnmarshalJSON(data []byte) error {
|
|
||||||
if j == nil {
|
|
||||||
return errors.New("JSONText.UnmarshalJSON: on nil pointer")
|
|
||||||
}
|
|
||||||
return json.Unmarshal(data, &j.Data)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *JsonType[T]) Value() (driver.Value, error) {
|
|
||||||
if j == nil {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
return j.MarshalJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (j *JsonType[T]) Scan(value any) error {
|
|
||||||
if value == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var b []byte
|
|
||||||
switch v := value.(type) {
|
|
||||||
case []byte:
|
|
||||||
b = v
|
|
||||||
case string:
|
|
||||||
b = []byte(v)
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("JSONText.Scan: expected []byte or string, got %T (%q)", value, value)
|
|
||||||
}
|
|
||||||
return j.UnmarshalJSON(b)
|
|
||||||
}
|
|
@ -0,0 +1,82 @@
|
|||||||
|
// Copyright 2023 ROC. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package types
|
||||||
|
|
||||||
|
import (
|
||||||
|
"database/sql"
|
||||||
|
"database/sql/driver"
|
||||||
|
stdjson "encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
|
||||||
|
"github.com/rocboss/paopao-ce/pkg/json"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_ stdjson.Marshaler = (*JsonBox[any])(nil)
|
||||||
|
_ stdjson.Unmarshaler = (*JsonBox[any])(nil)
|
||||||
|
_ driver.Valuer = (*JsonBox[any])(nil)
|
||||||
|
_ sql.Scanner = (*JsonBox[any])(nil)
|
||||||
|
_ Boxes[any] = (*JsonBox[any])(nil)
|
||||||
|
)
|
||||||
|
|
||||||
|
// JsonBox Json box for process database/sql json data
|
||||||
|
type JsonBox[T any] struct {
|
||||||
|
data T
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JsonBox[T]) MarshalJSON() ([]byte, error) {
|
||||||
|
if j == nil {
|
||||||
|
return []byte(`null`), nil
|
||||||
|
}
|
||||||
|
return json.Marshal(j.data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JsonBox[T]) Box(t T) {
|
||||||
|
j.data = t
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JsonBox[T]) Unbox() T {
|
||||||
|
return j.data
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JsonBox[T]) UnmarshalJSON(data []byte) error {
|
||||||
|
if j == nil {
|
||||||
|
return errors.New("JsonBox.UnmarshalJSON: on nil pointer")
|
||||||
|
}
|
||||||
|
return json.Unmarshal(data, &j.data)
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JsonBox[T]) Value() (driver.Value, error) {
|
||||||
|
if j == nil {
|
||||||
|
return nil, nil
|
||||||
|
}
|
||||||
|
return j.MarshalJSON()
|
||||||
|
}
|
||||||
|
|
||||||
|
func (j *JsonBox[T]) Scan(value any) error {
|
||||||
|
if value == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
var b []byte
|
||||||
|
switch v := value.(type) {
|
||||||
|
case []byte:
|
||||||
|
b = v
|
||||||
|
case string:
|
||||||
|
b = []byte(v)
|
||||||
|
default:
|
||||||
|
return fmt.Errorf("JsonBox.Scan: expected []byte or string, got %T (%q)", value, value)
|
||||||
|
}
|
||||||
|
return j.UnmarshalJSON(b)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewJsonBox create a new JsonBox instance
|
||||||
|
func NewJsonBox[T any](t ...T) *JsonBox[T] {
|
||||||
|
if len(t) > 0 {
|
||||||
|
return &JsonBox[T]{data: t[0]}
|
||||||
|
}
|
||||||
|
return &JsonBox[T]{}
|
||||||
|
}
|
@ -0,0 +1,85 @@
|
|||||||
|
// Copyright 2023 ROC. All rights reserved.
|
||||||
|
// Use of this source code is governed by a MIT style
|
||||||
|
// license that can be found in the LICENSE file.
|
||||||
|
|
||||||
|
package types_test
|
||||||
|
|
||||||
|
import (
|
||||||
|
"encoding/json"
|
||||||
|
|
||||||
|
. "github.com/onsi/ginkgo/v2"
|
||||||
|
. "github.com/onsi/gomega"
|
||||||
|
|
||||||
|
"github.com/rocboss/paopao-ce/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
var _ = Describe("JsonBox", Ordered, func() {
|
||||||
|
type jsonCases []struct {
|
||||||
|
j *types.JsonBox[json.RawMessage]
|
||||||
|
b []byte
|
||||||
|
}
|
||||||
|
var samples jsonCases
|
||||||
|
|
||||||
|
BeforeAll(func() {
|
||||||
|
samples = jsonCases{
|
||||||
|
{
|
||||||
|
j: types.NewJsonBox(json.RawMessage(`null`)),
|
||||||
|
b: []byte(`null`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
j: types.NewJsonBox(json.RawMessage(`{}`)),
|
||||||
|
b: []byte(`{}`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
j: types.NewJsonBox(json.RawMessage(`[]`)),
|
||||||
|
b: []byte(`[]`),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
j: types.NewJsonBox(json.RawMessage(`[{"b":true,"n":123},{"s":"foo","obj":{"f1":456,"f2":false}},[null]]`)),
|
||||||
|
b: []byte(`[{"b":true,"n":123},{"s":"foo","obj":{"f1":456,"f2":false}},[null]]`),
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("boxes Box and Unbox", func() {
|
||||||
|
for _, t := range samples {
|
||||||
|
jv := types.NewJsonBox[json.RawMessage]()
|
||||||
|
jv.Box(json.RawMessage(t.b))
|
||||||
|
Expect(jv.Unbox()).To(Equal(t.j.Unbox()))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("json marshaler", func() {
|
||||||
|
for _, t := range samples {
|
||||||
|
mv, err := t.j.MarshalJSON()
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
Expect(mv).To(Equal(t.b))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("json unmarshaler", func() {
|
||||||
|
for _, t := range samples {
|
||||||
|
jv := types.NewJsonBox[json.RawMessage]()
|
||||||
|
err := jv.UnmarshalJSON(t.b)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
Expect(t.j.Unbox()).To(Equal(jv.Unbox()))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("driver valuer", func() {
|
||||||
|
for _, t := range samples {
|
||||||
|
v, err := t.j.Value()
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
Expect(v).To(Equal(t.b))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
It("sql scaner", func() {
|
||||||
|
for _, t := range samples {
|
||||||
|
jv := types.NewJsonBox[json.RawMessage]()
|
||||||
|
err := jv.Scan(t.b)
|
||||||
|
Expect(err).To(BeNil())
|
||||||
|
Expect(jv.Unbox()).To(Equal(t.j.Unbox()))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
})
|
@ -1,60 +0,0 @@
|
|||||||
// Copyright 2023 ROC. All rights reserved.
|
|
||||||
// Use of this source code is governed by a MIT style
|
|
||||||
// license that can be found in the LICENSE file.
|
|
||||||
|
|
||||||
package types_test
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
|
|
||||||
. "github.com/onsi/ginkgo/v2"
|
|
||||||
. "github.com/onsi/gomega"
|
|
||||||
|
|
||||||
"github.com/rocboss/paopao-ce/pkg/types"
|
|
||||||
)
|
|
||||||
|
|
||||||
var _ = Describe("Json", Ordered, func() {
|
|
||||||
type jsonCases []struct {
|
|
||||||
j types.JsonType[json.RawMessage]
|
|
||||||
b []byte
|
|
||||||
}
|
|
||||||
var samples jsonCases
|
|
||||||
|
|
||||||
BeforeAll(func() {
|
|
||||||
samples = jsonCases{
|
|
||||||
{
|
|
||||||
j: types.JsonType[json.RawMessage]{json.RawMessage(`null`)},
|
|
||||||
b: []byte(`null`),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
j: types.JsonType[json.RawMessage]{json.RawMessage(`{}`)},
|
|
||||||
b: []byte(`{}`),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
j: types.JsonType[json.RawMessage]{json.RawMessage(`[]`)},
|
|
||||||
b: []byte(`[]`),
|
|
||||||
},
|
|
||||||
{
|
|
||||||
j: types.JsonType[json.RawMessage]{json.RawMessage(`[{"b":true,"n":123},{"s":"foo","obj":{"f1":456,"f2":false}},[null]]`)},
|
|
||||||
b: []byte(`[{"b":true,"n":123},{"s":"foo","obj":{"f1":456,"f2":false}},[null]]`),
|
|
||||||
},
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
It("driver valuer ", func() {
|
|
||||||
for _, t := range samples {
|
|
||||||
v, err := t.j.Value()
|
|
||||||
Expect(err).To(BeNil())
|
|
||||||
Expect(v).To(Equal(t.b))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
It("sql scan ", func() {
|
|
||||||
for _, t := range samples {
|
|
||||||
var jv types.JsonType[json.RawMessage]
|
|
||||||
err := jv.Scan(t.b)
|
|
||||||
Expect(err).To(BeNil())
|
|
||||||
Expect(jv.Data).To(Equal(t.j.Data))
|
|
||||||
}
|
|
||||||
})
|
|
||||||
})
|
|
Loading…
Reference in new issue