Home > Software design >  How do I fix json unmarshaling not working in golang
How do I fix json unmarshaling not working in golang

Time:12-17

I'm having a problem with unmarshaling some json data into go struct.

This an Update object I receive from the server :

{
    "update_id":433935577,
    "poll": {"id":"5899985794147287049","question":"How are you?","options":[{"text":"good","voter_count":0},{"text":"not bad","voter_count":0},{"text":"alright","voter_count":0},{"text":"bad","voter_count":1}],"total_voter_count":1,"is_closed":false,"is_anonymous":true,"type":"regular","allows_multiple_answers":false}
}

And this is the Update struct in my code :

type Update struct {
    Update_id          int                `json:"update_id"`
    Message            Message            `json:"message,omitempty"`
    Edited_message     Message            `json:"edited_message,omitempty"`
    ChannelPost        Message            `json:"channel_post,omitempty"`
    EditedChannelPost  Message            `json:"edited_channel_post,omitempty"`
    InlineQuery        InlineQuery        `json:"inline_query,omitempty"`
    ChosenInlineResult ChosenInlineResult `json:"chosen_inline_result,omitempty"`
    CallbackQuery      CallbackQuery      `json:"callback_query,omitempty"`
    ShippingQuery      ShippingQuery      `json:"shipping_query,omitempty"`
    PreCheckoutQuery   PreCheckoutQuery   `json:"pre_checkout_query,omitempty"`
    Poll               Poll               `json:"poll,omitempty"`
    PollAnswer         PollAnswer         `json:"poll_answer,omitempty"`
    MyChatMember       ChatMemberUpdated  `json:"my_chat_member,omitempty"`
    ChatMember         ChatMemberUpdated  `json:"chat_member,omitempty"`
    ChatJoinRequest    ChatJoinRequest    `json:"chat_join_request,omitempty"`
}

Basically every time one of the update fields is returned by the server, i mean some times server returns the update object with message field and some times when a poll is updated it returns it with poll field. There's no problem when server returns message field and it's unmarshaled successfully.

So normally json.Unmarshal() should unmarshal the data into the Update struct and populate the Poll field but it's not working and the Poll field is blank and not populated and I have no idea why.

And this is the Poll struct :

type Poll struct {
    Id                    string          `json:"id"`
    Question              string          `json:"quetion"`
    Options               []PollOption    `json:"options"`
    TotalVoterCount       int             `json:"total_voter_count"`
    IsClosed              bool            `json:"is_closed"`
    IsAnonymous           bool            `json:"is_anonymous"`
    Type                  string          `json:"type"`
    AllowsMultipleAnswers bool            `json:"allows_multiple_answers"`
    CorrectOptionId       int             `json:"correct_option_id,omitempty"`
    Explanation           string          `json:"explanation,omitempty"`
    ExplanationEntities   []MessageEntity `json:"explanation_entities,omitempty"`
    OpenPeriod            int             `json:"open_period,omitempty"`
    CloseDate             int             `json:"close_date,omitempty"`
}

I would appreciate it if you could help me how to fix it!


Some extra notes : The full data i receive from server is like this :

{"ok" : bool , "result" : array of update objects}

and this is the struct I have for this response :

type UpdateResult struct {
    Ok     bool     `json:"ok"`
    Result []Update `json:"result"`
}

And this is the code I use for unmarshaling :

ur := &UpdateResult{}
//body is a byte slice which contains the data received from server.
err := json.Unmarshal(body, ur)

When this code runs, err is nil but Poll is still not populated.

CodePudding user response:

The issue is that you're unmarshalling a single value to a slice

The Result in this type will hold

type UpdateResult struct {
    Ok     bool     `json:"ok"`
    Result []Update `json:"result"`
}

This

{
    "update_id":433935577,
    "poll": {"id":"58"...}
}

Then it will never work, it should be

type UpdateResult struct {
    Ok     bool     `json:"ok"`
    Result Update   `json:"result"`
}

Or you could Unmarshal to a single Result and then append it.

CodePudding user response:

I tried single and array of object both are working fine and also getting Poll data properly as expected.

Change the json tag quetion to question inside Poll struct.

 Question              string          `json:"quetion"`

You can run it here : https://go.dev/play/p/QKz98EXJkcc

Here is the code sample :

func main() {

    // {"ok" : bool , "result" : array of update objects}

    data := []byte(`{
    "ok":true,
    "result":[{
    "update_id":433935577,
    "poll": {"id":"5899985794147287049","question":"How are you?","options":[{"text":"good","voter_count":0},{"text":"not bad","voter_count":0},{"text":"alright","voter_count":0},{"text":"bad","voter_count":1}],"total_voter_count":1,"is_closed":false,"is_anonymous":true,"type":"regular","allows_multiple_answers":false}
  },
  {
    "update_id":433935577,
    "poll": {"id":"5899985794147287049","question":"How are you?","options":[{"text":"good","voter_count":0},{"text":"not bad","voter_count":0},{"text":"alright","voter_count":0},{"text":"bad","voter_count":1}],"total_voter_count":1,"is_closed":false,"is_anonymous":true,"type":"regular","allows_multiple_answers":false}
  }]
}`)

    type PollOption struct {
        Text       string `json:"text"`
        VoterCount int    `json:"voter_count"`
    }

    type Poll struct {
        Id                    string       `json:"id"`
        Question              string       `json:"question"`
        Options               []PollOption `json:"options"`
        TotalVoterCount       int          `json:"total_voter_count"`
        IsClosed              bool         `json:"is_closed"`
        IsAnonymous           bool         `json:"is_anonymous"`
        Type                  string       `json:"type"`
        AllowsMultipleAnswers bool         `json:"allows_multiple_answers"`
    }

    type Update struct {
        UpdateId int  `json:"update_id"`
        Poll     Poll `json:"poll,omitempty"`
    }

    type UpdateResult struct {
        Ok     bool     `json:"ok"`
        Result []Update `json:"result"`
    }

    ur := UpdateResult{}
    err := json.Unmarshal(data, &ur)

    if err != nil {
        fmt.Println("Error :", err)
    }
    fmt.Println(ur)

}

Output :

{true [{433935577 {5899985794147287049 How are you? [{good 0} {not bad 0} {alright 0} {bad 1}] 1 false true regular false}} {433935577 {5899985794147287049 How are you? [{good 0} {not bad 0} {alright 0} {bad 1}] 1 false true regular false}}]}
  • Related