How to append to an interface{} in json file - json

I'm trying to append a map[string]interface{} to an existing map[string]interface{} in a json file.
Original json file:
{
"frames": {
"d_65541723636int": {
"objectId": "d_65541723636"
}
}
}
expect json file after append:
{
"frames": {
"d_65541723636int": {
"objectId": "d_65541723636"
}
"anotherthing": {
"objectId": "d_65541723636"
}
}
}
How should I do it?

import (
"encoding/json"
"fmt"
)
func main() {
var m = make(map[string]interface{})
sjson := `{
"frames": {
"d_65541723636int": {
"objectId": "d_65541723636"
}
}
}`
json.Unmarshal([]byte(sjson), &m)
m["anotherthing"] = make(map[string]interface{})
m["anotherthing"].(map[string]interface{})["objectId"] = "d_65541723636"
fmt.Printf("%v\n", m)
}

Related

Convert DynamoDB JSON to AttributeValue, Go Object or Json

I am trying to convert simple DynamoDB Object string:
{
"Item": {
"Id": {
"S": "db31"
},
"CreateTime": {
"N": "1647882237618915000"
}
}
to either dynamodb.AttributeValue and then map to a go object (go type structure) or convert to a simple JSON go object.
I think, there are similar answers (1, 2, 3) in Java, but I didn't find a similar implementation in Golang.
You could create a struct type and use json.Unmarshal to unmarshal the JSON string like this:
package main
import (
"encoding/json"
"fmt"
"os"
)
type Record struct {
Item struct {
Id struct {
S string
}
CreateTime struct {
N string
}
}
}
func main() {
str := `{
"Item": {
"Id": {
"S": "db31"
},
"CreateTime": {
"N": "1647882237618915000"
}
}
}`
var record Record
if err := json.Unmarshal([]byte(str), &record); err != nil {
fmt.Fprintf(os.Stderr, "unmarshal failed: %v", err)
os.Exit(1)
}
fmt.Printf("%s %s", record.Item.Id.S, record.Item.CreateTime.N)
}
If you want a different approach, and want to transform the result into a structure that is different than the JSON, you could use a library like gjson.
Here is an example "flattening" the result into a simpler struct:
package main
import (
"fmt"
"github.com/tidwall/gjson"
)
type Record struct {
Id string
CreateTime string
}
func main() {
str := `{
"Item": {
"Id": {
"S": "db31"
},
"CreateTime": {
"N": "1647882237618915000"
}
}
}`
values := gjson.GetMany(str, "Item.Id.S", "Item.CreateTime.N")
record := Record{
Id: values[0].Str,
CreateTime: values[1].Str,
}
fmt.Printf("%s %s", record.Id, record.CreateTime)
}

Transform Prometheus Metrics to Json with Golang

I have prometgeus metrics and I want to convert it to json format using golang. I wrote some code but without success.
For example: Prometheus Metric:
# TYPE http_requests_total counter
http_requests_total{code="200",method="GET"} 28
http_requests_total{code="200",method="POST"} 3
The JSON I want to convert:
{
"http_requests_total": [
{
"http_requests_total": {
"code": "200",
"method": "GET",
"value": 28
}
},
{
"http_requests_total": {
"code": "200",
"method": "POST",
"value": 3
}
}
]
}
I'm assuming you're looking for this to be flexible, i.e. not just handling those specific metrics? If so, the following code should do the trick.
package main
import (
"encoding/json"
"fmt"
"log"
"os"
"strings"
dto "github.com/prometheus/client_model/go"
"github.com/prometheus/common/expfmt"
)
func main() {
if err := run(); err != nil {
log.Fatal(err)
}
}
func run() error {
str := `# TYPE http_requests_total counter
http_requests_total{code="200",method="GET"} 28
http_requests_total{code="200",method="POST"} 3
`
parser := &expfmt.TextParser{}
families, err := parser.TextToMetricFamilies(strings.NewReader(str))
if err != nil {
return fmt.Errorf("failed to parse input: %w", err)
}
out := make(map[string][]map[string]map[string]any)
for key, val := range families {
family := out[key]
for _, m := range val.GetMetric() {
metric := make(map[string]any)
for _, label := range m.GetLabel() {
metric[label.GetName()] = label.GetValue()
}
switch val.GetType() {
case dto.MetricType_COUNTER:
metric["value"] = m.GetCounter().GetValue()
case dto.MetricType_GAUGE:
metric["value"] = m.GetGauge().GetValue()
default:
return fmt.Errorf("unsupported type: %v", val.GetType())
}
family = append(family, map[string]map[string]any{
val.GetName(): metric,
})
}
out[key] = family
}
enc := json.NewEncoder(os.Stdout)
enc.SetIndent("", " ")
if err = enc.Encode(out); err != nil {
return fmt.Errorf("failed to encode json: %w", err)
}
return nil
}
Output:
{
"http_requests_total": [
{
"http_requests_total": {
"code": "200",
"method": "GET",
"value": 28
}
},
{
"http_requests_total": {
"code": "200",
"method": "POST",
"value": 3
}
}
]
}

Parse JSON File in Golang

I have JSON File
{
"info": {
"_postman_id": "ac691afd-f987-47ca-82d3-dae2a367e3df",
"name": "ParseGo",
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
},
"item": [
{
"name": "Gogo",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": "https://www.google.com/",
"protocol": "https",
"host": [
"www",
"google",
"com"
],
"path": [
""
]
}
},
"response": []
},
{
"name": "Golang",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": ""
}
},
"response": []
},
{
"name": "Hide Pool!",
"request": {
"method": "GET",
"header": [],
"url": {
"raw": ""
}
},
"response": []
}
],
"protocolProfileBehavior": {}
}
and i want parse this, i want see in terminal name and method. How i can this?
i try this but not work( help pls. I try use this code
package main
{
import (
"encoding/json"
"fmt"
"log"
"os"
)
type Student struct {
Name string
Standard int `json:"Standard"`
}
func main() {
// open the file pointer
studentFile, err := os.Open("data.json")
if err != nil {
log.Fatal(err)
}
defer studentFile.Close()
var studentDecoder *json.Decoder = json.NewDecoder(studentFile)
if err != nil {
log.Fatal(err)
}
var studentList []Student
err = studentDecoder.Decode(&studentList)
if err != nil {
log.Fatal(err)
}
for i, student := range studentList {
fmt.Println("Student", i+1)
fmt.Println("Student name:", student.Name)
fmt.Println("Student standard:", student.Standard)
}
}
I'm not strong in Go, how can I modify the code for my task and is it possible? if i try this code i have this error
2020/11/05 13:29:54 json: cannot unmarshal object into Go value of type []main.Student
exit status 1
You can try to do something like this:
package main
import (
"encoding/json"
"fmt"
"io/ioutil"
"os"
)
type Data struct {
Item []Item `json:"item"`
}
type Item struct {
Name string `json:"name"`
Request Request `json:"request"`
}
type Request struct {
Method string `json:"method"`
}
func main() {
filename := "/path/to/your_file.json"
jsonFile, err := os.Open(filename)
if err != nil {
fmt.Printf("failed to open json file: %s, error: %v", filename, err)
return
}
defer jsonFile.Close()
jsonData, err := ioutil.ReadAll(jsonFile)
if err != nil {
fmt.Printf("failed to read json file, error: %v", err)
return
}
data := Data{}
if err := json.Unmarshal(jsonData, &data); err != nil {
fmt.Printf("failed to unmarshal json file, error: %v", err)
return
}
// Print
for _, item := range data.Item {
fmt.Printf("Name: %s, Method: %s \n", item.Name, item.Request.Method)
}
}
Result must look like this:
Name: Gogo, Method: GET
Name: Golang, Method: GET
Name: Hide Pool!, Method: GET

How to empty an existing JSON array object without marshalling the entire document

I'm trying to import a large JSON document from a file, empty all arrays matching a specific key or pattern, then output it, without having to marshall the entire document.
It will be run as part of a periodic batch job, so performance/efficiency is not a priority.
Simplicity, and making sure the code is agnostic to the overall JSON structure, is more important.
Is there an easy way to do solve this in Go?
Example input:
{
"panels": [
{
"alert": {
"executionErrorState": "alerting",
"notifications": [
{
"uid": "fRLbH_6Zk"
},
{
"uid": "8gamKl6Waz"
}
]
}
},
{
"alert": {
"executionErrorState": "alerting",
"notifications": [
{
"uid": "DqjrD_6Zk"
}
]
}
}
]
}
Desired output (all entries in 'alert.notifications' in 'panels' removed):
{
"panels": [
{
"alert": {
"executionErrorState": "alerting",
"notifications": []
}
},
{
"alert": {
"executionErrorState": "alerting",
"notifications": []
}
}
]
}
you can use read streams, to read objects one by one. Code will be unmarshall first object, but will have error on the next one. Its like approve of state that code dont read whole file, here example:
package main
import (
"encoding/json"
"fmt"
"log"
"strings"
)
func main() {
const jsonStream = `
[
{"Name": "Ed", "Text": "Knock knock."},
asdasd sadasd,
`
type Message struct {
Name, Text string
}
dec := json.NewDecoder(strings.NewReader(jsonStream))
// read open bracket
t, err := dec.Token()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%T: %v\n", t, t)
// while the array contains values
for dec.More() {
var m Message
// decode an array value (Message)
err := dec.Decode(&m)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%v: %v\n", m.Name, m.Text)
}
// read closing bracket
t, err = dec.Token()
if err != nil {
log.Fatal(err)
}
fmt.Printf("%T: %v\n", t, t)
}

Converting JSON with array

I have written following code to get array from JSON, and want to retrieve something like
[{"id":"id1","friendly":"friendly1"},{"id":"id2","friendly":"friendly2"}]
But it's empty:
[{"id":"","friendly":""},{"id":"","friendly":""}]
package main
import (
"encoding/json"
"fmt"
)
var input = `[
{
"not needed": "",
"_source": {
"id": "id1",
"friendly": "friendly1"
}
},
{
"_source": {
"id": "id2",
"friendly": "friendly2"
}
}]`
type source struct {
Id string `json:"id"`
Friendly string `json:"friendly"`
}
func main() {
result := make([]source, 0)
sources := []source{}
json.Unmarshal([]byte(input), &sources)
for _, n := range sources {
result = append(result, n)
}
out, _ := json.Marshal(result)
fmt.Println(string(out))
}
Try creating an another struct that have one field called Source of type source. In my example below I called this struct outer. Your input should be an array of outer and your result an array of source.
Something like this:
import (
"encoding/json"
"fmt"
)
var input = `[
{
"not needed": "",
"_source": {
"id": "id1",
"friendly": "friendly1"
}
},
{
"_source": {
"id": "id2",
"friendly": "friendly2"
}
}]`
type outer struct {
Source source `json:"_source"`
}
type source struct {
Id string `json:"id"`
Friendly string `json:"friendly"`
}
func main() {
result := make([]source, 0)
sources := []outer{}
json.Unmarshal([]byte(input), &sources)
for _, n := range sources {
result = append(result, n.Source)
}
out, _ := json.Marshal(result)
fmt.Println(string(out))
}```