Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

how do we return an array of json as response #87

Closed
haoxian-zhao opened this issue Jul 28, 2014 · 8 comments
Closed

how do we return an array of json as response #87

haoxian-zhao opened this issue Jul 28, 2014 · 8 comments

Comments

@haoxian-zhao
Copy link

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

@pinscript
Copy link
Contributor

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"]

@manucorporat
Copy link
Contributor

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

@thellimist
Copy link

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?

@TheRealKira
Copy link

@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 notifications@github.com
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
#87 (comment).

@thellimist
Copy link

@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

@TheRealKira
Copy link

@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.

@thellimist
Copy link

@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.

@Praying
Copy link

Praying commented Jul 26, 2020

@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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

6 participants