dragoon
dragoon

Reputation: 169

JSON.stringify equivalent in Golang for map[string]interface{}

I'm new to Golang. I have to stringify a map[string]interface{} in Golang as you would do a JSON.stringify in javascript. In javascript keys which has their values undefined gets omitted when you do JSON.stringify and I want the same thing when I do json.Marshal in Golang for nil values. For e.g. in javascript

var activity = {"isvalid": true, "value": {"prop": undefined}, "prop": undefined}
console.log(JSON.stringify(activity)) 
// Output: {"isvalid":true,"value":{}}

But in Golang if I do this

activity := map[string]interface{}{
    "isvalid": true, 
    "value": map[string]interface{}{"prop": nil},
    "prop": nil,
}
jsonStr, _ := json.Marshal(activity)
fmt.Println(string(jsonStr)) 
// output: {"isvalid":true,"prop":null,"value":{"prop":null}}

https://play.golang.org/p/dvmz32phdNU

There is a difference in output, what is a good way to make the output same in Golang as of Javascript?

EDIT:

The use case involves getting data from various sources which are of type map[string]interface{} and keys can be arbitrary, so converting it into a struct is not an option for me.

Upvotes: 4

Views: 26666

Answers (1)

leoOrion
leoOrion

Reputation: 1957

https://play.golang.org/p/KeeU7eagWh6

Define your variable as a struct and mark how each field should be marshalled into a json. There is an omit tag that can be used to ignore nil fields. Refer to the example provided

Since OP has mentioned he cannot use structs, one other way is to recursively go through the map and remove entries where the value is nil.

https://play.golang.org/p/PWd9fpWrKZH

package main

import (
    "encoding/json"
    "fmt"
)


func main() {
    data := map[string]interface{}{
        "isvalid": true, 
        "value": map[string]interface{}{"prop": nil},
        "prop": nil,
    }    
    final := removeNils(data)
    out, err := json.Marshal(final)
    if err != nil {
        panic(err)
    }
    fmt.Println(string(out))
}

func removeNils(initialMap map[string]interface{}) map[string]interface{} {
    withoutNils := map[string]interface{}{}
    for key, value := range initialMap {
        _, ok := value.(map[string]interface{})
        if ok {
            value = removeNils(value.(map[string]interface{}))
            withoutNils[key] = value
            continue
        }
        if value != nil {
            withoutNils[key] = value
        }
    }
    return withoutNils
}

Upvotes: 9

Related Questions