code: func keepOrDeleteNullInObj(m map[string]interface{}, keepNull bool) (map[string]interface{}, error) {
  	filteredMap := make(map[string]interface{})
  	var err error
  	for key, val := range m {
  		switch {
  		case keepNull && val == nil:
  			filteredMap[key] = nil
  		case val != nil:
  			switch typedVal := val.(type) {
  			case map[string]interface{}:
  				// Explicitly-set empty maps are treated as values instead of empty patches
  				if len(typedVal) == 0 {
  					if !keepNull {
  						filteredMap[key] = typedVal
  					}
  					continue
  				}
  
  				var filteredSubMap map[string]interface{}
  				filteredSubMap, err = keepOrDeleteNullInObj(typedVal, keepNull)
  				if err != nil {
  					return nil, err
  				}
  
  				// If the returned filtered submap was empty, this is an empty patch for the entire subdict, so the key
  				// should not be set
  				if len(filteredSubMap) != 0 {
  					filteredMap[key] = filteredSubMap
  				}
  
  			case []interface{}, string, float64, bool, int64, nil:
  				// Lists are always replaced in Json, no need to check each entry in the list.
  				if !keepNull {
  					filteredMap[key] = val
  				}
  			default:
  				return nil, fmt.Errorf("unknown type: %v", reflect.TypeOf(typedVal))
  			}
  		}
  	}
  	return filteredMap, nil
  }
docs: // keepOrDeleteNullInObj will keep only the null value and delete all the others,
  // if keepNull is true. Otherwise, it will delete all the null value and keep the others.