From 9c7809d5fd7cc56a743a857af2a83739c02d2aab Mon Sep 17 00:00:00 2001 From: Kingcean Date: Sat, 11 Jan 2025 15:47:45 +0800 Subject: [PATCH] Optimize query data to support JSON. --- Core/Collection/Dictionary/KeyValuePairs.cs | 41 ++++++++++++++++++ Core/Net/Uri/QueryData.cs | 46 +++++++++++++++++++++ Core/Text/JsonNode/Values.cs | 13 ++++++ 3 files changed, 100 insertions(+) diff --git a/Core/Collection/Dictionary/KeyValuePairs.cs b/Core/Collection/Dictionary/KeyValuePairs.cs index 34e6a19..a5c48d8 100644 --- a/Core/Collection/Dictionary/KeyValuePairs.cs +++ b/Core/Collection/Dictionary/KeyValuePairs.cs @@ -6,6 +6,7 @@ using System.Runtime.Serialization; using System.Security; using System.Text; +using System.Text.Json; using System.Web; using Trivial.Text; @@ -142,6 +143,24 @@ public void Add(string key, long value, bool clearOthers = false) /// The value. /// true if clear the others of the property before adding; otherwise, false. public void Add(string key, double value, bool clearOthers = false) + => Add(key, double.IsNaN(value) ? null : value.ToString("g", CultureInfo.InvariantCulture), clearOthers); + + /// + /// Adds a key and the value to the end of the key value pairs. + /// + /// The key. + /// The value. + /// true if clear the others of the property before adding; otherwise, false. + public void Add(string key, float value, bool clearOthers = false) + => Add(key, float.IsNaN(value) ? null : value.ToString("g", CultureInfo.InvariantCulture), clearOthers); + + /// + /// Adds a key and the value to the end of the key value pairs. + /// + /// The key. + /// The value. + /// true if clear the others of the property before adding; otherwise, false. + public void Add(string key, decimal value, bool clearOthers = false) => Add(key, value.ToString("g", CultureInfo.InvariantCulture), clearOthers); /// @@ -153,6 +172,28 @@ public void Add(string key, double value, bool clearOthers = false) public void Add(string key, bool value, bool clearOthers = false) => Add(key, value ? JsonBooleanNode.TrueString : JsonBooleanNode.FalseString, clearOthers); + /// + /// Adds a key and the value to the end of the key value pairs. + /// + /// The key. + /// The value. + /// true if clear the others of the property before adding; otherwise, false. + public void Add(string key, BaseJsonValueNode value, bool clearOthers = false) + { + if (value is null || value.ValueKind == JsonValueKind.Null || value.ValueKind == JsonValueKind.Undefined) Add(key, null as string, clearOthers); + else if (value.ValueKind == JsonValueKind.True) Add(key, true, clearOthers); + else if (value.ValueKind == JsonValueKind.False) Add(key, false, clearOthers); + else if (value is IJsonValueNode str) Add(key, str.Value, clearOthers); + else if (value is IJsonValueNode i1) Add(key, i1.Value, clearOthers); + else if (value is IJsonValueNode i2) Add(key, i2.Value, clearOthers); + else if (value is IJsonValueNode i3) Add(key, i3.Value, clearOthers); + else if (value is JsonArrayNode arr) Add(key, arr.ToString(), clearOthers); + else if (value is JsonObjectNode obj) Add(key, obj.ToString(), clearOthers); + else if (value is IJsonValueNode b) Add(key, b.Value, clearOthers); + else if (value is IJsonValueNode i4) Add(key, i4.Value, clearOthers); + else if (value is IJsonValueNode i5) Add(key, i5.Value, clearOthers); + } + /// /// Adds a key and a set of value to the end of the key value pairs. /// diff --git a/Core/Net/Uri/QueryData.cs b/Core/Net/Uri/QueryData.cs index f0ea91f..0ab275e 100644 --- a/Core/Net/Uri/QueryData.cs +++ b/Core/Net/Uri/QueryData.cs @@ -7,6 +7,8 @@ using System.Runtime.InteropServices; using System.Runtime.Serialization; using System.Text; +using System.Text.Json.Serialization; +using System.Text.Json; using System.Threading.Tasks; using System.Web; @@ -19,6 +21,7 @@ namespace Trivial.Net; /// /// The query data in URI after question mark. /// +[JsonConverter(typeof(QueryDataConverter))] [Guid("E17633F1-1C54-484C-9751-C049368AE6FD")] public class QueryData : StringKeyValuePairs { @@ -431,3 +434,46 @@ public static async Task ParseAsync(Stream stream, Encoding encoding } #pragma warning restore IDE0056, IDE0057, CA1834 } + +/// +/// The JSON converter for query data. +/// +internal class QueryDataConverter : JsonConverter +{ + /// + public override QueryData Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) + { + switch (reader.TokenType) + { + case JsonTokenType.Null: + case JsonTokenType.False: + return null; + case JsonTokenType.True: + return new(); + case JsonTokenType.String: + return QueryData.Parse(reader.GetString()); + case JsonTokenType.StartObject: + { + var json = JsonObjectNode.ParseValue(ref reader); + if (json is null) return null; + var q = new QueryData(); + foreach (var prop in json) + { + if (string.IsNullOrWhiteSpace(prop.Key)) continue; + q.Add(prop.Key, prop.Value); + } + + return q; + } + default: + throw new JsonException($"The JSON value should be a string."); + } + } + + /// + public override void Write(Utf8JsonWriter writer, QueryData value, JsonSerializerOptions options) + { + if (value is null) writer.WriteNullValue(); + else writer.WriteStringValue(value.ToString()); + } +} diff --git a/Core/Text/JsonNode/Values.cs b/Core/Text/JsonNode/Values.cs index 2f0dc8b..c76a8ad 100644 --- a/Core/Text/JsonNode/Values.cs +++ b/Core/Text/JsonNode/Values.cs @@ -1886,6 +1886,19 @@ public static void WriteTo(Stream stream, object obj, JsonSerializerOptions opti return; } + /// + /// Writes this instance to the specified writer as a JSON value. + /// + /// The object to serialize. + /// The writer to which to write this instance. + public static void WriteTo(IJsonObjectHost source, Utf8JsonWriter writer) + { + if (writer is null) return; + var json = source?.ToJson(); + if (json is null) writer.WriteNullValue(); + else json.WriteTo(writer); + } + internal static void SkipComments(ref Utf8JsonReader reader) { while (reader.TokenType == JsonTokenType.Comment)