RtAttributesConverter
Namespace: Meshmakers.Octo.Runtime.Contracts.Serialization
System.Text.Json counterpart of RtNewtonsoftAttributesConverter. Materializes the attribute dictionary of RtTypeWithAttributes (the base of RtEntity and RtRecord) on deserialize.
public sealed class RtAttributesConverter : JsonConverter<IReadOnlyDictionary<String, Object>>
Inheritance Object → JsonConverter → JsonConverter<IReadOnlyDictionary<String, Object>> → RtAttributesConverter
Remarks:
Why this exists.RtTypeWithAttributes.Attributes is a get-only
IReadOnlyDictionary<TKey, TValue> over a private backing field. STJ serializes the
getter fine, but on deserialize it cannot write a get-only property and would silently discard the
whole dictionary — the classic Newtonsoft→STJ trap. RtEntity / RtRecord
therefore carry [JsonConstructor] on the attribute-taking constructor so STJ routes the
dictionary through the constructor, and this converter (registered against the constructor's
IReadOnlyDictionary<TKey, TValue> parameter type) does the value materialization.
Value materialization mirrors the production round-trip behaviour of
RtNewtonsoftAttributesConverter (in-memory JObject.FromObject →
JToken.ToObject, which preserves the source CLR type in JValue.Value):
integers that fit in Int32 stay Int32, larger integers become
Int64; reals stay Double; ISO-8601 strings become
DateTime; JSON objects carrying a CkRecordId become nested
RtRecord instances; arrays become List<T> of Object.
Producing CLR scalars (rather than leaving raw s) is required by
downstream consumers such as GetAttributeValue<T> (which calls
Convert.ChangeType(Object, TypeCode)) and by the MongoDB BSON serializer, which
dispatches on the value's CLR type.
The boxing rules are enforced as a contract by
Sdk.Common.PipelineParityTests.AttributeRoundTripClrTypeParityTests, which uses
Newtonsoft as the oracle. Some divergences are irreducible (float vs double, decimal vs double,
DateTimeOffset vs DateTime — JSON has no source-CLR-type marker for those); they are listed
in AttributeValueParityCorpus.IrreducibleDivergences.
Properties
HandleNull
public bool HandleNull { get; }
Property Value
Type
public Type Type { get; }
Property Value
Constructors
RtAttributesConverter()
public RtAttributesConverter()
Methods
Read(out Utf8JsonReader, Type, JsonSerializerOptions)
public IReadOnlyDictionary<string, object> Read(out Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
Parameters
reader Utf8JsonReader
typeToConvert Type
options JsonSerializerOptions
Returns
IReadOnlyDictionary<String, Object>
Write(Utf8JsonWriter, IReadOnlyDictionary<String, Object>, JsonSerializerOptions)
public void Write(Utf8JsonWriter writer, IReadOnlyDictionary<string, object> value, JsonSerializerOptions options)
Parameters
writer Utf8JsonWriter
value IReadOnlyDictionary<String, Object>
options JsonSerializerOptions