在esp8266(arduinoIDE)上从json获取长值时出现奇怪的错误

时间:2019-05-25 08:07:18

标签: json parsing arduino long-integer arduino-esp8266

Tldr;问题是esp8266上的long类型被转换为一个有符号的32bit int,它太小了以至于无法保存该值。使用unsigned long long作品。底部有更长的解释。

我想解析来自http://worldclockapi.com/api/json/utc/now的JSON响应并提取“ currentFileTime”字段。 作为硬件,我正在使用ESP-01。 不幸的是,我可以提取除所需字段以外的所有字段。

我正在使用版本6中的arduinoJSON库。我使用了https://arduinojson.org/v6/assistant/来生成反序列化所需的代码。我试图在文档中找到任何指示此行为的原因。如果键不存在,解析器将为变量返回默认值,这是预期的行为,即我看到的值为0,即使我验证键与jsonBuffer.containsKey("currentFileTime")一起存在,它仍会返回0。 我也尝试使用具有相同结果的StaticJsonDocument。

long GetDateTime() {
  HTTPClient http;  //Object of class HTTPClient
  http.begin("http://worldclockapi.com/api/json/utc/now");
  int httpCode = http.GET();
  //Check the returning code                                                                  
  if (httpCode > 0) {
    // Get the request response payload
    String payload = http.getString();
    const size_t capacity = JSON_OBJECT_SIZE(9) + 200;
    DynamicJsonDocument doc(capacity);

    // Just using this payload from the Arduino Assistant to test
    const char* json = "{\"$id\":\"1\",\"currentDateTime\":\"2019-05-25T07:40Z\",\"utcOffset\":\"00:00:00\",\"isDayLightSavingsTime\":false,\"dayOfTheWeek\":\"Saturday\",\"timeZoneName\":\"UTC\",\"currentFileTime\":132032436125212740,\"ordinalDate\":\"2019-145\",\"serviceResponse\":null}";

    deserializeJson(doc, json);

    const char* _id = doc["$id"]; // "1"
    const char* currentDateTime = doc["currentDateTime"]; // "2019-05-25T07:40Z"
    const char* utcOffset = doc["utcOffset"]; // "00:00:00"
    bool isDayLightSavingsTime = doc["isDayLightSavingsTime"]; // false
    const char* dayOfTheWeek = doc["dayOfTheWeek"]; // "Saturday"
    const char* timeZoneName = doc["timeZoneName"]; // "UTC"
    long currentFileTime = doc["currentFileTime"]; // 132032436125212740
    const char* ordinalDate = doc["ordinalDate"]; // "2019-145"
    Serial.println("What I want:");
    Serial.println(currentFileTime);
    Serial.println("The rest:");
    Serial.println(dayOfTheWeek);
    Serial.println(currentDateTime);
    Serial.println(utcOffset);
    Serial.println(isDayLightSavingsTime);
    Serial.println(timeZoneName);
    Serial.println(ordinalDate);

    if (doc.containsKey("currentFileTime")) {
      Serial.println("Yes currentFileTime is a key!");
      Serial.println(currentFileTime);
    } else {
      Serial.println("No currentFileTime is not a key!");
    }
    if (doc.containsKey("timeZoneName")) {
      Serial.println("Yes timeZoneName is a key!");
      Serial.println(timeZoneName);
    } else {
      Serial.println("No timeZoneName is not a key!");
    }

    return currentFileTime;
  }
  return 0;
}

在串行输出上,我得到:

What I want:
0
The rest:
Saturday
2019-05-25T07:40Z
00:00:00
0
UTC
2019-145
Yes currentFileTime is a key!
0
Yes timeZoneName is a key!
UTC

我希望“ currentFileTime”给我一个132032436125212740的值,但是会返回默认值0。 esp-01上的长数据类型可能会造成问题吗?

非常感谢!

修改: 错误搜索: 1.将值强制转换为字符串确实会产生正确的输出:

String currentFileTime = doc["currentFileTime"].as<String>(); // 132032436125212740

Ouput类似于1.3e ^ 17。因此,价值在于该领域,而关键不是问题。 2. In the esp8266 c_types.h我发现,该long被转换为一个有符号的int32(最大值:2,147,483,647),该整数大小很小。 3.使用无符号long long可以解决问题,它是一个int 64,最大值为18446744073709551616 4.我尝试使用

打印值
Serial.println(currentFileTime);

但收到错误:

call of overloaded 'println(long long unsigned int&)' is ambiguous

显然,串行库只能处理32位值,因此我遵循了this指南并安装了this库(将整个文件复制粘贴到我的标头中)。我最终可以打印出该值! 希望这会有所帮助。

0 个答案:

没有答案