package form import ( "git.diulo.com/mogfee/kit/encoding" "github.com/go-playground/form" "google.golang.org/protobuf/proto" "net/url" "reflect" ) const ( Name = "x-www-form-urlencoded" nullStr = "null" ) var ( encoder = form.NewEncoder() decoder = form.NewDecoder() ) func init() { decoder.SetTagName("json") encoder.SetTagName("json") encoding.RegisterCodec(codec{ encoder: encoder, decoder: decoder, }) } type codec struct { encoder *form.Encoder decoder *form.Decoder } func (c codec) Marshal(v any) ([]byte, error) { var vs url.Values var err error if m, ok := v.(proto.Message); ok { vs, err = EncodeValues(m) if err != nil { return nil, err } } else { vs, err = c.encoder.Encode(v) if err != nil { return nil, err } } for k, v := range vs { if len(v) == 0 { delete(vs, k) } } return []byte(vs.Encode()), err } func (c codec) Unmarshal(data []byte, v any) error { vs, err := url.ParseQuery(string(data)) if err != nil { return err } rv := reflect.ValueOf(v) if rv.Kind() == reflect.Ptr { if rv.IsNil() { rv.Set(reflect.New(rv.Type().Elem())) } rv = rv.Elem() } if m, ok := v.(proto.Message); ok { return DecodeValues(m, vs) } if m, ok := rv.Interface().(proto.Message); ok { return DecodeValues(m, vs) } return c.decoder.Decode(v, vs) } func (c codec) Name() string { return Name }