NewtonsoftParityInt32Converter
Namespace: Meshmakers.Octo.Sdk.Common.EtlDataPipeline
Read-side parity twin of NewtonsoftParityDoubleConverter for Int32.
public sealed class NewtonsoftParityInt32Converter : JsonConverter<Int32>
Inheritance Object → JsonConverter → JsonConverter<Int32> → NewtonsoftParityInt32Converter
Remarks:
System.Text.Json's built-in Int32 converter inspects the raw text of a number token:
reader.GetInt32() rejects the literal 5.0 even though the value is integral.
Newtonsoft's (int)JToken instead goes through Convert.ToInt32(double, InvariantCulture)
and accepts it.
That matters because the write side deliberately emits a trailing .0 for every
integral double (see NewtonsoftParityDoubleConverter: a double 0.0 written as the
JSON literal 0 would round-trip back as Int64 and land in MongoDB as a
BsonInt64 where Newtonsoft stored a BsonDouble). So every node that writes a double
— Math@1, LinearScaler@1, SumAggregation@1, ConvertDataType@1 to
Double, ExecuteCSharp@1 returning a double — stores 5.0, and every downstream
Get<int> on it threw. The strict built-in is a parity regression from the
Newtonsoft to System.Text.Json migration, not a designed contract (AB#5275).
Coercion rules, verified against the Newtonsoft oracle by
Sdk.Common.PipelineParityTests.IntegerCoercionParityTests:
exact integral literal — built-in fast path, no coercion, no precision loss
real literal or exponent — banker's rounding (MidpointRounding.ToEven),
matching Convert.ToInt32(double): 5.0 to 5, 5.7 to 6, 5.5 to 6,
4.5 to 4, -5.5 to -6
JSON string — honors , integer first and then real-tolerant
out of range or NaN — , deliberately NOT
OverflowException (which is what Convert.ToInt32 would throw), because
DateTimeNode catches to build its own
InvalidUnixTimestamp error
This does NOT touch JsonScalar.ToClr, the dynamic boxing path behind
IDataContext.GetValue() and RtAttributesConverter. Its contract is explicitly
"reals stay double"; coercing there would bring the BsonInt64 regression back. Only explicitly
typed reads change.
Two deliberate divergences from the oracle, pinned by the parity suite: a quoted real
("5.0") coerces here but throws in Newtonsoft, so the quoted and unquoted forms behave
alike for REST sources that stringify numbers; and a JSON boolean throws here but yields 1 in
Newtonsoft, because silently turning true into a number hides a real data bug.
Writing is byte-identical to the built-in converter.
Properties
HandleNull
public bool HandleNull { get; }
Property Value
Type
public Type Type { get; }
Property Value
Constructors
NewtonsoftParityInt32Converter()
public NewtonsoftParityInt32Converter()
Methods
Read(out Utf8JsonReader, Type, JsonSerializerOptions)
public int Read(out Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
Parameters
reader Utf8JsonReader
typeToConvert Type
options JsonSerializerOptions
Returns
Write(Utf8JsonWriter, Int32, JsonSerializerOptions)
public void Write(Utf8JsonWriter writer, int value, JsonSerializerOptions options)
Parameters
writer Utf8JsonWriter
value Int32
options JsonSerializerOptions
ReadAsPropertyName(out Utf8JsonReader, Type, JsonSerializerOptions)
public int ReadAsPropertyName(out Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
Parameters
reader Utf8JsonReader
typeToConvert Type
options JsonSerializerOptions
Returns
WriteAsPropertyName(Utf8JsonWriter, Int32, JsonSerializerOptions)
public void WriteAsPropertyName(Utf8JsonWriter writer, int value, JsonSerializerOptions options)
Parameters
writer Utf8JsonWriter
value Int32
options JsonSerializerOptions