"Fossies" - the Fresh Open Source Software Archive

Member "gdrive-2.1.1/vendor/google.golang.org/api/gensupport/json.go" (28 May 2021, 5007 Bytes) of package /linux/misc/gdrive-2.1.1.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) Go source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

    1 // Copyright 2015 The Go Authors. All rights reserved.
    2 // Use of this source code is governed by a BSD-style
    3 // license that can be found in the LICENSE file.
    4 
    5 package gensupport
    6 
    7 import (
    8     "encoding/json"
    9     "fmt"
   10     "reflect"
   11     "strings"
   12 )
   13 
   14 // MarshalJSON returns a JSON encoding of schema containing only selected fields.
   15 // A field is selected if:
   16 //   * it has a non-empty value, or
   17 //     * its field name is present in forceSendFields, and
   18 //     * it is not a nil pointer or nil interface.
   19 // The JSON key for each selected field is taken from the field's json: struct tag.
   20 func MarshalJSON(schema interface{}, forceSendFields []string) ([]byte, error) {
   21     if len(forceSendFields) == 0 {
   22         return json.Marshal(schema)
   23     }
   24 
   25     mustInclude := make(map[string]struct{})
   26     for _, f := range forceSendFields {
   27         mustInclude[f] = struct{}{}
   28     }
   29 
   30     dataMap, err := schemaToMap(schema, mustInclude)
   31     if err != nil {
   32         return nil, err
   33     }
   34     return json.Marshal(dataMap)
   35 }
   36 
   37 func schemaToMap(schema interface{}, mustInclude map[string]struct{}) (map[string]interface{}, error) {
   38     m := make(map[string]interface{})
   39     s := reflect.ValueOf(schema)
   40     st := s.Type()
   41 
   42     for i := 0; i < s.NumField(); i++ {
   43         jsonTag := st.Field(i).Tag.Get("json")
   44         if jsonTag == "" {
   45             continue
   46         }
   47         tag, err := parseJSONTag(jsonTag)
   48         if err != nil {
   49             return nil, err
   50         }
   51         if tag.ignore {
   52             continue
   53         }
   54 
   55         v := s.Field(i)
   56         f := st.Field(i)
   57         if !includeField(v, f, mustInclude) {
   58             continue
   59         }
   60 
   61         // nil maps are treated as empty maps.
   62         if f.Type.Kind() == reflect.Map && v.IsNil() {
   63             m[tag.apiName] = map[string]string{}
   64             continue
   65         }
   66 
   67         // nil slices are treated as empty slices.
   68         if f.Type.Kind() == reflect.Slice && v.IsNil() {
   69             m[tag.apiName] = []bool{}
   70             continue
   71         }
   72 
   73         if tag.stringFormat {
   74             m[tag.apiName] = formatAsString(v, f.Type.Kind())
   75         } else {
   76             m[tag.apiName] = v.Interface()
   77         }
   78     }
   79     return m, nil
   80 }
   81 
   82 // formatAsString returns a string representation of v, dereferencing it first if possible.
   83 func formatAsString(v reflect.Value, kind reflect.Kind) string {
   84     if kind == reflect.Ptr && !v.IsNil() {
   85         v = v.Elem()
   86     }
   87 
   88     return fmt.Sprintf("%v", v.Interface())
   89 }
   90 
   91 // jsonTag represents a restricted version of the struct tag format used by encoding/json.
   92 // It is used to describe the JSON encoding of fields in a Schema struct.
   93 type jsonTag struct {
   94     apiName      string
   95     stringFormat bool
   96     ignore       bool
   97 }
   98 
   99 // parseJSONTag parses a restricted version of the struct tag format used by encoding/json.
  100 // The format of the tag must match that generated by the Schema.writeSchemaStruct method
  101 // in the api generator.
  102 func parseJSONTag(val string) (jsonTag, error) {
  103     if val == "-" {
  104         return jsonTag{ignore: true}, nil
  105     }
  106 
  107     var tag jsonTag
  108 
  109     i := strings.Index(val, ",")
  110     if i == -1 || val[:i] == "" {
  111         return tag, fmt.Errorf("malformed json tag: %s", val)
  112     }
  113 
  114     tag = jsonTag{
  115         apiName: val[:i],
  116     }
  117 
  118     switch val[i+1:] {
  119     case "omitempty":
  120     case "omitempty,string":
  121         tag.stringFormat = true
  122     default:
  123         return tag, fmt.Errorf("malformed json tag: %s", val)
  124     }
  125 
  126     return tag, nil
  127 }
  128 
  129 // Reports whether the struct field "f" with value "v" should be included in JSON output.
  130 func includeField(v reflect.Value, f reflect.StructField, mustInclude map[string]struct{}) bool {
  131     // The regular JSON encoding of a nil pointer is "null", which means "delete this field".
  132     // Therefore, we could enable field deletion by honoring pointer fields' presence in the mustInclude set.
  133     // However, many fields are not pointers, so there would be no way to delete these fields.
  134     // Rather than partially supporting field deletion, we ignore mustInclude for nil pointer fields.
  135     // Deletion will be handled by a separate mechanism.
  136     if f.Type.Kind() == reflect.Ptr && v.IsNil() {
  137         return false
  138     }
  139 
  140     // The "any" type is represented as an interface{}.  If this interface
  141     // is nil, there is no reasonable representation to send.  We ignore
  142     // these fields, for the same reasons as given above for pointers.
  143     if f.Type.Kind() == reflect.Interface && v.IsNil() {
  144         return false
  145     }
  146 
  147     _, ok := mustInclude[f.Name]
  148     return ok || !isEmptyValue(v)
  149 }
  150 
  151 // isEmptyValue reports whether v is the empty value for its type.  This
  152 // implementation is based on that of the encoding/json package, but its
  153 // correctness does not depend on it being identical. What's important is that
  154 // this function return false in situations where v should not be sent as part
  155 // of a PATCH operation.
  156 func isEmptyValue(v reflect.Value) bool {
  157     switch v.Kind() {
  158     case reflect.Array, reflect.Map, reflect.Slice, reflect.String:
  159         return v.Len() == 0
  160     case reflect.Bool:
  161         return !v.Bool()
  162     case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
  163         return v.Int() == 0
  164     case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
  165         return v.Uint() == 0
  166     case reflect.Float32, reflect.Float64:
  167         return v.Float() == 0
  168     case reflect.Interface, reflect.Ptr:
  169         return v.IsNil()
  170     }
  171     return false
  172 }