I'm working with json and golang. I've made a TCP server and, I need to Unmarshal the message to know which type of service is asked, before Unmarshal the contained data. It's a bit hard to explain so this is my code:
package main
import (
"fmt"
"encoding/json"
)
type Container struct {
Type string
Object interface{}
}
type Selling struct {
Surname string
Firstname string
//......
Price int
}
type Buying struct {
ID int
Surname string
Firstname string
//..........
}
/*
type Editing struct {
ID int
...............
}
Informations, etc etc
*/
func main() {
tmp_message_json1 := Selling{Surname: "X", Firstname: "Mister", Price: 10}
//tmp_message_json1 := Buying{ID: 1, Surname: "X", Firstname: "Mister"}
tmp_container_json1 := Container{Type: "Selling", Object: tmp_message_json1}
json_tmp, _ := json.Marshal(tmp_container_json1)
/*...........
We init tcp etc etc and then a message comes up !
...........*/
c := Container{}
json.Unmarshal(json_tmp, &c)
//I unmarshal a first time to know the type of service asked
// first question: Does Unmarshal need to be used only one time?
// does I need to pass c.Object as a string to unmarshal it in the called functions?
if c.Type == "Buying" {
takeInterfaceBuying(c.Object)
} else if c.Type == "client" {
takeInterfaceSelling(c.Object)
} else {
fmt.Println("bad entry")
}
}
func takeInterfaceBuying(Object interface{}) {
bu := Object
fmt.Println(bu.Firstname, bu.Surname, "wants to buy the following product:", bu.ID)
}
func takeInterfaceSelling(Object interface{}) {
se := Object
fmt.Println(se.Firstname, se.Surname, "wants to sell something for:", se.Price)
}
I need to handle messages which comes up like it, but I don't know if it's possible? does it possible?
Thank for help !
There is json.RawMessage for this purpose.
package main
import (
"encoding/json"
"fmt"
)
type Container struct {
Type string
Object json.RawMessage
}
type Selling struct {
Surname string
Firstname string
Price int
}
type Buying struct {
ID int
Surname string
Firstname string
}
func main() {
rawJson1 := []byte(`{"Type":"Selling","Object":{"Surname":"X","Firstname":"Mister","Price":10}}`)
rawJson2 := []byte(`{"Type":"Buying","Object":{"ID":1,"Surname":"X","Firstname":"Mister"}}`)
processMessage(rawJson1)
processMessage(rawJson2)
}
func processMessage(data []byte) {
var c Container
json.Unmarshal(data, &c)
switch {
case c.Type == "Buying":
processBuying(c)
case c.Type == "Selling":
processSelling(c)
default:
fmt.Println("bad entry")
}
}
func processBuying(c Container) {
var bu Buying
json.Unmarshal(c.Object, &bu)
fmt.Println(bu.Firstname, bu.Surname, "wants to buy the following product:", bu.ID)
}
func processSelling(c Container) {
var se Selling
json.Unmarshal(c.Object, &se)
fmt.Println(se.Firstname, se.Surname, "wants to sell something for:", se.Price)
}
I might be wrong, but I don't think you can do it in one step.
First idea: Unmarshal in map[string]interface{}
Don't use type with unmarshal, instead use a map[string]interface{}, and then construct Selling/Buying from this map (or use directly the map)
type Container struct {
Type string
Object map[string]interface{}
}
Second idea: Two steps / clueless container
First: Unmarshall in a clueless Container that doesn't know the type
type CluelessContainer struct {
Type string
Object interface{} `json:"-"` // or just remove this line ?
}
Then unmarshall in the type aware container. You could use a factory pattern to come with the right struct.
How can I print (to the console) the Id, Title, Name, etc. of this struct in Golang?
type Project struct {
Id int64 `json:"project_id"`
Title string `json:"title"`
Name string `json:"name"`
Data Data `json:"data"`
Commits Commits `json:"commits"`
}
To print the name of the fields in a struct:
fmt.Printf("%+v\n", yourProject)
From the fmt package:
when printing structs, the plus flag (%+v) adds field names
That supposes you have an instance of Project (in 'yourProject')
The article JSON and Go will give more details on how to retrieve the values from a JSON struct.
This Go by example page provides another technique:
type Response2 struct {
Page int `json:"page"`
Fruits []string `json:"fruits"`
}
res2D := &Response2{
Page: 1,
Fruits: []string{"apple", "peach", "pear"}}
res2B, _ := json.Marshal(res2D)
fmt.Println(string(res2B))
That would print:
{"page":1,"fruits":["apple","peach","pear"]}
If you don't have any instance, then you need to use reflection to display the name of the field of a given struct, as in this example.
type T struct {
A int
B string
}
t := T{23, "skidoo"}
s := reflect.ValueOf(&t).Elem()
typeOfT := s.Type()
for i := 0; i < s.NumField(); i++ {
f := s.Field(i)
fmt.Printf("%d: %s %s = %v\n", i,
typeOfT.Field(i).Name, f.Type(), f.Interface())
}
I want to recommend go-spew, which according to their github "Implements a deep pretty printer for Go data structures to aid in debugging"
go get -u github.com/davecgh/go-spew/spew
usage example:
package main
import (
"github.com/davecgh/go-spew/spew"
)
type Project struct {
Id int64 `json:"project_id"`
Title string `json:"title"`
Name string `json:"name"`
Data string `json:"data"`
Commits string `json:"commits"`
}
func main() {
o := Project{Name: "hello", Title: "world"}
spew.Dump(o)
}
output:
(main.Project) {
Id: (int64) 0,
Title: (string) (len=5) "world",
Name: (string) (len=5) "hello",
Data: (string) "",
Commits: (string) ""
}
my 2cents would be to use json.MarshalIndent -- surprised this isn't suggested, as it is the most straightforward. for example:
func prettyPrint(i interface{}) string {
s, _ := json.MarshalIndent(i, "", "\t")
return string(s)
}
no external deps and results in nicely formatted output.
I think it would be better to implement a custom stringer if you want some kind of formatted output of a struct
for example
package main
import "fmt"
type Project struct {
Id int64 `json:"project_id"`
Title string `json:"title"`
Name string `json:"name"`
}
func (p Project) String() string {
return fmt.Sprintf("{Id:%d, Title:%s, Name:%s}", p.Id, p.Title, p.Name)
}
func main() {
o := Project{Id: 4, Name: "hello", Title: "world"}
fmt.Printf("%+v\n", o)
}
p = Project{...}
fmt.Printf("%+v", p)
fmt.Printf("%#v", p) //with type
Alternatively, try using this function PrettyPrint()
// print the contents of the obj
func PrettyPrint(data interface{}) {
var p []byte
// var err := error
p, err := json.MarshalIndent(data, "", "\t")
if err != nil {
fmt.Println(err)
return
}
fmt.Printf("%s \n", p)
}
In order to use this you do not need any additional packages with the exception of fmt and encoding/json, just a reference, pointer to, or literal of the struct you have created.
To use just take your struct, initialize it in main or whatever package you are in and pass it into PrettyPrint().
type Prefix struct {
Network string
Mask int
}
func valueStruct() {
// struct as a value
var nw Prefix
nw.Network = "10.1.1.0"
nw.Mask = 24
fmt.Println("### struct as a pointer ###")
PrettyPrint(&nw)
}
It's output would be
### struct as a pointer ###
{
"Network": "10.1.1.0",
"Mask": 24
}
Play around with the code here.
It is very convenient to use package fmt to output:
fmt.Printf("%+v \n", yourProject)
if you want to see the full type of the sturct, you can use # replace + :
fmt.Printf("%#v \n", yourProject)
I recommend to use Pretty Printer Library. In that you can print any struct very easily.
Install Library
https://github.com/kr/pretty
or
go get github.com/kr/pretty
Now do like this in your code
package main
import (
fmt
github.com/kr/pretty
)
func main(){
type Project struct {
Id int64 `json:"project_id"`
Title string `json:"title"`
Name string `json:"name"`
Data Data `json:"data"`
Commits Commits `json:"commits"`
}
fmt.Printf("%# v", pretty.Formatter(Project)) //It will print all struct details
fmt.Printf("%# v", pretty.Formatter(Project.Id)) //It will print component one by one.
}
Also you can get difference between component through this library and so more. You can also have a look on library Docs here.
I like litter.
From their readme:
type Person struct {
Name string
Age int
Parent *Person
}
litter.Dump(Person{
Name: "Bob",
Age: 20,
Parent: &Person{
Name: "Jane",
Age: 50,
},
})
Sdump is pretty handy in tests:
func TestSearch(t *testing.T) {
result := DoSearch()
actual := litterOpts.Sdump(result)
expected, err := ioutil.ReadFile("testdata.txt")
if err != nil {
// First run, write test data since it doesn't exist
if !os.IsNotExist(err) {
t.Error(err)
}
ioutil.Write("testdata.txt", actual, 0644)
actual = expected
}
if expected != actual {
t.Errorf("Expected %s, got %s", expected, actual)
}
}
To print the struct as JSON:
fmt.Printf("%#v\n", yourProject)
Also possible with (as it was mentioned above):
fmt.Printf("%+v\n", yourProject)
But the second option prints string values without "" so it is harder to read.
I suggest u use fmt.Printf("%#v\n", s) , It will print golang type at the same time
package main
import (
"fmt"
"testing"
)
type student struct {
id int32
name string
}
type Project struct {
Id int64 `json:"project_id"`
Title string `json:"title"`
Name string `json:"name"`
}
func TestPrint(t *testing.T) {
s := Project{1, "title","jack"}
fmt.Printf("%+v\n", s)
fmt.Printf("%#v\n", s)
}
result:
{Id:1 Title:title Name:jack}
main.Project{Id:1, Title:"title", Name:"jack"}
You can do the json mashal first and print it as a string. There you can see it the whole struct value completely.
package main
import "fmt"
import "json"
type Project struct {
Id int64 `json:"project_id"`
Title string `json:"title"`
Name string `json:"name"`
}
func main() {
o := Project{Id: 4, Name: "hello", Title: "world"}
om, _ := json.marshal(o)
log.Printf("%s\n", string(om))
}
When you have more complex structures, you might need to convert to JSON before printing:
// Convert structs to JSON.
data, err := json.Marshal(myComplexStruct)
fmt.Printf("%s\n", data)
Source: https://gist.github.com/tetsuok/4942960
Sometimes, it might be handy to print the struct as valid Go code (the go/ast equivalent). For this purpose, https://github.com/hexops/valast does a great job:
package main
import (
"fmt"
"github.com/hexops/valast"
)
type ProjectData struct {
Title string `json:"title"`
Name string `json:"name"`
Data string `json:"data"`
Commits string `json:"commits"`
}
type Project struct {
Id int64 `json:"project_id"`
Data *ProjectData `json:"data"`
}
func main() {
p := Project{
Id: 1,
Data: &ProjectData{
Title: "Test",
Name: "Mihai",
Data: "Some data",
Commits: "Test Message",
},
}
fmt.Println(valast.String(p))
}
Output:
go run main.go
Project{Id: 1, Data: &ProjectData{
Title: "Test",
Name: "Mihai",
Data: "Some data",
Commits: "Test Message",
}}
Visit here to see the complete code. Here you will also find a link for an online terminal where the complete code can be run and the program represents how to extract structure's information(field's name their type & value). Below is the program snippet that only prints the field names.
package main
import "fmt"
import "reflect"
func main() {
type Book struct {
Id int
Name string
Title string
}
book := Book{1, "Let us C", "Enjoy programming with practice"}
e := reflect.ValueOf(&book).Elem()
for i := 0; i < e.NumField(); i++ {
fieldName := e.Type().Field(i).Name
fmt.Printf("%v\n", fieldName)
}
}
/*
Id
Name
Title
*/
Maybe this shouldn't be applied for production requests but if you are on debugging mode I suggest you follow the below approach.
marshalledText, _ := json.MarshalIndent(inputStruct, "", " ")
fmt.Println(string(marshalledText))
This results in formatting the data in json format with increased readability.
i suggest to use json.Unmarshal()
i try to print the id with this hope its helpfull:
var jsonString = `{"Id": 1, "Title": "the title", "Name": "the name","Data": "the data","Commits" : "the commits"}`
var jsonData = []byte(jsonString)
var data Project
var err = json.Unmarshal(jsonData, &data)
if err != nil {
fmt.Println(err.Error())
return
}
fmt.Println("Id :", data.Id)
There's also go-render, which handles pointer recursion and lots of key sorting for string and int maps.
Installation:
go get github.com/luci/go-render/render
Example:
type customType int
type testStruct struct {
S string
V *map[string]int
I interface{}
}
a := testStruct{
S: "hello",
V: &map[string]int{"foo": 0, "bar": 1},
I: customType(42),
}
fmt.Println("Render test:")
fmt.Printf("fmt.Printf: %#v\n", a)))
fmt.Printf("render.Render: %s\n", Render(a))
Which prints:
fmt.Printf: render.testStruct{S:"hello", V:(*map[string]int)(0x600dd065), I:42}
render.Render: render.testStruct{S:"hello", V:(*map[string]int){"bar":1, "foo":0}, I:render.customType(42)}
fmt.Printf("%+v\n", project)
This is the basic way of printing the details
You don't even need the verb. This dumps everything inside of data:
fmt.Println(data)
very simple
I don't have the structure of Data and Commits So I changed the
package main
import (
"fmt"
)
type Project struct {
Id int64 `json:"project_id"`
Title string `json:"title"`
Name string `json:"name"`
Data string `json:"data"`
Commits string `json:"commits"`
}
func main() {
p := Project{
1,
"First",
"Ankit",
"your data",
"Commit message",
}
fmt.Println(p)
}
For learning you can take help from here : https://gobyexample.com/structs
If you want to write in a log file, as I was searching previously. Then you should use:
log.Infof("Information %+v", structure)
Note:: This will not work with log.Info or log.Debug. In this case, "%v" will get printed, and all the values of the structure will be printed without printing the key/variable name.
A lot of answers for a simple question. I might as well throw my hat in the ring.
package main
import "fmt"
type Project struct {
Id int64 `json:"project_id"`
Title string `json:"title"`
Name string `json:"name"`
//Data Data `json:"data"`
//Commits Commits `json:"commits"`
}
var (
Testy Project
)
func dump_project(foo Project) {
fmt.Println("== Dump Project Struct ====")
fmt.Printf("Id: %d\n", foo.Id)
fmt.Println("Title: ", foo.Title)
fmt.Printf("Name: %v\n", foo.Name)
}
func main() {
fmt.Println("hello from go")
Testy.Id = 3
Testy.Title = "yo"
Testy.Name = "my name"
fmt.Println(Testy)
dump_project(Testy)
}
The output of the various print methods
hello from go
{3 yo my name}
== Dump Project Struct ====
Id: 3
Title: yo
Name: my name
Without using external libraries and with new line after each field:
log.Println(
strings.Replace(
fmt.Sprintf("%#v", post), ", ", "\n", -1))
type Response struct {
UserId int `json:"userId"`
Id int `json:"id"`
Title string `json:"title"`
Body string `json:"body"`
}
func PostsGet() gin.HandlerFunc {
return func(c *gin.Context) {
xs, err := http.Get("https://jsonplaceholder.typicode.com/posts")
if err != nil {
log.Println("The HTTP request failed with error: ", err)
}
data, _ := ioutil.ReadAll(xs`enter code here`.Body)
// this will print the struct in console
fmt.Println(string(data))
// this is to send as response for the API
bytes := []byte(string(data))
var res []Response
json.Unmarshal(bytes, &res)
c.JSON(http.StatusOK, res)
}
}
Another way is, create a func called toString that takes struct, format the
fields as you wish.
import (
"fmt"
)
type T struct {
x, y string
}
func (r T) toString() string {
return "Formate as u need :" + r.x + r.y
}
func main() {
r1 := T{"csa", "ac"}
fmt.Println("toStringed : ", r1.toString())
}
Most of these packages are relying on the reflect package to make such things possible.
fmt.Sprintf() is using -> func (p *pp) printArg(arg interface{}, verb rune) of standard lib
Go to line 638 -> https://golang.org/src/fmt/print.go
Reflection:
https://golang.org/pkg/reflect/
Example code:
https://github.com/donutloop/toolkit/blob/master/debugutil/prettysprint.go
fmt.Println("%+v", structure variable)
A better way to do this would be to create a global constant for the string "%+v" in a package called "commons"(maybe) and use it everywhere in your code
//In commons package
const STRUCTURE_DATA_FMT = "%+v"
//In your code everywhere
fmt.Println(commons.STRUCTURE_DATA_FMT, structure variable)