16

I want to parse a JSON file to a map[string]interface{}:

var migrations map[string]interface{}
json.Unmarshal(raw, &migrations)

fmt.Println(migrations["create_user"])

But I modified my code to point data to interface{}:

var migrations interface{}
json.Unmarshal(raw, &migrations)

// compile wrong here
fmt.Println(migrations["create_user"])

I don't understand much about difference between map[string]interface{} and interface{} in above case.

2 Answers 2

48

The difference between those two types is just what it seems:

  1. interface{} is the "any" type, since all types implement the interface with no functions.

  2. map[string]interface{} is a map whose keys are strings and values are any type.

When unmarshaling a byte array from JSON into memory it's easiest to use the interface{} type, since it can store any type of JSON document (objects, arrays, primitives, etc.); however, it may require more reflection to handle the underlying data. Using a map[string]interface{} is common when you know the JSON document is an object and []interface{} is common when you know the document is an array.

However, the best approach for unmarshaling JSON - especially when you know the structure of the documents ahead of time - is to define and use custom struct types that describe the data exactly. This way you can avoid any reflection and improve the legibility of your code.

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

1 Comment

thanks. The problem I meet is: I have an array of "object": each object is on different type, so different struct, depend on field "type". So I must get each block separate before parsing.
16

It is because by default you need to type assert interface{} to get the underlying value of map[string]interface{}.

As per GoLang Specification

For an expression x of interface type and a type T, the primary expression

x.(T)

asserts that x is not nil and that the value stored in x is of type T. The notation x.(T) is called a type assertion.

Also Unmarshal function requires pointer to migration of type interface{} or map[string]interface{}

var migrations interface{}
json.Unmarshal(raw, &migrations)

fmt.Println(migrations.(interface{}).(map[string]interface{})["create_user"])

Since migrations is not a map. So you cannot use its key to get the value. Interface{} don't have keys

2 Comments

Can I asked a question. If an object have similar field with one struct, can we cast that object to that struct. thanks.
yes we can Unmarshal the data into struct having tags for json. Checkout this link

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.