0
votes

I have a large String which I want to convert to a Map in groovy.

The String data is an array of key value pairs each key and value is enclosed in square brackets [] and separated by commas. Full data string here: https://pastebin.com/raw/4rBWRzMs

Some of the values can be empty e.g. '[]' or a list of values containing , and : characters e.g. [1BLL:220,1BLE:641,2BLL:871,2BLE:475,SW:10029,KL:0,KD:78,ODT:148,AVB:358]

I only want to split on these characters if they are not enclosed in square brackets [].

The code I have tried but breaks when there are a list of values. Is there a better way? Thanks.

String testData="[[DEVICE_PROVISIONED]: [1], [aaudio.hw_burst_min_usec]: [2000],[debug.hwui.use_buffer_age]: [false], [ro.boot.boottime][1BLL:220,1BLE:641,2BLL:871,2BLE:475,SW:10029,KL:0,KD:78,ODT:148,AVB:358], ro.boot.hardware]: [walleye],[dev.mnt.blk.postinstall]: [],[ro.boot.usbradioflag]: [0],                                                                                        [ro.boot.vbmeta.avb_version]: [1.0], [ro.boot.vbmeta.device]: [/dev/sda18], [ro.boot.vbmeta.device_state]: [unlocked]]"

def map = [:]

testData.replaceAll('\\[]','null').replaceAll("\\s","").replaceAll('\\[','').replaceAll(']','').split(",").each {param ->
    def nameAndValue = param.split(":")
    map[nameAndValue[0]] = nameAndValue[1]
}

1
You probably need to write a parser for this - m0skit0
Can there be nested brackets apart from the first "[" and last "]" or does the data only consist of simple [key]: [value] pairs? Can there be square brackets within the key and/or value, which would have to be escaped somehow? BTW your testData string seems to be syntactically invalid (e. g. missing ":" after [ro.boot.boottime]and missing a "[" before ro.boot.hardware). Splitting the string into multiple lines would aid reading. - zett42

1 Answers

2
votes

I'd grep the key-value-tuples from that format and build a map from there. Once this is done it's easier to deal with further transformations. E.g.

def testData="[DEVICE_PROVISIONED]: [1], [aaudio.hw_burst_min_usec]: [2000],[debug.hwui.use_buffer_age]: [false], [ro.boot.boottime]: [1BLL:220,1BLE:641,2BLL:871,2BLE:475,SW:10029,KL:0,KD:78,ODT:148,AVB:358], [ro.boot.hardware]: [walleye],[dev.mnt.blk.postinstall]: [],[ro.boot.usbradioflag]: [0], [ro.boot.vbmeta.avb_version]: [1.0], [ro.boot.vbmeta.device]: [/dev/sda18], [ro.boot.vbmeta.device_state]: [unlocked]"

def map = [:]
(testData =~ /\s*\[(.*?)\]\s*:\s*\[(.*?)\]\s*,?\s*/).findAll{ _, k, v ->
    map.put(k,v)
}

println map.inspect()
// → ['DEVICE_PROVISIONED':'1', 'aaudio.hw_burst_min_usec':'2000', 'debug.hwui.use_buffer_age':'false', 'ro.boot.boottime':'1BLL:220,1BLE:641,2BLL:871,2BLE:475,SW:10029,KL:0,KD:78,ODT:148,AVB:358', 'ro.boot.hardware':'walleye', 'dev.mnt.blk.postinstall':'', 'ro.boot.usbradioflag':'0', 'ro.boot.vbmeta.avb_version':'1.0', 'ro.boot.vbmeta.device':'/dev/sda18', 'ro.boot.vbmeta.device_state':'unlocked']

Note that I have fixed some syntax in the testData and removed the outer []. If the original testData are actually containing invalid syntax to the rules given, then this will not work.