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)
}
CodePudding user response:
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