mirror of
				https://github.com/go-kratos/kratos.git
				synced 2025-10-30 23:47:59 +02:00 
			
		
		
		
	
		
			
				
	
	
		
			88 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			88 lines
		
	
	
		
			1.6 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
| package form
 | |
| 
 | |
| import (
 | |
| 	"net/url"
 | |
| 	"reflect"
 | |
| 
 | |
| 	"github.com/go-playground/form/v4"
 | |
| 	"google.golang.org/protobuf/proto"
 | |
| 
 | |
| 	"github.com/go-kratos/kratos/v2/encoding"
 | |
| )
 | |
| 
 | |
| const (
 | |
| 	// Name is form codec name
 | |
| 	Name = "x-www-form-urlencoded"
 | |
| 	// Null value string
 | |
| 	nullStr = "null"
 | |
| )
 | |
| 
 | |
| var (
 | |
| 	encoder = form.NewEncoder()
 | |
| 	decoder = form.NewDecoder()
 | |
| )
 | |
| 
 | |
| // This variable can be replaced with -ldflags like below:
 | |
| // go build "-ldflags=-X github.com/go-kratos/kratos/v2/encoding/form.tagName=form"
 | |
| var tagName = "json"
 | |
| 
 | |
| func init() {
 | |
| 	decoder.SetTagName(tagName)
 | |
| 	encoder.SetTagName(tagName)
 | |
| 	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()), nil
 | |
| }
 | |
| 
 | |
| func (c codec) Unmarshal(data []byte, v any) error {
 | |
| 	vs, err := url.ParseQuery(string(data))
 | |
| 	if err != nil {
 | |
| 		return err
 | |
| 	}
 | |
| 
 | |
| 	rv := reflect.ValueOf(v)
 | |
| 	for 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 (codec) Name() string {
 | |
| 	return Name
 | |
| }
 |