1

I want to read full response from the server, but I don't know precise size of it.

I would expect this to work:

message, err := ioutil.ReadAll(conn)

But server is not sending EOF, so this statement just hangs.

I know its a JSON response, so I could read data until the last }, but that seems not the best way how it could be done.

What is the best practice to read full response?


update:

after some while I found out that it's possible this way:

var m map[string]interface{}
d := json.NewDecoder(conn)
d.Decode(&m)

for key, value := range m {
    fmt.Print(key)
    fmt.Print(" : ")
    fmt.Print(value)
    fmt.Print("\n")
    switch vv := value.(type) {
    case map[string]interface{}:
        for k, v := range vv {
            fmt.Print(k)
            fmt.Print(" : ")
            fmt.Print(v)
            fmt.Print("\n")
        }
    }
}

2 Answers 2

2

Use a json.Decoder. Here's how to read multiple messages:

 d := json.NewDecoder(conn)
 for {
     var m message // <-- use whatever type is appropriate for your app
     err := d.Decode(&m)
     if err == io.EOF {
         break
     } else if err != nil {
         // handle error
     }
     // do something with m
}

Remove the loop if you expect exactly one message.

Sign up to request clarification or add additional context in comments.

5 Comments

Unable to make it work. Just to be sure its a Json string coming from conn, _ := net.Dial("unix", "/var/run/some.sock"). The programm don't hang anymore, but m is empty. Getting this error: json: cannot unmarshal object into Go value of type string
Declare m to match the type of the data. It sounds like you declared m as a string, but the JSON value is an object. Try var m map[string]interface{} (which will handle a JSON object) or var m interface{} (which will handle any JSON value).
Ok it reads data in m, but now how to access data in the interface?
Edit the question to show what you actually tried and examples of the JSON. Without that information, it's impossible to help further.
I was thinking of generic working with json responses, added an update in question.
1

You want a json.Decoder. The decoder is meant to read a stream of JSON objects. It reads from the stream until it receives a complete object, and then unmarshals it onto the provided object pointer.

Example:

package main

import (
    "encoding/json"
    "fmt"
    "io"
)

func main() {
    pr, pw := io.Pipe()
    go pw.Write([]byte(`{"foo":"bar"}`))
    var data map[string]string
    json.NewDecoder(pr).Decode(&data)
    fmt.Printf("Data: %v\n", data)
}

https://play.golang.org/p/JQMXGzrDAH-

Which outputs:

Data: map[foo:bar]

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.