I need to unmarshal an API response that not always includes values for some of the structs defined inside the main struct. The main struct looks like this:
type CaseResponse struct {
Result struct {
GroupList string `json:"group_list"`
UCopiedFrom string `json:"u_copied_from"`
UOfferVariant string `json:"u_offer_variant"`
SyncDriver string `json:"sync_driver"`
PrimaryContact *PrimaryContact `json:"primary_contact,omitempty"`
Entitlement string `json:"entitlement"`
CaseReport *CaseReport `json:"case_report,omitempty"`
ResolvedAt string `json:"resolved_at"`
} `json:"result"`
}
The internal structs for above json are defined as:
type PrimaryContact struct {
Link string `json:"link,omitempty"`
Value string `json:"value,omitempty"`
}
type CaseReport struct {
Link string `json:"link,omitempty"`
Value string `json:"value,omitempty"`
}
It is common for PrimaryContact and CaseReport to return empty, and when they do, Go throws error: json cannot unmarshal string into Go struct .result.case_report of type main.CaseReport
I looked for possible fixes. First I added the ",omitempty" to the values for the internal structs, but didn't fix the problem. Then added the pointers for PrimaryContact and CaseReport as found in some other postings, but I'm still hitting the same error when the response comes back with those fields with no data such as:
{
"result": {
"group_list": "",
"u_copied_from": "",
"u_offer_variant": "",
"sync_driver": "false",
"primary_contact":"",
"entitlement": "",
"case_report": "",
"resolved_at": ""
}
but works fine when primary_contact and case_report values come back as:
{
"result": {
"group_list": "",
"u_copied_from": "",
"u_offer_variant": "",
"sync_driver": "false",
"primary_contact": {
"link": "some link",
"value": "1e717ed013897b00f2345aa12244b003"
},
"entitlement": "",
"case_report": {
"link": "some link",
"value": "2b10fa5e1b1b19d45836ea89bd4bcb35"
},
"resolved_at": ""
}
How can the response be safely unmarshal when those fields have no value returned?
CodePudding user response:
Implement the unmarshaler interface on PrimaryContact
and CaseReport
. Do nothing when the value is the empty string.
func (pc *PrimaryContact) UnmarshalJSON(p []byte) error {
if string(p) == `""` {
// empty string, do nothing
return nil
}
// Prevent recursion to this method by declaring a new
// type with same underlying type as PrimaryContact and
// no methods.
type x PrimaryContact
return json.Unmarshal(p, (*x)(pc))
}
https://go.dev/play/p/UHJobDw5RR2
Go throws error ...
The encoding/json package function returned the error. Go does not have the throw feature.