using System; using System.ComponentModel; using System.Text.Json; using System.Text.Json.Serialization; namespace Jellyfin.Extensions.Json.Converters { /// /// Convert delimited string to array of type. /// /// Type to convert to. public abstract class JsonDelimitedArrayConverter : JsonConverter { private readonly TypeConverter _typeConverter; /// /// Initializes a new instance of the class. /// protected JsonDelimitedArrayConverter() { _typeConverter = TypeDescriptor.GetConverter(typeof(T)); } /// /// Gets the array delimiter. /// protected virtual char Delimiter { get; } /// public override T[]? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { if (reader.TokenType == JsonTokenType.String) { // GetString can't return null here because we already handled it above var stringEntries = reader.GetString()?.Split(Delimiter, StringSplitOptions.RemoveEmptyEntries); if (stringEntries == null || stringEntries.Length == 0) { return Array.Empty(); } var parsedValues = new object[stringEntries.Length]; var convertedCount = 0; for (var i = 0; i < stringEntries.Length; i++) { try { parsedValues[i] = _typeConverter.ConvertFrom(stringEntries[i].Trim()); convertedCount++; } catch (FormatException) { // TODO log when upgraded to .Net6 // https://github.com/dotnet/runtime/issues/42975 // _logger.LogDebug(e, "Error converting value."); } } var typedValues = new T[convertedCount]; var typedValueIndex = 0; for (var i = 0; i < stringEntries.Length; i++) { if (parsedValues[i] != null) { typedValues.SetValue(parsedValues[i], typedValueIndex); typedValueIndex++; } } return typedValues; } return JsonSerializer.Deserialize(ref reader, options); } /// public override void Write(Utf8JsonWriter writer, T[]? value, JsonSerializerOptions options) { throw new NotImplementedException(); } } }