JSON.Net、匿名类型和破折号

3
在C#中,有效的变量名不能包含破折号。但是在Json中,所有属性名称都基于字符串,因此对于C#变量名来说被认为是无效字符的内容,在Json中可能被认为是有效的。
我的问题是,当尝试反序列化为匿名类型时,在属性名称中使用破折号或其他无效数据时,JSON.Net如何处理,更重要的是,您需要用什么替换匿名类型中的无效字符才能捕获它。
如果需要示例数据,我可以提供,但老实说,只需向Json属性名称添加一个破折号(-),您就可以了解我的情况。
P.S:我无法更改Json本身,因为它正在从API中获取。
2个回答

2
您可以使用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()
            });


    }
}

它将UpperCamelCaselowerCamelCase转换为lower-dash-case,从而映射到您的JSON输入。
这个重载的DeserializeAnonymousType并不总是可用的,并且在Visual Studio 2013版本中也不可用。当前(稳定)的NuGet包中包含此重载。

这似乎是我想要的东西,但我需要理解您在For循环中的逻辑,我不太明白它在做什么... - Nikey646
我不知道为什么你的ContractResolver会在属性名中添加额外的破折号,但是这个魔法正在起作用,而且正是我想要的!编辑:在输出newName和propertyName之后,我意识到我看错了。它将我想要的名称转换为应该查找的JSON名称。 - Nikey646
@Nikey646 是的,这就是 JSON.Net 的工作方式,它会获取你的对象,然后找到匹配该对象的属性。 它只是用旧字符和偶尔的破折号填充一个稍微更大的新数组(以适应破折号),它不测试0长度或null字符串(因为它无法处理这些情况),但我有点假定 JSON.Net 不会将这些传递给你,因为在 C# 中不能有零长度或null变量名。(而且我非常确定在.NET中通常也是如此。) - Aidiakapi

1
我建议您查看Json.Net的Dynamic UI而不是Anonymous UI,它可以将您的数据反序列化为ExpandoObject,这是一种动态类型,其行为类似于字典 - 即类似于JavaScript对象。这将意味着允许的属性名称范围增加了,因为它们变成了字典键而不是.Net属性。
有点像:使用JSON.NET将属性反序列化为ExpandoObject

我实际上正在放弃使用动态对象,因为使用数组时遇到了一些麻烦,必须重新序列化才能从动态对象返回对象。 - Nikey646

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接