github.com/opentelekomcloud/gophertelekomcloud@v0.9.3/internal/build/request_body.go (about)

     1  package build
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  )
     7  
     8  // Body wraps original request data providing root tag support.
     9  //
    10  // Example:
    11  //
    12  //	wrapped := structure {
    13  //		Field string `json:"field"`
    14  //	} {"data"}
    15  //
    16  //	Body{
    17  //		RootTag: "root",
    18  //		Wrapped: wrapped,
    19  //	}
    20  //
    21  // Will produce the following json:
    22  //
    23  //	{
    24  //	  "root": {"field": "data"}
    25  //	}
    26  type Body struct {
    27  	RootTag string
    28  	Wrapped interface{}
    29  }
    30  
    31  // prepared returns request body, wrapped into a root tag, if required.
    32  func (r Body) prepared() interface{} {
    33  	if r.RootTag == "" {
    34  		return r.Wrapped
    35  	}
    36  
    37  	return map[string]interface{}{
    38  		r.RootTag: r.Wrapped,
    39  	}
    40  }
    41  
    42  // MarshalJSON satisfies json.Marshaler interface.
    43  func (r Body) MarshalJSON() ([]byte, error) {
    44  	return json.Marshal(r.prepared())
    45  }
    46  
    47  // String allows simple pretty-print of prepared value.
    48  func (r Body) String() string {
    49  	jsonData, err := json.MarshalIndent(r.prepared(), "", "  ")
    50  	if err != nil {
    51  		return fmt.Sprintf("!err: %s", err.Error())
    52  	}
    53  
    54  	return string(jsonData)
    55  }
    56  
    57  // RequestBody validates given structure by its tags and build the body ready to be marshalled to the JSON.
    58  func RequestBody(opts interface{}, parent string) (*Body, error) {
    59  	if opts == nil {
    60  		return nil, fmt.Errorf("error building request body: %w", ErrNilOpts)
    61  	}
    62  
    63  	if err := ValidateTags(opts); err != nil {
    64  		return nil, fmt.Errorf("error building request body: %w", err)
    65  	}
    66  
    67  	return &Body{
    68  		RootTag: parent,
    69  		Wrapped: opts,
    70  	}, nil
    71  }
    72  
    73  func (r Body) ToMap() (map[string]interface{}, error) {
    74  	var res map[string]interface{}
    75  
    76  	marshal, err := r.MarshalJSON()
    77  	if err != nil {
    78  		return nil, err
    79  	}
    80  
    81  	err = json.Unmarshal(marshal, &res)
    82  	return res, err
    83  }
    84  
    85  func RequestBodyMap(opts interface{}, parent string) (map[string]interface{}, error) {
    86  	body, err := RequestBody(opts, parent)
    87  	if err != nil {
    88  		return nil, err
    89  	}
    90  
    91  	return body.ToMap()
    92  }