【问题标题】:Convert property name to valid json field identifier将属性名称转换为有效的 json 字段标识符
【发布时间】:2018-06-11 04:17:20
【问题描述】:

我正在编写一个方便的小扩展方法,它将接受一个字符串并将其返回格式,就好像它是一个 lowerCamelCase JSON 标识符一样。

这是我目前所拥有的......请问我可以帮助改进它吗?

我需要以下行为:

  • 用户名 => 用户名
  • 用户 ID => 用户 ID
  • 用户 => 用户
  • 钓鱼之旅 => 钓鱼之旅
  • 123123123 => 123123123
  • aaa123 => aaa123
  • 你好,这就是我 => helloWorldThisIsMe

奖励 - 如果我们能以某种方式去除非 [A-Za-z0-9] 字符?我想我可以再做一轮正则表达式?

感谢您的帮助!

    public static string ToJsonIdentifier(string s)
    {
        // special case, s is empty
        if (string.IsNullOrEmpty(s)) return s;

        // clean up the string, remove any non-standard chars
        s = Regex.Replace(s, @"[^A-Za-z0-9\s]+", "");

        // special case s is whitespace
        if (string.IsNullOrWhiteSpace(s)) return String.Empty;

        // special case s is only 1 letter
        if (!string.IsNullOrEmpty(s) && s.Length == 1) 
            return s.ToLowerInvariant();

        // detect word boundaries where the case changes and add whitespace there, so the next code splits it up
        s = Regex.Replace(s, "([a-z])([A-Z])", m=> m.Groups[1].Value + " " + m.Groups[2].Value);

        // multiple words, so for each whitespace separated bit, uppercase the first letter, and deal with special cases
        if (s.Contains(" "))
        {
            s = string.Join("", s.Split(' ').ToList().Select(z => 
                {
                    if (string.IsNullOrWhiteSpace(z)) return string.Empty;
                    if (z.Length == 1) return z.ToUpperInvariant();
                    return z.ToUpperInvariant()
                            .Substring(0, 1) + z.Substring(1).ToLowerInvariant();
                }));
        }


        // lowercase the first letter
        return char.ToLower(s[0]) + s.Substring(1);
    }

研究:我看过这些问题,似乎相关:

我正在进行的尝试:https://dotnetfiddle.net/PR31Hl

【问题讨论】:

  • 你能显示你的 json 并且是 's' 指定你的 json 字符串吗?
  • 这是一个扩展方法,所以你可以在任何字符串上调用它。我已经添加了我所期望的行为,请你解释一下你需要什么?

标签: c# json


【解决方案1】:

您的代码似乎已经给出了预期的结果。您想改进哪一部分?

我认为这不是您需要的答案。但我只是想分享我将如何解决这个问题,我不使用 Linq/Regex 而只是检查字符串中的每个字符的内存(并且没有 Linq/Regex 库)效率。我想这在这个过程中也应该更轻量级。但请注意,这可能不容易阅读。

public static string ToJsonIdentifier(string s)
{
    // special case, s is empty
    if (string.IsNullOrEmpty(s)) return s;

    var result = new StringBuilder();

    bool isFirst = true; // Is First (non-whitespace) Character Flag
    bool isSpace = false; // Is Whitespace Flag
    bool isUpperCase = false; // Is Uppercase Flag
    foreach(char c in s)
    {
        // filter to be letter or digit only
        if(!char.IsLetterOrDigit(c))
        {
            continue;
        }

        if(isFirst)
        {
            if (!char.IsWhiteSpace(c))
            {
                // if first character, set to lower case
                result.Append(char.ToLower(c));
                isFirst = false; // no more first flag
            }
            // if WhiteSpace, ignore the character
        }
        else if(char.IsWhiteSpace(c))
        {
            isSpace = true; // set the Whitespace flag, so next char should be uppercase
        }
        else if(char.IsUpper(c))
        {
            if (!isUpperCase)
            {
                // if previous char is lower case, set it as it is (as uppercase) 
                result.Append(c);
                isUpperCase = true;
            }
            else
            {
                // if previous char is uppercase, set this to lower instead
                result.Append(char.ToLower(c));
                // and keep the uppercase flag on, so multiple uppercase in the row will be converted to lower, until lower case is found.
            }
        }
        else if(char.IsLower(c))
        {
            if(isSpace) // if previous char is whitespace, set char to be upper case
            {
                isSpace = false; // no more whitespace flag
                result.Append(char.ToUpper(c));
                isUpperCase = true;  // set upper case flag on
            }
            else
            {
                isUpperCase = false; // no more upper case flag
                result.Append(c);
            }
        }
        else if(char.IsDigit(c))
        {
            // reset all flags
            isSpace = false;
            isUpperCase = false;
            result.Append(c);
        }
    }
    return result.ToString();
}

【讨论】:

  • 是的,这就是我希望/寻找的 - 非正则表达式,单次通过字符串,似乎比我的方法更有效
猜你喜欢
  • 2015-04-02
  • 1970-01-01
  • 2016-11-08
  • 2016-02-06
  • 2020-01-25
  • 2022-01-27
  • 2021-01-09
  • 1970-01-01
  • 2020-02-02
相关资源
最近更新 更多