---
title: GetContentArray<T>
summary: Normalize a JSON payload (array, object, or scalar) into a uniform array.
status: draft
owner: bendy
last_reviewed: 2026-09-15
library: SAIF.Web.API.Clients
reference_type: package
operation_id: OP-07
trigger: GetResult<T> step 6; GetApiResponse<T> step 1
---

# GetContentArray<T>

`GetContentArray<T>` is the shape-normalizing deserializer that lets every consumer of `JsonHttpClient` treat a response body as `T[]` regardless of whether the underlying API returned a JSON array, a single object, or a scalar value. It is `internal static`; no `InternalsVisibleTo` attribute exists, so it is not reachable from outside the assembly*.

| Field | Value |
| --- | --- |
| **Operation ID** | OP-07 |
| **Trigger** | [GetResult\<T\>](get-result.md) step 6; [GetApiResponse\<T\>](get-api-response.md) step 1. |
| **Inputs** | `jsonContent` (string), `DateTimeZoneHandling`. |
| **Outputs** | `T[]` (may be empty; may be `null`). |
| **Primary components** | `JsonHttpClient.GetContentArray<T>(string, DateTimeZoneHandling)` (`internal static`) |
| **Entry point** | `src/SAIF.Web.API.Clients/JsonHttpClient.cs` |

## Steps

1. If `jsonContent` is null/empty, skip to step 6 (empty list) ([BR-CLI-012](../business-rules.md#br-cli-012-response-payload-shape-normalization)).
   - Returns an empty `T[]`.
2. Open a `JsonTextReader` with `DateTimeZoneHandling = <configured>` and `DateParseHandling = DateTime`, then `JToken.ReadFrom` ([BR-CLI-011](../business-rules.md#br-cli-011-date-time-zone-handling-consistency)).
   - Dates are materialized as `DateTime` (never `DateTimeOffset`) in the configured zone.
3. If the token is a `JArray`: `token.ToObject<List<T>>()` ([BR-CLI-012](../business-rules.md#br-cli-012-response-payload-shape-normalization)).
4. Else if the token is a `JObject`, or `T` is not primitive: wrap `token.ToObject<T>()` into a single-element list ([BR-CLI-012](../business-rules.md#br-cli-012-response-payload-shape-normalization)).
   - This is the branch that lets a scalar JSON value hydrate a non-primitive `T` (for example `string`, `DateTime?`).
5. Else if the token is a `JValue`: if `token.Value<T>()` is `null` yield `{ default(T) }`, else `{ (T)Convert.ChangeType(jvalue.Value, typeof(T)) }` ([BR-CLI-012](../business-rules.md#br-cli-012-response-payload-shape-normalization), [BR-CLI-013](../business-rules.md#br-cli-013-single-value-result-coercion)).
   - Guarantees a single-element array for scalars rather than an empty one.
6. `catch (Exception ex)`: if `typeof(T).Name == "String"`, add `ex.Message` to the result as if it were data; otherwise swallow the exception and fall through with whatever was accumulated ([BR-CLI-016](../business-rules.md#br-cli-016-deserialization-failure-masking)).
   - On failure: a deserialization failure is silently converted into an empty result for non-string `T`, and into a fake data value for `string` `T` — callers cannot distinguish "no data" from "parse failed".
7. Return `result?.ToArray()`.
   - The `?.` guards a `null` assignment from `ToObject<List<T>>()` (JSON `null` array) → returns `null`, not an empty array.

## Process flow

The following diagrams visualize this operation's control flow, split by concern so each renders at a readable width.

The first diagram shows the initial null/empty check and the scalar-shape path:

```mermaid
flowchart TD
	Start([GetContentArray called]) --> Empty{jsonContent null/empty?}
	Empty -->|Yes| ReturnEmpty([Return empty array])
	Empty -->|No| Read[JToken.ReadFrom]
	Read --> Shape{Token shape?}
	Shape -->|JValue| Scalar["Convert.ChangeType or<br>default T"]
	Scalar --> Return([Return T array or null])
```

The second diagram shows the array and object/non-primitive shape paths:

```mermaid
flowchart TD
	Read[JToken.ReadFrom] --> Shape{Token shape?}
	Shape -->|JArray| ToList[ToObject List of T]
	Shape -->|"JObject or non-primitive<br>T"| Wrap["Wrap ToObject T in<br>single-element list"]
	ToList --> Return([Return T array or null])
	Wrap --> Return
```

The third diagram shows the exception-handling path:

```mermaid
flowchart TD
	Read[JToken.ReadFrom] -->|exception| Catch{T is string?}
	Catch -->|Yes| FakeData["Append ex.Message as<br>data"] --> Return([Return T array or null])
	Catch -->|No| Swallow["Swallow exception, keep<br>accumulated"] --> Return
```

## Failure and edge-case behavior
- A deserialization exception is never propagated to the caller; it is masked per [BR-CLI-016](../business-rules.md#br-cli-016-deserialization-failure-masking), which is flagged as a defect risk.
- A JSON `null` array (`ToObject<List<T>>()` returning `null`) yields a `null` result, distinct from an empty array.

## Related documentation
- [Operations and processes](../operations-processes.md)
- [Business rules](../business-rules.md)

> **Note:** Statements marked with `*` were inferred from code structure, naming conventions, or
> contextual evidence where direct confirmation was not available in source artifacts.

## Sources
- `src/SAIF.Web.API.Clients/JsonHttpClient.cs`
- `src/SAIF.Web.API.Clients/Properties/AssemblyInfo.cs`
