Skip to content

Commit

Permalink
😊 修复 新流变(粘土)对象错误处理 AutoCreateNestedArrays 配置问题
Browse files Browse the repository at this point in the history
  • Loading branch information
MonkSoul committed Jan 22, 2025
1 parent 0e64da5 commit 17cef14
Show file tree
Hide file tree
Showing 8 changed files with 172 additions and 120 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
// ------------------------------------------------------------------------

using Furion.Extensions;
using System.ComponentModel.DataAnnotations;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
Expand Down Expand Up @@ -728,7 +729,17 @@ public bool Delete(Index start, Index end)
return AsEnumerableArray();
}

return Helpers.DeserializeNode(JsonCanvas, resultType, jsonSerializerOptions ?? Options.JsonSerializerOptions);
// 将 JsonNode 转换为目标类型
var result = Helpers.DeserializeNode(JsonCanvas, resultType,
jsonSerializerOptions ?? Options.JsonSerializerOptions);

// 检查是否启用转换后执行模型验证
if (result is not null && Options.ValidateAfterConversion)
{
Validator.ValidateObject(result, new ValidationContext(result), true);
}

return result;
}

/// <summary>
Expand Down Expand Up @@ -938,6 +949,39 @@ public Clay KRSort(ClayOptions? options = null)
return Parse(sortedDesc, options);
}

/// <summary>
/// 重建 <see cref="Clay" /> 实例
/// </summary>
/// <param name="options">
/// <see cref="ClayOptions" />
/// </param>
/// <returns>
/// <see cref="Clay" />
/// </returns>
public Clay Rebuilt(ClayOptions? options = null)
{
// 初始化 ClayOptions 实例
var clayOptions = options ?? ClayOptions.Default;

// 创建 JsonNode 选项
var (jsonNodeOptions, jsonDocumentOptions) = CreateJsonNodeOptions(clayOptions);

// 处理是否将键值对格式的 JSON 字符串解析为单一对象
if (clayOptions.KeyValueJsonToObject &&
TryConvertKeyValueJsonToObject(JsonCanvas, jsonNodeOptions, jsonDocumentOptions, out var jsonObject))
{
JsonCanvas = jsonObject;
}
else
{
JsonCanvas = JsonNode.Parse(JsonCanvas.ToJsonString(), jsonNodeOptions, jsonDocumentOptions)!;
}

Options = clayOptions;

return this;
}

/// <summary>
/// 单一对象
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
// ------------------------------------------------------------------------

using Furion.Extensions;
using System.ComponentModel.DataAnnotations;
using System.Dynamic;
using System.Reflection;
using System.Text.Json;
Expand Down Expand Up @@ -210,13 +209,6 @@ public override bool TryConvert(ConvertBinder binder, out object? result)
{
// 转换为目标类型
result = As(binder.Type, Options.JsonSerializerOptions);

// 检查是否启用转换后执行模型验证
if (result is not null && Options.ValidateAfterConversion)
{
Validator.ValidateObject(result, new ValidationContext(result), true);
}

return true;
}

Expand Down
90 changes: 40 additions & 50 deletions framework/Furion.Pure/V5_Experience/Shapeless/Clay/Clay.cs
Original file line number Diff line number Diff line change
Expand Up @@ -163,11 +163,9 @@ internal bool RemoveValue(object identifier)
// 检查键是否是不受支持的类型
ThrowIfUnsupportedKeyType(key);

// 将键转换为字符串类型
var stringKey = key.ToString()!;

// 处理嵌套带空传播字符 ? 的标识符
var identifier = ProcessNestedNullPropagationIdentifier(stringKey);
var identifier =
ProcessNestedNullPropagationIdentifier(key, Options.AutoCreateNestedObjects, out var isUnchanged);

// 将 JsonCanvas 转换为 JsonObject 实例
var jsonObject = JsonCanvas.AsObject();
Expand All @@ -185,7 +183,7 @@ internal bool RemoveValue(object identifier)
}

// 检查是否需要处理嵌套带空传播字符 ? 的标识符
if (identifier == stringKey || !Options.AutoCreateNestedObjects)
if (isUnchanged || !Options.AutoCreateNestedObjects)
{
return null;
}
Expand Down Expand Up @@ -218,8 +216,12 @@ internal bool RemoveValue(object identifier)
? idx.IsFromEnd ? jsonArray.Count - idx.Value : idx.Value
: index;

// 处理嵌套带空传播字符 ? 的标识符
var identifier =
ProcessNestedNullPropagationIdentifier(arrayIndex, Options.AutoCreateNestedArrays, out var isUnchanged);

// 检查数组索引合法性
EnsureLegalArrayIndex(arrayIndex, out var intIndex);
EnsureLegalArrayIndex(identifier, out var intIndex);

