Skip to content

GetContentArray

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> step 6; GetApiResponse\<T> 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).
  2. Returns an empty T[].
  3. Open a JsonTextReader with DateTimeZoneHandling = <configured> and DateParseHandling = DateTime, then JToken.ReadFrom (BR-CLI-011).
  4. Dates are materialized as DateTime (never DateTimeOffset) in the configured zone.
  5. If the token is a JArray: token.ToObject<List<T>>() (BR-CLI-012).
  6. Else if the token is a JObject, or T is not primitive: wrap token.ToObject<T>() into a single-element list (BR-CLI-012).
  7. This is the branch that lets a scalar JSON value hydrate a non-primitive T (for example string, DateTime?).
  8. 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, BR-CLI-013).
  9. Guarantees a single-element array for scalars rather than an empty one.
  10. 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).
  11. 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".
  12. Return result?.ToArray().
  13. 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:

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:

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:

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, 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.

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