Zum Hauptinhalt springen

JsonScalar

Namespace: Meshmakers.Octo.Runtime.Contracts.Serialization

Converts a scalar JSON value to its Newtonsoft-parity CLR boxing — the single source of the rules previously hand-rolled across many pipeline nodes and inside RtAttributesConverter. Integers that fit in Int32 box to Int32, larger integers to Int64, reals to Double, ISO-8601 strings to DateTime (when requested), bools to Boolean; objects/arrays return null (callers navigate those structurally).

public static class JsonScalar

Inheritance Object → JsonScalar

Remarks:

The boxing rules are verified empirically against Newtonsoft by Sdk.Common.PipelineParityTests.AttributeRoundTripClrTypeParityTests. That suite is the authoritative contract — any divergence between these rules and what Newtonsoft's JObject.FromObject / JToken.ToObject in-memory round-trip produces is a regression. Irreducible divergences (float vs double, decimal vs double, DateTimeOffset vs DateTime — lost because JSON has no source-CLR-type marker for those) are listed in AttributeValueParityCorpus.IrreducibleDivergences.

Methods​

ToClr(JsonElement, Boolean)​

Newtonsoft-parity scalar boxing of element.

public static object ToClr(JsonElement element, bool parseDateStrings)

Parameters​

element JsonElement

parseDateStrings Boolean

Returns​

Object

ToClr(JsonValue, Boolean)​

Newtonsoft-parity scalar boxing of a .

public static object ToClr(JsonValue value, bool parseDateStrings)

Parameters​

value JsonValue

parseDateStrings Boolean

Returns​

Object

Remarks:

A is either element-backed (parsed JSON / Deserialize<JsonNode> / SerializeToNode of a boxed primitive) or CLR-backed (JsonValue.Create(primitive) and its DeepClone — what pipeline nodes produce when they author a scalar, e.g. TransformStringNode's Set(path, JsonValue.Create(result)), surviving the overlay store and detach). Only the element-backed form can be read via GetValue<JsonElement>(); a CLR-backed value throws InvalidOperationException there. So element-backed values route through the proven JsonScalar.ToClr(JsonElement, Boolean), and CLR-backed values are unwrapped by kind with the SAME Newtonsoft-parity boxing (string→string, ISO-string→DateTime, Int32 then Int64 then Double, bool→bool). The Number arm tries Int32 before Int64 before Double because STJ's TryGetValue<T> on a CLR-backed value is exact-type (no numeric coercion): a boxed double 2.0 fails TryGetValue<int> and stays a Double rather than collapsing to Int32 (the Int32-vs-double regression the parity converters guard against).

TryToNumber<T>(JsonNode, out T)​

Reads node as numeric T. Accepts JSON numbers natively; parses JSON strings under invariant culture. Returns false otherwise.

public static bool TryToNumber<T>(JsonNode node, out T value)

Type Parameters​

T

Parameters​

node JsonNode

value T

Returns​

Boolean

TryToDouble(JsonNode, out Double)​

Reads node as a Double — the non-generic counterpart of TryToNumber<T>. Accepts JSON numbers natively and parses numeric JSON strings under invariant culture; returns false otherwise. Unlike the generic overload (which needs IParsable<T>), this one has no generic constraint, so callers that cannot use the generic still get the shared parity rules.

public static bool TryToDouble(JsonNode node, out Double value)

Parameters​

node JsonNode

value Double

Returns​

Boolean