Made some progress on my little app today (code updates happening on the development branch). This week, I learned the importance of composing structs when working with JSON (at least for working with in-memory data structures). What does all that mean?
So in python you have dictionaries that easily convert to json and vice versa, it’s like a couple of lines of code. Go is statically typed, so you have to model out the structure of the json body to tell go what tyes the values should be. Ok so you figure that out no worries, not too hard.
Now let’s talk about nesting.
Say you have json body with lists in it. if you want to be able to access those lists and work with them programmatically, then you need to do composition.
In this example, there’s a response with a list of certificates (only one shown here for brevity). If you wanted to work with those certificates individually, you would need to define a certificate struct, then a response struct, then make the certificate a slice of certificates inside the response. The way I figured it out was to print out the type of the struct I was getting from json.unmashal, to see if it was a generic struct or one I had defined.
{
"response": [
{
"id": "8c75350b-ea1b-4a51-a2e7-d37118ac04ae",
"friendlyName": "Default self-signed server certificate",
"serialNumberDecimalFormat": "16801809625158750310575466749",
"issuedTo": "ise1.pod1.abl.ninja",
"issuedBy": "ise1.pod1.abl.ninja",
"validFrom": "Thu Mar 30 12:56:02 UTC 2023",
"expirationDate": "Sat Mar 29 12:56:02 UTC 2025",
"usedBy": "EAP Authentication, Admin, Portal, RADIUS DTLS",
"keySize": 4096,
"groupTag": "Default Portal Certificate Group",
"selfSigned": true,
"signatureAlgorithm": "SHA384withRSA",
"portalsUsingTheTag": '"BYOD Portal (default), Blocked List Portal...',
"sha256Fingerprint": "20af57d758f156d33a7616a664c58d605e53e7a1f678ebf08561421d6571cad6",
"link": {
"rel": "self",
"href": "https://10.253.68.202/api/v1/certs/system-certificate/ise1/8c75350b-ea1b-4a51-a2e7-d37118ac04ae",
"type": "application/json"
}
},
],
]
Ok so here’s how I modeled this in Go:
type CertList struct {
Response []Cert
}
type Cert struct {
ID string `json:"id"`
FriendlyName string `json:"friendlyName"`
SerialNumberDecimalFormat string `json:"serialNumberDecimalFormat"`
IssuedTo string `json:"issuedTo"`
IssuedBy string `json:"issuedBy"`
ValidFrom string `json:"validFrom"`
ExpirationDate string `json:"expirationDate"`
UsedBy string `json:"usedBy"`
KeySize int `json:"keySize"`
GroupTag string `json:"groupTag"`
SelfSigned bool `json:"selfSigned"`
SignatureAlgorithm string `json:"signatureAlgorithm"`
PortalsUsingTheTag string `json:"portalsUsingTheTag"`
Sha256Fingerprint string `json:"sha256Fingerprint"`
Link struct {
Rel string `json:"rel"`
Href string `json:"href"`
} `json:"link"`
}
So why did I do that? Because I wanted to get the certificate list for each node and simply bolt on to the node struct. to do that I can add my certificate type to my node type like this:
type node struct {
Id string
Name string
Link struct {
Rel string
Href string
}
Certs []Cert
}
Time for bed.
-s