From e4911054e31feb18e784bd30e647e89487462938 Mon Sep 17 00:00:00 2001 From: Boris Date: Thu, 8 Feb 2024 18:34:47 +0100 Subject: [PATCH] Better formatting of caps as json --- .../Helpers/LowerCaseNamingStrategy.cs | 9 ++++++ src/Jackett.Common/Helpers/XmlToJsonWriter.cs | 29 +++++++++++++++++++ .../Models/TorznabCapabilities.cs | 17 +++++++++++ .../Controllers/ResultsController.cs | 16 +++++++++- 4 files changed, 70 insertions(+), 1 deletion(-) create mode 100644 src/Jackett.Common/Helpers/LowerCaseNamingStrategy.cs create mode 100644 src/Jackett.Common/Helpers/XmlToJsonWriter.cs diff --git a/src/Jackett.Common/Helpers/LowerCaseNamingStrategy.cs b/src/Jackett.Common/Helpers/LowerCaseNamingStrategy.cs new file mode 100644 index 000000000..a50847353 --- /dev/null +++ b/src/Jackett.Common/Helpers/LowerCaseNamingStrategy.cs @@ -0,0 +1,9 @@ +using Newtonsoft.Json.Serialization; + +namespace Jackett.Common.Helpers +{ + public class LowerCaseNamingStrategy : NamingStrategy + { + protected override string ResolvePropertyName(string name) => name.ToLowerInvariant(); + } +} diff --git a/src/Jackett.Common/Helpers/XmlToJsonWriter.cs b/src/Jackett.Common/Helpers/XmlToJsonWriter.cs new file mode 100644 index 000000000..d48de88af --- /dev/null +++ b/src/Jackett.Common/Helpers/XmlToJsonWriter.cs @@ -0,0 +1,29 @@ +using System.IO; +using Newtonsoft.Json; + +namespace Jackett.Common.Helpers +{ + /// + /// JsonTextWriter to convert XML to JSON. + /// Makes sure that XML attributes do not have the '@' or '#' prefix in the JSON output. + /// https://stackoverflow.com/a/43485727 + /// + public class XmlToJsonWriter : JsonTextWriter + { + public XmlToJsonWriter(TextWriter textWriter) : base(textWriter) + { + } + + public override void WritePropertyName(string name) + { + if (name.StartsWith("@") || name.StartsWith("#")) + { + base.WritePropertyName(name.Substring(1)); + } + else + { + base.WritePropertyName(name); + } + } + } +} diff --git a/src/Jackett.Common/Models/TorznabCapabilities.cs b/src/Jackett.Common/Models/TorznabCapabilities.cs index 93b167733..ad24b850e 100644 --- a/src/Jackett.Common/Models/TorznabCapabilities.cs +++ b/src/Jackett.Common/Models/TorznabCapabilities.cs @@ -1,7 +1,11 @@ using System; using System.Collections.Generic; +using System.IO; using System.Linq; +using System.Text; using System.Xml.Linq; +using Jackett.Common.Helpers; +using Newtonsoft.Json; namespace Jackett.Common.Models { @@ -352,6 +356,19 @@ namespace Jackett.Common.Models public string ToXml() => GetXDocument().Declaration + Environment.NewLine + GetXDocument(); + public string ToJson(JsonSerializerSettings serializerSettings = null) + { + var stringBuilder = new StringBuilder(); + var serializer = JsonSerializer.Create(serializerSettings); + + using var stringWriter = new StringWriter(stringBuilder); + using var jsonWriter = new XmlToJsonWriter(stringWriter); + + serializer.Serialize(jsonWriter, GetXDocument().Root); + + return stringBuilder.ToString(); + } + public static TorznabCapabilities Concat(TorznabCapabilities lhs, TorznabCapabilities rhs) { lhs.SearchAvailable = lhs.SearchAvailable || rhs.SearchAvailable; diff --git a/src/Jackett.Server/Controllers/ResultsController.cs b/src/Jackett.Server/Controllers/ResultsController.cs index c978557b2..61683e618 100644 --- a/src/Jackett.Server/Controllers/ResultsController.cs +++ b/src/Jackett.Server/Controllers/ResultsController.cs @@ -8,6 +8,7 @@ using System.Threading.Tasks; using System.Xml.Linq; using Jackett.Common; using Jackett.Common.Exceptions; +using Jackett.Common.Helpers; using Jackett.Common.Indexers; using Jackett.Common.Indexers.Meta; using Jackett.Common.Models; @@ -20,6 +21,8 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Filters; using Microsoft.AspNetCore.Routing; using Microsoft.Net.Http.Headers; +using Newtonsoft.Json; +using Newtonsoft.Json.Converters; using Newtonsoft.Json.Linq; using NLog; @@ -176,6 +179,17 @@ namespace Jackett.Server.Controllers private readonly IServerService serverService; private readonly ICacheService cacheService; private readonly Common.Models.Config.ServerConfig serverConfig; + private static readonly JsonSerializerSettings _JsonSerializerSettings = new JsonSerializerSettings + { + Converters = new List + { + new StringEnumConverter + { + NamingStrategy = new LowerCaseNamingStrategy() + } + }, + NullValueHandling = NullValueHandling.Ignore + }; public ResultsController(IIndexerManagerService indexerManagerService, IServerService ss, ICacheService c, Logger logger, Common.Models.Config.ServerConfig sConfig) { @@ -342,7 +356,7 @@ namespace Jackett.Server.Controllers if (string.Equals(CurrentQuery.QueryType, "caps", StringComparison.InvariantCultureIgnoreCase)) { return CurrentQuery.IsJson ? - (IActionResult)Json(CurrentIndexer.TorznabCaps) : + (IActionResult)Json(CurrentIndexer.TorznabCaps.ToJson(_JsonSerializerSettings)) : Content(CurrentIndexer.TorznabCaps.ToXml(), "application/rss+xml", Encoding.UTF8); }