func (m *Macaroon) parseBinaryV1(data []byte) ([]byte, error) {
	var err error
	loc, err := expectPacketV1(data, fieldNameLocation)
	if err != nil {
		return nil, err
	}
	data = data[loc.totalLen:]
	id, err := expectPacketV1(data, fieldNameIdentifier)
	if err != nil {
		return nil, err
	}
	data = data[id.totalLen:]
	m.init(id.data, string(loc.data), V1)
	var cav Caveat
	for {
		p, err := parsePacketV1(data)
		if err != nil {
			return nil, err
		}
		data = data[p.totalLen:]
		switch field := string(p.fieldName); field {
		case fieldNameSignature:
			if cav.Id != nil {
				m.caveats = append(m.caveats, cav)
			}
			if len(p.data) != hashLen {
				return nil, fmt.Errorf("signature has unexpected length %d", len(p.data))
			}
			copy(m.sig[:], p.data)
			return data, nil
		case fieldNameCaveatId:
			if cav.Id != nil {
				m.caveats = append(m.caveats, cav)
				cav = Caveat{}
			}
			cav.Id = p.data
		case fieldNameVerificationId:
			if cav.VerificationId != nil {
				return nil, fmt.Errorf("repeated field %q in caveat", fieldNameVerificationId)
			}
			cav.VerificationId = p.data
		case fieldNameCaveatLocation:
			if cav.Location != "" {
				return nil, fmt.Errorf("repeated field %q in caveat", fieldNameLocation)
			}
			cav.Location = string(p.data)
		default:
			return nil, fmt.Errorf("unexpected field %q", field)
		}
	}
}
The original (v1) binary format of a macaroon is as follows.
Each identifier represents a v1 packet.

location
identifier
(
caveatId?
verificationId?
caveatLocation?
)*
signature
parseBinaryV1 parses the given data in V1 format into the macaroon. The macaroon's
internal data structures will retain references to the data. It
returns the data after the end of the macaroon.
package macaroon
import (
	"encoding/base64"
	"encoding/hex"
	"encoding/json"
	"fmt"
	"unicode/utf8"
)
type macaroonJSONV1 struct {
	Caveats    []caveatJSONV1 `json:"caveats"`
	Location   string         `json:"location"`
	Identifier string         `json:"identifier"`
	Signature  string         `json:"signature"`  
}
type caveatJSONV1 struct {
	CID      string `json:"cid"`
	VID      string `json:"vid,omitempty"`
	Location string `json:"cl,omitempty"`
}
func (m *Macaroon) marshalJSONV1() ([]byte, error) {
	if !utf8.Valid(m.id) {
		return nil, fmt.Errorf("macaroon id is not valid UTF-8")
	}
	mjson := macaroonJSONV1{
		Location:   m.location,
		Identifier: string(m.id),
		Signature:  hex.EncodeToString(m.sig[:]),
		Caveats:    make([]caveatJSONV1, len(m.caveats)),
	}
	for i, cav := range m.caveats {
		if !utf8.Valid(cav.Id) {
			return nil, fmt.Errorf("caveat id is not valid UTF-8")
		}
		mjson.Caveats[i] = caveatJSONV1{
			Location: cav.Location,
			CID:      string(cav.Id),
			VID:      base64.RawURLEncoding.EncodeToString(cav.VerificationId),
		}
	}
	data, err := json.Marshal(mjson)
	if err != nil {
		return nil, fmt.Errorf("cannot marshal json data: %v", err)
	}
	return data, nil
}
func (m *Macaroon) initJSONV1(mjson *macaroonJSONV1) error {
	m.init([]byte(mjson.Identifier), mjson.Location, V1)
	sig, err := hex.DecodeString(mjson.Signature)
	if err != nil {
		return fmt.Errorf("cannot decode macaroon signature %q: %v", m.sig, err)
	}
	if len(sig) != hashLen {
		return fmt.Errorf("signature has unexpected length %d", len(sig))
	}
	copy(m.sig[:], sig)
	m.caveats = m.caveats[:0]
	for _, cav := range mjson.Caveats {
		vid, err := Base64Decode([]byte(cav.VID))
		if err != nil {
			return fmt.Errorf("cannot decode verification id %q: %v", cav.VID, err)
		}
		m.appendCaveat([]byte(cav.CID), vid, cav.Location)
	}
	return nil
}