github.com/kaydxh/golang@v0.0.131/go/runtime/marshaler/jsonpb.marshaler.go (about)

     1  /*
     2   *Copyright (c) 2022, kaydxh
     3   *
     4   *Permission is hereby granted, free of charge, to any person obtaining a copy
     5   *of this software and associated documentation files (the "Software"), to deal
     6   *in the Software without restriction, including without limitation the rights
     7   *to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     8   *copies of the Software, and to permit persons to whom the Software is
     9   *furnished to do so, subject to the following conditions:
    10   *
    11   *The above copyright notice and this permission notice shall be included in all
    12   *copies or substantial portions of the Software.
    13   *
    14   *THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    15   *IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    16   *FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
    17   *AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    18   *LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
    19   *OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
    20   *SOFTWARE.
    21   */
    22  package marshaler
    23  
    24  import (
    25  	"encoding/json"
    26  	"fmt"
    27  
    28  	structpb "github.com/golang/protobuf/ptypes/struct"
    29  	"github.com/grpc-ecosystem/grpc-gateway/v2/runtime"
    30  	"google.golang.org/protobuf/proto"
    31  )
    32  
    33  type JSONPb struct {
    34  	runtime.JSONPb
    35  	opts struct {
    36  		useProtoNames   bool
    37  		useEnumNumbers  bool
    38  		emitUnpopulated bool
    39  		discardUnknown  bool
    40  		allowPartial    bool
    41  		indent          string
    42  	}
    43  }
    44  
    45  func NewDefaultJSONPb() *JSONPb {
    46  	return NewJSONPb(
    47  		// ummarshal for input
    48  		// marshal for output
    49  		// use json name
    50  		// only for mashaler
    51  		WithUseProtoNames(false),
    52  		//false means use enum string for output
    53  		WithUseEnumNumbers(false),
    54  		WithEmitUnpopulated(true),
    55  		WithIndent("\t"),
    56  		// only for unmarshal
    57  		WithDiscardUnknown(true),
    58  		// for marshal , unmarshal
    59  		WithAllowPartial(true),
    60  	)
    61  }
    62  
    63  func NewJSONPb(options ...JSONPbOption) *JSONPb {
    64  	j := &JSONPb{}
    65  	j.ApplyOptions(options...)
    66  
    67  	if j.opts.useProtoNames {
    68  		j.MarshalOptions.UseProtoNames = true
    69  	}
    70  	if j.opts.useEnumNumbers {
    71  		j.MarshalOptions.UseEnumNumbers = true
    72  	}
    73  	if j.opts.emitUnpopulated {
    74  		j.MarshalOptions.EmitUnpopulated = true
    75  	}
    76  	if j.opts.indent != "" {
    77  		j.MarshalOptions.Indent = j.opts.indent
    78  	}
    79  	if j.opts.allowPartial {
    80  		j.MarshalOptions.AllowPartial = true
    81  		j.UnmarshalOptions.AllowPartial = true
    82  	}
    83  	if j.opts.discardUnknown {
    84  		j.UnmarshalOptions.DiscardUnknown = true
    85  	}
    86  
    87  	return j
    88  }
    89  
    90  func (j *JSONPb) Marshal(v interface{}) ([]byte, error) {
    91  	return j.JSONPb.Marshal(v)
    92  }
    93  
    94  func (j *JSONPb) MarshaToStructpb(v interface{}) (*structpb.Struct, error) {
    95  	var jb []byte
    96  	switch v := v.(type) {
    97  	case nil:
    98  		return &structpb.Struct{}, nil
    99  
   100  	case *structpb.Struct:
   101  		return v, nil
   102  
   103  	case proto.Message:
   104  		data, err := j.JSONPb.Marshal(v)
   105  		if err != nil {
   106  			return nil, fmt.Errorf("failed to Marshal json: %v", err)
   107  		}
   108  		jb = []byte(data)
   109  
   110  	case []byte:
   111  		jb = v
   112  	case *[]byte:
   113  		jb = *v
   114  	case string:
   115  		jb = []byte(v)
   116  	case *string:
   117  		jb = []byte(*v)
   118  	default:
   119  		var err error
   120  		jb, err = json.Marshal(v)
   121  		if err != nil {
   122  			return nil, fmt.Errorf("failed to Marshal json: %v", err)
   123  		}
   124  	}
   125  
   126  	var dataStructpb structpb.Struct
   127  	if err := j.JSONPb.Unmarshal(jb, &dataStructpb); err != nil {
   128  		return nil, err
   129  	}
   130  	return &dataStructpb, nil
   131  }
   132  
   133  /*
   134  // if implemet the function, can parse some field from req data
   135  func (j *JSONPb) NewDecoder(r io.Reader) runtime.Decoder {
   136  	return runtime.DecoderFunc(func(v interface{}) error {
   137  		rawData, err := ioutil.ReadAll(r)
   138  		if err != nil {
   139  			return err
   140  		}
   141  		err = j.JSONPb.Unmarshal(rawData, v)
   142  		if err != nil {
   143  			return err
   144  		}
   145  		id := reflect_.RetrieveId(v, reflect_.FieldNameRequestId)
   146  		_ = id
   147  		return nil
   148  	})
   149  }
   150  */