3

This is my struct:

type Media struct {
    MediaID   string `json:"media_id"`
    MediaType float64    `json:"media_type"`
    ViewCount float64    `json:"view_count"`
}

I'm writing an API to serve some media files and I'm using json.NewDecoder to decode and work with the response. I populate my struct like this way:

media := Media{
                MediaID:   media["media_id"].(string),
                MediaType: media["media_type"].(float64),
                ViewCount: media["view_count"].(float64),
}

It works fine in many situations but the problem is that sometimes view_count is null and it gives me this error:

interface conversion: interface {} is nil, not float64

I really appreciate any comments!

This is all the code before trying to extract response fields:

var (
    r  map[string]interface{}
)

var buf bytes.Buffer

query := map[string]interface{}{
    "query": map[string]interface{}{
        "match": map[string]interface{}{
            "content": params["q"],
        },
    },
}

if err := json.NewEncoder(&buf).Encode(query); err != nil {
    log.Fatalf("Error encoding query: %s", err)
}

res, err = es.Search(
    es.Search.WithContext(context.Background()),
    es.Search.WithIndex("myindex"),
    es.Search.WithBody(&buf),
    es.Search.WithTrackTotalHits(true),
    es.Search.WithPretty(),
)

if err := json.NewDecoder(res.Body).Decode(&r); err != nil {
    log.Fatalf("Error parsing the response body: %s", err)
}
7
  • 2
    Are you decoding the JSON to the media? If so, why not decode directly to the struct? To answer the question, use a two-value type assertion and handle the false value. Commented Jul 5, 2020 at 17:59
  • I'm decoding the response to map[string]interface{}. Then I try to populate Media struct like this. Is there any get(value or None) solution like in python?? Commented Jul 5, 2020 at 18:09
  • Is there a reason why you do not decode directly to the struct? Commented Jul 5, 2020 at 18:30
  • 1
    It is not necessary to declare a struct field for every key in the JSON object. It might be helpful to show some more of the code. If the JSON is decoded to map[string]interface{} and you have no control over that, then this question is not about type assertions and not JSON. Commented Jul 5, 2020 at 19:01
  • 1
    Decode to the struct directly: var media Media; if err := json.NewDecoder(res.Body).Decode(&media); err != nil { /* handle error */} Commented Jul 5, 2020 at 19:52

2 Answers 2

2

If you have nil for some fields, solution is POINTER!

this code is enough if you use binding

type Media struct {
    MediaID   string `json:"media_id"`
    MediaType float64    `json:"media_type"`
    ViewCount *float64    `json:"view_count"`
}

but if you wanna assign it field by field (which is not a good idea) before assigning you should check if media["view_count"] is exist or not

var viewCount float64
tmpViewCount, ok := madia["view_count"]
if ok {
   viewCount = tmpViewCount.(float64)
}

media := Media{
   MediaID:   media["media_id"].(string),
   MediaType: media["media_type"].(float64),
   ViewCount: viewCount,
}
Sign up to request clarification or add additional context in comments.

6 Comments

When I use your method it gives me this error: interface conversion: interface {} is float64, not *float64
my method is two different part, erase * from float64.
I'm looking for something like your first method but it doesn't work and gives me the above error. your second solution works fine.
@Neo if you working with JSON you can try json.Unmarshal ednsquare.com/story/…
I found out that for stream application like in my case, it's better to use NewDecoder rather than Unmarshal
|
1

The numeric fields in Media should probably be integer values instead of floating point values:

type Media struct {
    MediaID   string `json:"media_id"`
    MediaType int    `json:"media_type"`
    ViewCount int    `json:"view_count"`
}

Use pointers if the numeric fields if the JSON document uses null for these values. Hopefully that's not the case because the application must write a bit of extra code to deference the pointers.

type Media struct {
    MediaID   string `json:"media_id"`
    MediaType *int    `json:"media_type"`
    ViewCount *int    `json:"view_count"`
}

Either way, decode directly to Media as suggested in the question's commentary:

var media Media
if err := json.NewDecoder(res.Body).Decode(&media); err != nil {
    log.Fatalf("Error parsing the response body: %s", err)
}

Comments

Your Answer

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

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.