Merge branch '21535-multi-wf-delete'
[arvados.git] / sdk / go / arvados / resource_list.go
index 14ce098cfc1a54f0f0de74aa9cf60ca8274a693e..7f319b41210a6839447056f81ebfbdb52123f0e9 100644 (file)
@@ -4,7 +4,10 @@
 
 package arvados
 
-import "encoding/json"
+import (
+       "encoding/json"
+       "fmt"
+)
 
 // ResourceListParams expresses which results are requested in a
 // list/index API.
@@ -27,7 +30,44 @@ type Filter struct {
        Operand  interface{}
 }
 
-// MarshalJSON encodes a Filter in the form expected by the API.
+// MarshalJSON encodes a Filter to a JSON array.
 func (f *Filter) MarshalJSON() ([]byte, error) {
        return json.Marshal([]interface{}{f.Attr, f.Operator, f.Operand})
 }
+
+// UnmarshalJSON decodes a JSON array to a Filter.
+func (f *Filter) UnmarshalJSON(data []byte) error {
+       var decoded interface{}
+       err := json.Unmarshal(data, &decoded)
+       if err != nil {
+               return err
+       }
+       switch decoded := decoded.(type) {
+       case string:
+               // Accept "(foo < bar)" as a more obvious way to spell
+               // ["(foo < bar)","=",true]
+               *f = Filter{decoded, "=", true}
+       case []interface{}:
+               if len(decoded) != 3 {
+                       return fmt.Errorf("invalid filter %q: must have 3 decoded", data)
+               }
+               attr, ok := decoded[0].(string)
+               if !ok {
+                       return fmt.Errorf("invalid filter attr %q", decoded[0])
+               }
+               op, ok := decoded[1].(string)
+               if !ok {
+                       return fmt.Errorf("invalid filter operator %q", decoded[1])
+               }
+               operand := decoded[2]
+               switch operand.(type) {
+               case string, float64, []interface{}, nil, bool:
+               default:
+                       return fmt.Errorf("invalid filter operand %q", decoded[2])
+               }
+               *f = Filter{attr, op, operand}
+       default:
+               return fmt.Errorf("invalid filter: json decoded as %T instead of array or string", decoded)
+       }
+       return nil
+}