Hi, @mistergo, welcome to the forum!
Go’s documentation is pretty thorough, but I’ll admit that sometimes it’s hard to see how different packages interact, which is what’s happening here between the net
and encoding/json
packages:
Explanation
I looked up the documentation for that package’s IPTables.StructuredStats
function and saw that it returns a slice of Stat
types.
That type’s Source
and Destination
fields are of type net.IPNet
which itself has the IP
and Mask
fields that you’re seeing.
The json.Marshal
function’s documentation says this:
If an encountered value implements the Marshaler interface and is not a nil pointer, Marshal calls its MarshalJSON method to produce JSON. If no MarshalJSON method is present but the value implements encoding.TextMarshaler instead, Marshal calls its MarshalText method and encodes the result as a JSON string.
(emphasis mine)
The IP
field has type net.IP
and that type has a MarshalText
method, so when you marshal it to JSON, you get a nice string representation. The Mask
field is of type IPMask
and it does not have a MarshalText
method, so you get the default behavior of marshaling IPMask
’s backing type: []byte
. The Marshal
documentation says this about []byte
:
Array and slice values encode as JSON arrays, except that []byte encodes as a base64-encoded string, and a nil slice encodes as the null JSON value.
(emphasis mine)
So that explains why the Mask
field is appearing as base-64: It does not have a MarshalJSON
, or MarshalText
, and its backing type is []byte
which is encoded as base-64 by default.
Question
So my question is: Can you clarify what you mean by “dynamically decode?” If you want to marshal into JSON with a different format, you will have to define your own structure and maybe your own MarshalText
/MarshalJSON
methods. We can give you more specific answers if you can clarify what it is you would like to see instead of what you’re getting.