user1858851
user1858851

Reputation: 147

Convert a groovy string to a map in groovy

I need to convert a groovy string to a map object. The string exactly is :

"\"{\\\"1\\\":[],\\\"2\\\":[],\\\"3\\\":[{\\\"name\\\":\\\"PVR_Test_Product\\\",\\\"id\\\":\\\"100048\\\"}],\\\"4\\\":[],\\\"5\\\":[]}\""

I need to fetch the value corresponding to "name". I have tried using the JsonBuilder, JsonSlurper and regexp approach for this problem. But I have not yet come to a solution.

For Simplifying things I have removed the backslashes with : replaceAll.The reduced string is :

""{"1":[],"2":[],"3":[{"name":"PVR_Test_Product","id":"100048"}],"4":[],"5":[]}""

Looking forward to any help on this.I am using grails 2.5.1 and groovy 2.4.10.

Upvotes: 2

Views: 40438

Answers (4)

Andy Xiao
Andy Xiao

Reputation: 109

The code below converts the JSON like string to an object or an array:

#!/usr/bin/env groovy

/**
 * Get the nearest object or array end
 */
def getNearestEnd(String json, int start, String head, String tail) {
    def end = start
    def count = 1
    while (count > 0) {
        end++
        def c = json.charAt(end)
        if (c == head) {
            count++
        } else if (c == tail) {
            count--
        }
    }
    return end;
}

/**
 * Parse the object
 */
def parseObject(String json) {
    def map = [:]
    def length = json.length()
    def index = 1
    def state = 'none' // none, string-value, other-value
    def key = ''
    while (index < length -1) {
        def c = json.charAt(index)
        switch(c) {
            case '"':
                if (state == 'none') {
                    def keyStart = index + 1;
                    def keyEnd = keyStart;
                    while (json.charAt(keyEnd) != '"') {
                        keyEnd++
                    }
                    index = keyEnd
                    def keyValue = json[keyStart .. keyEnd - 1]
                    key = keyValue
                } else if (state == 'value') {
                    def stringStart = index + 1;
                    def stringEnd = stringStart;
                    while (json.charAt(stringEnd) != '"') {
                        stringEnd++
                    }
                    index = stringEnd
                    def stringValue = json[stringStart .. stringEnd - 1]
                    map.put(key, stringValue)
                }
                break

            case '{':
                def objectStart = index
                def objectEnd = getNearestEnd json, index, '{', '}'
                def objectValue = json[objectStart .. objectEnd]
                map.put(key, parseObject(objectValue))
                index = objectEnd
                break

            case '[':
                def arrayStart = index
                def arrayEnd = getNearestEnd(json, index, '[', ']')
                def arrayValue = json[arrayStart .. arrayEnd]
                map.put(key, parseArray(arrayValue))
                index = arrayEnd
                break

            case ':':
                state = 'value'
                break

            case ',':
                state = 'none'
                key = ''
                break;

            case ["\n", "\t", "\r", " "]:
                break

            default:
                break
        }
        index++
    }

    return map
}

/**
 * Parse the array
 */
def parseArray(String json) {
    def list = []
    def length = json.length()
    def index = 1
    def state = 'none' // none, string-value, other-value
    while (index < length -1) {
        def c = json.charAt(index)
        switch(c) {
            case '"':
                def stringStart = index + 1;
                def stringEnd = stringStart;
                while (json.charAt(stringEnd) != '"') {
                    stringEnd++
                }
                def stringValue = json[stringStart .. stringEnd - 1]
                list.add(stringValue)
                index = stringEnd
                break

            case '{':
                def objectStart = index
                def objectEnd = getNearestEnd(json, index, '{', '}')
                def objectValue = json[objectStart .. objectEnd]
                list.add(parseObject(objectValue))
                index = objectEnd
                break

            case '[':
                def arrayStart = index
                def arrayEnd = getNearestEnd(json, index, '[', ']')
                def arrayValue = json[arrayStart .. arrayEnd]
                list.add(parseArray(arrayValue))
                index = arrayEnd
                break

            case ["\n", "\t", "\r", " "]:
                break

            case ',':
                state = 'none'
                key = ''
                break;

            default:
                break
        }
        index++
    }

    return list
}

/**
 * Parse the JSON, object or array
 */
def parseJson(String json) {
    def start = json[0]
    if (start == '[') {
        return parseArray(json)
    } else if (start == '{') {
        return parseObject(json)
    } else {
        return null
    }
}

// Test code
println parseJson('{"abdef":["Jim","Tom","Sam",["XYZ","ABC"]],{"namek":["adbc","cdef"]}}')

Upvotes: 1

cfrick
cfrick

Reputation: 37008

Someone is handing you down the JSON of the JSON of your data. Blindly removing the \ might end up badly. But you can just de-JSON twice.

As always in such cases: if someone is giving you data in that shape you can talk to, make sure, they have a perfectly fine reason to do such things. More often than not, this some sort of error.

def jsonOfJson = "\"{\\\"1\\\":[],\\\"2\\\":[],\\\"3\\\":[{\\\"name\\\":\\\"PVR_Test_Product\\\",\\\"id\\\":\\\"100048\\\"}],\\\"4\\\":[],\\\"5\\\":[]}\""
def slurper = new groovy.json.JsonSlurper()
def json = slurper.parseText(jsonOfJson)
println(json.inspect())
// -> '{"1":[],"2":[],"3":[{"name":"PVR_Test_Product","id":"100048"}],"4":[],"5":[]}'
def data = slurper.parseText(json)
println(data.inspect())
// -> ['1':[], '2':[], '3':[['name':'PVR_Test_Product', 'id':'100048']], '4':[], '5':[]]
assert data["3"].size()==1

Upvotes: 0

daggett
daggett

Reputation: 28564

/*

i put exactly this string into the file 1.gr
"\"{\\\"1\\\":[],\\\"2\\\":[],\\\"3\\\":[{\\\"name\\\":\\\"PVR_Test_Product\\\",\\\"id\\\":\\\"100048\\\"}],\\\"4\\\":[],\\\"5\\\":[]}\""

*/

def s= new File("./1.gr").text
println s 
// output> "\"{\\\"1\\\":[],\\\"2\\\":[],\\\"3\\\":[{\\\"name\\\":\\\"PVR_Test_Product\\\",\\\"id\\\":\\\"100048\\\"}],\\\"4\\\":[],\\\"5\\\":[]}\""
s=Eval.me(s)
println s 
// output> "{\"1\":[],\"2\":[],\"3\":[{\"name\":\"PVR_Test_Product\",\"id\":\"100048\"}],\"4\":[],\"5\":[]}"
s=Eval.me(s)
println s 
// output> {"1":[],"2":[],"3":[{"name":"PVR_Test_Product","id":"100048"}],"4":[],"5":[]}

//now it's possible to parse json
def json = new groovy.json.JsonSlurper().parseText(s)

Upvotes: 0

Rao
Rao

Reputation: 21359

You have a json string which can be parsed with JsonSlurper.

Here you go:

def string = """{"1":[],"2":[],"3":[{"name":"PVR_Test_Product","id":"100048"}],"4":[],"5":[]}"""
def json = new groovy.json.JsonSlurper().parseText(string)
assert json instanceof Map​​​​​

You may quickly try this online Demo

Upvotes: 10

Related Questions