# Introduction

> Source: https://www.ymotongpoo.com/books/go-json-v2-history/00-introduction/


{{< message >}}
All execution results in this book were measured on go1.27 darwin/arm64. Source code quotations are from the same version.
{{< /message >}}

Write the following code in Go, and the `Name` field ends up holding `gopher`.

```go
type User struct {
	Name string `json:"name"`
}

var u User
json.Unmarshal([]byte(`{"NAME":"gopher"}`), &u)
```

The JSON key is `NAME` and the name specified in the struct tag is `name`, yet they still match. `nAmE` or `Name` would match just the same. It is surprising the first time you run into it, and it felt wrong to me too. But this is not a bug. It is specified behavior: the `encoding/json` documentation explicitly states that matching is case-insensitive.

And precisely because it was specified, the behavior went unchanged for 14 years.

In 2016, an [issue](https://github.com/golang/go/issues/14750) was filed asking whether this was really right. Security concerns were raised, and someone even wrote an actual [patch](https://go-review.googlesource.com/c/go/+/224079) to fix it. It still wasn't fixed. Until `encoding/json/v2` officially landed in Go 1.27, this behavior never changed once.

Why wasn't it fixed, and why was it rebuilt under a different name instead? After 14 years, what shape did it finally take?

Part of the answer lies outside the standard library. The fast JSON libraries such as [`goccy/go-json`](https://github.com/goccy/go-json) and [`bytedance/sonic`](https://github.com/bytedance/sonic) exist precisely because v1 could not be fixed. And in the pursuit of speed, they took on the odd job of faithfully replicating even v1's flaws. That faithfulness produced real bugs.

## Prerequisites

You need only three pieces of background.

* `encoding/json` is a standard package that has existed since Go 1.0 (2012); `Marshal` converts Go values to JSON, and `Unmarshal` converts JSON to Go values.
* Go has a backward compatibility guarantee. Programs written to the Go 1 specification will continue to compile and behave the same on later versions of Go.
* `GOEXPERIMENT` is an environment variable specified at build time, used to enable features that are not yet official or to revert a new default to its old behavior. It is distinct from `GODEBUG`, which takes effect at run time.

