Gin: how do we return an array of json as response

Created on 28 Jul 2014  Â·  8Comments  Â·  Source: gin-gonic/gin

from the example looks like we can only return a single json file for response? could you please advice? thanks

Most helpful comment

Context.JSON accepts an interface{} which means that you can pass any value.

res := []string{"foo", "bar"}
c.JSON(200, res)

Has the expected result:

["foo","bar"]

All 8 comments

Context.JSON accepts an interface{} which means that you can pass any value.

res := []string{"foo", "bar"}
c.JSON(200, res)

Has the expected result:

["foo","bar"]

@alexandernyquist is right.
Check this out: http://golang.org/pkg/encoding/json/
Context.JSON uses it

For context.JSON supporting slice of nested structs

type Tag struct {
    Name          string `json:"name" form:"name" binding:"required"`
    Description   string `json:"description" form:"description" binding:"required"`
    ExtraData   TagExtra `json:"extra"`
}

tags := getTags() // which return []Tag

c.JSON(200, tags)

in result ExtraData looks empty even though ExtraData exist

[
  {
    "name": "question",
    "description": "question is something cool",
    "extra": {}
  },
  {
    "name": "intro",
    "description": "intro is something cool",
    "extra": {}
  },
...
]

when assigning to an interface slice everything seems to work out.

type Tag struct {
    Name          string `json:"name" form:"name" binding:"required"`
    Description   string `json:"description" form:"description" binding:"required"`
    ExtraData   TagExtra `json:"extra"`
}

tags := getTags() // which return []Tag

var interfaceSlice []interface{} = make([]interface{}, len(tags))
for i, tag := range tags {
    interfaceSlice[i] = tag
}

c.JSON(200, interfaceSlice) 
[
  {
    "name": "question",
    "description": "question is something cool",
    "extra": 
    {
       "id": 1,
       "created_at": "2015-08-25T00:35:55.408537Z"
       ...
  },
...
]

For now i'm reassigning to interfaceslice. Is there a better way to do this?

@thellimist
Try taking your []Tag slice and converting it to a []byte slice and write
it manually like this (you need to import "encoding/json"):

byteSlice,err := json.Marshal(yourSlice)
if err != nil {
panic(err)
}
c.Writer.Header().Set("Content-Type","application/json")
c.Writer.WriteHeader(200)
c.Writer.Write(byteSlice)

Can you see ExtraData in the json output if you do it this way? Do you get
an error at all? Maybe this can give you some more insight as to how your
Struct is being misinterpreted by gins c.JSON function.

You say, "nested arrays", but it looks like ExtraData is just a dictionary, make sure you are using a slice to hold the data that is inside ExtraData (eg. []TagExtra) if you want an array.

Lastly, you don't want to display ExtraData if its empty, but you are sacrificing your output fieldname to do so. The "encoding/json" package allows you to double up with the omitempty option like so: json:"myName,omitempty"

On Mon, Aug 24, 2015 at 3:26 PM, Furkan Yilmaz [email protected]
wrote:

type Tag struct {
Name string json:"name" form:"name" binding:"required"
Description string json:"description" form:"description" binding:"required"
ExtraData TagExtra json:"extra"
}

tags := getTags() // which return []Tag

c.JSON(200, tags)

results is although ExtraData exist

[
{
"name": "question",
"description": "question is something cool",
"ExtraData": {}
},
{
"name": "intro",
"description": "intro is something cool",
"ExtraData": {}
},
...
]

when assigning to an interface slice everything seems to work out.

type Tag struct {
Name string json:"name" form:"name" binding:"required"
Description string json:"description" form:"description" binding:"required"
ExtraData TagExtra json:"extra"
}

tags := getTags() // which return []Tag

var interfaceSlice []interface{} = make([]interface{}, len(tags))
for i, tag := range tags {
interfaceSlice[i] = tag
}

c.JSON(200, interfaceSlice)

[
{
"name": "question",
"description": "question is something cool",
"ExtraData":
{
"id": 1,
"created_at": "2015-08-25T00:35:55.408537Z"
...
},
...
]

—
Reply to this email directly or view it on GitHub
https://github.com/gin-gonic/gin/issues/87#issuecomment-134399364.

@TheRealKira

byteSlice,err := json.Marshal(yourSlice)
if err != nil {
panic(err)
}
c.Writer.Header().Set("Content-Type","application/json")
c.Writer.WriteHeader(200)
c.Writer.Write(byteSlice)

this doesn't work.

You say, "nested arrays"..

I meant "slice of nested structs" sorry for that misunderstanding. Edited the comment

@thellimist could you post the code for your getTags() function? I'm trying to figure out where in your Extra struct the non interface type screws with encoding/json.

When you said array I knew you meant slice, I just wanted to make sure you were storing a slice []ExtraData and not just ExtraData in your top level struct.

@TheRealKira

type Tag struct {
    Name          string `json:"name" form:"name" binding:"required"`
    Description   string `json:"description" form:"description" binding:"required"`
    ExtraData   TagExtra `json:"extra"`
}

type TagExtra struct {
    TypeInformation   TypeInformation `json:"type_information"`
    SenderUser        User            `json:"sender_user"`
}

and getTags returns []Tag. The inner struct (TagExtra) screws encoding/json somehow.

tags := getTags() 

var interfaceSlice []interface{} = make([]interface{}, len(tags))
for i, tag := range tags {
    interfaceSlice[i] = tag
}

c.JSON(200, tags[0]) // returns TagExtra's information correctly
c.JSON(200, tags) // returns TagExtra's information empty
c.JSON(200, interfaceSlice) // returns TagExtra's information correctly

So expected result will be something like

[
  {
    "name": "question",
    "description": "question is something cool",
    "extra": 
    {
       "type_information":
       {
               ...
       },
      "sender_user":
       {
               ...
       }
   }
  },
...
]

but instead it returns

[
  {
    "name": "question",
    "description": "question is something cool",
    "extra":  {}
  },
...
]

I hope I was able to clarify. Thank you.

@TheRealKira

byteSlice,err := json.Marshal(yourSlice)
if err != nil {
panic(err)
}
c.Writer.Header().Set("Content-Type","application/json")
c.Writer.WriteHeader(200)
c.Writer.Write(byteSlice)

this doesn't work.

You say, "nested arrays"..

I meant "slice of nested structs" sorry for that misunderstanding. Edited the comment

I also want to know how to response that string as json.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

xpbliss picture xpbliss  Â·  3Comments

lilee picture lilee  Â·  3Comments

nxvl picture nxvl  Â·  3Comments

ccaza picture ccaza  Â·  3Comments

rawoke083 picture rawoke083  Â·  3Comments