// 获取 JsonArray 长度
var count = jsonArray.Count;
Expand All @@ -236,8 +238,8 @@ internal bool RemoveValue(object identifier)
ThrowIfOutOfRange(intIndex, count);
}

// 检查是否自动创建嵌套的数组实例
if (Options is not { AutoCreateNestedArrays: true, AutoExpandArrayWithNulls: true })
// 检查是否需要处理嵌套带空传播字符 ? 的标识符
if (isUnchanged || !Options.AutoCreateNestedArrays)
{
return null;
}
Expand All @@ -257,11 +259,8 @@ internal void SetNodeInObject(object key, object? value)
// 检查键是否是不受支持的类型
ThrowIfUnsupportedKeyType(key);

// 将键转换为字符串类型
var stringKey = key.ToString()!;

// 处理嵌套带空传播字符 ? 的标识符
var identifier = ProcessNestedNullPropagationIdentifier(stringKey);
var identifier = ProcessNestedNullPropagationIdentifier(key, Options.AutoCreateNestedObjects, out _);

// 将 JsonCanvas 转换为 JsonObject 实例
var jsonObject = JsonCanvas.AsObject();
Expand Down Expand Up @@ -312,8 +311,12 @@ internal void SetNodeInArray(object index, object? value, bool insert = false)
? idx.IsFromEnd ? jsonArray.Count - idx.Value : idx.Value
: index;

// 处理嵌套带空传播字符 ? 的标识符
var identifier =
ProcessNestedNullPropagationIdentifier(arrayIndex, Options.AutoCreateNestedArrays, out _);

// 检查数组索引合法性
EnsureLegalArrayIndex(arrayIndex, out var intIndex);
EnsureLegalArrayIndex(identifier, out var intIndex);

// 获取 JsonArray 长度
var count = jsonArray.Count;
Expand Down Expand Up @@ -389,11 +392,8 @@ internal bool RemoveNodeFromObject(object key)
// 检查键是否是不受支持的类型
ThrowIfUnsupportedKeyType(key);

// 将键转换为字符串类型
var stringKey = key.ToString()!;

// 处理嵌套带空传播字符 ? 的标识符
var identifier = ProcessNestedNullPropagationIdentifier(stringKey);
var identifier = ProcessNestedNullPropagationIdentifier(key, Options.AutoCreateNestedObjects, out _);

// 将 JsonCanvas 转换为 JsonObject 实例
var jsonObject = JsonCanvas.AsObject();
Expand Down Expand Up @@ -448,8 +448,12 @@ internal bool RemoveNodeFromArray(object index)
? idx.IsFromEnd ? jsonArray.Count - idx.Value : idx.Value
: index;

// 处理嵌套带空传播字符 ? 的标识符
var identifier =
ProcessNestedNullPropagationIdentifier(arrayIndex, Options.AutoCreateNestedArrays, out _);

// 检查数组索引合法性
EnsureLegalArrayIndex(arrayIndex, out var intIndex);
EnsureLegalArrayIndex(identifier, out var intIndex);

// 获取 JsonArray 长度
var count = jsonArray.Count;
Expand Down Expand Up @@ -520,7 +524,7 @@ internal bool TryGetDelegate(object key, out Delegate? @delegate)
}

// 处理嵌套带空传播字符 ? 的标识符
var identifier = ProcessNestedNullPropagationIdentifier(key.ToString()!);
var identifier = ProcessNestedNullPropagationIdentifier(key, Options.AutoCreateNestedObjects, out _);

return DelegateMap.TryGetValue(identifier, out @delegate);
}
Expand Down Expand Up @@ -573,48 +577,34 @@ internal bool TryGetDelegate(object key, out Delegate? @delegate)
};

/// <summary>
/// 重建 <see cref="Clay" /> 实例
/// 处理嵌套带空传播字符 <c>?</c> 的标识符
/// </summary>
/// <param name="options">
/// <see cref="ClayOptions" />
/// </param>
/// <param name="identifier">标识符</param>
/// <param name="enable">是否启用处理</param>
/// <param name="isUnchanged">标识符是否未被改变</param>
/// <returns>
/// <see cref="Clay" />
/// <see cref="string" />
/// </returns>
internal Clay Rebuilt(ClayOptions? options = null)
internal static string ProcessNestedNullPropagationIdentifier(object identifier, bool enable, out bool isUnchanged)
{
// 初始化 ClayOptions 实例
var clayOptions = options ?? ClayOptions.Default;

// 创建 JsonNode 选项
var (jsonNodeOptions, jsonDocumentOptions) = CreateJsonNodeOptions(clayOptions);
// 将标识符转换为字符串类型
var stringIdentifier = identifier.ToString()!;

// 处理是否将键值对格式的 JSON 字符串解析为单一对象
if (clayOptions.KeyValueJsonToObject &&
TryConvertKeyValueJsonToObject(JsonCanvas, jsonNodeOptions, jsonDocumentOptions, out var jsonObject))
// 检查是否启用空传播字符 ? 处理
if (!enable)
{
JsonCanvas = jsonObject;
}
else
{
JsonCanvas = JsonNode.Parse(JsonCanvas.ToJsonString(), jsonNodeOptions, jsonDocumentOptions)!;
isUnchanged = true;
return stringIdentifier;
}

Options = clayOptions;
// 尝试移除字符串标识符末尾字符 ?
var finalIdentifier = stringIdentifier.TrimEnd('?');

return this;
// 如果没有变化,则表示未修改
isUnchanged = stringIdentifier == finalIdentifier;
return finalIdentifier;
}

