A
A
Artem Rogozin2020-01-24 17:32:16
go
Artem Rogozin, 2020-01-24 17:32:16

How do custom unmarshal and marshal work in go?

In general, in the database there is a table from which we drag data, there is a column in which some fields are filled, some are null. In order for all this to be normally converted into a structure, I use sql.NullString. Accordingly, I need to give the resulting structure json. But sql.Nullstring and others like it have two fields, so the json is "unexpected". I found in the documentation that you can make a custom unmarshal and marshal. Made. Only when redefining the unmarshal method did I make a mistake and made the receiver of the method not a pointer to a structure, but a value. When I found what the error was, the question immediately arose, why, in fact, the unmarshal stops working, there is a receiver of the method - a value. And the same question about the marshal, why it also stops working if, on the contrary, the recipient method is a pointer.

type NullString struct {
  sql.NullString
}

func (ns *NullString) MarshalJSON() ([]byte, error) {
  if !ns.Valid {
    return json.Marshal(nil)
  }
  return json.Marshal(ns.String)
}

func (ns NullString) UnmarshalJSON(b []byte) error {
  err := json.Unmarshal(b, &ns.String)
  ns.Valid = err == nil
  return err
}

Answer the question

In order to leave comments, you need to log in

1 answer(s)
P
Papa, 2020-01-24
@syberianv

The language specifies that if *T implements the methods of an interface I then only a
*T (pointer) value will satisfy I, and not a T (value) value. So encoding/json can't see
that *DecimalE8 implements MarshalJSON because it only has a DecimalE8 value.
It is important to preserve this property, because a value implemented on *T might
assume that it can modify the underlying T value (which, given a value receiver, it
could not).

https://github.com/golang/go/issues/7536

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question