I had a back and forth with someone who really didn't want to change that behavior and their reasoning was that since you can create and provide an empty map or slice.. having the marshaler do that for you, and then also needing a way to disable that behavior, was unnecessary complexity.
To be precise.. empty slices and maps sometimes behave like nil (len, range etc) and sometimes not (inserting into a nil map). The former is a neat convenience, and I think extending that to JSON marshaling makes sense.
Not sure what you mean here by "most JavaScript parser rejects null" - did you mean "JSON parsers"? And why would they reject null, which is a valid JSON value?
It's more that when building an API that adheres to a specification, whether formal or informal, if the field is supposed to be a JSON array then it should be a JSON array. Not _sometimes_ a JSON array and _sometimes_ null, but always an array. That way clients consuming the JSON output can write code consuming that array without needing to be overly defensive
Well those are different things, aren't they? Empty slice/map is different from nil. So it makes a lot of sense that nil = null and []string{} = [], and you have an option to use both. That being said, it starts to make less sense if you work with go where the API mostly treats it as equivalent (append, len, []). So that would be my guess how it ended up the way it did.
Also, now that nil map is an empty object, shouldn't that extend to every nil struct that doesn't have a custom marshaller? It would be an object if it wasn't nil after all...
It is different from nil, but then again a nil map in Go behaves like an empty map when reading from it. If you consider serialization to be "reading", therefore, it makes sense to interpret it accordingly.
How did that make it into the v1 design?