Search code examples
jsonstringgoreplacetokenize

How can I replace substrings in a string with JSON values in GO?


If I have the following JSON file for specifying how to run a program:

{
   "programBinary" : "/usr/bin/foo",
   "extraArgs" : " --arg1=%argumentOne --arg2=%argumentTwo",
   "argumentOne" : "foo",
   "argumentTwo" : "bar"
}

In golang, how can I parse the extraArgs string to find JSON keys specified by % and replace them with their value in the JSON file?

I know golang has a built-in replace function, but what I'm unclear on is how to parse the string and find tokens that only begin with "%".

Basically I need something along the lines of the following go-pseudocode:

var rawMap map[string]json.RawMessage;
rawErr := json.Unmarshal(byteValue, &rawMap)
if(rawErr != nil) {
    log.Printf("JSON Marshalling error (raw): %s\n" , rawErr.Error());
}
extraArgString, _ := rawMap["extraArgs"];
argTokens := magicStringTokenizer(extraArgString, "%"); //Need code for this!
for _, argToken := range argTokens {    
     argValue, _ := rawMap[argToken];
     extraArgString = string.Replace(extraArgString, argToken, argValue);
}

Obviously there'd need to be error handling if the key isn't found, but I've omitted that for clarity.

As one can see, I only want substrings beginning with "%" so all the other parts of the string should be discarded.


Solution

  • You can check go regexp for find pattern "%" as your question. However since your string is simple, and you only want substring, replace the value of %paramName. You can only use bytes.Replace to resolve your problem. (I didn't use strings.Replace since there is no need to parse to string).

    go playground

    package main
    
    import (
        "encoding/json"
        "log"
        "bytes"
    )
    
    func main() {
        byteValue := []byte(`{
           "programBinary" : "/usr/bin/foo",
           "extraArgs" : " --arg1=%argumentOne --arg2=%argumentTwo",
           "argumentOne" : "foo",
           "argumentTwo" : "bar"
        }`)
        var rawMap map[string]json.RawMessage;
        rawErr := json.Unmarshal(byteValue, &rawMap)
        if(rawErr != nil) {
            log.Printf("JSON Marshalling error (raw): %s\n" , rawErr.Error());
        }
        
        byteResult := make([]byte, len(byteValue))
        copy(byteResult, byteValue)
        
        for key, value := range rawMap {
            stringEscaped := bytes.Replace([]byte(value), []byte("\""), []byte(""), 2);//Can either remove quotes, replace them with single quotes, or escape with \" here
            byteResult = bytes.Replace(byteResult, []byte("%"+key), stringEscaped, 1)
        }   
        log.Printf("Result:\n %s", string(byteResult))
    }