在Go中通过MQTT发布的Unmarshal JSON对象

问题描述 投票:3回答:2

我正在通过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"]

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

json go mqtt unmarshalling
2个回答
2
投票

切片与单个对象

你宣布一个切片:

var sensorData []Data

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

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

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

尝试将该声明更改为:

var sensorData Data

然后,您需要只检查一个数据实例,而不是迭代它。

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

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

`{'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

区分两种不同的有效载荷

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

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

if i.Temp[2] > 20

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

假设您总是在sensor消息中收到传感器名称,那么只有当您处理其他消息时才会出现空字符串的唯一情况。


1
投票

你的错误有两个主要原因一个是你有温度和湿度的float值,但你正在通过切片的int

type Data struct {
    Sensor string        `json:"sensor"`
    Temp []int           `json: "temperature"` // this should be []float64
    Hum []int           `json: "humidity"` // this should be []float64
}

另外在msg.Payload中有两个对象,它们不是Data结构的一部分。工作代码。

package main

import (
    "encoding/json"
    "fmt"
)

type Data struct {
    Sensor string    `json:"sensor"`
    Temp   []float64 `json:"temperature"`
    Hum    []float64 `json:"humidity"`
}

func main() {
    bytes := []byte(`{
        "sensor": "DHT22", 
        "temperature": [22.7, 22.7, 22.8], 
        "humidity": [51.9, 52.0, 52.0]
    }`)

    var sensorData Data
    if err := json.Unmarshal(bytes, &sensorData); err != nil {
        fmt.Println(err)
    }
    fmt.Println(sensorData)

}

检查Go playground上的工作代码

© www.soinside.com 2019 - 2024. All rights reserved.