Home > database >  json: cannot unmarshal string into Go struct field .result.case_report of type main.CaseReport
json: cannot unmarshal string into Go struct field .result.case_report of type main.CaseReport

Time:12-17

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.

  • Related