This commit is contained in:
182
Railway/ErrorJsonConverter.cs
Normal file
182
Railway/ErrorJsonConverter.cs
Normal file
@@ -0,0 +1,182 @@
|
||||
using System.Collections.Immutable;
|
||||
|
||||
namespace Just.Railway;
|
||||
|
||||
public sealed class ErrorJsonConverter : JsonConverter<Error>
|
||||
{
|
||||
public override Error? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return reader.TokenType switch
|
||||
{
|
||||
JsonTokenType.StartObject => ToExpectedError(ReadOne(ref reader)),
|
||||
JsonTokenType.StartArray => ReadMany(ref reader),
|
||||
JsonTokenType.None => null,
|
||||
JsonTokenType.Null => null,
|
||||
_ => throw new JsonException("Unexpected JSON token.")
|
||||
};
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, Error value, JsonSerializerOptions options)
|
||||
{
|
||||
if (value is ManyErrors manyErrors)
|
||||
{
|
||||
writer.WriteStartArray();
|
||||
foreach (var err in manyErrors)
|
||||
{
|
||||
WriteOne(writer, err);
|
||||
}
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteOne(writer, value);
|
||||
}
|
||||
}
|
||||
|
||||
internal static ManyErrors ReadMany(ref Utf8JsonReader reader)
|
||||
{
|
||||
List<Error> errors = [];
|
||||
while (reader.Read())
|
||||
{
|
||||
if (reader.TokenType == JsonTokenType.StartObject)
|
||||
{
|
||||
errors.Add(ToExpectedError(ReadOne(ref reader)));
|
||||
}
|
||||
}
|
||||
return new ManyErrors(errors);
|
||||
}
|
||||
internal static ExpectedError ToExpectedError(in (string Type, string Message, ImmutableDictionary<string, string> ExtensionData) errorInfo)
|
||||
=> new(errorInfo.Type, errorInfo.Message) { ExtensionData = errorInfo.ExtensionData };
|
||||
internal static (string Type, string Message, ImmutableDictionary<string, string> ExtensionData) ReadOne(ref Utf8JsonReader reader)
|
||||
{
|
||||
List<KeyValuePair<string, string>>? extensionData = null;
|
||||
string type = "error";
|
||||
string message = "";
|
||||
while (reader.Read())
|
||||
{
|
||||
switch (reader.TokenType)
|
||||
{
|
||||
case JsonTokenType.PropertyName:
|
||||
{
|
||||
var propname = reader.GetString();
|
||||
reader.Read();
|
||||
|
||||
if (reader.TokenType == JsonTokenType.Null)
|
||||
break;
|
||||
|
||||
while (reader.TokenType == JsonTokenType.Comment) reader.Read();
|
||||
|
||||
if (!(reader.TokenType == JsonTokenType.String))
|
||||
throw new JsonException("Unable to deserialize Error type.");
|
||||
|
||||
var propvalue = reader.GetString();
|
||||
if (string.IsNullOrEmpty(propvalue))
|
||||
break;
|
||||
|
||||
if (propname == "type" || string.Equals(propname, "type", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
type = propvalue;
|
||||
}
|
||||
else if (propname == "msg" || string.Equals(propname, "msg", StringComparison.InvariantCultureIgnoreCase))
|
||||
{
|
||||
message = propvalue;
|
||||
}
|
||||
else if (!string.IsNullOrEmpty(propname))
|
||||
{
|
||||
extensionData ??= [];
|
||||
extensionData.Add(new(propname, propvalue));
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
case JsonTokenType.Comment: break;
|
||||
case JsonTokenType.EndObject: goto endLoop;
|
||||
default: throw new JsonException("Unable to deserialize Error type.");
|
||||
}
|
||||
}
|
||||
endLoop:
|
||||
return (type, message, extensionData?.ToImmutableDictionary() ?? ImmutableDictionary<string, string>.Empty);
|
||||
}
|
||||
internal static void WriteOne(Utf8JsonWriter writer, Error value)
|
||||
{
|
||||
writer.WriteStartObject();
|
||||
|
||||
writer.WriteString("type", value.Type);
|
||||
writer.WriteString("msg", value.Message);
|
||||
|
||||
if (value.ExtensionData?.Count > 0)
|
||||
{
|
||||
foreach (var (key, val) in value.ExtensionData)
|
||||
{
|
||||
writer.WriteString(key, val);
|
||||
}
|
||||
}
|
||||
|
||||
writer.WriteEndObject();
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ExpectedErrorJsonConverter : JsonConverter<ExpectedError>
|
||||
{
|
||||
public override ExpectedError? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return reader.TokenType switch
|
||||
{
|
||||
JsonTokenType.StartObject => ErrorJsonConverter.ToExpectedError(ErrorJsonConverter.ReadOne(ref reader)),
|
||||
JsonTokenType.None => null,
|
||||
JsonTokenType.Null => null,
|
||||
_ => throw new JsonException("Unexpected JSON token.")
|
||||
};
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, ExpectedError value, JsonSerializerOptions options)
|
||||
{
|
||||
ErrorJsonConverter.WriteOne(writer, value);
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class ExceptionalErrorJsonConverter : JsonConverter<ExceptionalError>
|
||||
{
|
||||
public override ExceptionalError? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return reader.TokenType switch
|
||||
{
|
||||
JsonTokenType.StartObject => ToExceptionalError(ErrorJsonConverter.ReadOne(ref reader)),
|
||||
JsonTokenType.None => null,
|
||||
JsonTokenType.Null => null,
|
||||
_ => throw new JsonException("Unexpected JSON token.")
|
||||
};
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, ExceptionalError value, JsonSerializerOptions options)
|
||||
{
|
||||
ErrorJsonConverter.WriteOne(writer, value);
|
||||
}
|
||||
|
||||
private static ExceptionalError ToExceptionalError(in (string Type, string Message, ImmutableDictionary<string, string> ExtensionData) errorInfo)
|
||||
=> new(errorInfo.Type, errorInfo.Message) { ExtensionData = errorInfo.ExtensionData };
|
||||
}
|
||||
|
||||
public sealed class ManyErrorsJsonConverter : JsonConverter<ManyErrors>
|
||||
{
|
||||
public override ManyErrors? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
|
||||
{
|
||||
return reader.TokenType switch
|
||||
{
|
||||
JsonTokenType.StartArray => ErrorJsonConverter.ReadMany(ref reader),
|
||||
JsonTokenType.None => null,
|
||||
JsonTokenType.Null => null,
|
||||
_ => throw new JsonException("Unexpected JSON token.")
|
||||
};
|
||||
}
|
||||
|
||||
public override void Write(Utf8JsonWriter writer, ManyErrors value, JsonSerializerOptions options)
|
||||
{
|
||||
writer.WriteStartArray();
|
||||
foreach (var err in value)
|
||||
{
|
||||
ErrorJsonConverter.WriteOne(writer, err);
|
||||
}
|
||||
writer.WriteEndArray();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user