代码之家  ›  专栏  ›  技术社区  ›  user230910

将属性名转换为有效的json字段标识符

  •  -1
  • user230910  · 技术社区  · 6 年前

    我想编写一个方便的小扩展方法,它将接收一个字符串并将其格式化,就像它是一个低级CAMELSE JSON标识符一样。

    这就是我目前所拥有的…请帮我改进一下好吗?

    我需要以下行为:

    • 用户名=>用户名
    • 用户ID=>用户ID
    • 用户=>用户
    • 钓鱼之旅=>钓鱼之旅
    • 123123123=>123123123
    • aaa123=>aaa123级
    • 你好,世界,这是我=>你好,世界,这是我

    如果我们能把非[a-za-z0-9]字符去掉?我想我可以再做一轮regex吗?

    谢谢你的帮助!

        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

    1 回复  |  直到 6 年前
        1
  •  1
  •   kurakura88    6 年前

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

    我认为这不是你所需要的答案。但我只想分享我将如何解决这个问题,我不使用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();
    }