1

In my code,a method listen to a redis queue. I took the data sent by Redis as "payload" variable for following code example. "currenttime" variable is a time.time, but json.unmarshall change it as string value. How can I prevent this? I want to obtain a time.time data from currenttime. Also the "value" data changes dynamically. "count", "name" and "currenttime" variable names can be changed every time. I can just look at the values.

type Event struct {
    ID    string      `json:"id"`
    Value interface{} `json:"value"`
}

func main() {

    payload := "{\"id\":\"61e310f79b9a4db146a8cb7d\",\"value\":{\"Value\":{\"count\":55,\"currenttime\":\"2022-02-23T00:00:00Z\",\"name\":\"numberone\"}}}"
    var event Event
    if err := json.Unmarshal([]byte(payload), &event); err != nil {
        fmt.Println(err)
    }
    fmt.Println(event)
}

0

1 Answer 1

2

If Event.Value.Value has a pre-defined structure

Use proper struct to model your input JSON, where you can use time.Time for the currenttime JSON property:

type Event struct {
    ID    string `json:"id"`
    Value struct {
        Value struct {
            Count       int       `json:"count"`
            CurrentTime time.Time `json:"currenttime"`
            Name        string    `json:"name"`
        } `json:"Value"`
    } `json:"value"`
}

Printing it like:

fmt.Println(event)
fmt.Printf("%+v\n", event)
fmt.Printf("%T %v\n", event.Value.Value.CurrentTime, event.Value.Value.CurrentTime)

Output is (try it on the Go Playground):

{61e310f79b9a4db146a8cb7d {{55 2022-02-23 00:00:00 +0000 UTC numberone}}}
{ID:61e310f79b9a4db146a8cb7d Value:{Value:{Count:55 CurrentTime:2022-02-23 00:00:00 +0000 UTC Name:numberone}}}
time.Time 2022-02-23 00:00:00 +0000 UTC

If Event.Value.Value has no pre-defined structure

If properties of Event.Value.Value can change dynamically, use a map (map[string]interface{}) to unmarshal into. Since we can't tell this time that we want a time.Time value (other properties do not hold time values), the time field will be unmarshaled into a string. So you have to iterate over its values and try to parse the values with the proper layout. If parsing it as a time succeeds, we have what we want.

Here's how it would look like:

type Event struct {
    ID    string `json:"id"`
    Value struct {
        Value map[string]interface{} `json:"Value"`
    } `json:"value"`
}

func main() {

    payload := "{\"id\":\"61e310f79b9a4db146a8cb7d\",\"value\":{\"Value\":{\"foo\":55,\"mytime\":\"2022-02-23T00:00:00Z\",\"bar\":\"numberone\"}}}"
    var event Event
    if err := json.Unmarshal([]byte(payload), &event); err != nil {
        fmt.Println(err)
    }

    for _, v := range event.Value.Value {
        if s, ok := v.(string); ok {
            t, err := time.Parse("2006-01-02T15:04:05Z", s)
            if err == nil {
                fmt.Println("Found time:", t)
            }
        }
    }
}

This will output (try it on the Go Playground):

Found time: 2022-02-23 00:00:00 +0000 UTC
Sign up to request clarification or add additional context in comments.

3 Comments

I forgot to add that the data changes dynamically
@oakkose What data? My code solves the problem outlined in the question. Please edit your question with the missing details.
@oakkose Added example how to get the time if Event.Value.Value has no pre-defined structure.

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.