21910: Merge branch 'main' into 21910-remove-api_client_id
[arvados.git] / sdk / go / arvados / resource_list.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: Apache-2.0
4
5 package arvados
6
7 import (
8         "encoding/json"
9         "fmt"
10 )
11
12 // ResourceListParams expresses which results are requested in a
13 // list/index API.
14 type ResourceListParams struct {
15         Select             []string `json:"select,omitempty"`
16         Filters            []Filter `json:"filters,omitempty"`
17         IncludeTrash       bool     `json:"include_trash,omitempty"`
18         IncludeOldVersions bool     `json:"include_old_versions,omitempty"`
19         Limit              *int     `json:"limit,omitempty"`
20         Offset             int      `json:"offset,omitempty"`
21         Order              string   `json:"order,omitempty"`
22         Distinct           bool     `json:"distinct,omitempty"`
23         Count              string   `json:"count,omitempty"`
24 }
25
26 // A Filter restricts the set of records returned by a list/index API.
27 type Filter struct {
28         Attr     string
29         Operator string
30         Operand  interface{}
31 }
32
33 // MarshalJSON encodes a Filter to a JSON array.
34 func (f *Filter) MarshalJSON() ([]byte, error) {
35         return json.Marshal([]interface{}{f.Attr, f.Operator, f.Operand})
36 }
37
38 // UnmarshalJSON decodes a JSON array to a Filter.
39 func (f *Filter) UnmarshalJSON(data []byte) error {
40         var decoded interface{}
41         err := json.Unmarshal(data, &decoded)
42         if err != nil {
43                 return err
44         }
45         switch decoded := decoded.(type) {
46         case string:
47                 // Accept "(foo < bar)" as a more obvious way to spell
48                 // ["(foo < bar)","=",true]
49                 *f = Filter{decoded, "=", true}
50         case []interface{}:
51                 if len(decoded) != 3 {
52                         return fmt.Errorf("invalid filter %q: must have 3 decoded", data)
53                 }
54                 attr, ok := decoded[0].(string)
55                 if !ok {
56                         return fmt.Errorf("invalid filter attr %q", decoded[0])
57                 }
58                 op, ok := decoded[1].(string)
59                 if !ok {
60                         return fmt.Errorf("invalid filter operator %q", decoded[1])
61                 }
62                 operand := decoded[2]
63                 switch operand.(type) {
64                 case string, float64, []interface{}, nil, bool:
65                 default:
66                         return fmt.Errorf("invalid filter operand %q", decoded[2])
67                 }
68                 *f = Filter{attr, op, operand}
69         default:
70                 return fmt.Errorf("invalid filter: json decoded as %T instead of array or string", decoded)
71         }
72         return nil
73 }