extractJSONColumn extracts column values from one of three accepted shapes: a bare array of strings, an array of string-valued objects (the column field of each), or an object mapping the column to an array of strings. The column is matched only against top-level keys; nested paths are not interpret
(content []byte, column string)
| 163 | // of each), or an object mapping the column to an array of strings. The column |
| 164 | // is matched only against top-level keys; nested paths are not interpreted. |
| 165 | func extractJSONColumn(content []byte, column string) ([]string, error) { |
| 166 | trimmed := bytes.TrimSpace(content) |
| 167 | if len(trimmed) == 0 { |
| 168 | return nil, errors.New("empty JSON policy input file") |
| 169 | } |
| 170 | |
| 171 | switch trimmed[0] { |
| 172 | case '[': |
| 173 | // Bare array of strings. |
| 174 | var strs []string |
| 175 | if err := json.Unmarshal(trimmed, &strs); err == nil { |
| 176 | return filterNonEmpty(strs), nil |
| 177 | } |
| 178 | |
| 179 | // Array of string-valued objects: pull the column field from each. |
| 180 | var objs []map[string]string |
| 181 | if err := json.Unmarshal(trimmed, &objs); err != nil { |
| 182 | return nil, fmt.Errorf("parsing JSON array (expected an array of strings or of string-valued objects): %w", err) |
| 183 | } |
| 184 | values := make([]string, 0, len(objs)) |
| 185 | for _, obj := range objs { |
| 186 | if v, ok := matchKey(obj, column); ok { |
| 187 | values = append(values, v) |
| 188 | } |
| 189 | } |
| 190 | return filterNonEmpty(values), nil |
| 191 | case '{': |
| 192 | // Object mapping the column to an array of strings. The values are |
| 193 | // decoded into a typed []string; sibling keys are left as raw messages |
| 194 | // so fields of other types don't break the parse. |
| 195 | var obj map[string]json.RawMessage |
| 196 | if err := json.Unmarshal(trimmed, &obj); err != nil { |
| 197 | return nil, fmt.Errorf("parsing JSON object: %w", err) |
| 198 | } |
| 199 | raw, ok := matchKey(obj, column) |
| 200 | if !ok { |
| 201 | return nil, fmt.Errorf("key %q not found in JSON object", column) |
| 202 | } |
| 203 | var strs []string |
| 204 | if err := json.Unmarshal(raw, &strs); err != nil { |
| 205 | return nil, fmt.Errorf("value of %q is not an array of strings: %w", column, err) |
| 206 | } |
| 207 | return filterNonEmpty(strs), nil |
| 208 | default: |
| 209 | return nil, errors.New("JSON policy input file must be an array or object") |
| 210 | } |
| 211 | } |
| 212 | |
| 213 | // matchKey returns the value whose key matches column case-insensitively |
| 214 | // (trimming surrounding whitespace). |
no test coverage detected