sync:core algorithm
This commit is contained in:
parent
fc73d4d85c
commit
1e5ebb398e
@ -4,7 +4,6 @@ using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Web;
|
||||
using System.Xml;
|
||||
using Fake.Application;
|
||||
using Fake.DependencyInjection;
|
||||
using InterfaceForward.Application.Contracts.ForwardCore;
|
||||
using InterfaceForward.Application.Helpers;
|
||||
|
||||
@ -45,7 +45,7 @@ public class InterfaceForwardCommon(
|
||||
.ToObject<ForwardCoreContextCache>();
|
||||
if (cacheContext == null)
|
||||
{
|
||||
var systemInterface = await interfaceForwardQuery.GetInterfaceByCodesAsync(upStreamCode);
|
||||
var systemInterface = await interfaceForwardQuery.GetInterfaceByCodeAsync(upStreamCode);
|
||||
if (systemInterface == null) throw new BusinessException(message: "系统接口不存在");
|
||||
|
||||
logRepository.AppRequestLog.InterfaceCode = systemInterface.Code;
|
||||
|
||||
@ -38,7 +38,8 @@ internal class CustomContractResolver : DefaultContractResolver
|
||||
if (member.DeclaringType == typeof(InterfaceParameterMapDto))
|
||||
{
|
||||
if (member.Name.IsIn(nameof(InterfaceParameterMapDto.Id), nameof(InterfaceParameterMapDto.PId),
|
||||
nameof(InterfaceParameterMapDto.InterfaceId))) return true;
|
||||
nameof(InterfaceParameterMapDto.InterfaceId),
|
||||
nameof(InterfaceParameterMapDto.FreeMap))) return true;
|
||||
}
|
||||
// 其他判断逻辑...
|
||||
|
||||
|
||||
@ -59,7 +59,7 @@ public class InterfaceMapPublishService(
|
||||
public async Task<InterfaceMapPublishedDifferenceVO> GetPublishCompareAsync([Required] string interfaceCode,
|
||||
[Required] int serviceProviderId, string? version)
|
||||
{
|
||||
var systemInterface = await interfaceForwardQuery.GetInterfaceByCodesAsync(interfaceCode);
|
||||
var systemInterface = await interfaceForwardQuery.GetInterfaceByCodeAsync(interfaceCode);
|
||||
if (systemInterface == null) throw new BusinessException(message: "系统接口不存在");
|
||||
|
||||
var serviceProvider = await interfaceForwardQuery.GetServiceProviderByIdAsync(serviceProviderId);
|
||||
@ -98,7 +98,7 @@ public class InterfaceMapPublishService(
|
||||
[HttpPost("InterfaceMap/Publish")]
|
||||
public async Task<bool> PublishAsync(InterfaceMapPublishInput input)
|
||||
{
|
||||
var systemInterface = await interfaceForwardQuery.GetInterfaceByCodesAsync(input.InterfaceCode);
|
||||
var systemInterface = await interfaceForwardQuery.GetInterfaceByCodeAsync(input.InterfaceCode);
|
||||
if (systemInterface == null) throw new BusinessException(message: "系统接口不存在");
|
||||
|
||||
var serviceProvider = await interfaceForwardQuery.GetServiceProviderByIdAsync(input.ServiceProviderId);
|
||||
@ -151,7 +151,7 @@ public class InterfaceMapPublishService(
|
||||
[HttpPost("InterfaceMap/PublishRollback")]
|
||||
public async Task<bool> PublishRollbackAsync(InterfaceMapRollbackInput input)
|
||||
{
|
||||
var systemInterface = await interfaceForwardQuery.GetInterfaceByCodesAsync(input.InterfaceCode);
|
||||
var systemInterface = await interfaceForwardQuery.GetInterfaceByCodeAsync(input.InterfaceCode);
|
||||
if (systemInterface == null) throw new BusinessException(message: "系统接口不存在");
|
||||
var serviceProvider = await interfaceForwardQuery.GetServiceProviderByIdAsync(input.ServiceProviderId);
|
||||
if (serviceProvider == null) throw new BusinessException(message: "服务商不存在");
|
||||
|
||||
@ -108,7 +108,7 @@ public class ServiceProviderAuthService : ApplicationService
|
||||
}
|
||||
|
||||
res.FixedEffectTime = authConfigs.FirstOrDefault(x => x.Flag == AuthParameterFlag.FixedEffectTime)?.Value1.ToInt();
|
||||
res.Script = authConfigs.FirstOrDefault(x => x.Flag == AuthParameterFlag.Script)?.Value1;
|
||||
res.Script = authConfigs.FirstOrDefault(x => x.Flag == AuthParameterFlag.PrefixScript)?.Value1;
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -192,7 +192,7 @@ public class ServiceProviderAuthService : ApplicationService
|
||||
{
|
||||
authConfigsEntities.Add(new ServiceProviderAuthConfigEntity
|
||||
{
|
||||
Flag = AuthParameterFlag.Script,
|
||||
Flag = AuthParameterFlag.PrefixScript,
|
||||
Value1 = input.Script,
|
||||
});
|
||||
}
|
||||
|
||||
@ -77,6 +77,11 @@ public class TargetInterfaceSummary
|
||||
/// </summary>
|
||||
public List<ParameterNode> InParamTreeList { get; set; } = [];
|
||||
|
||||
/// <summary>
|
||||
/// MapAlias不为空的入参映射,便于快速查找
|
||||
/// </summary>
|
||||
public List<InterfaceParameterMapDto> InParamMappedList { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 固定值列表
|
||||
/// </summary>
|
||||
|
||||
@ -33,6 +33,11 @@ public class InterfaceParameterMapDto
|
||||
/// 映射参数别名(被重构的)
|
||||
///</summary>
|
||||
public string MapAlias { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 数组映射别名,原数据存储数组都是结构只映射具体的值,用于重新构建数组映射,有叶子节点映射则构建映射的数组层级
|
||||
/// </summary>
|
||||
public string ArrayMapPath { get; set; }
|
||||
|
||||
///<summary>
|
||||
/// 参数类型
|
||||
@ -43,4 +48,9 @@ public class InterfaceParameterMapDto
|
||||
/// 必填的
|
||||
/// </summary>
|
||||
public bool IsRequired { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// 自由映射
|
||||
/// </summary>
|
||||
public bool FreeMap { get; set; }
|
||||
}
|
||||
@ -9,5 +9,6 @@ public enum AuthParameterFlag
|
||||
Token = 2,
|
||||
EffectTime = 3,
|
||||
FixedEffectTime = 4,
|
||||
Script = 5
|
||||
PrefixScript = 5,
|
||||
PostfixScript = 6,
|
||||
}
|
||||
@ -1,4 +1,6 @@
|
||||
using Fake;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
using Fake;
|
||||
using Fake.Application;
|
||||
using InterfaceForward.Domain.Shared.Dtos;
|
||||
using InterfaceForward.Domain.Shared.Enum;
|
||||
@ -8,37 +10,22 @@ namespace InterfaceForward.Domain.Shared.Helpers;
|
||||
|
||||
public static class JsonHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// json重构
|
||||
/// </summary>
|
||||
/// <param name="jtoken"></param>
|
||||
/// <param name="treeList"></param>
|
||||
/// <param name="jsonType">返回的json类型</param>
|
||||
/// <returns></returns>
|
||||
public static JToken Restructure(JToken jtoken, List<ParameterNode>? treeList,
|
||||
private static readonly Regex StarRegex = new(@"\[\*\]", RegexOptions.Compiled);
|
||||
|
||||
public static JToken Restructure(JToken jtoken, List<ParameterNode> treeList,
|
||||
ParameterType jsonType = ParameterType.Object)
|
||||
{
|
||||
// 没有映射时,是空树
|
||||
if (treeList == default || treeList.Count == 0) return jtoken;
|
||||
if (treeList == null || treeList.Count == 0) return jtoken;
|
||||
|
||||
var idxList = new List<int>();
|
||||
var hash = Json2Hash(jtoken); // 将json转化成hash
|
||||
|
||||
switch (jsonType)
|
||||
var arrLenHashMap = new Dictionary<string,int>(); //为构造数组长度的kv
|
||||
var hash = Json2Hash(jtoken,arrLenHashMap);
|
||||
return jsonType switch
|
||||
{
|
||||
case ParameterType.Array:
|
||||
idxList.Add(-1);
|
||||
return dfs_array(jtoken, treeList[0], hash, idxList);
|
||||
case ParameterType.String:
|
||||
case ParameterType.Float:
|
||||
case ParameterType.Boolean:
|
||||
case ParameterType.Integer:
|
||||
var value = hash[treeList[0].MapAlias!];
|
||||
return new JValue(value);
|
||||
case ParameterType.Object:
|
||||
default:
|
||||
return dfs_object(jtoken, treeList, hash, idxList);
|
||||
}
|
||||
ParameterType.Array => CreateArray(jtoken, treeList[0], hash, idxList),
|
||||
ParameterType.Object => CreateObject(jtoken, treeList, hash, idxList),
|
||||
_ => new JValue(hash[treeList[0].MapAlias!])
|
||||
};
|
||||
}
|
||||
|
||||
public static void RemoveNullProperties(JToken token)
|
||||
@ -70,28 +57,19 @@ public static class JsonHelper
|
||||
}
|
||||
}
|
||||
|
||||
private static Dictionary<string, JToken> Json2Hash(JToken jtoken)
|
||||
private static Dictionary<string, JToken> Json2Hash(JToken jtoken,Dictionary<string,int> arrLenHashMap)
|
||||
{
|
||||
if (jtoken is JObject obj)
|
||||
return jtoken switch
|
||||
{
|
||||
return Jobject2Hash(obj);
|
||||
}
|
||||
|
||||
if (jtoken is JArray arr)
|
||||
{
|
||||
return JArrayToHash(arr);
|
||||
}
|
||||
|
||||
// jvalue
|
||||
return new Dictionary<string, JToken>()
|
||||
{
|
||||
{ jtoken.Path, jtoken }
|
||||
JObject obj => Jobject2Hash(obj,arrLenHashMap),
|
||||
JArray arr => JArrayToHash(arr,arrLenHashMap),
|
||||
_ => new Dictionary<string, JToken> { { jtoken.Path, jtoken } }
|
||||
};
|
||||
}
|
||||
|
||||
private static Dictionary<string, JToken> Jobject2Hash(JObject jobject)
|
||||
private static Dictionary<string, JToken> Jobject2Hash(JObject jobject,Dictionary<string,int> arrLenHashMap)
|
||||
{
|
||||
Dictionary<string, JToken> res = new();
|
||||
var res = new Dictionary<string, JToken>();
|
||||
var q = new Queue<JProperty>(jobject.Properties());
|
||||
while (q.Count > 0)
|
||||
{
|
||||
@ -105,11 +83,11 @@ public static class JsonHelper
|
||||
}
|
||||
else if (cur.Value is JArray arr)
|
||||
{
|
||||
Add(res, JArrayToHash(arr));
|
||||
Add(res, JArrayToHash(arr,arrLenHashMap));
|
||||
}
|
||||
else
|
||||
{
|
||||
res.Add(cur.Path, cur.Value);
|
||||
res[cur.Path] = cur.Value;
|
||||
}
|
||||
}
|
||||
|
||||
@ -118,33 +96,46 @@ public static class JsonHelper
|
||||
|
||||
public static List<ParameterNode> BuildTreeList(IReadOnlyCollection<InterfaceParameterMapDto> list)
|
||||
{
|
||||
if (list.All(x => x.MapAlias.IsNullOrWhiteSpace()))
|
||||
{
|
||||
}
|
||||
|
||||
return DoBuild(list, 0);
|
||||
return list.All(x => x.MapAlias.IsNullOrWhiteSpace()) ? null : DoBuild(list, 0);
|
||||
}
|
||||
|
||||
private static List<ParameterNode> DoBuild(IReadOnlyCollection<InterfaceParameterMapDto> list, int pid)
|
||||
{
|
||||
var res = new List<ParameterNode>();
|
||||
|
||||
foreach (var child in list.Where(x => x.PId == pid))
|
||||
foreach (var item in list.Where(x => x.PId == pid))
|
||||
{
|
||||
var node = new ParameterNode();
|
||||
node.Id = child.Id;
|
||||
node.PId = child.PId;
|
||||
node.Name = child.Name;
|
||||
node.Type = child.Type;
|
||||
node.Alias = child.Alias;
|
||||
node.IsRequired = child.IsRequired;
|
||||
var node = new ParameterNode
|
||||
{
|
||||
Id = item.Id,
|
||||
PId = item.PId,
|
||||
Name = item.Name,
|
||||
Type = item.Type,
|
||||
Alias = item.Alias,
|
||||
IsRequired = item.IsRequired,
|
||||
MapAlias = item.MapAlias
|
||||
};
|
||||
|
||||
if (node.Type is ParameterType.Object or ParameterType.Array)
|
||||
{
|
||||
node.Children = DoBuild(list, child.Id);
|
||||
node.Children = DoBuild(list, item.Id);
|
||||
GetMapPath(node);
|
||||
}
|
||||
else
|
||||
else if (item.FreeMap && !item.MapAlias.IsNullOrEmpty())
|
||||
{
|
||||
node.MapAlias = child.MapAlias;
|
||||
var left = item.Alias.Split("[*]");
|
||||
var right = item.MapAlias.Split("[*]");
|
||||
int count = Math.Abs(left.Length - right.Length);
|
||||
if (count != 0)
|
||||
{
|
||||
if (left.Length > right.Length)
|
||||
{
|
||||
node.Alias = StarRegex.Replace(item.Alias, m => count-- > 0 ? "[0]" : m.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
node.MapAlias = StarRegex.Replace(item.MapAlias, m => count-- > 0 ? "[0]" : m.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
res.Add(node);
|
||||
@ -153,24 +144,78 @@ public static class JsonHelper
|
||||
return res;
|
||||
}
|
||||
|
||||
private static Dictionary<string, JToken> JArrayToHash(JArray jarr)
|
||||
/// <summary>
|
||||
/// 构建并可返回数组映射的路径MapPath,只在DoBuild递归方法中适用
|
||||
/// </summary>
|
||||
/// <param name="node">数组的node</param>
|
||||
/// <returns></returns>
|
||||
private static string GetMapPath(ParameterNode node){
|
||||
string path=null;
|
||||
if(node.Children.Count>0){
|
||||
//如果是数组,则以第一个子节点MapAlias的上一级构造为数组的MapPath;如果数组是一个基础类型则直接取MapAlias
|
||||
//逐级构造,但是只有是数组时才取用,其他类型只为数组提供依据
|
||||
if((node.Type is ParameterType.Array ) && (node.Children[0].Type is ParameterType.Object || node.Children[0].Type is ParameterType.Array) ){
|
||||
if (!node.Children[0].ArrayMapPath.IsNullOrWhiteSpace()){
|
||||
int len=node.Children[0].ArrayMapPath.LastIndexOf('.')>0?node.Children[0].ArrayMapPath.LastIndexOf('.'):node.Children[0].ArrayMapPath.Length;
|
||||
path=string.IsNullOrWhiteSpace(node.Children[0].ArrayMapPath)?null:
|
||||
node.Children[0].ArrayMapPath.Substring(0,len);
|
||||
// else{
|
||||
// path=node.Children[0].ArrayMapPath;
|
||||
// }
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(node.Type is ParameterType.Array){ //子对象为基础数据类型
|
||||
path=node.Children[0].MapAlias;
|
||||
}
|
||||
|
||||
if(node.Type is ParameterType.Object){
|
||||
if(!(node.Children[0].Type is ParameterType.Object || node.Children[0].Type is ParameterType.Array) && !string.IsNullOrWhiteSpace(node.Children[0].MapAlias)){
|
||||
if (!node.Children[0].MapAlias.IsNullOrWhiteSpace() && node.Name!="obj"){
|
||||
int len=node.Children[0].MapAlias.LastIndexOf('.')>0?node.Children[0].MapAlias.LastIndexOf('.'):node.Children[0].MapAlias.Length;
|
||||
path=string.IsNullOrWhiteSpace(node.Children[0].MapAlias)?null:
|
||||
node.Children[0].MapAlias.Substring(0,len);
|
||||
}
|
||||
else{
|
||||
path=node.Children[0].MapAlias;
|
||||
}
|
||||
}
|
||||
else{
|
||||
if (!node.Children[0].ArrayMapPath.IsNullOrWhiteSpace() && node.Name!="obj"){
|
||||
int len=node.Children[0].ArrayMapPath.LastIndexOf('.')>0?node.Children[0].ArrayMapPath.LastIndexOf('.'):node.Children[0].ArrayMapPath.Length;
|
||||
path=string.IsNullOrWhiteSpace(node.Children[0].ArrayMapPath)?null:
|
||||
node.Children[0].ArrayMapPath.Substring(0,len);
|
||||
}
|
||||
else{
|
||||
path=node.Children[0].ArrayMapPath;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
node.ArrayMapPath=path;
|
||||
return path;
|
||||
}
|
||||
|
||||
private static Dictionary<string, JToken> JArrayToHash(JArray jarr,Dictionary<string,int> arrLenHashMap)
|
||||
{
|
||||
Dictionary<string, JToken> res = new();
|
||||
//res.Add(jarr.Path, jarr.Count);
|
||||
var res = new Dictionary<string, JToken>();
|
||||
arrLenHashMap.Add(jarr.Path,jarr.Count);
|
||||
for (var i = 0; i < jarr.Count; i++)
|
||||
{
|
||||
var jToken = jarr[i];
|
||||
if (jToken is JArray arr)
|
||||
switch (jToken)
|
||||
{
|
||||
Add(res, JArrayToHash(arr));
|
||||
}
|
||||
else if (jToken is JObject obj)
|
||||
{
|
||||
Add(res, Jobject2Hash(obj));
|
||||
}
|
||||
else
|
||||
{
|
||||
res.Add(jToken.Path, jToken);
|
||||
case JArray arr:
|
||||
Add(res, JArrayToHash(arr,arrLenHashMap));
|
||||
break;
|
||||
case JObject obj:
|
||||
Add(res, Jobject2Hash(obj,arrLenHashMap));
|
||||
break;
|
||||
default:
|
||||
res[jToken.Path] = jToken;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@ -181,179 +226,70 @@ public static class JsonHelper
|
||||
{
|
||||
foreach (var item in b)
|
||||
{
|
||||
a.Add(item.Key, item.Value);
|
||||
a[item.Key] = item.Value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static JObject dfs_object(JToken jtoken, List<ParameterNode> list, Dictionary<string, JToken> hash,
|
||||
#region V1版本
|
||||
private static JObject CreateObject(JToken jtoken, List<ParameterNode> list, Dictionary<string, JToken> hash,
|
||||
List<int> idxList)
|
||||
{
|
||||
var res = new JObject();
|
||||
foreach (var item in list)
|
||||
{
|
||||
string name = item.Name;
|
||||
|
||||
if (item.Type == ParameterType.Object)
|
||||
res.Add(name, item.Type switch
|
||||
{
|
||||
res.Add(name, dfs_object(jtoken, item.Children, hash, idxList));
|
||||
}
|
||||
else if (item.Type == ParameterType.Array)
|
||||
{
|
||||
idxList.Add(-1);
|
||||
var jarray = dfs_array(jtoken, item, hash, idxList);
|
||||
|
||||
bool isEmptyArray = jarray.All(el => el.Type == JTokenType.Null);
|
||||
res.Add(item.Name, isEmptyArray ? null : jarray);
|
||||
|
||||
idxList.RemoveAt(idxList.Count - 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(item.MapAlias))
|
||||
{
|
||||
// if (item.IsRequired)
|
||||
// throw new BusinessException(message: $"必填参数{item.Name}({item.Alias})必须建立映射");
|
||||
res.Add(name, null);
|
||||
continue;
|
||||
}
|
||||
|
||||
//if (item.Alias.Split("[*]").Length != item.MapAlias.Split("[*]").Length) continue;
|
||||
JToken val = JValue.CreateNull();
|
||||
|
||||
string path = "";
|
||||
|
||||
if (item.Alias.IndexOf('[') == -1 && item.MapAlias.IndexOf('[') != -1)
|
||||
path = item.MapAlias.Replace("[*]", "[0]");
|
||||
else
|
||||
{
|
||||
for (int i = 0, j = 0; i < item.MapAlias.Length; i++)
|
||||
{
|
||||
if (item.MapAlias[i] == '[')
|
||||
{
|
||||
i += 2;
|
||||
if (j >= idxList.Count)
|
||||
throw new BusinessException(
|
||||
message: $"{item.Name}({item.MapAlias} -> {item.Alias})是非法映射");
|
||||
path += $"[{idxList[j]}]";
|
||||
j++;
|
||||
}
|
||||
else path += item.MapAlias[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (hash.ContainsKey(path!))
|
||||
{
|
||||
val = hash[path];
|
||||
}
|
||||
|
||||
val = ValidationValue(item, val);
|
||||
res.Add(name, val);
|
||||
}
|
||||
ParameterType.Object => CreateObject(jtoken, item.Children, hash, idxList),
|
||||
ParameterType.Array => CreateArray(jtoken, item, hash,idxList),
|
||||
// ParameterType.Array => CreateArray(jtoken, item, hash, idxList),
|
||||
_ => CreateValue(item, hash, idxList)
|
||||
});
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static JArray dfs_array(JToken jobject, ParameterNode arr, Dictionary<string, JToken> hash,
|
||||
private static JToken CreateArray(JToken jobject, ParameterNode arr, Dictionary<string, JToken> hash,
|
||||
List<int> idxList)
|
||||
{
|
||||
idxList.Add(-1);
|
||||
var res = new JArray();
|
||||
|
||||
var item = arr.Children[0];
|
||||
int len = get_len(jobject, item, idxList.Count);
|
||||
int len = GetLength(jobject, item, idxList);
|
||||
for (int idx = 0; idx < len; idx++)
|
||||
{
|
||||
idxList[^1]++;
|
||||
if (item.Type == ParameterType.Object)
|
||||
res.Add(item.Type switch
|
||||
{
|
||||
res.Add(dfs_object(jobject, item.Children, hash, idxList));
|
||||
}
|
||||
else if (item.Type == ParameterType.Array)
|
||||
{
|
||||
idxList.Add(-1);
|
||||
var jarray = dfs_array(jobject, item, hash, idxList);
|
||||
res.Add(jarray);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (string.IsNullOrEmpty(item.MapAlias))
|
||||
{
|
||||
// if (item.IsRequired)
|
||||
// throw new BusinessException(message: $"必填参数{item.Name}({item.Alias})必须建立映射");
|
||||
continue;
|
||||
}
|
||||
|
||||
//if (item.Alias.Split("[*]").Length != item.MapAlias.Split("[*]").Length) continue;
|
||||
//var key = item.MapAlias.Replace("[*]", $"[{idx}]");
|
||||
|
||||
JToken val;
|
||||
|
||||
string path = "";
|
||||
var strs = item.MapAlias.Split("[*]");
|
||||
if (strs.Length < 2) path = item.MapAlias;
|
||||
var i = 0;
|
||||
for (; i < strs.Length - 1; i++)
|
||||
{
|
||||
path += $"{strs[i]}[{idxList[i]}]";
|
||||
}
|
||||
|
||||
if (i != 0) path += strs[i]; // suffix
|
||||
|
||||
if (hash.ContainsKey(path!))
|
||||
{
|
||||
val = hash[path];
|
||||
}
|
||||
else break;
|
||||
|
||||
val = ValidationValue(item, val);
|
||||
res.Add(val);
|
||||
}
|
||||
ParameterType.Object => CreateObject(jobject, item.Children, hash, idxList),
|
||||
ParameterType.Array => CreateArray(jobject, item, hash, idxList),
|
||||
_ => CreateValue(item, hash, idxList)
|
||||
});
|
||||
}
|
||||
|
||||
return res;
|
||||
idxList.RemoveAt(idxList.Count - 1);
|
||||
return res.Count == 0 ? JValue.CreateNull() : res;
|
||||
}
|
||||
|
||||
private static int get_len(JToken jobject, ParameterNode item, int cnt)
|
||||
private static int GetLength(JToken jobject, ParameterNode item, List<int> idxList)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(item.MapAlias))
|
||||
{
|
||||
if (item.Type != ParameterType.Array && item.Type != ParameterType.Object) return 0;
|
||||
return get_sub_len(jobject, item, cnt);
|
||||
return item.Type is ParameterType.Array or ParameterType.Object ? GetSubLength(jobject, item, idxList) : 0;
|
||||
}
|
||||
|
||||
// 数组层级不对等情况
|
||||
if (item.Alias.Split("[*]").Length != item.MapAlias.Split("[*]").Length) return 1;
|
||||
|
||||
int index = -1;
|
||||
for (int i = 0; i < cnt; i++)
|
||||
{
|
||||
index = item.MapAlias.IndexOf("[*]", index + 1, StringComparison.Ordinal);
|
||||
if (index == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
var path = item.MapAlias.Substring(0, index + 3);
|
||||
// for (int i = 0; i < idxList.Count; i++)
|
||||
// {
|
||||
// var idx = path.IndexOf("[*]", StringComparison.Ordinal);
|
||||
// if (idx >= 0)
|
||||
// {
|
||||
// path = path.Remove(idx,3).Insert(idx,$"[{idxList[i]}]");
|
||||
// }
|
||||
// }
|
||||
string path = BuildPath(item.MapAlias, idxList);
|
||||
return jobject.SelectTokens(path).Count();
|
||||
}
|
||||
|
||||
|
||||
private static int get_sub_len(JToken jobject, ParameterNode node, int cnt)
|
||||
private static int GetSubLength(JToken jobject, ParameterNode node, List<int> idxList)
|
||||
{
|
||||
int res = 0;
|
||||
foreach (var item in node.Children)
|
||||
{
|
||||
var len = get_len(jobject, item, cnt);
|
||||
if (item.Type == ParameterType.Array) continue;
|
||||
var len = GetLength(jobject, item, idxList);
|
||||
if (len == 0) continue;
|
||||
if (res != 0 && res != len) throw new BusinessException(message: $"组成元素数量不对等,请检查{node.Alias}的组成");
|
||||
res = Math.Max(len, res);
|
||||
@ -362,13 +298,255 @@ public static class JsonHelper
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
private static JToken ValidationValue(ParameterNode node, JToken val)
|
||||
private static string BuildPath(string mapAlias, List<int> idxList)
|
||||
{
|
||||
// if (node.IsRequired && val.ToString() == "")
|
||||
// throw new BusinessException(message: $"服务商参数{node.Name}是必填的(系统{node.MapAlias}->服务商{node.Alias})");
|
||||
if (!node.IsRequired && val.Type is JTokenType.Null) return val;
|
||||
var split = mapAlias.Split(new[] { "[*]" }, StringSplitOptions.None);
|
||||
var path = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < split.Length; i++)
|
||||
{
|
||||
path.Append(split[i]);
|
||||
if (i + 1 < split.Length) // array path
|
||||
{
|
||||
var idx = idxList[idxList.Count - split.Length + i + 1];
|
||||
path.Append(idx == -1 ? "[*]" : $"[{idx}]");
|
||||
}
|
||||
}
|
||||
|
||||
return path.ToString();
|
||||
}
|
||||
|
||||
private static JToken CreateValue(ParameterNode item, Dictionary<string, JToken> hash,
|
||||
List<int> idxList)
|
||||
{
|
||||
if (string.IsNullOrEmpty(item.MapAlias))
|
||||
{
|
||||
if (item.IsRequired)
|
||||
throw new BusinessException(message: $"必填参数{item.Name}({item.Alias})必须建立映射或传入固定值");
|
||||
return JValue.CreateNull();
|
||||
}
|
||||
|
||||
if (item.Alias.Split("[*]").Length != item.MapAlias.Split("[*]").Length)
|
||||
{
|
||||
throw new BusinessException(message: $"{item.Alias}<-{item.MapAlias}是不对等映射");
|
||||
}
|
||||
|
||||
string path = BuildPath(item.MapAlias, idxList);
|
||||
JToken val = hash.TryGetValue(path, out var value) ? value : JValue.CreateNull();
|
||||
return ValidateValue(item, val);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region V2版本
|
||||
public static JToken RestructureV2(JToken jtoken, List<ParameterNode> treeList,
|
||||
ParameterType jsonType = ParameterType.Object)
|
||||
{
|
||||
if (treeList == null || treeList.Count == 0) return jtoken;
|
||||
|
||||
var idxList = new List<int>();
|
||||
var arrLenHashMap = new Dictionary<string,int>(); //为构造数组长度的kv
|
||||
var hash = Json2Hash(jtoken,arrLenHashMap);
|
||||
return jsonType switch
|
||||
{
|
||||
ParameterType.Array => CreateArrayV2(jtoken, treeList[0], hash,string.Empty),
|
||||
ParameterType.Object => CreateObjectV2(jtoken, treeList, hash, string.Empty),
|
||||
_ => new JValue(hash[treeList[0].MapAlias!])
|
||||
};
|
||||
}
|
||||
|
||||
private static JObject CreateObjectV2(JToken jtoken, List<ParameterNode> list, Dictionary<string, JToken> hash,string parentArrItemPath)
|
||||
{
|
||||
var res = new JObject();
|
||||
foreach (var item in list)
|
||||
{
|
||||
string name = item.Name;
|
||||
res.Add(name, item.Type switch
|
||||
{
|
||||
ParameterType.Object => CreateObjectV2(jtoken, item.Children, hash, parentArrItemPath),
|
||||
ParameterType.Array => CreateArrayV2(jtoken, item, hash,parentArrItemPath),
|
||||
// ParameterType.Array => CreateArray(jtoken, item, hash, idxList),
|
||||
_ => CreateValueV2(item, hash,-1,parentArrItemPath)
|
||||
});
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static JToken CreateArrayV2(JToken jobject, ParameterNode arr, Dictionary<string, JToken> hash,string parentArrItemPath)
|
||||
{
|
||||
var res = new JArray();
|
||||
var item = arr.Children[0]; //拿数组元素的结构
|
||||
var len = GetArrLen(jobject, arr, parentArrItemPath); //拿数组长度
|
||||
|
||||
for (int idx = 0; idx < len; idx++)
|
||||
{
|
||||
var arrItemPath=GetArrItemPath(arr,parentArrItemPath,idx);
|
||||
res.Add(item.Type switch
|
||||
{
|
||||
ParameterType.Object => CreateObjectV2(jobject, item.Children, hash, arrItemPath),
|
||||
ParameterType.Array => CreateArrayV2(jobject, item, hash,arrItemPath),
|
||||
_ => CreateValueV2(item, hash, -1, arrItemPath)
|
||||
});
|
||||
}
|
||||
|
||||
return res.Count == 0 ? JValue.CreateNull() : res;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 获取数组元素的路径
|
||||
/// </summary>
|
||||
/// <param name="item">数组item</param>
|
||||
/// <param name="parentArrItemPath">上级数组的path</param>
|
||||
/// <param name="idx">下标</param>
|
||||
/// <returns></returns>
|
||||
private static string GetArrItemPath(ParameterNode item,string parentArrItemPath,int idx)
|
||||
{
|
||||
var path = new StringBuilder();
|
||||
if (item.Type is ParameterType.Array && !string.IsNullOrWhiteSpace(item.ArrayMapPath))
|
||||
{
|
||||
var itemPathArr=item.ArrayMapPath.Trim().Split(new[] { "[*]" }, StringSplitOptions.RemoveEmptyEntries);
|
||||
|
||||
if(item.Alias.Split(new []{"[*]" },StringSplitOptions.RemoveEmptyEntries).Length!=item.ArrayMapPath.Split(new []{"[*]" },StringSplitOptions.RemoveEmptyEntries).Length){
|
||||
if(item.ArrayMapPath.Split(new []{"[*]" },StringSplitOptions.RemoveEmptyEntries).Length>1){
|
||||
//如果存在层级,则需判断层级是否在父层级中,在则增加父级路径,不在无法判断映射层级关系(抛异常或者只取所有父级0元素的最后一级数组)
|
||||
string pattern = @"\[\*]|\[.*?\]";
|
||||
string parentPath = Regex.Replace(parentArrItemPath, pattern, string.Empty);
|
||||
string itemPath = Regex.Replace(item.ArrayMapPath, pattern, string.Empty);
|
||||
if(itemPath.Contains(parentPath)&& (itemPath.Split('.').Length-parentPath.Split('.').Length)==1){
|
||||
path.Append(parentArrItemPath);
|
||||
}
|
||||
else{
|
||||
for (int i = 0; i < itemPathArr.Length-1; i++)
|
||||
{
|
||||
path.Append(itemPathArr[i]);
|
||||
path.Append($"[0]");
|
||||
}
|
||||
|
||||
}
|
||||
// if(!string.IsNullOrWhiteSpace(parentArrItemPath)){
|
||||
// path.Append(parentArrItemPath);
|
||||
// }
|
||||
}
|
||||
path.Append(itemPathArr[itemPathArr.Length-1]);
|
||||
if(idx>-1){
|
||||
path.Append($"[{idx}]");
|
||||
}
|
||||
}
|
||||
else{
|
||||
if(!string.IsNullOrWhiteSpace(parentArrItemPath)){
|
||||
path.Append(parentArrItemPath);
|
||||
}
|
||||
path.Append(itemPathArr[itemPathArr.Length-1]);
|
||||
if(idx>-1){
|
||||
path.Append($"[{idx}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return path.ToString();
|
||||
}
|
||||
private static int GetArrLen(JToken jobject,ParameterNode item,string parentArrItemPath)
|
||||
{
|
||||
var len = 0;
|
||||
|
||||
if (item.Type is ParameterType.Array && !string.IsNullOrWhiteSpace(item.ArrayMapPath))
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(parentArrItemPath)){
|
||||
// len= jobject.SelectTokens(item.ArrayMapPath.TrimEnd("[*]".ToArray())).Count();
|
||||
len= jobject.SelectTokens(item.ArrayMapPath).Count();
|
||||
}
|
||||
else{
|
||||
//服用GetArrItemPath方法来得到数组的路径
|
||||
var arrPath= GetArrItemPath(item,parentArrItemPath,-1)+"[*]";
|
||||
len= jobject.SelectTokens(arrPath).Count();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
|
||||
|
||||
|
||||
// private static string BuildPath(string mapAlias, List<int> idxList)
|
||||
// {
|
||||
// var split = mapAlias.Split(new[] { "[*]" }, StringSplitOptions.None);
|
||||
// var path = new StringBuilder();
|
||||
|
||||
// for (int i = 0; i < split.Length; i++)
|
||||
// {
|
||||
// path.Append(split[i]);
|
||||
// if (i + 1 < split.Length) // array path
|
||||
// {
|
||||
// path.Append("[0]");
|
||||
// }
|
||||
// }
|
||||
|
||||
// return path.ToString();
|
||||
// }
|
||||
|
||||
private static string BuildPathV2(string mapAlias, int arrIndex,string parentArrItemPath)
|
||||
{
|
||||
var split = mapAlias.Split(new[] { "[*]" }, StringSplitOptions.None);
|
||||
var path = new StringBuilder();
|
||||
|
||||
if(!string.IsNullOrWhiteSpace(parentArrItemPath)){
|
||||
path.Append(parentArrItemPath);
|
||||
|
||||
path.Append(split[split.Length-1]);
|
||||
if(arrIndex>-1){
|
||||
path.Append($"[{arrIndex}]");
|
||||
}
|
||||
}
|
||||
else{
|
||||
for (int i = 0; i < split.Length; i++)
|
||||
{
|
||||
path.Append(split[i]);
|
||||
if (i + 1 < split.Length) // array path
|
||||
{
|
||||
path.Append($"[{arrIndex}]");
|
||||
}
|
||||
}
|
||||
}
|
||||
// for (int i = 0; i < split.Length; i++)
|
||||
// {
|
||||
// path.Append(split[i]);
|
||||
// if (i + 1 < split.Length) // array path
|
||||
// {
|
||||
// path.Append($"[{arrIndex}]");
|
||||
// }
|
||||
// }
|
||||
|
||||
return path.ToString();
|
||||
}
|
||||
|
||||
private static JToken CreateValueV2(ParameterNode item, Dictionary<string, JToken> hash,
|
||||
int arrIndex, string parentArrItemPath)
|
||||
{
|
||||
if (string.IsNullOrEmpty(item.MapAlias))
|
||||
{
|
||||
if (item.IsRequired)
|
||||
throw new BusinessException(message: $"必填参数{item.Name}({item.Alias})必须建立映射或传入固定值");
|
||||
return JValue.CreateNull();
|
||||
}
|
||||
|
||||
if (item.Alias.Split("[*]").Length != item.MapAlias.Split("[*]").Length)
|
||||
{
|
||||
throw new BusinessException(message: $"{item.Alias}<-{item.MapAlias}是不对等映射");
|
||||
}
|
||||
|
||||
string path = BuildPathV2(item.MapAlias, arrIndex,parentArrItemPath);
|
||||
JToken val = hash.TryGetValue(path, out var value) ? value : JValue.CreateNull();
|
||||
return ValidateValue(item, val);
|
||||
}
|
||||
|
||||
#endregion
|
||||
private static JToken ValidateValue(ParameterNode node, JToken val)
|
||||
{
|
||||
if (node.IsRequired && val.Type is JTokenType.Null)
|
||||
throw new BusinessException(message: $"服务商参数{node.Name}是必填的(系统{node.MapAlias}->服务商{node.Alias})");
|
||||
|
||||
if (val.Type is JTokenType.Null) return val;
|
||||
|
||||
var equal = false;
|
||||
if (node.Type == ParameterType.Boolean)
|
||||
@ -406,10 +584,9 @@ public static class JsonHelper
|
||||
if (equal) val = v;
|
||||
}
|
||||
|
||||
|
||||
if (!equal)
|
||||
throw new BusinessException(message:
|
||||
$"参数{node.Name}({node.Alias})期望的类型是{node.Type},当实际分配的是{val.Type}类型的{val}({val.Path})");
|
||||
$"服务商参数{node.Name}({node.Alias})期望的类型是{node.Type},但实际分配的是{val.Type}类型的{val}({val.Path})");
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
@ -127,7 +127,8 @@ ORDER BY `b`.`Sort` ASC
|
||||
var isMultiMap = mapIds.Count > 1;
|
||||
// 因为入参映射有多个 出参映射只有一个(挂在第一个映射)
|
||||
return await Context.SqlQueryable<InterfaceParameterMapDto>(@$"
|
||||
select `b`.`Id` AS `Id` , `b`.`PId` AS `PId` , b.InterfaceId, `b`.`Name` AS `Name` ,b.Sort, `b`.`Type` AS `Type` , `b`.`Alias` AS `Alias` , {(isMultiMap ? "CONCAT(d.Code, '.', c.Alias)" : "c.Alias")} AS `MapAlias` , `b`.`IsRequired` AS `IsRequired`
|
||||
select `b`.`Id` AS `Id` , `b`.`PId` AS `PId` , b.InterfaceId, `b`.`Name` AS `Name` ,b.Sort, `b`.`Type` AS `Type` , `b`.`Alias` AS `Alias` ,
|
||||
{(isMultiMap ? "CONCAT(d.Code, '.', c.Alias)" : "c.Alias")} AS `MapAlias` , `b`.`IsRequired` AS `IsRequired` , t.FreeMap
|
||||
from t_interface_map t
|
||||
LEFT JOIN `t_parameter` `b` ON {(isInParaMap ? "t.DownStreamId" : "t.UpStreamId")} = `b`.`InterfaceId` and b.IsInPara = {isInParaMap} AND ( `b`.`IsDeleted` = 0 )
|
||||
Left JOIN `t_interface_map_detail` `a` ON ( `t`.`Id` = `a`.`InterfaceMapId` ) and b.id = a.ParaId and a.IsDeleted = 0
|
||||
@ -142,9 +143,9 @@ ORDER BY `b`.`Sort` ASC").ToListAsync();
|
||||
/// </summary>
|
||||
/// <param name="interfaceCode"></param>
|
||||
/// <returns></returns>
|
||||
public async Task<InterfaceDto?> GetInterfaceByCodesAsync(string interfaceCode)
|
||||
public async Task<InterfaceDto?> GetInterfaceByCodeAsync(string interfaceCode)
|
||||
{
|
||||
var res = await GetInterfaceByCodesAsync(new[] { interfaceCode });
|
||||
var res = await GetInterfaceByCodesAsync(interfaceCode);
|
||||
return res.FirstOrDefault();
|
||||
}
|
||||
|
||||
@ -191,21 +192,24 @@ ORDER BY `b`.`Sort` ASC").ToListAsync();
|
||||
) // 构建系统返参数树形结构
|
||||
};
|
||||
|
||||
if (serviceProvider.AuthInterfaceCode != null)
|
||||
if (!serviceProvider.AuthInterfaceCode.IsNullOrEmpty())
|
||||
{
|
||||
var authInterface = await GetInterfaceByCodesAsync(serviceProvider.AuthInterfaceCode);
|
||||
if (authInterface == null)
|
||||
var authInterface = await GetInterfaceByCodeAsync(serviceProvider.AuthInterfaceCode);
|
||||
if (authInterface != null)
|
||||
{
|
||||
throw new BusinessException($"授权接口{serviceProvider.AuthInterfaceCode}不存在");
|
||||
var authPrefixScript = context.ServiceProviderAuthConfigs
|
||||
.FirstOrDefault(x => x.Flag == AuthParameterFlag.PrefixScript)?.Value1 ?? String.Empty;
|
||||
context.ServiceProviderAuthInterface = new TargetInterfaceSummary
|
||||
{
|
||||
TargetInterface = authInterface,
|
||||
PrefixScript = authPrefixScript,
|
||||
PostfixScript = null,
|
||||
InParamTreeList = null,
|
||||
FixedFieldList = await GetAllFixedFieldListAsync(serviceProvider.Id, authInterface.Id),
|
||||
ReturnConfigList = await GetInterfaceReturnConfigListAsync(authInterface.Id),
|
||||
FormFieldList = await GetFormFieldListAsync(authInterface.Id),
|
||||
};
|
||||
}
|
||||
|
||||
context.ServiceProviderAuthInterface = new TargetInterfaceSummary
|
||||
{
|
||||
TargetInterface = authInterface,
|
||||
FixedFieldList = await GetAllFixedFieldListAsync(serviceProvider.Id, authInterface.Id),
|
||||
ReturnConfigList = await GetInterfaceReturnConfigListAsync(authInterface.Id),
|
||||
FormFieldList = await GetFormFieldListAsync(authInterface.Id),
|
||||
};
|
||||
}
|
||||
|
||||
var inParaMaps = await GetParameterMapListAsync(mapIds, true);
|
||||
@ -214,20 +218,19 @@ ORDER BY `b`.`Sort` ASC").ToListAsync();
|
||||
var targetInterface = targetInterfaceList.First(x => map.DownStreamCode == x.Code);
|
||||
var items = inParaMaps.Where(x => x.InterfaceId == targetInterface.Id).ToList();
|
||||
var fixedFieldList = await GetAllFixedFieldListAsync(serviceProvider.Id, targetInterface.Id);
|
||||
if (targetInterface.MappedParamType == ParameterType.Array)
|
||||
|
||||
foreach (var item in items)
|
||||
{
|
||||
var rootLen = items.First(x => x.PId == 0).Alias.Length;
|
||||
foreach (var item in fixedFieldList.Where(x => x.FieldPosition == FieldPosition.Body))
|
||||
{
|
||||
// 去除固定参数[*]前面的路径
|
||||
item.FieldName = item.FieldName[rootLen..];
|
||||
}
|
||||
var fixedField = fixedFieldList.FirstOrDefault(x =>
|
||||
x.FieldPosition == FieldPosition.Body && x.FieldName == item.Alias);
|
||||
if (fixedField != default) item.IsRequired = false; // 有固定值就不需要校验必填了
|
||||
}
|
||||
|
||||
context.TargetInterfaces.Add(new TargetInterfaceSummary
|
||||
{
|
||||
TargetInterface = targetInterface,
|
||||
InParamTreeList = JsonHelper.BuildTreeList(items), // 构建目标接口入参树形结构
|
||||
InParamMappedList=items?.Where(x=>x.MapAlias!=null).ToList(),
|
||||
FixedFieldList = fixedFieldList,
|
||||
ReturnConfigList = await GetInterfaceReturnConfigListAsync(targetInterface.Id),
|
||||
PrefixScript = map.PrefixScript,
|
||||
|
||||
Loading…
Reference in New Issue
Block a user