首页 > 解决方案 > 在 Go 中解组通过 MQTT 发布的 JSON 对象

问题描述

我正在通过 MQTT 接收传感器数据。我想检查温度是否超过20度,如果是,请发送消息。

var f MQTT.MessageHandler = func(client MQTT.Client, msg MQTT.Message) {
    type Data struct {
        Sensor string        `json:"sensor"`
        Temp []int           `json: "temperature"`
        Hum []int           `json: "humidity"`
    }
    var sensorData []Data
    message := ""
    err := json.Unmarshal(msg.Payload(), &sensorData)
    if err != nil {
        panic(err)
    }else {

    //access certain element in the Data struct
        for _, i := range sensorData {
            if i.Temp[2] > 20 { //where the temperature is stored
                fmt.Println("Temperature too high")
                message = "Temperature too high"
            }else{
                fmt.Println("Perfect temperature")
                message = "Perfect temperature"
        }
    }

    }

    // Publish further instructions to "sensor/instruction"
    token := client.Publish("sensor/instruction", 0, false, message)
    token.Wait()
}

目前我正在发布两个要接收的 JSON 对象。我认为部分问题在于区分这两个对象。这是我得到的错误panic: json: cannot unmarshal object into Go value of type []main.Data。这些是我发布到主题的 JSON 对象:

{'sensor': 'DHT22', 'temperature': [22.7, 22.7, 22.8], 'humidity': [51.9, 52.0, 52.0]}
{'actuator': 'arduinoLED', 'blink': ['false', 'false', 'false']}

msg.Payload()给_

{"sensor": "DHT22", "temperature": [22.9, 22.9, 22.9], "humidity": [50.9, 50.9, 50.9]}
{"actuator": "arduinoLED", "blink": ["false", "false", "false"]

这些对象在循环中不断发布。我想解组第一个对象并访问特定元素。

标签: jsongomqttunmarshalling

解决方案


切片与单个对象

您正在声明一个切片:

var sensorData []Data

但是你的有效载荷不是一个数组,而只是一个对象:

{'sensor': 'DHT22', 'temperature': [22.7, 22.7, 22.8], 'humidity': [51.9, 52.0, 52.0]}

因此,该错误消息告诉您它不能将单个对象解组为切片。

尝试将该声明更改为:

var sensorData Data

然后,您只需检查一个数据实例,而不是对其进行迭代。

有效负载和结构类型之间的其他不匹配

在那之后,你可能会得到另一个错误,因为temperatureandhumidity数组似乎包含十进制数字:

`{'sensor': 'DHT22', 'temperature': [22.7, 22.7, 22.8], 'humidity': [51.9, 52.0, 52.0]`

但是您int在代码中将它们声明为切片:

Temp []int           `json: "temperature"`
Hum []int           `json: "humidity"`

所以你需要改变那些[]float64

区分两种不同的有效载荷

关于区分这两种对象类型,如果你尝试这样做会更好,但即使你不这样做,json如果字段名称不匹配,Go 的库也会忽略问题,所以当反序列化你的actuator有效载荷到Data,所有字段都将具有其默认值,但不会收到错误。

此检查可能会抛出一个panic,因为在这种情况下数组将为空:

if i.Temp[2] > 20

解决此问题的一种“hacky”方法是仅在sensor字段不是空白字符串时处理数据。

假设您总是在消息中收到传感器名称sensor,唯一会导致空字符串的情况是您刚刚处理了其他消息之一。


推荐阅读