Unmarshaling Into an Interface{} and Then Performing Type Assertion
Master System Design with Codemia
Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.
Introduction
In Go, unmarshaling JSON into interface{} or any is a way to accept data with a shape you do not know in advance. Once you do that, you must inspect the concrete types that encoding/json produced and use type assertions carefully.
What json.Unmarshal Produces
When JSON is decoded into interface{}, Go uses a small set of default concrete types:
- JSON object becomes
map[string]any - JSON array becomes
[]any - JSON string becomes
string - JSON boolean becomes
bool - JSON number becomes
float64 - JSON null becomes
nil
That mapping explains why later assertions succeed or fail.
The printed type will be map[string]interface {}.
Safe Type Assertion
After decoding, use the two-result form of a type assertion so your code does not panic if the data shape is different from what you expected.
The ok result is what makes the assertion safe.
Type Switches Help with Mixed Shapes
When the decoded value might be one of several shapes, a type switch is often cleaner than repeated individual assertions.
This is easier to read when the schema is genuinely loose.
Numbers Surprise People
One of the biggest surprises is that numbers become float64 when you decode into interface{}.
That means code like this fails:
because the value is actually float64, not int.
If numeric precision matters, you may want to move away from interface{} decoding or use a decoder with UseNumber.
Prefer Structs When the Shape Is Known
If the JSON has a stable schema, decoding into a struct is usually the better design.
This avoids most type assertions and gives you compile-time structure.
When interface{} Is Actually Appropriate
Decoding into interface{} makes sense when:
- the JSON shape is truly dynamic
- you are writing generic tooling
- you need to inspect arbitrary payloads before deciding what they are
If the schema is known ahead of time, interface{} usually creates extra work rather than flexibility.
Common Pitfalls
Assuming JSON numbers become int is a classic mistake. They become float64 by default.
Using single-result assertions can panic when the input shape changes unexpectedly.
Decoding into interface{} even when a concrete struct would be simpler often makes the code harder to read and test.
Forgetting that arrays become []any and objects become map[string]any leads to failed assertions in nested data.
Summary
- Unmarshaling into
interface{}is useful for dynamic JSON, not for stable schemas. - '
encoding/jsonmaps JSON values to default Go types such asmap[string]any,[]any, andfloat64.' - Use safe type assertions or type switches after decoding.
- If the schema is known, prefer decoding into a concrete struct.
- The most common source of confusion is number handling, not the interface itself.

