简体   繁体   中英

Grails convert String to Map with comma in string values

I want convert string to Map in grails. I already have a function of string to map conversion. Heres the code,

static def StringToMap(String reportValues){
    Map result=[:]
         result=reportValues.replace('[','').replace(']','').replace('  ','').split(',').inject([:]){map,token ->
            List tokenizeStr=token.split(':');
            tokenizeStr.size()>1?tokenizeStr?.with {map[it[0]?.toString()?.trim()]=it[1]?.toString()?.trim()}:tokenizeStr?.with {map[it[0]?.toString()?.trim()]=''}
            map
        }
   return result
    }

But, I have String with comma in the values, so the above function doesn't work for me. Heres my String

[program_type:, subsidiary_code:, groupName:, termination_date:, effective_date:, subsidiary_name:ABC, INC]

my function returns ABC only. not ABC, INC. I googled about it but couldnt find any concrete help.

Generally speaking, if I have to convert a Stringified Map to a Map object I try to make use of Eval.me . Your example String though isn't quite right to do so, if you had the following it would "just work":

// Note I have added '' around the values.
​String a = "[program_type:'', subsidiary_code:'', groupName:'', termination_date:'', effective_date:'', subsidiary_name:'ABC']"
Map b = Eval.me(a)​
// returns b = [program_type:, subsidiary_code:, groupName:, termination_date:, effective_date:, subsidiary_name:ABC]

If you have control of the String then if you can create it following this kind of pattern, it would be the easiest solution I suspect.

In case it is not possible to change the input parameter, this might be a not so clean and not so short option. It relies on the colon instead of comma values.

​String reportValues = "[program_type:, subsidiary_code:, groupName:, termination_date:, effective_date:, subsidiary_name:ABC, INC]"
reportValues = reportValues[1..-2]
def m = reportValues.split(":")
def map = [:]
def length = m.size()
m.eachWithIndex { v, i ->
    if(i != 0) {
        List l = m[i].split(",")
        if (i == length-1) {
             map.put(m[i-1].split(",")[-1], l.join(","))
        } else {
             map.put(m[i-1].split(",")[-1], l[0..-2].join(","))
        }
    }
}
map.each {key, value -> println "key: " + key + " value: " + value}

BTW: Only use eval on trusted input, AFAIK it executes everything.

You could try messing around with this bit of code:

String tempString = "[program_type:11, 'aa':'bb', subsidiary_code:, groupName:, termination_date:, effective_date:, subsidiary_name:ABC, INC]"
        List StringasList = tempString.tokenize('[],')
        def finalMap=[:]
        StringasList?.each { e->
             def f = e?.split(':')
             finalMap."${f[0]}"= f.size()>1 ? f[1] : null

        }
        println """--  tempString: ${tempString.getClass()} StringasList: ${StringasList.getClass()}
                        finalMap: ${finalMap.getClass()} \n Results\n finalMap ${finalMap}
            """

Above produces:

--  tempString: class java.lang.String StringasList: class java.util.ArrayList
                        finalMap: class java.util.LinkedHashMap 
 Results
 finalMap [program_type:11,  'aa':'bb',  subsidiary_code:null,  groupName:null,  termination_date:null,  effective_date:null,  subsidiary_name:ABC,  INC:null]

It tokenizes the String then converts ArrayList by iterating through the list and passing each one again split against : into a map. It also has to check to ensure the size is greater than 1 otherwise it will break on f[1]

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM