Hacker Newsnew | past | comments | ask | show | jobs | submitlogin

I think other languages cause folks to understand JSON responses as a big bag of keys and values, which have many convenient ways of being represented in those languages. When you get to Go and you want to parse a JSON response, it has to be a well-defined thing that you understand ahead of time, but I also think you adapt when doing this more than once in Go.


If I had one complaint, it’s the use of ‘tags’ to configure how json is handled on a struct, such that it basically becomes part of the struct’s type. It can lead to a fair bit of duplication of structs whose only difference is the json handling, or otherwise a lot of boilerplate code with custom marshal/unmarshal methods. In some cases the advice is even to do parse the json into a map, do the conversion, and then serialise it again!

The case I ran into is where one API returned camelCase json but we wanted snake_case instead. Had to basically create another struct type with different json tags, rather than having something like decoders and encoders that can configure the output.

I like Go and a lot of the decisions it makes, but it has its fair share of pain points because of early decisions made in its design that results in repetitive and overly imperative code, and while that does help create code that is clear and comprehensible (mostly), it can distract attention away from the intended behaviour of the code.


As an aside, you may be interested in some of the ongoing work to improve the Go JSON serializer/deserializer:

https://pkg.go.dev/github.com/go-json-experiment/json


That’s some good news that will hopefully smooth json handling out.


You could wrap it in another struct and use a custom MarshalJSON implementation.


    var res map[string]any
    err := json.Unmarshal(&res)


Uh huh....and what comes next?

Trying to descend more than a couple of layers into a GoLang JSON object is a mess of casts.


Well, one used to have https://github.com/mitchellh/mapstructure which assisted here, but the lib then got abandoned.



The same things that happens in JS or python.

If you get a key wrong it throws (panics in go)


I wasn't talking about getting the keys wrong, but rather the insane verbosity of GoLang - `myVariable := retrievedObject.(map[string]interface{})["firstLevelKey"].(map[string]interface{})["secondLevelKey"].(string)` vs. `myVariable = retrievedObject["firstLevelKey"]["secondLevelKey"]`

"Oh, but that's just how it is in strongly-typed languages" - that may well be true, but we're comparing "JS or python" with GoLang here.


Especially when you're not certain of the type used for numbers.




Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact

Search: