Confusion with new JSON marshaler

There’s no mention about de DevEUI format change… It seems that it’s in Base64. Is JSON legacy marshaler using old plain deveuis?

PD: I’m seeing integrations already created that have JSON marshaler and still posts DevEUI in plain HEX:

And the newer ones in Base64:

But there’s this legacy option and it’s confusing… if I still want plain hex strings in deveui I need to switch to legacy marshaler? why does the old applications still push deveui as hex and the marshaler is not the legacy one?

Thanks in advance!

There’s actually a note for the rationale for this in the “Important” box at the top of:

It was driven by the use of protobuf format for integration payloads, versus the now-legacy version that used Go structs with JSON tags and less specific requirements around byte fields.

Thanks @bconway. Didn’t read the most important part of the documentation :stuck_out_tongue:

I’ll assume that the “old” applications (the ones that were there before the upgrade to 3.11) are actually using the legacy JSON marshaler. It’s late night here and I can’t make much testing to ensure this.

When upgrading, the integrations have no marshaler option set and will fallback to the marshaler option set in the chirpstack-application-server.toml file, with json_v3 (the legacy option) as default.

Last week I have added some example code for building integrations :slight_smile: This also demonstrate how you can still print the DevEUI as HEX string. For example to build a HTTP endpoint:

func (h *handler) up(b []byte) error {
    var up integration.UplinkEvent
    if err := h.unmarshal(b, &up); err != nil {
        return err
    log.Printf("Uplink received from %s with payload: %s", hex.EncodeToString(up.DevEui), hex.EncodeToString(up.Data))
    return nil

Switching between the JSON and Protobuf (binary) format is really easy:

func (h *handler) unmarshal(b []byte, v proto.Message) error {
    if h.json {
        unmarshaler := &jsonpb.Unmarshaler{
            AllowUnknownFields: true, // we don't want to fail on unknown fields
        return unmarshaler.Unmarshal(bytes.NewReader(b), v)
    return proto.Unmarshal(b, v)

There are also Python examples (for the HTTP integration, but also Azure, AWS and GCP integrations, please refer to the documentation).

Hi @brocaar.

Thanks for the info.
The change in the integration is rather easy. It’s just a bunch of base64 convertions. My confusion araised from the fact that the old applications still shows in it’s integration configuration on the ChirpStack frontend as JSON (not the legacy one) but they are actually using the JSON (legacy).

PD: We still develop our API’s in Typescript\NodeJS. Would love to switch to Go but the time effort is a deal breaker.