How do I merge/modify json when unmarshaling?

Viewed 52

I have some sample json like this:

"payment_details": {
   "acc_number": "",
   "sort_code_1": "00",
   "sort_code_2": "11",
   "sort_code_3": "22"
},

which I am unmarshaling like so

i := &MyStruct{}
return i, json.Unmarshal(theJson, &i)

and I want MyStruct to look like this

type MyStruct struct {
    AccNumber *string `json:"acc_number"`
    SortCode *string `json:"sort_code"`
}

However I'd like to combine the separate sort code fields into one, so that in the end MyStruct will look like this

type MyStruct struct {
    AccNumber *string `json:"acc_number"` 
    SortCode *string `json:"sort_code"` // "00-11-22"
}

Is there a clever way to do this while unmarshaling?

1 Answers

You can write your own unmarshaller. The easiest way is to use a secondary struct that represents the json form. (Complete working example on the playground)

type MyStruct struct {
    AccNumber *string
    SortCode *string
}

type MyStruct_JSON struct {
    AccNumber *string `json:"acc_number"`
    SortCode1 string `json:"sort_code_1"`
    SortCode2 string `json:"sort_code_2"`
    SortCode3 string `json:"sort_code_3"`
}

func (ms *MyStruct) UnmarshalJSON(d []byte) error {
    var msj MyStruct_JSON
    if err := json.Unmarshal(d, &msj); err != nil {
        return err
    }
    // TODO: error checking for sort codes to check they're well-formed
    sortCode := msj.SortCode1 + "-" + msj.SortCode2 + "-" + msj.SortCode3
    *ms = MyStruct{
        AccNumber: msj.AccNumber,
        SortCode: &sortCode,
    }
    return nil
}

Note: it's not clear if you need all the pointers like *string or whether you can just use string. The latter is generally easy to use (and definitely will help you avoid nil-pointer dereferences), but has the potential downside of not being able to distinguish empty values from missing values. I use plain string for SortCode[1,2,3] because it looks like they have to be two-digit codes for them to be valid, so empty strings or missing fields are both errors.

Related