< Summary

Information
Class: Chronicler.StateJsonConverter<T1, T2>
Assembly: Chronicler
File(s): /home/runner/work/Chronicler/Chronicler/src/Chronicler/Serialization/Json/StateJsonConverter.cs
Line coverage
72%
Covered lines: 18
Uncovered lines: 7
Coverable lines: 25
Total lines: 67
Line coverage: 72%
Branch coverage
50%
Covered branches: 10
Total branches: 20
Branch coverage: 50%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Crap Score Cyclomatic complexity Line coverage
.ctor(...)50%22100%
Read(...)50%281664.28%
Write(...)50%2275%

File(s)

/home/runner/work/Chronicler/Chronicler/src/Chronicler/Serialization/Json/StateJsonConverter.cs

#LineLine coverage
 1using System;
 2using System.Text.Json;
 3using System.Text.Json.Serialization;
 4
 5namespace Chronicler;
 6
 7/// <summary>
 8/// Serializes and deserializes an object through its canonical state value.
 9/// </summary>
 10/// <typeparam name="TRecord">The state-backed record type.</typeparam>
 11/// <typeparam name="TState">The serializable state type.</typeparam>
 12public sealed class StateJsonConverter<TRecord, TState> : JsonConverter<TRecord>
 13    where TRecord : class, IStateBacked<TState>
 14{
 15    private const string StatePropertyName = "State";
 16
 17    private readonly Func<TState, TRecord> _factory;
 18
 19    /// <summary>
 20    /// Creates a converter that restores records from serialized state using the supplied factory.
 21    /// </summary>
 122    public StateJsonConverter(Func<TState, TRecord> factory)
 23    {
 124        _factory = factory ?? throw new ArgumentNullException(nameof(factory));
 125    }
 26
 27    /// <inheritdoc />
 28    public override TRecord Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
 29    {
 130        if (reader.TokenType != JsonTokenType.StartObject)
 031            throw new JsonException($"Expected JSON object for state-backed type '{typeToConvert}'.");
 32
 133        if (!reader.Read()
 134            || reader.TokenType != JsonTokenType.PropertyName
 135            || !reader.ValueTextEquals(StatePropertyName))
 36        {
 037            throw new JsonException($"Expected '{StatePropertyName}' property for state-backed type '{typeToConvert}'.")
 38        }
 39
 140        if (!reader.Read())
 041            throw new JsonException($"Expected '{StatePropertyName}' value for state-backed type '{typeToConvert}'.");
 42
 143        TState? state = JsonSerializer.Deserialize<TState>(ref reader, options);
 144        if (state == null)
 045            throw new JsonException($"Unable to deserialize '{StatePropertyName}' for state-backed type '{typeToConvert}
 46
 147        if (!reader.Read() || reader.TokenType != JsonTokenType.EndObject)
 048            throw new JsonException($"Expected end of JSON object for state-backed type '{typeToConvert}'.");
 49
 150        return _factory(state);
 51    }
 52
 53    /// <inheritdoc />
 54    public override void Write(Utf8JsonWriter writer, TRecord value, JsonSerializerOptions options)
 55    {
 156        if (value == null)
 57        {
 058            writer.WriteNullValue();
 059            return;
 60        }
 61
 162        writer.WriteStartObject();
 163        writer.WritePropertyName(StatePropertyName);
 164        JsonSerializer.Serialize(writer, value.State, options);
 165        writer.WriteEndObject();
 166    }
 67}