I have the following json structure for image:
{"image": [
{
"bytesize": "-2",
"default": "redlight_drdefault"
},
{
"active": "JV77tdMcHkChFaF2H9uoDHepPhUcrlprYEsQr-r-1lg=",
"bytesize": "566806"
}
]}
I want to change the the field named "active" to "inactive" without changing the value stored in the field like the following:
{"image": [
{
"bytesize": "-2",
"default": "redlight_drdefault"
},
{
"inactive": "JV77tdMcHkChFaF2H9uoDHepPhUcrlprYEsQr-r-1lg=",
"bytesize": "566806"
}
]}
Do anyone has the solution how to do this??If u can show this on playground it will be great.
I am having difficulty in appending new value which is:
mapactive := map[string]string{"active": "gj65vn768=",
"bytesize":"76878768" }
How to append this to the solutions provided to me???This should be appended at the end of making all active keys inactive.
Golang allows direct conversion between structures that are identical in types, even if they differ in field tags. That is, you can convert directly between:
type Active struct {
Active string `json:"active"`
ByteSize string `json:"bytesize"`
}
and
type Inactive struct {
Active string `json:"inactive"`
ByteSize string `json:"bytesize"`
}
Using the following:
var a Active
// decode JSON into a
var b Inactive = Inactive(a) // direct conversion allowed
However, your input JSON won't easily support this. Your input JSON is listing the image
field as a list, despite the various entries in the list not actually being identical in type or fields. The only real option in that case is to parse it as a nested set of map[string]interface{}
:
https://play.golang.org/p/4NgiKLlHg8c
parsed := make(map[string]interface{})
if err := json.Unmarshal([]byte(input), &parsed); err != nil {
panic(err)
}
img, ok := parsed["image"]
if ok {
if imglist, ok := img.([]interface{}); ok {
for i, mi := range imglist {
if m, ok := mi.(map[string]interface{}); ok {
for k, v := range m {
if k == "active" {
m["inactive"] = v
delete(m, "active")
imglist[i] = m
}
}
}
}
}
}
b, err := json.Marshal(img)
if err != nil {
panic(err)
}
Note that I've removed a lot of sanity checks from this code to make it shorter and more readable. Using nested interface maps for handling JSONs is inherently messy. If you can change how the input JSON is formatted, you'll have a lot better luck, and more easily maintainable code, by doing so.
package main
import (
"fmt"
"encoding/json"
)
func main() {
fmt.Println("Hello, playground")
var x S
json.Unmarshal(data,&x)
for _,img:=range x.Image {
Deactive(img)
}
b,_:=json.Marshal(x)
fmt.Println(string(b))
}
type S struct {
Image []map[string]interface{} `json:"image"`
}
func Deactive(x map[string]interface{}) {
if v,ok := x["active"]; ok {
delete(x,"active")
x["inactvie"]=v
}
}
var data = []byte(` {"image": [
{
"bytesize": "-2",
"default": "redlight_drdefault"
},
{
"active": "JV77tdMcHkChFaF2H9uoDHepPhUcrlprYEsQr-r-1lg=",
"bytesize": "566806"
}
]}
`)
As I said, use map[string]interface{}
. But put it as deep as possible in the nested structure for it is messy and tricky.
The Deactive
takes in the map and looks for an active
key, if there is one, it will take the value, insert an inactive
key with that value, and delete actvie
.
Solution with predefined structures. https://play.golang.org/p/Y3xpESlbbN3
package main
import (
"encoding/json"
"fmt"
)
type (
images struct {
Image []image `json:"image"`
}
image struct {
Active string `json:"active,omitempty"`
common
}
newImages struct {
Image []newImage `json:"image"`
}
newImage struct {
common
Inactive string `json:"inactive,omitempty"`
}
common struct {
Bytesize string `json:"bytesize"`
Default string `json:"default,omitempty"`
}
)
var i = []byte(`
{"image": [
{
"bytesize": "-2",
"default": "redlight_drdefault"
},
{
"active": "JV77tdMcHkChFaF2H9uoDHepPhUcrlprYEsQr-r-1lg=",
"bytesize": "566806"
}
]}
`)
func main() {
var images images
e := json.Unmarshal(i, &images)
if e != nil {
panic(e)
}
var newImages newImages
for k, _ := range images.Image {
newImg := newImage{}
if len(images.Image[k].Active) > 0 {
newImg.Inactive = images.Image[k].Active
}
newImg.Default = images.Image[k].Default
newImg.Bytesize = images.Image[k].Bytesize
newImages.Image = append(newImages.Image, newImg)
}
result, e := json.Marshal(newImages)
if e != nil {
panic(e)
}
fmt.Println(string(result))
}