/// <summary>
/// 处理嵌套带空传播字符 <c>?</c> 的标识符
/// </summary>
/// <param name="identifier">标识符</param>
/// <returns>
/// <see cref="string" />
/// </returns>
internal string ProcessNestedNullPropagationIdentifier(string identifier) =>
!Options.AutoCreateNestedObjects ? identifier : identifier.TrimEnd('?');

/// <summary>
/// 对数组进行 null 值补位
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,7 +70,7 @@ public sealed class ClayOptions
/// </summary>
/// <remarks>
/// 当 <see cref="Clay.IsArray" /> 和 <see cref="AutoCreateNestedArrays" /> 为 <c>true</c> 时有效。默认值为:<c>false</c>
/// ,当设置为 <c>true</c> 时,如果尝试访问或设置超出数组长度的索引时,将自动补位新的 <see cref="Clay" /> 数组实例。
/// ,当设置为 <c>true</c> 时,如果尝试访问或设置超出数组长度的索引并且索引器带 <c>?</c> 后缀的键时,将自动创建一个新的 <see cref="Clay" /> 数组实例。
/// </remarks>
public bool AutoCreateNestedArrays { get; set; }

Expand Down
46 changes: 45 additions & 1 deletion framework/Furion/V5_Experience/Shapeless/Clay/Clay.Exports.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
// ------------------------------------------------------------------------

using Furion.Extensions;
using System.ComponentModel.DataAnnotations;
using System.Text.Encodings.Web;
using System.Text.Json;
using System.Text.Json.Nodes;
Expand Down Expand Up @@ -728,7 +729,17 @@ public bool Delete(Index start, Index end)
return AsEnumerableArray();
}

return Helpers.DeserializeNode(JsonCanvas, resultType, jsonSerializerOptions ?? Options.JsonSerializerOptions);
// 将 JsonNode 转换为目标类型
var result = Helpers.DeserializeNode(JsonCanvas, resultType,
jsonSerializerOptions ?? Options.JsonSerializerOptions);

// 检查是否启用转换后执行模型验证
if (result is not null && Options.ValidateAfterConversion)
{
Validator.ValidateObject(result, new ValidationContext(result), true);
}

return result;
}

/// <summary>
Expand Down Expand Up @@ -938,6 +949,39 @@ public Clay KRSort(ClayOptions? options = null)
return Parse(sortedDesc, options);
}

/// <summary>
/// 重建 <see cref="Clay" /> 实例
/// </summary>
/// <param name="options">
/// <see cref="ClayOptions" />
/// </param>
/// <returns>
/// <see cref="Clay" />
/// </returns>
public Clay Rebuilt(ClayOptions? options = null)
{
// 初始化 ClayOptions 实例
var clayOptions = options ?? ClayOptions.Default;

// 创建 JsonNode 选项
var (jsonNodeOptions, jsonDocumentOptions) = CreateJsonNodeOptions(clayOptions);

// 处理是否将键值对格式的 JSON 字符串解析为单一对象
if (clayOptions.KeyValueJsonToObject &&
TryConvertKeyValueJsonToObject(JsonCanvas, jsonNodeOptions, jsonDocumentOptions, out var jsonObject))
{
JsonCanvas = jsonObject;
}
else
{
JsonCanvas = JsonNode.Parse(JsonCanvas.ToJsonString(), jsonNodeOptions, jsonDocumentOptions)!;
}

Options = clayOptions;

return this;
}

/// <summary>
/// 单一对象
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
// ------------------------------------------------------------------------

using Furion.Extensions;
using System.ComponentModel.DataAnnotations;
using System.Dynamic;
using System.Reflection;
using System.Text.Json;
Expand Down Expand Up @@ -210,13 +209,6 @@ public override bool TryConvert(ConvertBinder binder, out object? result)
{
// 转换为目标类型
result = As(binder.Type, Options.JsonSerializerOptions);

// 检查是否启用转换后执行模型验证
if (result is not null && Options.ValidateAfterConversion)
{
Validator.ValidateObject(result, new ValidationContext(result), true);
}

return true;
}

Expand Down
Loading

0 comments on commit 17cef14

Please sign in to comment.