JSON.Net、匿名类型和破折号
JSON.Net, AnonymousTypes and Dashes
在 C# 中,有效的变量名不能包含破折号。但是在 Json 中,所有 属性 名称都是基于字符串的,因此对于 C# 变量名称来说,被认为是无效字符的字符在 Json.[=11= 中可能被认为是有效的]
我的问题是,当尝试反序列化为匿名类型时,JSON.Net 如何处理 属性 名称中的破折号或其他无效数据,更重要的是,您如何处理将匿名类型中的无效字符替换为捕获它。
如果需要示例数据,我可以提供,但坦率地说,只需在 Json 属性 名称中添加破折号 (-),您就可以简要了解我的情况。
P.S:我无法更改 Json 本身,因为它是从 API.
消耗的
对于 Json.Net,我建议查看动态而不是匿名 UI,它可以将您的数据反序列化为 ExpandoObject,这是一种行为类似于字典的动态类型 - 即类似于一个 JavaScript 对象。这将意味着允许的 属性 名称范围扩大,因为它们成为字典键而不是 .Net 属性。
有点喜欢:Deserialize a property as an ExpandoObject using JSON.NET
您可以使用 ContractResolver
来操纵 JSON.Net 如何将 C# 属性 名称映射到 JSON 名称。
对于您的示例,此代码执行此操作:
class DashContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
protected override string ResolvePropertyName(string propertyName)
{
// Count capital letters
int upperCount = propertyName.Skip(1).Count(x => char.IsUpper(x));
// Create character array for new name
char[] newName = new char[propertyName.Length + upperCount];
// Copy over the first character
newName[0] = char.ToLowerInvariant(propertyName[0]);
// Fill the character, and an extra dash for every upper letter
int iChar = 1;
for (int iProperty = 1; iProperty < propertyName.Length; iProperty++)
{
if (char.IsUpper(propertyName[iProperty]))
{
// Insert dash and then lower-cased char
newName[iChar++] = '-';
newName[iChar++] = char.ToLowerInvariant(propertyName[iProperty]);
}
else
newName[iChar++] = propertyName[iProperty];
}
return new string(newName, 0, iChar);
}
}
class Program
{
static void Main(string[] args)
{
string json = @"{""text-example"":""hello""}";
var anonymous = new { textExample = "" };
var obj = JsonConvert.DeserializeAnonymousType(json, anonymous,
new JsonSerializerSettings
{
ContractResolver = new DashContractResolver()
});
}
}
它将UpperCamelCase
和lowerCamelCase
转换为lower-dash-case
。因此映射到您的 JSON 输入。
DeserializeAnonymousType
的这种重载并不总是可用,并且在 Visual Studio 2013 发布的版本中不可用。当前(稳定的)NuGet 包有这个超载。
在 C# 中,有效的变量名不能包含破折号。但是在 Json 中,所有 属性 名称都是基于字符串的,因此对于 C# 变量名称来说,被认为是无效字符的字符在 Json.[=11= 中可能被认为是有效的]
我的问题是,当尝试反序列化为匿名类型时,JSON.Net 如何处理 属性 名称中的破折号或其他无效数据,更重要的是,您如何处理将匿名类型中的无效字符替换为捕获它。
如果需要示例数据,我可以提供,但坦率地说,只需在 Json 属性 名称中添加破折号 (-),您就可以简要了解我的情况。
P.S:我无法更改 Json 本身,因为它是从 API.
消耗的对于 Json.Net,我建议查看动态而不是匿名 UI,它可以将您的数据反序列化为 ExpandoObject,这是一种行为类似于字典的动态类型 - 即类似于一个 JavaScript 对象。这将意味着允许的 属性 名称范围扩大,因为它们成为字典键而不是 .Net 属性。
有点喜欢:Deserialize a property as an ExpandoObject using JSON.NET
您可以使用 ContractResolver
来操纵 JSON.Net 如何将 C# 属性 名称映射到 JSON 名称。
对于您的示例,此代码执行此操作:
class DashContractResolver : Newtonsoft.Json.Serialization.DefaultContractResolver
{
protected override string ResolvePropertyName(string propertyName)
{
// Count capital letters
int upperCount = propertyName.Skip(1).Count(x => char.IsUpper(x));
// Create character array for new name
char[] newName = new char[propertyName.Length + upperCount];
// Copy over the first character
newName[0] = char.ToLowerInvariant(propertyName[0]);
// Fill the character, and an extra dash for every upper letter
int iChar = 1;
for (int iProperty = 1; iProperty < propertyName.Length; iProperty++)
{
if (char.IsUpper(propertyName[iProperty]))
{
// Insert dash and then lower-cased char
newName[iChar++] = '-';
newName[iChar++] = char.ToLowerInvariant(propertyName[iProperty]);
}
else
newName[iChar++] = propertyName[iProperty];
}
return new string(newName, 0, iChar);
}
}
class Program
{
static void Main(string[] args)
{
string json = @"{""text-example"":""hello""}";
var anonymous = new { textExample = "" };
var obj = JsonConvert.DeserializeAnonymousType(json, anonymous,
new JsonSerializerSettings
{
ContractResolver = new DashContractResolver()
});
}
}
它将UpperCamelCase
和lowerCamelCase
转换为lower-dash-case
。因此映射到您的 JSON 输入。
DeserializeAnonymousType
的这种重载并不总是可用,并且在 Visual Studio 2013 发布的版本中不可用。当前(稳定的)NuGet 包有这个超载。