listor.go 928 B

123456789101112131415161718192021222324252627282930313233343536373839
  1. package internal
  2. import (
  3. "encoding/json"
  4. )
  5. // ListOr[T any] is a slice that can contain either a single T or multiple T values.
  6. // During JSON unmarshaling, it checks if the first character is '[' to determine
  7. // whether to treat the JSON as an array or a single value.
  8. type ListOr[T any] []T
  9. func (lo *ListOr[T]) UnmarshalJSON(data []byte) error {
  10. if len(data) == 0 {
  11. return nil
  12. }
  13. // Check if first non-whitespace character is '['
  14. firstChar := data[0]
  15. for i := 0; i < len(data); i++ {
  16. if data[i] != ' ' && data[i] != '\t' && data[i] != '\n' && data[i] != '\r' {
  17. firstChar = data[i]
  18. break
  19. }
  20. }
  21. if firstChar == '[' {
  22. // It's an array, unmarshal directly
  23. return json.Unmarshal(data, (*[]T)(lo))
  24. } else {
  25. // It's a single value, unmarshal as a single item in a slice
  26. var single T
  27. if err := json.Unmarshal(data, &single); err != nil {
  28. return err
  29. }
  30. *lo = ListOr[T]{single}
  31. }
  32. return nil
  33. }