问题描述
我想获取一个 System.Web.Mvc.ModelStateDictionary
并将其转换(unflatten)为一个可读对象,该对象可以在 Json 中安全地序列化以进行日志记录。
模型状态输入看起来像这样:
{
"FirstName": "Somebody","LastName": "Awesome","Emails[0].EmailType": "Primary","Emails[0].EmailAddress": "asdf@tempuri.com","Emails[0].UpdatedBy": "tester","UpdatedBy": null
}
我想要的输出是这样的:
{
"Emails": {
"0": {
"EmailAddress": "asdf@tempuri.com","EmailType": "Primary","UpdatedBy": "tester"
}
},"FirstName": "Somebody","UpdatedBy": null
}
是否有内置的方法可以使用 Mvc 甚至外部库来完成此操作?
解决方法
执行此操作的本土函数是:
public Dictionary<string,object> Convert(ModelStateDictionary modelState)
{
var o = new Dictionary<string,object>();
var sorted = modelState.OrderBy(_ => _.Key).ToList();
foreach (var ms in sorted)
{
string key = ms.Key;
// each key starts at the root node
var node = o;
int i = 0;
int ic = 0;
string token;
// extract each token and build dictionaries
for (; i < key.Length - 1; i++)
{
var c = key[i];
switch (c)
{
case '.':
// don't bother with lists just use a dictionary,just easier!
case '[':
case ']':
if (i - ic > 0)
{
token = key.Substring(ic,i - ic);
if (!node.TryGetValue(token,out var cn) || !(cn is Dictionary<string,object> v))
{
node[token] = v = new Dictionary<string,object>();
}
node = v;
}
ic = i + 1;
break;
default:
break;
}
}
i++;
token = key.Substring(ic,i - ic);
node[token] = ms.Value.Value?.AttemptedValue;
}
return o;
}