diff --git a/FreeTubeSyncer/Library/GlobalJsonOptions.cs b/FreeTubeSyncer/Library/GlobalJsonOptions.cs new file mode 100644 index 0000000..68d85f9 --- /dev/null +++ b/FreeTubeSyncer/Library/GlobalJsonOptions.cs @@ -0,0 +1,12 @@ +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace FreeTubeSyncer.Library; + +public static class GlobalJsonOptions +{ + public static JsonSerializerOptions Options { get; } = new JsonSerializerOptions + { + NumberHandling = JsonNumberHandling.AllowReadingFromString + }; +} \ No newline at end of file diff --git a/FreeTubeSyncer/Library/StringToLongConverter.cs b/FreeTubeSyncer/Library/StringToLongConverter.cs new file mode 100644 index 0000000..13922ad --- /dev/null +++ b/FreeTubeSyncer/Library/StringToLongConverter.cs @@ -0,0 +1,69 @@ +using System; +using System.Buffers; +using System.Buffers.Text; +using System.Globalization; +using System.Text; +using System.Text.Json; +using System.Text.Json.Serialization; + +namespace FreeTubeSyncer.Library; + +public class StringToLongJsonConverter : JsonConverter +{ + private readonly bool _writeValueAsString; + static string[] formats = { + @"m\:ss", @"mm\:ss" + }; + + public StringToLongJsonConverter(bool writeValueAsString) + { + _writeValueAsString = writeValueAsString; + } + + /// + /// Reads long value from quoted string + /// + public override long Read(ref Utf8JsonReader reader, Type type, JsonSerializerOptions options) + { + if (reader.TokenType == JsonTokenType.String) + { + var span = reader.HasValueSequence ? reader.ValueSequence.ToArray() : reader.ValueSpan; + if (Utf8Parser.TryParse(span, out long number, out var bytesConsumed) && span.Length == bytesConsumed) + return number; + + var strNumber = reader.GetString(); + if (strNumber.Contains(':')) + { + TimeSpan tspan; + if (TimeSpan.TryParseExact(strNumber, formats, CultureInfo.InvariantCulture, out tspan)) + return (long)tspan.TotalSeconds; + + } + if (long.TryParse(strNumber, out number)) + return number; + + throw new InvalidOperationException($"{strNumber} is not a correct long value!") + { + /* + * Here is a source from internal const System.Text.Json.ThrowHelper.ExceptionSourceValueToRethrowAsJsonException + * to restore a detailed info about current json context (line number and path) + */ + Source = "System.Text.Json.Rethrowable" + }; + } + + return reader.GetInt64(); + } + + /// + /// Writes a long value as number if is false + /// or as string if is true + /// + public override void Write(Utf8JsonWriter writer, long value, JsonSerializerOptions options) + { + if (_writeValueAsString) + writer.WriteStringValue(value.ToString()); + else + writer.WriteNumberValue(value); + } +} \ No newline at end of file diff --git a/FreeTubeSyncer/Program.cs b/FreeTubeSyncer/Program.cs index 2901a1f..9ed5302 100644 --- a/FreeTubeSyncer/Program.cs +++ b/FreeTubeSyncer/Program.cs @@ -20,6 +20,7 @@ class Program [STAThread] public static void Main(string[] args) { + GlobalJsonOptions.Options.Converters.Add(new StringToLongJsonConverter(false)); var path = "/home/eumario/.var/app/io.freetubeapp.FreeTube/config/FreeTube/"; var dbWatcher = new DBSyncWatcher(path); var historySyncer = new Syncer(dbWatcher, Path.Join(path, "history.db"), "history.db", "/history"); diff --git a/FreeTubeSyncer/REST/Syncer.cs b/FreeTubeSyncer/REST/Syncer.cs index 552e9ae..b0fc24d 100644 --- a/FreeTubeSyncer/REST/Syncer.cs +++ b/FreeTubeSyncer/REST/Syncer.cs @@ -38,7 +38,7 @@ public class Syncer where T : class, IDataModel if (entry == "") continue; try { - var item = JsonSerializer.Deserialize(entry); + var item = JsonSerializer.Deserialize(entry, GlobalJsonOptions.Options); if (item == null) continue; if (_entries.Any(x => x.EqualId(item.Id()))) _entries.RemoveAll(x => x.EqualId(item.Id()));