通过Azure Function同步IoT Hub数据至Azure Digital Twin遇编码问题
解决方案:修复IoT Hub遥测数据编码问题,实现Azure Function同步至Digital Twin
问题根源分析
你看到的body内容eyJwb3dlciI6ICIxLjciLCAid2luZF9zcGVlZCI6ICIxLjciLCAid2luZF9kaXJlY3Rpb24iOiAiMS43In0=是Base64编码后的JSON,并非乱码。Azure Function报错Cannot access child value on Newtonsoft.Json.Linq.JValue,是因为代码直接将Base64编码的字符串当作JSON对象处理,而非先解码。另外你的Python发送代码存在冗余编码操作,导致数据在IoT Hub中以Base64形式存储,增加了解析复杂度。
修复步骤
1. 简化Python发送代码,避免冗余编码
requests.post会自动处理JSON数据的编码,无需手动encode("utf8"),直接传递字典或已序列化的JSON字符串即可。修改后的代码:
import datetime import requests import json deviceID = "JanTestDT" IoTHubName = "IoTJanTest" iotHubAPIVer = "2018-04-01" iotHubRestURI = f"https://{IoTHubName}.azure-devices.net/devices/{deviceID}/messages/events?api-version={iotHubAPIVer}" SASToken = 'SharedAccessSignature' headers = { 'Authorization': SASToken, 'Content-Type': "application/json; charset=utf-8" # 合并Content-Type和charset字段,符合HTTP规范 } current_datetime = datetime.datetime.now() payload = { 'power': "1.7", 'wind_speed': "1.7", 'wind_direction': "1.7" } # 直接用json参数传递字典,requests会自动完成JSON序列化和UTF-8编码 resp = requests.post(iotHubRestURI, json=payload, headers=headers)
- 用
f-string简化URI拼接,提升可读性 - 合并
Content-Type与charset为单个头字段,避免格式歧义 - 使用
requests.post的json参数,自动处理编码逻辑,避免手动操作引发的问题
2. 修改Azure Function代码,正确解析遥测数据
如果暂时无法修改发送端代码,需在Azure Function中先对body进行Base64解码,再解析为JSON。以下是对应你日志中Newtonsoft.Json报错的C#示例:
using System; using System.Text; using Microsoft.Azure.WebJobs; using Microsoft.Extensions.Logging; using Newtonsoft.Json.Linq; public static void Run(string myIoTHubMessage, ILogger log) { try { // 解码Base64字符串 byte[] data = Convert.FromBase64String(myIoTHubMessage); string jsonString = Encoding.UTF8.GetString(data); // 解析JSON对象 JObject telemetryData = JObject.Parse(jsonString); // 后续同步至Digital Twin的业务逻辑 string power = telemetryData["power"].ToString(); log.LogInformation($"Parsed power value: {power}"); } catch (Exception ex) { log.LogError($"Error in ingest function: {ex.Message}"); } }
如果是Python Function,解码逻辑如下:
import base64 import json import logging def main(myIoTHubMessage: str, log: logging.Logger) -> None: try: # 解码Base64编码内容 decoded_bytes = base64.b64decode(myIoTHubMessage) telemetry_data = json.loads(decoded_bytes.decode('utf-8')) # 后续同步至Digital Twin的业务逻辑 log.info(f"Parsed power value: {telemetry_data['power']}") except Exception as e: log.error(f"Error in ingest function: {str(e)}")
验证要点
- 发送数据后,检查IoT Hub消息的body是否为明文JSON(而非Base64编码内容)
- 在Function日志中确认解析后的JSON字段可正常访问,无
JValue相关报错
内容的提问来源于stack exchange,提问作者Eamz
相关产品推荐
相关产品推荐

