|
Dumb question about dealing with json in GO. In powershell, let's pretend the json body I am working with is: code:
code:
Similarly in python I can store that json statement as data and then: code:
How can I do this same thing in Go? I've googled and sure, I can declare a struct, but I'm writing this to service API calls to dozens of different endpoints, all with different json responses, I shouldn't need to define dozens of structs as well. Googling how to do this more dynamically leads me to use map[string]interface{} which just pollutes the data. with "map" prefixes and brackets all over the place. This seems like such a basic thing, I'm shocked that I can't more easily do this. Blame Pyrrhus fucked around with this message at 08:52 on Jul 9, 2020 |
# ¿ Jul 9, 2020 04:50 |
|
|
# ¿ May 11, 2024 06:55 |
|
geonetix posted:There's typicall two schools of thought about the json stuff in go as far as I've seen: declare your expected responses explicitely and unmarshal into that, or use the map method. In neither python nor PowerShell have I ever had to pre-define a response structure and then populate the data. I've had to declare classes, which expect a structure and use the resulting REST response object to help populate a class properties. But how do people deal with REST APIs using Go if they have to pre-write structs to deal with the dozens, sometimes hundreds of different responses? By literally writing dozens, sometimes hundreds of structs? Really? I want to write a helper function to invoke a rest call and leave parsing of the response to the functions that invoke that helper function. JSON in -> object out. For instance, in PowerShell, I'll write a bespoke Invoke-ProductRestCall function that does all of the heavy lifting (authentication, URI construction and validation, response error handling, etc) Then I'll write a cmdlet as a function for like, Get-ProductObject that will use the Invoke-ProductRestCall to populate object data. For a very basic example in PowerShell, look at lines 32 and 33 here. Line 32 invokes a custom rest call to the API and populates a (generic PSObject) $response, and then the cmdlet function returns that response as-is. At no point do I ever need to pre-define a struct. I get that powershell is often regarded as a weaker language, and I'm obviously no developer so idk, I'm sure it is. But I can't believe that a modern language like Go is this much more cumbersome for basic JSON management. Blame Pyrrhus fucked around with this message at 17:05 on Jul 9, 2020 |
# ¿ Jul 9, 2020 16:07 |
|
gariig posted:Go is very opinionated language. One of those opinions is that it's strongly typed and statically checked, like 99%. Like geonetix said you can use map[string]interface{} but Go is going to fight you every step of the way. Forcing you to cast and check when assigning to something not an interface{}. Go is going to push you to define a struct and say how to marshal the JSON to that struct. You can choose not to do this but since you are going against Go's opinion it's going to make it VERY difficult. This makes some sense, and honestly when I re-read my last post it comes across as more angry than I intended. It's an approach that - as an operations person who writes code in service of automating "things" like (IaaS deployments) - seems counter-intuitive, but that's mostly because I am just dumb. Ultimately my goal with learning Go was to author a basic terraform provider for an API-driven storage platform, and at a high level everything about how a terraform provider is written is pretty straight forward. provider() and main() functions largely seem to serve as schemas that map the resource -> resourceFunction relationship, and downstream from that you write the CRUD functions to do all of the heavy lifting. This is going to involve modeling a lot of REST calls to our platform, so I've been looking more closely at the parts involved with doing that specifically. You're right about Go fighting you though, it's pretty easy to create an inferred "struct" of sorts by declaring a map[string]interface{} but the moment I try to do something like, access a pointer by name within that map, or range loop through over an 'interface{}' type, lint just yells at me and calls me an idiot. Which apparently I am. As for the $object.foo in PowerShell, not sure if this is what you mean, but you can enforce foo as string when you create the class. It's flexible, either let the object infer it's own type for foo via convert when it doesn't matter, or if it does matter just build a class and enforce the type like: code:
Blame Pyrrhus fucked around with this message at 22:14 on Jul 9, 2020 |
# ¿ Jul 9, 2020 22:08 |
|
Yeah I'm just maintaining a types.go in the project and appending it as-needed. Worked close with an old friend to build out the bones of a SDK and learned a few good practices around dealing with API calls, as well as using mapstructure for dealing with json responses a little more easily. Now I'm having a blast writing functions in a small Go SDK for our platform and using those when I build out resource functions in our terraform provider. Learning a lot, and can really appreciate how well documented a lot of things in Go (and terraform) are, since I'm not a developer at all but can make sense of what I am reading. Now when I see lint I immediately know where I hosed up.
|
# ¿ Aug 20, 2020 01:07 |