如何从 map[string]interface{} 中提取数据?

huangapple go评论94阅读模式
英文:

How to extract data from map[string]interface{}?

问题

我正在将数据发送到API,如下所示:

{"after": {"amount": 811,"id":123,"status":"Hi"}, "key": [70]}

并且在打印时我得到以下结果:

map[after:map[amount:811 id:123 status:Hi ] key:[70]]

有没有办法像这样打印单个字段呢?
amount::800
id:123
status:Hi

代码如下:

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

var (
	PORT = ":8080"
)

func main() {
	fmt.Println("In Main")
	http.HandleFunc("/", changedData)
	http.ListenAndServe(PORT, nil)
}

type Data struct {
	Id     int64   `json:"id"`
	Amount float64 `json:"amount"`
	Status string  `json:"status"`
}

type mark map[string]interface{}

func changedData(w http.ResponseWriter, r *http.Request) {
	fmt.Println("Coming From API")

	reqBody, _ := ioutil.ReadAll(r.Body)
	fmt.Println("Data coming from API ", string(reqBody))

	digit := json.NewDecoder(strings.NewReader(string(reqBody)))

	for digit.More() {
		var result mark
		err := digit.Decode(&result)
		if err != nil {
			if err != io.EOF {
				log.Fatal(err)
			}
			break
		}
		fmt.Println("final_data ", result)
	}
}
英文:

I am sending the data to the API like following:

{"after": {"amount": 811,"id":123,"status":"Hi"}, "key": [70]}

and i am getting following while printing :

 map[after:map[amount:811 id:123 status:Hi ] key:[70]]

Is there any way to print individual field like this??
amount::800
id:123
status:Hi

The code:

package main

import (
	"encoding/json"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"
	"strings"
)

var (
	PORT       = ":8080"
)

func main() {
	fmt.Println("In Main")
	http.HandleFunc("/", changedData)
	http.ListenAndServe(PORT, nil)
}

type Data struct {
	Id               int64 `json:"id"`
	Amount           float64 `json:"amount"`
	Status           string  `json:"status"`
	
}


type mark map[string]interface{}

func changedData(w http.ResponseWriter, r *http.Request) {
	fmt.Println("Coming From API")
	
	reqBody, _ := ioutil.ReadAll(r.Body)
	fmt.Println("Data coming from API ", string(reqBody))

	digit := json.NewDecoder(strings.NewReader(string(reqBody)))

	for digit.More() {
		var result mark
		err := digit.Decode(&result)
		if err != nil {
			if err != io.EOF {
				log.Fatal(err)
			}
			break
		}
		fmt.Println("final_data ", result)
}
}

答案1

得分: 2

将其解码为与JSON文档结构匹配的Go类型。您为“after”字段声明了一个类型。将该类型与一个结构体包装以匹配文档。

func changedData(w http.ResponseWriter, r *http.Request) {
    var v struct{ After Data }
    err := json.NewDecoder(r.Body).Decode(&v)
    if err != nil {
        http.Error(w, "bad request", 400)
        return
    }
    fmt.Printf("final_data: %#v", v.After)
}

Playground示例

英文:

Decode to a Go type that matches the structure of the JSON document. You declared a type for the "after" field. Wrap that type with a struct to match the document.

func changedData(w http.ResponseWriter, r *http.Request) {
	var v struct{ After Data }
	err := json.NewDecoder(r.Body).Decode(&v)
	if err != nil {
		http.Error(w, "bad request", 400)
		return
	}
	fmt.Printf("final_data: %#v", v.After)
}

Playground example.

答案2

得分: 1

我认为如果你了解JSON文件的格式,或者JSON格式是预定义的,你可以定义一个struct类型。据我所知,当你不知道JSON格式或者没有预定义的格式时,大多数情况下使用interface{}是一种方法。如果你定义了一个struct类型并在将JSON解组为结构体时使用它,你可以通过像data.Iddata.Status这样的方式访问变量。

这是一个示例代码:

package main

import (
	"encoding/json"
	"fmt"
)

type Data struct {
	AfterData After `json:"after"`
	Key       []int `json:"key"`
}

type After struct {
	Id     int64   `json:"id"`
	Amount float64 `json:"amount"`
	Status string  `json:"status"`
}

func main() {
	j := []byte(`{"after": {"amount": 811,"id":123,"status":"Hi"}, "key": [70]}`)
	var data *Data
	err := json.Unmarshal(j, &data)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	fmt.Println(data.AfterData)
	fmt.Println(data.AfterData.Id)
	fmt.Println(data.AfterData.Amount)
	fmt.Println(data.AfterData.Status)
}

输出将会是:

{123 811 Hi}
123
811
Hi

Go Playground

英文:

I think you can define a struct type if you know the JSON file format or if the JSON format is predefined. As far as I know that mostly using interface{} is a way when you don't know the JSON format or there is no predefined format of the JSON. If you define a struct type  and use it while unmarshaling the JSON to struct, you can access the variables by typing like data.Id or data.Status.

Here's an example code:

package main

import (
	"encoding/json"
	"fmt"
)

type Data struct {
	AfterData After `json:"after"`
	Key       []int `json:"key"`
}

type After struct {
	Id     int64   `json:"id"`
	Amount float64 `json:"amount"`
	Status string  `json:"status"`
}

func main() {
	j := []byte(`{"after": {"amount": 811,"id":123,"status":"Hi"}, "key": [70]}`)
	var data *Data
	err := json.Unmarshal(j, &data)
	if err != nil {
		fmt.Println(err.Error())
		return
	}
	fmt.Println(data.AfterData)
	fmt.Println(data.AfterData.Id)
	fmt.Println(data.AfterData.Amount)
	fmt.Println(data.AfterData.Status)

}

Output will be

{123 811 Hi}
123
811
Hi

Go Playground

huangapple
  • 本文由 发表于 2021年11月14日 00:40:06
  • 转载请务必保留本文链接:https://go.coder-hub.com/69956272.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定