Best way to code this, string to map conversion in Groovy

后端 未结 8 1874
情深已故
情深已故 2020-12-31 07:22

I have a string like

def data = \"session=234567893egshdjchasd&userId=12345673456&timeOut=1800000\"

I want to convert it to a map

相关标签:
8条回答
  • 2020-12-31 07:51

    If you are in a grails controller, then this is nice and simple:

    GrailsParameterMap map = new GrailsParameterMap(request)
    

    http://grails.org/doc/latest/api/org/codehaus/groovy/grails/web/servlet/mvc/GrailsParameterMap.html

    0 讨论(0)
  • 2020-12-31 07:51

    I wouldn't suggest using split at all.

    Split creates a new string, whereas when creating a collection of environment variables, you would probably want a list of maps.

    Tokenize both on the initial break (&) and on the nested break (=). While most interpreters will still work, some may run the split literally, and you'll end up with a list of strings, rather than a list of maps.

    def data= "test1=val1&test2=val2"
    def map = [:]
    
    map = data.tokenize("&").collectEntries {
        it.tokenize("=").with {
            [(it[0]):it[1]]
        }
    }
    
    0 讨论(0)
  • 2020-12-31 07:52

    If you use Grails, the best way I find is WebUtils the function fromQueryString.

    https://grails.github.io/grails-doc/2.0.x/api/org/codehaus/groovy/grails/web/util/WebUtils.html

    0 讨论(0)
  • 2020-12-31 08:01

    I don't know if this is more efficient, but to my eyes, it's a bit simpler (YMMV)

    def data = "session=234567893egshdjchasd&userId=12345673456&timeOut=1800000"
    def map = [:]
    
    data.split("&").each {param ->
        def nameAndValue = param.split("=")
        map[nameAndValue[0]] = nameAndValue[1]
    }
    
    0 讨论(0)
  • 2020-12-31 08:03

    Here's my effort, which initializes and fills the map in one go, and avoids the inject method which I personally find hard to follow:-

        def map = data.split('&').collectEntries {
            def kvp = it.split('=').collect { string ->
                string = string.trim()
                return string
        }
        [(kvp[0]): kvp.size() > 1 ? kvp[1] ?: '' : '']
        // the null check is almost certainly overkill so you could use :-
        // [(kvp[0]): kvp.size() > 1 ? kvp[1] : '']
        // this just checks that a value was found and inserts an empty string instead of null 
    }
    
    0 讨论(0)
  • 2020-12-31 08:07

    After some searching, "collectEntries()" is the magic thing to use, it creates a map element. Work just like "collect()" that creates a list. So given

    def params = "a1=b1&a2=b2&a3&a4=&a5=x=y"
    

    the one-liner is

    map = params.tokenize("&").collectEntries{ 
              it.split("=",2).with{ 
                  [ (it[0]): (it.size()<2) ? null : it[1] ?: null ] 
              }
          }
    

    which creates

    map = [a1:b1, a2:b2, a3:null, a4:null, a5:x=y]
    

    Depending how you want to handle the cases "a3" and "a4=" you can also use a slightly shorter version

    ...
    [ (it[0]): (it.size()<2) ? null : it[1] ] 
    ...
    

    and then you get this:

    map = [a1:b1, a2:b2, a3:null, a4:, a5:x=y]
    
    0 讨论(0)
提交回复
热议问题