forked from mirror/go-json
fix query
This commit is contained in:
parent
e09e0ff5b3
commit
4828b299ce
|
@ -1,6 +1,7 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
|
||||||
"github.com/goccy/go-json"
|
"github.com/goccy/go-json"
|
||||||
|
@ -21,69 +22,66 @@ type UserAddress struct {
|
||||||
Address2 string
|
Address2 string
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserAddressResolver func() (*UserAddress, error)
|
type UserRepository struct {
|
||||||
|
uaRepo *UserAddressRepository
|
||||||
func (resolver UserAddressResolver) MarshalJSON() ([]byte, error) {
|
|
||||||
address, err := resolver()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return json.Marshal(address)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (resolver UserAddressResolver) ResolveQueryJSON(q *json.Query) (interface{}, error) {
|
func NewUserRepository() *UserRepository {
|
||||||
// validate or rewrite json.Query
|
return &UserRepository{
|
||||||
//
|
uaRepo: NewUserAddressRepository(),
|
||||||
address, err := resolver()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
return address, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type UserRepository struct{}
|
|
||||||
|
|
||||||
func (r UserRepository) FindByID(id int64) (*User, error) {
|
|
||||||
v := User{ID: id, Name: "Ken", Age: 20}
|
|
||||||
// resolve relation from User to UserAddress
|
|
||||||
uaRepo := new(UserAddressRepository)
|
|
||||||
v.Address = func() (*UserAddress, error) {
|
|
||||||
return uaRepo.FindByUserID(v.ID)
|
|
||||||
}
|
|
||||||
return v, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type UserAddressRepository struct{}
|
type UserAddressRepository struct{}
|
||||||
|
|
||||||
func (r UserAddressRepository) FindByUserID(id int64) (*UserAddress, error) {
|
func NewUserAddressRepository() *UserAddressRepository {
|
||||||
return &UserAddress{UserID: id, City: "A", Address1: "hoge", Address2: "fuga"}, nil
|
return &UserAddressRepository{}
|
||||||
|
}
|
||||||
|
|
||||||
|
type UserAddressResolver func(context.Context) (*UserAddress, error)
|
||||||
|
|
||||||
|
func (resolver UserAddressResolver) MarshalJSON(ctx context.Context) ([]byte, error) {
|
||||||
|
address, err := resolver(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return json.MarshalWithQuery(address, json.QueryFromContext(ctx))
|
||||||
|
}
|
||||||
|
|
||||||
|
func (r *UserRepository) FindByID(ctx context.Context, id int64) (*User, error) {
|
||||||
|
v := User{ID: id, Name: "Ken", Age: 20}
|
||||||
|
// resolve relation from User to UserAddress
|
||||||
|
v.Address = func(ctx context.Context) (*UserAddress, error) {
|
||||||
|
return r.uaRepo.FindByUserID(ctx, v.ID)
|
||||||
|
}
|
||||||
|
return v, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (*UserAddressRepository) FindByUserID(ctx context.Context, id int64) (*UserAddress, error) {
|
||||||
|
return &UserAddress{
|
||||||
|
UserID: id,
|
||||||
|
City: "A",
|
||||||
|
Address1: "hoge",
|
||||||
|
Address2: "fuga",
|
||||||
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
user, err := new(UserRepository).FindByID(1)
|
userRepo := NewUserRepository()
|
||||||
|
user, err := userRepo.FindByID(context.Background(), 1)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
{
|
q := json.NewQuery().Fields(
|
||||||
b, err := json.Marshal(user)
|
"Name",
|
||||||
if err != nil {
|
"Age",
|
||||||
panic(err)
|
json.NewQuery("Address").Fields(
|
||||||
}
|
"City",
|
||||||
fmt.Println(string(b))
|
),
|
||||||
}
|
)
|
||||||
{
|
b, err := json.MarshalWithQuery(user, q)
|
||||||
//json.QueryFromJSON(`["Name", "Age", { "Address": [ "City" ] }]`)
|
if err != nil {
|
||||||
q := json.NewQuery().Fields(
|
panic(err)
|
||||||
"Name",
|
|
||||||
"Age",
|
|
||||||
json.NewQuery("Address").Fields(
|
|
||||||
"City",
|
|
||||||
),
|
|
||||||
)
|
|
||||||
b, err := json.MarshalWithQuery(user, q)
|
|
||||||
if err != nil {
|
|
||||||
panic(err)
|
|
||||||
}
|
|
||||||
fmt.Println(string(b))
|
|
||||||
}
|
}
|
||||||
|
fmt.Println(string(b))
|
||||||
}
|
}
|
||||||
|
|
57
query.go
57
query.go
|
@ -1,20 +1,26 @@
|
||||||
package json
|
package json
|
||||||
|
|
||||||
import "fmt"
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
)
|
||||||
|
|
||||||
type Query struct {
|
type Query struct {
|
||||||
query *subQuery
|
name string
|
||||||
err error
|
fields []*Query
|
||||||
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type queryKey struct{}
|
||||||
|
|
||||||
func (q *Query) String() string {
|
func (q *Query) String() string {
|
||||||
if q.err != nil {
|
if q.err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
if q.query == nil {
|
if q.fields == nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
b, err := Marshal(q.query.dump())
|
b, err := Marshal(q.dump())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
@ -29,9 +35,9 @@ func (q *Query) Fields(fieldNameOrQueryList ...interface{}) *Query {
|
||||||
for _, fieldNameOrQuery := range fieldNameOrQueryList {
|
for _, fieldNameOrQuery := range fieldNameOrQueryList {
|
||||||
switch v := fieldNameOrQuery.(type) {
|
switch v := fieldNameOrQuery.(type) {
|
||||||
case string:
|
case string:
|
||||||
q.fields = append(q.fields, &subQuery{name: v})
|
q.fields = append(q.fields, &Query{name: v})
|
||||||
case *Query:
|
case *Query:
|
||||||
q.fields = append(q.fields, v.query)
|
q.fields = append(q.fields, v)
|
||||||
q.err = v.err
|
q.err = v.err
|
||||||
default:
|
default:
|
||||||
q.err = fmt.Errorf("children types must be string or *Query but found %T", fieldNameOrQuery)
|
q.err = fmt.Errorf("children types must be string or *Query but found %T", fieldNameOrQuery)
|
||||||
|
@ -43,21 +49,7 @@ func (q *Query) Fields(fieldNameOrQueryList ...interface{}) *Query {
|
||||||
return q
|
return q
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewQuery(name ...string) *Query {
|
func (q *Query) dump() interface{} {
|
||||||
if len(name) > 1 {
|
|
||||||
return &Query{err: fmt.Errorf(
|
|
||||||
"NewQuery's argument allow empty or single name only, but passed %v", name,
|
|
||||||
)}
|
|
||||||
}
|
|
||||||
return &Query{query: &subQuery{name: name}}
|
|
||||||
}
|
|
||||||
|
|
||||||
type subQuery struct {
|
|
||||||
name string
|
|
||||||
fields []*subQuery
|
|
||||||
}
|
|
||||||
|
|
||||||
func (q *subQuery) dump() interface{} {
|
|
||||||
fields := []interface{}{}
|
fields := []interface{}{}
|
||||||
for _, field := range q.fields {
|
for _, field := range q.fields {
|
||||||
fields = append(fields, field.dump())
|
fields = append(fields, field.dump())
|
||||||
|
@ -69,3 +61,24 @@ func (q *subQuery) dump() interface{} {
|
||||||
}
|
}
|
||||||
return interface{}(fields)
|
return interface{}(fields)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func NewQuery(name ...string) *Query {
|
||||||
|
if len(name) > 1 {
|
||||||
|
return &Query{err: fmt.Errorf(
|
||||||
|
"NewQuery's argument allow empty or single name only, but passed %v", name,
|
||||||
|
)}
|
||||||
|
}
|
||||||
|
return &Query{name: name}
|
||||||
|
}
|
||||||
|
|
||||||
|
func QueryFromContext(ctx context.Context) *Query {
|
||||||
|
query := ctx.Value(queryKey{})
|
||||||
|
if query == nil {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
q, ok := query.(*Query)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return q
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue